in FreeRTOS-Plus-POSIX/source/FreeRTOS_POSIX_pthread_mutex.c [177:248]
int pthread_mutex_timedlock( pthread_mutex_t * mutex,
const struct timespec * abstime )
{
int iStatus = 0;
pthread_mutex_internal_t * pxMutex = ( pthread_mutex_internal_t * ) ( mutex );
TickType_t xDelay = portMAX_DELAY;
BaseType_t xFreeRTOSMutexTakeStatus = pdFALSE;
/* If mutex in uninitialized, perform initialization. */
prvInitializeStaticMutex( pxMutex );
/* At this point, the mutex should be initialized. */
configASSERT( pxMutex->xIsInitialized == pdTRUE );
/* Convert abstime to a delay in TickType_t if provided. */
if( abstime != NULL )
{
struct timespec xCurrentTime = { 0 };
/* Get current time */
if( clock_gettime( CLOCK_REALTIME, &xCurrentTime ) != 0 )
{
iStatus = EINVAL;
}
else
{
iStatus = UTILS_AbsoluteTimespecToDeltaTicks( abstime, &xCurrentTime, &xDelay );
}
/* If abstime was in the past, still attempt to lock the mutex without
* blocking, per POSIX spec. */
if( iStatus == ETIMEDOUT )
{
xDelay = 0;
iStatus = 0;
}
}
/* Check if trying to lock a currently owned mutex. */
if( ( iStatus == 0 ) &&
( pxMutex->xAttr.iType == PTHREAD_MUTEX_ERRORCHECK ) && /* Only PTHREAD_MUTEX_ERRORCHECK type detects deadlock. */
( pxMutex->xTaskOwner == xTaskGetCurrentTaskHandle() ) ) /* Check if locking a currently owned mutex. */
{
iStatus = EDEADLK;
}
if( iStatus == 0 )
{
/* Call the correct FreeRTOS mutex take function based on mutex type. */
if( pxMutex->xAttr.iType == PTHREAD_MUTEX_RECURSIVE )
{
xFreeRTOSMutexTakeStatus = xSemaphoreTakeRecursive( ( SemaphoreHandle_t ) &pxMutex->xMutex, xDelay );
}
else
{
xFreeRTOSMutexTakeStatus = xSemaphoreTake( ( SemaphoreHandle_t ) &pxMutex->xMutex, xDelay );
}
/* If the mutex was successfully taken, set its owner. */
if( xFreeRTOSMutexTakeStatus == pdPASS )
{
pxMutex->xTaskOwner = xTaskGetCurrentTaskHandle();
}
/* Otherwise, the mutex take timed out. */
else
{
iStatus = ETIMEDOUT;
}
}
return iStatus;
}