libs/posutils/puthread.c
pthread_t pu_thread_create(
    pu_thread_fct_t fctMain,
    void*           pMainArg,
    size_t          uiStackSize,
    const char*     szName )
{
    pthread_attr_t       attr;
    int                  iResult = -1;
    pu_thread_context_t* pNode = NULL;
    pthread_t            iPid = (pthread_t)0;

    /* pre-condition */
    ASSERT( uiPageSize > 0 );
    ASSERT( fctMain );
    ASSERT( szName );
    ASSERT( uiStackSize <= PU_THREAD_STUPID_STACKSIZE);
    if ((uiPageSize > 0) && fctMain && szName && (uiStackSize <= PU_THREAD_STUPID_STACKSIZE))
    {
        iResult = pthread_attr_init( &attr );
        ASSERT( 0 == iResult );
        if (0 == iResult)
        {
            /* set stack size and guard size */
            uiStackSize = pu_thread_stacksize_fix( uiStackSize );
            iResult = pthread_attr_setstacksize( &attr, uiStackSize );
            ASSERT( 0 == iResult );

            /* GLIBC will by default set the guard size to one page whenever we set the stack size.
             * uClibC does NOT do this, so we always force the guard size
             */
            if (0 == iResult)
            {
                iResult = pthread_attr_setguardsize( &attr, uiPageSize );
                ASSERT( 0 == iResult );
            }
            if (0 == iResult)
            {
                pNode = (pu_thread_context_t*)malloc( sizeof( pu_thread_context_t ) );
                ASSERT( NULL != pNode );
                if (NULL != pNode)
                {
                    memset( pNode, 0, sizeof(pu_thread_context_t) );
                    pNode->fctMain  = fctMain;
                    pNode->pMainArg = pMainArg;

                    /* simply copy the name pointer. This is constant and persistent,
                     * it does not need a separate allocation
                     */
                    pNode->szName = (char*)szName;
                    iResult = pthread_create(
                        &(pNode->pid),
                        &attr,
                        pu_thread_entry_handler,
                        (void*)pNode );
                    ASSERT( 0 == iResult );
                    if (0 != iResult)
                    {
                        free( pNode );
                    }

                    /* Store the PID, set the system thread name. This name is 15+null long,
                     * so will often cause the input name to be truncated. This means the debug name and
                     * the name in the system may be different.
                     */
                    else
                    {
                        iPid = pNode->pid;
                        char szSysName[16];
                        strncpy( szSysName, szName, 16 );
                        szSysName[15] = 0;
                        pthread_setname_np( iPid, szSysName );

                        /* TODO: Find a way around this!!
                         * At this point we would like to use:
                         * - pthread_setname_np()
                         * to set the thread name in the system. but it does not seem
                         * to work
                         *
                         * char szSysName[16];
                         * strncpy( szSysName, szName, 16 );
                         * szSysName[15] = 0;
                         * pthread_setname_np( iPid, szSysName );
                         */
                    }
                }
            }
            pthread_attr_destroy( &attr );
        }
    }
    if (0 == iPid)
    {
        LOG_ERROR( "PU_THREAD(create):proc=%s, cannot create %s\n", szProcName, szName );
        ASSERT(0 != iPid);
    }

    /* Done */
    return (iPid);
}
/**
 * @brief   Creates a non-RT pthread with the Comet constraints applied
 *
 * @param[in] fctMain     : Thread main function (entry point)
 * @param[in] pMainArg    : Argument for main
 * @param[in] fctExit     : Thread exit handler function
 * @param[in] pExitArg    : Exit handler argument
 * @param[in] uiStackSize : Stack size
 * @param[in] szName      : Thread name
 * @retval  A non-zero pthread ID indicates success
 * @retval  A zero pthread ID means failure
 *
 * @pre     The entry function (main) is non-NULL
 * @pre     The name is non-NULL
 * @post    The pthread is created.
 *
 * @par Description
 * Creates a standard pthread (SCHED_OTHER) with the passed in parameters. The stack size will be
 * rounded up to the nearest multiple of the page size, i.e. (n * 4k).
 *
 * @par Exit handling
 * The are two main ways a thread can exit. It can terminate on its own either by simply coming to
 * the end of the main loop or invoking pthread_exit(). In this case the thread is aware it is going to exit,
 * and will naturally clean up after itself. The second scenario is when the thread is terminated
 * by another thread, i.e. as a result of a call to pthread_cancel(pid). Is this case the exit handler
 * will be invoked. This allows us to do clean up during an on-demand process shutdown.
 *
 * @par Note
 * If there is no need for an exit handler, then simply set the \c fctExit parameter to NULL.
 *
 * @par Note
 * The thread name (szName) \b MUST be persistent and null terminated.. In the code the \b pointer to the
 * name will simply be copied, the string itself will not be copied (i.e. there will be no strcpy call).
 * If you use the provided macros this will not be an issue, as the entry function is string-ised into a
 * constant persistent string.
 */


