mirror of
https://github.com/google/pebble.git
synced 2025-05-18 17:34:59 +00:00
Import of the watch repository from Pebble
This commit is contained in:
commit
3b92768480
10334 changed files with 2564465 additions and 0 deletions
507
third_party/FreeRTOS/Source/light_mutex.c
vendored
Normal file
507
third_party/FreeRTOS/Source/light_mutex.c
vendored
Normal file
|
@ -0,0 +1,507 @@
|
|||
/*
|
||||
FreeRTOS V8.2.1 - Copyright (C) 2015 Real Time Engineers Ltd.
|
||||
All rights reserved
|
||||
|
||||
VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
|
||||
|
||||
This file is part of the FreeRTOS distribution.
|
||||
|
||||
FreeRTOS is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License (version 2) as published by the
|
||||
Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.
|
||||
|
||||
***************************************************************************
|
||||
>>! NOTE: The modification to the GPL is included to allow you to !<<
|
||||
>>! distribute a combined work that includes FreeRTOS without being !<<
|
||||
>>! obliged to provide the source code for proprietary components !<<
|
||||
>>! outside of the FreeRTOS kernel. !<<
|
||||
***************************************************************************
|
||||
|
||||
FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. Full license text is available on the following
|
||||
link: http://www.freertos.org/a00114.html
|
||||
|
||||
***************************************************************************
|
||||
* *
|
||||
* FreeRTOS provides completely free yet professionally developed, *
|
||||
* robust, strictly quality controlled, supported, and cross *
|
||||
* platform software that is more than just the market leader, it *
|
||||
* is the industry's de facto standard. *
|
||||
* *
|
||||
* Help yourself get started quickly while simultaneously helping *
|
||||
* to support the FreeRTOS project by purchasing a FreeRTOS *
|
||||
* tutorial book, reference manual, or both: *
|
||||
* http://www.FreeRTOS.org/Documentation *
|
||||
* *
|
||||
***************************************************************************
|
||||
|
||||
http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading
|
||||
the FAQ page "My application does not run, what could be wrong?". Have you
|
||||
defined configASSERT()?
|
||||
|
||||
http://www.FreeRTOS.org/support - In return for receiving this top quality
|
||||
embedded software for free we request you assist our global community by
|
||||
participating in the support forum.
|
||||
|
||||
http://www.FreeRTOS.org/training - Investing in training allows your team to
|
||||
be as productive as possible as early as possible. Now you can receive
|
||||
FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers
|
||||
Ltd, and the world's leading authority on the world's leading RTOS.
|
||||
|
||||
http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
|
||||
including FreeRTOS+Trace - an indispensable productivity tool, a DOS
|
||||
compatible FAT file system, and our tiny thread aware UDP/IP stack.
|
||||
|
||||
http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.
|
||||
Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.
|
||||
|
||||
http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High
|
||||
Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS
|
||||
licenses offer ticketed support, indemnification and commercial middleware.
|
||||
|
||||
http://www.SafeRTOS.com - High Integrity Systems also provide a safety
|
||||
engineered and independently SIL3 certified version for use in safety and
|
||||
mission critical applications that require provable dependability.
|
||||
|
||||
1 tab == 4 spaces!
|
||||
*/
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining
|
||||
all the API functions to use the MPU wrappers. That should only be done when
|
||||
task.h is included from an application file. */
|
||||
#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
|
||||
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
#include "light_mutex.h"
|
||||
|
||||
/* Lint e961 and e750 are suppressed as a MISRA exception justified because the
|
||||
MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be defined for the
|
||||
header files above, but not in this file, in order to generate the correct
|
||||
privileged Vs unprivileged linkage and placement. */
|
||||
#undef MPU_WRAPPERS_INCLUDED_FROM_API_FILE /*lint !e961 !e750. */
|
||||
|
||||
/* Remove the whole file if light mutexes not being used. */
|
||||
#if( configUSE_LIGHT_MUTEXES != 0 )
|
||||
|
||||
#if( configUSE_PREEMPTION == 0 )
|
||||
/* If the cooperative scheduler is being used then a yield should not be
|
||||
performed just because a higher priority task has been woken. */
|
||||
#define mutexYIELD_IF_USING_PREEMPTION()
|
||||
#else
|
||||
#define mutexYIELD_IF_USING_PREEMPTION() portYIELD_WITHIN_API()
|
||||
#endif
|
||||
|
||||
typedef struct LightMutexDefinition
|
||||
{
|
||||
TaskHandle_t pxMutexHolder;
|
||||
|
||||
int16_t uxRecursiveCallCount; /*< Maintains a count of the number of times a recursive mutex has been recursively 'taken'. */
|
||||
int8_t uxLocked;
|
||||
|
||||
List_t xTasksWaitingToLock; /*< List of tasks that are blocked waiting to lock this mutex. Stored in priority order. */
|
||||
} LightMutex_t;
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Uses a critical section to determine whether the mutex is locked.
|
||||
*/
|
||||
static BaseType_t prvIsMutexLocked( const LightMutex_t *pxMutex ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/*
|
||||
* Unlocks the mutex, clearing the mutex holder.
|
||||
*/
|
||||
static BaseType_t prvMutexSetUnlocked( LightMutex_t * const pxMutex ) PRIVILEGED_FUNCTION;
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
LightMutexHandle_t xLightMutexCreate( void ) {
|
||||
LightMutex_t *pxNewMutex;
|
||||
pxNewMutex = ( LightMutex_t * ) pvPortMalloc( sizeof( LightMutex_t ) );
|
||||
if( pxNewMutex != NULL )
|
||||
{
|
||||
/* Information required for priority inheritance. */
|
||||
pxNewMutex->pxMutexHolder = NULL;
|
||||
pxNewMutex->uxRecursiveCallCount = 0;
|
||||
|
||||
pxNewMutex->uxLocked = pdFALSE;
|
||||
|
||||
/* Ensure the event queues start with the correct state. */
|
||||
vListInitialise( &( pxNewMutex->xTasksWaitingToLock ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
traceCREATE_LIGHT_MUTEX_FAILED();
|
||||
}
|
||||
|
||||
configASSERT( pxNewMutex );
|
||||
return pxNewMutex;
|
||||
}
|
||||
|
||||
|
||||
BaseType_t xLightMutexUnlock( LightMutexHandle_t xMutex ) {
|
||||
BaseType_t xReturn, xYieldRequired;
|
||||
|
||||
LightMutex_t * const pxMutex = ( LightMutex_t * ) xMutex;
|
||||
|
||||
configASSERT_SAFE_TO_CALL_FREERTOS_API();
|
||||
configASSERT( pxMutex );
|
||||
|
||||
taskENTER_CRITICAL();
|
||||
{
|
||||
/* Check if the mutex is ready to be unlocked */
|
||||
if( pxMutex->uxLocked == pdTRUE )
|
||||
{
|
||||
traceUNLOCK_LIGHT_MUTEX( pxMutex );
|
||||
xYieldRequired = prvMutexSetUnlocked( pxMutex );
|
||||
|
||||
/* If there was a task waiting to lock the mutex then unblock it now. */
|
||||
if( listLIST_IS_EMPTY( &( pxMutex->xTasksWaitingToLock ) ) == pdFALSE )
|
||||
{
|
||||
if( xTaskRemoveFromEventList( &( pxMutex->xTasksWaitingToLock ) ) == pdTRUE )
|
||||
{
|
||||
/* The unblocked task has a priority higher than
|
||||
our own so yield immediately. Yes it is ok to do
|
||||
this from within the critical section - the kernel
|
||||
takes care of that. */
|
||||
mutexYIELD_IF_USING_PREEMPTION();
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
else if( xYieldRequired != pdFALSE )
|
||||
{
|
||||
/* This path is a special case that will only get
|
||||
executed if the task was holding multiple mutexes and
|
||||
the mutexes were given back in an order that is
|
||||
different to that in which they were taken. */
|
||||
mutexYIELD_IF_USING_PREEMPTION();
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
|
||||
xReturn = pdPASS;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* The mutex was already unlocked?. */
|
||||
traceUNLOCK_LIGHT_MUTEX_FAILED( pxQueue );
|
||||
|
||||
xReturn = pdFAIL;
|
||||
}
|
||||
}
|
||||
taskEXIT_CRITICAL();
|
||||
|
||||
return xReturn;
|
||||
}
|
||||
|
||||
BaseType_t xLightMutexLock( LightMutexHandle_t xMutex, TickType_t xTicksToWait )
|
||||
{
|
||||
BaseType_t xEntryTimeSet = pdFALSE;
|
||||
TimeOut_t xTimeOut;
|
||||
LightMutex_t * const pxMutex = ( LightMutex_t * ) xMutex;
|
||||
|
||||
configASSERT_SAFE_TO_CALL_FREERTOS_API();
|
||||
configASSERT( pxMutex );
|
||||
#if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) )
|
||||
{
|
||||
configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) );
|
||||
}
|
||||
#endif
|
||||
|
||||
/* This function relaxes the coding standard somewhat to allow return
|
||||
statements within the function itself. This is done in the interest
|
||||
of execution time efficiency. */
|
||||
|
||||
for( ;; )
|
||||
{
|
||||
taskENTER_CRITICAL();
|
||||
{
|
||||
/* Is the mutex unlocked yet? To be running the calling task
|
||||
must be the highest priority task wanting to acquire the mutex. */
|
||||
if( pxMutex->uxLocked == pdFALSE )
|
||||
{
|
||||
traceUNLOCK_LIGHT_MUTEX( pxMutex )
|
||||
pxMutex->uxLocked = pdTRUE;
|
||||
|
||||
/* Record the information required to implement
|
||||
priority inheritance should it become necessary. */
|
||||
pxMutex->pxMutexHolder = pvTaskIncrementMutexHeldCount();
|
||||
|
||||
taskEXIT_CRITICAL();
|
||||
return pdPASS;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( xTicksToWait == ( TickType_t ) 0 )
|
||||
{
|
||||
/* The mutex was locked and no block time is specified (or
|
||||
the block time has expired) so leave now. */
|
||||
taskEXIT_CRITICAL();
|
||||
traceLOCK_LIGHT_MUTEX_FAILED( pxMutex );
|
||||
return errQUEUE_EMPTY;
|
||||
}
|
||||
else if( xEntryTimeSet == pdFALSE )
|
||||
{
|
||||
/* The mutex was locked and a block time was specified so
|
||||
configure the timeout structure. */
|
||||
vTaskSetTimeOutState( &xTimeOut );
|
||||
xEntryTimeSet = pdTRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Entry time was already set. */
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
}
|
||||
taskEXIT_CRITICAL();
|
||||
|
||||
/* Interrupts and other tasks can send to and receive from the queue
|
||||
now the critical section has been exited. */
|
||||
|
||||
vTaskSuspendAll();
|
||||
|
||||
/* Update the timeout state to see if it has expired yet. */
|
||||
if( xTaskCheckForTimeOut( &xTimeOut, &xTicksToWait ) == pdFALSE )
|
||||
{
|
||||
if( prvIsMutexLocked( pxMutex ) == pdTRUE )
|
||||
{
|
||||
traceLOCK_LIGHT_MUTEX_BLOCKED( pxMutex );
|
||||
taskENTER_CRITICAL();
|
||||
{
|
||||
vTaskPriorityInherit( pxMutex->pxMutexHolder );
|
||||
}
|
||||
taskEXIT_CRITICAL();
|
||||
|
||||
vTaskPlaceOnEventList( &( pxMutex->xTasksWaitingToLock ), xTicksToWait );
|
||||
if( xTaskResumeAll() == pdFALSE )
|
||||
{
|
||||
portYIELD_WITHIN_API();
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Try again. */
|
||||
( void ) xTaskResumeAll();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
( void ) xTaskResumeAll();
|
||||
traceLOCK_LIGHT_MUTEX_FAILED( pxMutex );
|
||||
return errQUEUE_EMPTY;
|
||||
}
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
UBaseType_t xLightMutexIsTaskWaiting( LightMutexHandle_t xMutex, void *task_handle)
|
||||
{
|
||||
LightMutex_t *pxMutex = ( LightMutex_t * ) xMutex;
|
||||
|
||||
taskENTER_CRITICAL();
|
||||
|
||||
ListItem_t const *pxListItem, *pxListEnd;
|
||||
List_t *pxList;
|
||||
pxList = &pxMutex->xTasksWaitingToLock;
|
||||
UBaseType_t is_waiting = 0;
|
||||
|
||||
pxListItem = listGET_HEAD_ENTRY( pxList );
|
||||
pxListEnd = listGET_END_MARKER( pxList );
|
||||
|
||||
while (pxListItem != pxListEnd) {
|
||||
if (listGET_LIST_ITEM_OWNER(pxListItem) == (TaskHandle_t)task_handle) {
|
||||
is_waiting = 1;
|
||||
break;
|
||||
}
|
||||
pxListItem = listGET_NEXT( pxListItem );
|
||||
}
|
||||
|
||||
taskEXIT_CRITICAL();
|
||||
return (is_waiting);
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if ( INCLUDE_xSemaphoreGetMutexHolder == 1 )
|
||||
|
||||
void* xLightMutexGetHolder( LightMutexHandle_t xMutex )
|
||||
{
|
||||
void *pxReturn;
|
||||
|
||||
/* Note: This is a good way of determining if the
|
||||
calling task is the mutex holder, but not a good way of determining the
|
||||
identity of the mutex holder, as the holder may change between the
|
||||
following critical section exiting and the function returning. */
|
||||
taskENTER_CRITICAL();
|
||||
{
|
||||
pxReturn = ( void * ) ( ( LightMutex_t * ) xMutex )->pxMutexHolder;
|
||||
}
|
||||
taskEXIT_CRITICAL();
|
||||
|
||||
return pxReturn;
|
||||
}
|
||||
|
||||
#endif
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
#if ( configUSE_RECURSIVE_LIGHT_MUTEXES == 1 )
|
||||
|
||||
UBaseType_t uxLightMutexGetRecursiveCallCount( LightMutexHandle_t xMutex ) {
|
||||
LightMutex_t * const pxMutex = ( LightMutex_t * ) xMutex;
|
||||
|
||||
configASSERT_SAFE_TO_CALL_FREERTOS_API();
|
||||
configASSERT( pxMutex );
|
||||
|
||||
// only the thread which owns the lock will call this routine so we
|
||||
// don't need a critical section
|
||||
const UBaseType_t uxCount = pxMutex->uxRecursiveCallCount;
|
||||
|
||||
return uxCount;
|
||||
}
|
||||
|
||||
BaseType_t xLightMutexUnlockRecursive( LightMutexHandle_t xMutex ) {
|
||||
BaseType_t xReturn;
|
||||
LightMutex_t * const pxMutex = ( LightMutex_t * ) xMutex;
|
||||
|
||||
configASSERT_SAFE_TO_CALL_FREERTOS_API();
|
||||
configASSERT( pxMutex );
|
||||
|
||||
/* If this is the task that holds the mutex then pxMutexHolder will not
|
||||
change outside of this task. If this task does not hold the mutex then
|
||||
pxMutexHolder can never coincidentally equal the tasks handle, and as
|
||||
this is the only condition we are interested in it does not matter if
|
||||
pxMutexHolder is accessed simultaneously by another task. Therefore no
|
||||
mutual exclusion is required to test the pxMutexHolder variable. */
|
||||
if( pxMutex->pxMutexHolder == xTaskGetCurrentTaskHandle() )
|
||||
{
|
||||
traceUNLOCK_LIGHT_MUTEX_RECURSIVE( pxMutex );
|
||||
|
||||
/* uxRecursiveCallCount cannot be zero if pxMutexHolder is equal to
|
||||
the task handle, therefore no underflow check is required. Also,
|
||||
uxRecursiveCallCount is only modified by the mutex holder, and as
|
||||
there can only be one, no mutual exclusion is required to modify the
|
||||
uxRecursiveCallCount member. */
|
||||
( pxMutex->uxRecursiveCallCount )--;
|
||||
|
||||
/* Have we unwound the call count? */
|
||||
if( pxMutex->uxRecursiveCallCount == ( UBaseType_t ) 0 )
|
||||
{
|
||||
/* Return the mutex. This will automatically unblock any other
|
||||
task that might be waiting to access the mutex. */
|
||||
( void ) xLightMutexUnlock( pxMutex );
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
|
||||
xReturn = pdPASS;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* The mutex cannot be given because the calling task is not the holder. */
|
||||
xReturn = pdFAIL;
|
||||
|
||||
traceUNLOCK_LIGHT_MUTEX_RECURSIVE_FAILED( pxMutex );
|
||||
}
|
||||
|
||||
return xReturn;
|
||||
}
|
||||
|
||||
BaseType_t xLightMutexLockRecursive( LightMutexHandle_t xMutex, TickType_t xTicksToWait ) {
|
||||
BaseType_t xReturn;
|
||||
LightMutex_t * const pxMutex = ( LightMutex_t * ) xMutex;
|
||||
|
||||
configASSERT_SAFE_TO_CALL_FREERTOS_API();
|
||||
configASSERT( pxMutex );
|
||||
|
||||
/* Comments regarding mutual exclusion as per those within
|
||||
xMutexUnlockRecursive(). */
|
||||
|
||||
traceLOCK_LIGHT_MUTEX_RECURSIVE( pxMutex );
|
||||
|
||||
if( pxMutex->pxMutexHolder == xTaskGetCurrentTaskHandle() )
|
||||
{
|
||||
( pxMutex->uxRecursiveCallCount )++;
|
||||
xReturn = pdPASS;
|
||||
}
|
||||
else
|
||||
{
|
||||
xReturn = xLightMutexLock( pxMutex, xTicksToWait );
|
||||
|
||||
/* pdPASS will only be returned if the mutex was successfully
|
||||
obtained. The calling task may have entered the Blocked state
|
||||
before reaching here. */
|
||||
if( xReturn == pdPASS )
|
||||
{
|
||||
( pxMutex->uxRecursiveCallCount )++;
|
||||
}
|
||||
else
|
||||
{
|
||||
traceLOCK_LIGHT_MUTEX_RECURSIVE_FAILED( pxMutex );
|
||||
}
|
||||
}
|
||||
|
||||
return xReturn;
|
||||
}
|
||||
|
||||
#endif /* configUSE_RECURSIVE_LIGHT_MUTEXES */
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
void vLightMutexDelete( LightMutexHandle_t xMutex )
|
||||
{
|
||||
LightMutex_t * const pxMutex = ( LightMutex_t * ) xMutex;
|
||||
|
||||
configASSERT( pxMutex );
|
||||
vPortFree( pxMutex );
|
||||
}
|
||||
/*-----------------------------------------------------------*/
|
||||
|
||||
static BaseType_t prvMutexSetUnlocked( LightMutex_t * const pxMutex )
|
||||
{
|
||||
BaseType_t xReturn = pdFALSE;
|
||||
|
||||
/* The mutex is no longer being held. Reset the priority of the mutex holder. */
|
||||
xReturn = xTaskPriorityDisinherit( pxMutex->pxMutexHolder );
|
||||
pxMutex->pxMutexHolder = NULL;
|
||||
|
||||
pxMutex->uxLocked = pdFALSE;
|
||||
|
||||
return xReturn;
|
||||
}
|
||||
|
||||
static BaseType_t prvIsMutexLocked( const LightMutex_t *pxMutex ) {
|
||||
BaseType_t xReturn;
|
||||
|
||||
taskENTER_CRITICAL();
|
||||
{
|
||||
if( pxMutex->uxLocked == pdTRUE )
|
||||
{
|
||||
xReturn = pdTRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
xReturn = pdFALSE;
|
||||
}
|
||||
}
|
||||
taskEXIT_CRITICAL();
|
||||
|
||||
return xReturn;
|
||||
}
|
||||
|
||||
#endif /* configUSE_LIGHT_MUTEXES == 0 */
|
Loading…
Add table
Add a link
Reference in a new issue