int pthread_create()

in FreeRTOS-Plus-POSIX/source/FreeRTOS_POSIX_pthread.c [285:366]


int pthread_create( pthread_t * thread,
                    const pthread_attr_t * attr,
                    void *( *startroutine )( void * ),
                    void * arg )
{
    int iStatus = 0;
    pthread_internal_t * pxThread = NULL;
    struct sched_param xSchedParam = { .sched_priority = tskIDLE_PRIORITY };

    /* Allocate memory for new thread object. */
    pxThread = ( pthread_internal_t * ) pvPortMalloc( sizeof( pthread_internal_t ) );

    if( pxThread == NULL )
    {
        /* No memory. */
        iStatus = EAGAIN;
    }

    if( iStatus == 0 )
    {
        /* No attributes given, use default attributes. */
        if( attr == NULL )
        {
            pxThread->xAttr = xDefaultThreadAttributes;
        }
        /* Otherwise, use provided attributes. */
        else
        {
            pxThread->xAttr = *( ( pthread_attr_internal_t * ) ( attr ) );
        }

        /* Get priority from attributes */
        xSchedParam.sched_priority = ( int ) pthreadGET_SCHED_PRIORITY( pxThread->xAttr.usSchedPriorityDetachState );

        /* Set argument and start routine. */
        pxThread->xTaskArg = arg;
        pxThread->pvStartRoutine = startroutine;

        /* If this thread is joinable, create the synchronization mechanisms for
         * pthread_join. */

        if( pthreadIS_JOINABLE( pxThread->xAttr.usSchedPriorityDetachState ) )
        {
            /* These calls will not fail when their arguments aren't NULL. */
            ( void ) xSemaphoreCreateMutexStatic( &pxThread->xJoinMutex );
            ( void ) xSemaphoreCreateBinaryStatic( &pxThread->xJoinBarrier );
        }
    }

    if( iStatus == 0 )
    {
        /* Suspend all tasks to create a critical section. This ensures that
         * the new thread doesn't exit before a tag is assigned. */
        vTaskSuspendAll();

        /* Create the FreeRTOS task that will run the pthread. */
        if( xTaskCreate( prvRunThread,
                         posixconfigPTHREAD_TASK_NAME,
                         ( uint16_t ) ( pxThread->xAttr.usStackSize / sizeof( StackType_t ) ),
                         ( void * ) pxThread,
                         xSchedParam.sched_priority,
                         &pxThread->xTaskHandle ) != pdPASS )
        {
            /* Task creation failed, no memory. */
            vPortFree( pxThread );
            iStatus = EAGAIN;
        }
        else
        {
            /* Store the pointer to the thread object in the task tag. */
            vTaskSetApplicationTaskTag( pxThread->xTaskHandle, ( TaskHookFunction_t ) pxThread );

            /* Set the thread object for the user. */
            *thread = ( pthread_t ) pxThread;
        }

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

    return iStatus;
}