@pre     The entry function (main) is non-NULL
@pre     The name is non-NULL
@post    The pthread is created.

@par Description
Creates a standard pthread (SCHED_OTHER) with the passed in parameters. The stack size will be
rounded up to the nearest multiple of the page size, i.e.

@par Exit handling
The are two main ways a thread can exit. It can terminate on its own either by simply coming to
the end of the main loop or invoking pthread_exit(). In this case the thread is aware it is going to exit,
and will naturally clean up after itself. The second scenario is when the thread is terminated
by another thread, i.e. as a result of a call to pthread_cancel(pid). Is this case the exit handler
will be invoked. This allows us to do clean up during an on-demand process shutdown.

@par Note
If there is no need for an exit handler, then simply set the \c fctExit parameter to NULL.

@par Note
The thread name (szName) \b MUST be persistent and null terminated.. In the code the \b pointer to the
name will simply be copied, the string itself will not be copied .
If you use the provided macros this will not be an issue, as the entry function is string-ised into a
constant persistent string.
@pre The entry function ( main ) is non - NULL @pre The name is non - NULL @post The pthread is created . @par Description Creates a standard pthread ( SCHED_OTHER ) with the passed in parameters . The stack size will be rounded up to the nearest multiple of the page size i . e . @par Exit handling The are two main ways a thread can exit . It can terminate on its own either by simply coming to the end of the main loop or invoking pthread_exit () . In this case the thread is aware it is going to exit and will naturally clean up after itself . The second scenario is when the thread is terminated by another thread i . e . as a result of a call to pthread_cancel ( pid ) . Is this case the exit handler will be invoked . This allows us to do clean up during an on - demand process shutdown . @par Note If there is no need for an exit handler then simply set the \ c fctExit parameter to NULL . @par Note The thread name ( szName ) \ b MUST be persistent and null terminated .. In the code the \ b pointer to the name will simply be copied the string itself will not be copied . If you use the provided macros this will not be an issue as the entry function is string - ised into a constant persistent string .
pthread_t pu_thread_create(
    pu_thread_fct_t fctMain,
    void*           pMainArg,
    size_t          uiStackSize,
    const char*     szName )
{
    pthread_attr_t       attr;
    int                  iResult = -1;
    pu_thread_context_t* pNode = NULL;
    pthread_t            iPid = (pthread_t)0;
    ASSERT( uiPageSize > 0 );
    ASSERT( fctMain );
    ASSERT( szName );
    ASSERT( uiStackSize <= PU_THREAD_STUPID_STACKSIZE);
    if ((uiPageSize > 0) && fctMain && szName && (uiStackSize <= PU_THREAD_STUPID_STACKSIZE))
    {
        iResult = pthread_attr_init( &attr );
        ASSERT( 0 == iResult );
        if (0 == iResult)
        {
            uiStackSize = pu_thread_stacksize_fix( uiStackSize );
            iResult = pthread_attr_setstacksize( &attr, uiStackSize );
            ASSERT( 0 == iResult );
            if (0 == iResult)
            {
                iResult = pthread_attr_setguardsize( &attr, uiPageSize );
                ASSERT( 0 == iResult );
            }
            if (0 == iResult)
            {
                pNode = (pu_thread_context_t*)malloc( sizeof( pu_thread_context_t ) );
                ASSERT( NULL != pNode );
                if (NULL != pNode)
                {
                    memset( pNode, 0, sizeof(pu_thread_context_t) );
                    pNode->fctMain  = fctMain;
                    pNode->pMainArg = pMainArg;
                    pNode->szName = (char*)szName;
                    iResult = pthread_create(
                        &(pNode->pid),
                        &attr,
                        pu_thread_entry_handler,
                        (void*)pNode );
                    ASSERT( 0 == iResult );
                    if (0 != iResult)
                    {
                        free( pNode );
                    }
                    else
                    {
                        iPid = pNode->pid;
                        char szSysName[16];
                        strncpy( szSysName, szName, 16 );
                        szSysName[15] = 0;
                        pthread_setname_np( iPid, szSysName );
                    }
                }
            }
            pthread_attr_destroy( &attr );
        }
    }
    if (0 == iPid)
    {
        LOG_ERROR( "PU_THREAD(create):proc=%s, cannot create %s\n", szProcName, szName );
        ASSERT(0 != iPid);
    }
    return (iPid);
}
pthread_t pu_thread_create ( pu_thread_fct_t fctMain , void * pMainArg , size_t uiStackSize , const char * szName ) { pthread_attr_t attr ; int iResult = -1 ; pu_thread_context_t * pNode = NULL ; pthread_t iPid = ( pthread_t ) 0 ; ASSERT ( uiPageSize > 0 ) ; ASSERT ( fctMain ) ; ASSERT ( szName ) ; ASSERT ( uiStackSize <= PU_THREAD_STUPID_STACKSIZE ) ; if ( ( uiPageSize > 0 ) && fctMain && szName && ( uiStackSize <= PU_THREAD_STUPID_STACKSIZE ) ) { iResult = pthread_attr_init ( & attr ) ; ASSERT ( 0 == iResult ) ; if ( 0 == iResult ) { uiStackSize = pu_thread_stacksize_fix ( uiStackSize ) ; iResult = pthread_attr_setstacksize ( & attr , uiStackSize ) ; ASSERT ( 0 == iResult ) ; if ( 0 == iResult ) { iResult = pthread_attr_setguardsize ( & attr , uiPageSize ) ; ASSERT ( 0 == iResult ) ; } if ( 0 == iResult ) { pNode = ( pu_thread_context_t * ) malloc ( sizeof ( pu_thread_context_t ) ) ; ASSERT ( NULL != pNode ) ; if ( NULL != pNode ) { memset ( pNode , 0 , sizeof ( pu_thread_context_t ) ) ; pNode -> fctMain = fctMain ; pNode -> pMainArg = pMainArg ; pNode -> szName = ( char * ) szName ; iResult = pthread_create ( & ( pNode -> pid ) , & attr , pu_thread_entry_handler , ( void * ) pNode ) ; ASSERT ( 0 == iResult ) ; if ( 0 != iResult ) { free ( pNode ) ; } else { iPid = pNode -> pid ; char szSysName [ 16 ] ; strncpy ( szSysName , szName , 16 ) ; szSysName [ 15 ] = 0 ; pthread_setname_np ( iPid , szSysName ) ; } } } pthread_attr_destroy ( & attr ) ; } } if ( 0 == iPid ) { LOG_ERROR ( " \n " , szProcName , szName ) ; ASSERT ( 0 != iPid ) ; } return ( iPid ) ; }
@brief   Creates a non-RT pthread with the Comet constraints applied
 @param[in] fctMain     : Thread main function (entry point)
 @param[in] pMainArg    : Argument for main
 @param[in] fctExit     : Thread exit handler function
 @param[in] pExitArg    : Exit handler argument
 @param[in] uiStackSize : Stack size
 @param[in] szName      : Thread name
 @retval  A non-zero pthread ID indicates success
 @retval  A zero pthread ID means failure
@brief Creates a non - RT pthread with the Comet constraints applied @param [ in ] fctMain : Thread main function ( entry point ) @param [ in ] pMainArg : Argument for main @param [ in ] fctExit : Thread exit handler function @param [ in ] pExitArg : Exit handler argument @param [ in ] uiStackSize : Stack size @param [ in ] szName : Thread name @retval A non - zero pthread ID indicates success @retval A zero pthread ID means failure
/* pre-condition */ /* set stack size and guard size */ /* GLIBC will by default set the guard size to one page whenever we set the stack size.
             * uClibC does NOT do this, so we always force the guard size
             */ /* simply copy the name pointer. This is constant and persistent,
                     * it does not need a separate allocation
                     */ /* Store the PID, set the system thread name. This name is 15+null long,
                     * so will often cause the input name to be truncated. This means the debug name and
                     * the name in the system may be different.
                     */ /* TODO: Find a way around this!!
                         * At this point we would like to use:
                         * - pthread_setname_np()
                         * to set the thread name in the system. but it does not seem
                         * to work
                         *
                         * char szSysName[16];
                         * strncpy( szSysName, szName, 16 );
                         * szSysName[15] = 0;
                         * pthread_setname_np( iPid, szSysName );
                         */ /* Done */