int pthread_join()

in FreeRTOS-Plus-POSIX/source/FreeRTOS_POSIX_pthread.c [406:474]


int pthread_join( pthread_t pthread,
                  void ** retval )
{
    int iStatus = 0;
    pthread_internal_t * pxThread = ( pthread_internal_t * ) pthread;

    /* Make sure pthread is joinable. Otherwise, this function would block
     * forever waiting for an unjoinable thread. */
    if( !pthreadIS_JOINABLE( pxThread->xAttr.usSchedPriorityDetachState ) )
    {
        iStatus = EDEADLK;
    }

    /* Only one thread may attempt to join another. Lock the join mutex
     * to prevent other threads from calling pthread_join on the same thread. */
    if( iStatus == 0 )
    {
        if( xSemaphoreTake( ( SemaphoreHandle_t ) &pxThread->xJoinMutex, 0 ) != pdPASS )
        {
            /* Another thread has already joined the requested thread, which would
             * cause this thread to wait forever. */
            iStatus = EDEADLK;
        }
    }

    /* Attempting to join the calling thread would cause a deadlock. */
    if( iStatus == 0 )
    {
        if( pthread_equal( pthread_self(), pthread ) != 0 )
        {
            iStatus = EDEADLK;
        }
    }

    if( iStatus == 0 )
    {
        /* Wait for the joining thread to finish. Because this call waits forever,
         * it should never fail. */
        ( void ) xSemaphoreTake( ( SemaphoreHandle_t ) &pxThread->xJoinBarrier, portMAX_DELAY );

        /* Create a critical section to clean up the joined thread. */
        vTaskSuspendAll();

        /* Release xJoinBarrier and delete it. */
        ( void ) xSemaphoreGive( ( SemaphoreHandle_t ) &pxThread->xJoinBarrier );
        vSemaphoreDelete( ( SemaphoreHandle_t ) &pxThread->xJoinBarrier );

        /* Release xJoinMutex and delete it. */
        ( void ) xSemaphoreGive( ( SemaphoreHandle_t ) &pxThread->xJoinMutex );
        vSemaphoreDelete( ( SemaphoreHandle_t ) &pxThread->xJoinMutex );

        /* Delete the FreeRTOS task that ran the thread. */
        vTaskDelete( pxThread->xTaskHandle );

        /* Set the return value. */
        if( retval != NULL )
        {
            *retval = pxThread->xReturn;
        }

        /* Free the thread object. */
        vPortFree( pxThread );

        /* End the critical section. */
        xTaskResumeAll();
    }

    return iStatus;
}