Home | History | Annotate | Download | only in src
      1 /*
      2  * Copyright (C) 2011 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 /**
     18  ************************************************************************
     19  * @file         M4OSA_Thread.c
     20  * @ingroup      OSAL
     21  * @brief        Implements and manipulate threads
     22  * @note         This file implements functions to manipulate threads
     23  ************************************************************************
     24 */
     25 
     26 #include <sched.h>
     27 #include <time.h>
     28 #include <pthread.h>
     29 #include <errno.h>
     30 
     31 #include <utils/threads.h>
     32 #include "M4OSA_Debug.h"
     33 #include "M4OSA_Memory.h"
     34 #include "M4OSA_Thread.h"
     35 #include "M4OSA_Thread_priv.h"
     36 #include "M4OSA_Mutex.h"
     37 #include "M4OSA_Semaphore.h"
     38 #include "M4OSA_CharStar.h"
     39 
     40 
     41 void* M4OSA_threadSyncForEverDo(void *context)
     42 {
     43    M4OSA_ThreadContext* threadContext = (M4OSA_ThreadContext*)context;
     44    M4OSA_Bool auto_kill = M4OSA_FALSE;
     45 
     46     /*
     47        M4OSA_Void* userData;
     48     */
     49 
     50    M4OSA_TRACE2_1("M4OSA_threadSyncForEverDo\t\tLPVOID 0x%x", context);
     51 
     52     /*
     53        userData = threadContext->userData;
     54     */
     55 
     56    M4OSA_mutexLock(threadContext->stateMutex, M4OSA_WAIT_FOREVER);
     57 
     58 
     59    threadContext->state = M4OSA_kThreadRunning;
     60 
     61    M4OSA_semaphorePost(threadContext->semStartStop);
     62 
     63    while(threadContext->state == M4OSA_kThreadRunning)
     64    {
     65       M4OSA_mutexUnlock(threadContext->stateMutex);
     66 
     67       if((threadContext->func(threadContext->param)) != M4NO_ERROR)
     68       {
     69          M4OSA_mutexLock(threadContext->stateMutex, M4OSA_WAIT_FOREVER);
     70 
     71          if(threadContext->state == M4OSA_kThreadRunning)
     72          {
     73 
     74             //PR 2354 - ACO : Suppress stopping state and don't
     75             //         unlock mutex before closing the thread
     76             threadContext->state = M4OSA_kThreadOpened;
     77             M4OSA_mutexUnlock(threadContext->stateMutex);
     78             return 0;
     79          }
     80 
     81          M4OSA_mutexUnlock(threadContext->stateMutex);
     82       }
     83 
     84       M4OSA_mutexLock(threadContext->stateMutex, M4OSA_WAIT_FOREVER);
     85    }
     86 
     87 
     88    M4OSA_semaphorePost(threadContext->semStartStop);
     89 
     90 
     91    M4OSA_mutexUnlock(threadContext->stateMutex);
     92 
     93 
     94    return 0;
     95 }
     96 
     97 
     98 
     99 
    100 
    101 /**
    102  ************************************************************************
    103   * @brief      This method creates a new thread. After this call the thread is
    104  *             identified by its "context". The thread function is provided by
    105  *             the "func" parameter. This function creates & allocates a unique
    106  *             context. It's the OSAL real time responsibility for managing its
    107  *             context. It must be freed by the M4OSA_threadSyncClose function.
    108  *             The context parameter will be sent back to any OSAL core thread
    109  *             functions to allow retrieving data associated to the opened
    110  *             thread.
    111  * @note       This function creates the thread, but the thread is not running.
    112  * @note       Once the thread is created, the state is M4OSA_kThreadOpened.
    113  * @param      context:(OUT) Context of the created thread
    114  * @param      func:(IN) "doIt" function pointer to run
    115  * @return     M4NO_ERROR: there is no error
    116  * @return     M4ERR_PARAMETER: at least one parameter is NULL
    117  * @return     M4ERR_ALLOC: there is no more available memory
    118  * @return     M4ERR_CONTEXT_FAILED: the context creation failed
    119   ************************************************************************
    120 */
    121 M4OSA_ERR M4OSA_threadSyncOpen(M4OSA_Context* context,
    122                                M4OSA_ThreadDoIt func)
    123 {
    124    M4OSA_ThreadContext* threadContext = M4OSA_NULL;
    125    M4OSA_ERR err_code;
    126 
    127    M4OSA_TRACE1_2("M4OSA_threadSyncOpen\t\tM4OSA_Context* 0x%x\t"
    128                   "M4OSA_ThreadDoIt 0x%x", context, func);
    129 
    130    M4OSA_DEBUG_IF2(context == M4OSA_NULL,
    131                    M4ERR_PARAMETER, "M4OSA_threadSyncOpen");
    132 
    133    M4OSA_DEBUG_IF2(func == M4OSA_NULL,
    134                     M4ERR_PARAMETER, "M4OSA_threadSyncOpen");
    135 
    136    *context = M4OSA_NULL;
    137 
    138    threadContext =
    139       (M4OSA_ThreadContext*)M4OSA_32bitAlignedMalloc(sizeof(M4OSA_ThreadContext),
    140       M4OSA_THREAD, (M4OSA_Char*)"M4OSA_threadSyncOpen: thread context");
    141 
    142    if(threadContext == M4OSA_NULL)
    143    {
    144       M4OSA_DEBUG(M4ERR_ALLOC, "M4OSA_threadSyncOpen");
    145 
    146       return M4ERR_ALLOC;
    147    }
    148 
    149    threadContext->func = func;
    150    threadContext->stackSize = 64 * 1024;
    151    threadContext->name = M4OSA_NULL;
    152    threadContext->threadID = 0;
    153    threadContext->coreID = M4OSA_THREAD;
    154    threadContext->state = M4OSA_kThreadOpened;
    155    threadContext->priority = M4OSA_kThreadNormalPriority ;
    156 
    157    err_code = M4OSA_mutexOpen(&(threadContext->stateMutex));
    158 
    159    if(M4OSA_ERR_IS_ERROR(err_code))
    160    {
    161       M4OSA_DEBUG(err_code, "M4OSA_threadSyncOpen: M4OSA_mutexOpen");
    162 
    163       return err_code;
    164    }
    165 
    166    err_code = M4OSA_semaphoreOpen(&(threadContext->semStartStop), 0);
    167 
    168    if(M4OSA_ERR_IS_ERROR(err_code))
    169    {
    170       M4OSA_DEBUG(err_code, "M4OSA_threadSyncOpen: M4OSA_semaphoreOpen");
    171 
    172       return err_code;
    173    }
    174 
    175    *context = threadContext;
    176 
    177    return M4NO_ERROR;
    178 }
    179 
    180 
    181 
    182 
    183 
    184 /**
    185  ************************************************************************
    186  * @brief      This method runs a specified thread. The "param" parameter
    187  *             allows the application to set a specific parameter to the
    188  *             created thread. This parameter will be used as the second one of
    189  *             the "M4OSA_ThreadDoIt" function.
    190  * @note       This method is a blocking up to the thread is running.
    191  *             Before calling this method, the state is M4OSA_kThreadOpened.
    192  *             Once the method is called, the state is M4OSA_kThreadStarting.
    193  *             Once the thread is running, the state is M4OSA_kThreadRunning.
    194  * @note       This method returns immediately. If the "threadStarted" optionID
    195  *             is not NULL, the thread will call it before running the doIt
    196  *             function.
    197  * @param      context:(IN/OUT) Context of the thread
    198  * @param      param:(IN) Application data thread parameter
    199  * @return     M4NO_ERROR: there is no error
    200  * @return     M4ERR_PARAMETER: at least one parameter is NULL
    201  * @return     M4ERR_BAD_CONTEXT: provided context is not a valid one
    202  * @return     M4ERR_STATE: this function cannot be called now
    203  * @return     M4ERR_THREAD_NOT_STARTED: the thread did not start
    204  ************************************************************************
    205 */
    206 M4OSA_ERR M4OSA_threadSyncStart(M4OSA_Context context,
    207                                 M4OSA_Void* param)
    208 {
    209    M4OSA_ThreadContext* threadContext =  (M4OSA_ThreadContext*)context;
    210    pthread_attr_t     attribute = { 0, 0, 0, 0, 0, 0 };
    211    int                min       = 0;
    212    int                max       = 0;
    213    int                priority  = 0;
    214    struct sched_param sched     = { 0 };
    215 
    216    M4OSA_TRACE1_2("M4OSA_threadSyncStart\t\tM4OSA_Context 0x%x\tM4OSA_Void* "
    217                   "0x%x", context, param);
    218 
    219    M4OSA_DEBUG_IF2(context == M4OSA_NULL,
    220                    M4ERR_PARAMETER, "M4OSA_threadSyncStart");
    221 
    222    M4OSA_DEBUG_IF2(threadContext->coreID != M4OSA_THREAD,
    223                    M4ERR_BAD_CONTEXT, "M4OSA_threadSyncStart");
    224 
    225    M4OSA_mutexLock(threadContext->stateMutex, M4OSA_WAIT_FOREVER);
    226 
    227    if(threadContext->state != M4OSA_kThreadOpened)
    228    {
    229       M4OSA_mutexUnlock(threadContext->stateMutex);
    230 
    231       M4OSA_DEBUG(M4ERR_STATE, "M4OSA_threadSyncStart");
    232 
    233       return M4ERR_STATE;
    234    }
    235 
    236    threadContext->state = M4OSA_kThreadStarting;
    237 
    238    M4OSA_mutexUnlock(threadContext->stateMutex);
    239    threadContext->param = param;
    240 
    241    if ( 0 == pthread_attr_init( &attribute ) )
    242    {
    243       if ( 0 == pthread_attr_setdetachstate( &attribute, PTHREAD_CREATE_DETACHED ) )
    244       {
    245          if ( 0 == pthread_attr_setstacksize( &attribute, (size_t)threadContext->stackSize ) )
    246          {
    247             if ( 0 == pthread_attr_setschedpolicy( &attribute, SCHED_OTHER ) )
    248             {
    249                 /* Tentative patches to handle priorities in a better way : */
    250                 /* Use Android's predefined priorities (range +19..-20)
    251                  *rather than Linux ones (0..99)*/
    252 
    253                 /* Get min and max priorities */
    254                 min = sched_get_priority_min( SCHED_FIFO );
    255                 max = sched_get_priority_max( SCHED_FIFO );
    256 
    257                 M4OSA_TRACE1_2("M4OSA_threadSyncStart MAX=%d MIN=%d", max, min);
    258 
    259                 /* tentative modification of the priorities */
    260                 /* Set the priority based on default android priorities */
    261                 /* This probably requires some more tuning,
    262                  * outcome of this priority settings are not yet satisfactory */
    263                 /* Implementing thread handling based on Android's thread creation
    264                  * helpers might bring some improvement (see threads.h) */
    265                 switch(threadContext->priority)
    266                 {
    267                 case M4OSA_kThreadLowestPriority:
    268                     priority = ANDROID_PRIORITY_NORMAL;
    269                     break;
    270                 case M4OSA_kThreadLowPriority:
    271                     priority = ANDROID_PRIORITY_DISPLAY;
    272                     break;
    273                 case M4OSA_kThreadNormalPriority:
    274                     priority = ANDROID_PRIORITY_URGENT_DISPLAY;
    275                     break;
    276                 case M4OSA_kThreadHighPriority:
    277                     priority = ANDROID_PRIORITY_AUDIO;
    278                     break;
    279                 case M4OSA_kThreadHighestPriority:
    280                     priority = ANDROID_PRIORITY_URGENT_AUDIO;
    281                     break;
    282                 }
    283                 sched.sched_priority = priority;
    284 
    285                 if ( 0 == pthread_attr_setschedparam( &attribute, &sched ) )
    286                 {
    287                     if ( 0 == pthread_create( &threadContext->threadID,
    288                                               &attribute,
    289                                               &M4OSA_threadSyncForEverDo,
    290                                               (void *)threadContext ) )
    291                     {
    292                         if ( M4OSA_FALSE == M4OSA_ERR_IS_ERROR( M4OSA_semaphoreWait(
    293                                                                     threadContext->semStartStop,
    294                                                                     M4OSA_WAIT_FOREVER ) ) )
    295                         {
    296                             return M4NO_ERROR;
    297                         }
    298                     }
    299                 }
    300             }
    301          }
    302       }
    303       pthread_attr_destroy( &attribute );
    304    }
    305 
    306    M4OSA_mutexLock(threadContext->stateMutex, M4OSA_WAIT_FOREVER);
    307 
    308    threadContext->state = M4OSA_kThreadOpened;
    309 
    310    M4OSA_mutexUnlock(threadContext->stateMutex);
    311 
    312    M4OSA_DEBUG(M4ERR_THREAD_NOT_STARTED, "M4OSA_threadSyncStart");
    313 
    314    return M4ERR_THREAD_NOT_STARTED;
    315 }
    316 
    317 
    318 
    319 
    320 /**
    321  ************************************************************************
    322  * @brief      This method stops a specified thread.
    323  * @note       This call is a blocking one up to the "M4OSA_ThreadDoIt"
    324  *             function has returned.
    325  *             Before the method is called, the state is M4OSA_kThreadRunning.
    326  *             Once the method is called, the state is M4OSA_kThreadStopping.
    327  *             Once the thread is stopped, the state is M4OSA_kThreadOpened.
    328  * @note       This method returns once the thread has been stopped. If the
    329  *             "threadStopped" optionID is not NULL, the thread will call it
    330  *             before dying.
    331  * @param      context:(IN/OUT) Context of the thread
    332  * @return     M4NO_ERROR: there is no error
    333  * @return     M4ERR_PARAMETER: at least one parameter is NULL
    334  * @return     M4ERR_STATE: this function cannot be called now
    335  * @return     M4ERR_BAD_CONTEXT: provided context is not a valid one
    336  ************************************************************************
    337 */
    338 M4OSA_ERR M4OSA_threadSyncStop(M4OSA_Context context)
    339 {
    340    M4OSA_ThreadContext* threadContext = (M4OSA_ThreadContext*)context;
    341 
    342    M4OSA_TRACE1_1("M4OSA_threadSyncStop\t\tM4OSA_Context 0x%x", context);
    343 
    344    M4OSA_DEBUG_IF2(context == M4OSA_NULL,
    345                    M4ERR_PARAMETER, "M4OSA_threadSyncStop");
    346 
    347    M4OSA_DEBUG_IF2(threadContext->coreID != M4OSA_THREAD,
    348                    M4ERR_BAD_CONTEXT, "M4OSA_threadSyncStop");
    349 
    350    M4OSA_mutexLock(threadContext->stateMutex, M4OSA_WAIT_FOREVER);
    351 
    352    if(threadContext->state != M4OSA_kThreadRunning)
    353    {
    354       M4OSA_mutexUnlock(threadContext->stateMutex);
    355 
    356       M4OSA_DEBUG(M4ERR_STATE, "M4OSA_threadSyncStop");
    357 
    358       return M4ERR_STATE;
    359    }
    360 
    361    threadContext->state = M4OSA_kThreadStopping;
    362 
    363    M4OSA_mutexUnlock(threadContext->stateMutex);
    364 
    365    M4OSA_semaphoreWait(threadContext->semStartStop, M4OSA_WAIT_FOREVER);
    366 
    367    M4OSA_mutexLock(threadContext->stateMutex, M4OSA_WAIT_FOREVER);
    368 
    369    threadContext->state = M4OSA_kThreadOpened;
    370 
    371    M4OSA_mutexUnlock(threadContext->stateMutex);
    372 
    373    return M4NO_ERROR;
    374 }
    375 
    376 
    377 
    378 
    379 /**
    380  ************************************************************************
    381  * @brief      This method deletes a thread (identified by its context). After
    382  *             this call the thread and its context are no more useable. This
    383  *             function frees all the memory related to this thread.
    384  * @note       Before the method is called, the state is M4OSA_kThreadOpened.
    385  *             Once the method is called, the state is M4OSA_kThreadClosed.
    386  * @param      context:(IN/OUT) Context of the thread
    387  * @return     M4NO_ERROR: there is no error
    388  * @return     M4ERR_PARAMETER: at least one parameter is NULL
    389  * @return     M4ERR_STATE: this function cannot be called now
    390  * @return     M4ERR_BAD_CONTEXT: provided context is not a valid one
    391  ************************************************************************
    392 */
    393 M4OSA_ERR M4OSA_threadSyncClose(M4OSA_Context context)
    394 {
    395    M4OSA_ThreadContext* threadContext = (M4OSA_ThreadContext*)context;
    396    M4OSA_ERR err_code;
    397 
    398    M4OSA_TRACE1_1("M4OSA_threadSyncClose\t\tM4OSA_Context 0x%x", context);
    399 
    400    M4OSA_DEBUG_IF2(context == M4OSA_NULL,
    401                    M4ERR_PARAMETER, "M4OSA_threadSyncClose");
    402 
    403    M4OSA_DEBUG_IF2(threadContext->coreID != M4OSA_THREAD,
    404                    M4ERR_BAD_CONTEXT, "M4OSA_threadSyncClose");
    405 
    406    M4OSA_DEBUG_IF2(threadContext->state == M4OSA_kThreadClosed,
    407                    M4ERR_BAD_CONTEXT, "M4OSA_threadSyncClose");
    408 
    409    M4OSA_mutexLock(threadContext->stateMutex, M4OSA_WAIT_FOREVER);
    410 
    411    if(threadContext->state != M4OSA_kThreadOpened)
    412    {
    413       M4OSA_mutexUnlock(threadContext->stateMutex);
    414 
    415       M4OSA_DEBUG(M4ERR_STATE, "M4OSA_threadSyncClose");
    416 
    417       return M4ERR_STATE;
    418    }
    419 
    420    threadContext->state = M4OSA_kThreadClosed;
    421 
    422    M4OSA_mutexUnlock(threadContext->stateMutex);
    423 
    424    err_code = M4OSA_mutexClose(threadContext->stateMutex);
    425 
    426    if(M4OSA_ERR_IS_ERROR(err_code))
    427    {
    428       M4OSA_DEBUG(err_code, "M4OSA_threadSyncClose: M4OSA_mutexClose");
    429 
    430       return err_code;
    431    }
    432 
    433    err_code = M4OSA_semaphoreClose(threadContext->semStartStop);
    434 
    435    if(M4OSA_ERR_IS_ERROR(err_code))
    436    {
    437       M4OSA_DEBUG(err_code, "M4OSA_threadSyncClose: M4OSA_semaphoreClose");
    438 
    439       return err_code;
    440    }
    441 
    442    if(threadContext->name != M4OSA_NULL)
    443    {
    444       free(threadContext->name);
    445    }
    446 
    447    free(threadContext);
    448 
    449    return M4NO_ERROR;
    450 }
    451 
    452 
    453 
    454 
    455 /**
    456  ************************************************************************
    457  * @brief      This method asks the thread to return its state.
    458  * @note       The caller is responsible for allocating/deallocating the state
    459  *             field.
    460  * @param      context:(IN) Context of the thread
    461  * @param      state:(OUT) Thread state
    462  * @return     M4NO_ERROR: there is no error
    463  * @return     M4ERR_PARAMETER: at least one parameter is NULL
    464  * @return     M4ERR_BAD_CONTEXT: provided context is not a valid one
    465  ************************************************************************
    466 */
    467 M4OSA_ERR M4OSA_threadSyncGetState(M4OSA_Context context,
    468                                    M4OSA_ThreadState* state)
    469 {
    470    M4OSA_ThreadContext* threadContext = (M4OSA_ThreadContext*)context;
    471 
    472    M4OSA_TRACE1_2("M4OSA_threadSyncGetState\t\tM4OSA_Context 0x%x\t"
    473                   "M4OSA_ThreadState* 0x%x", context, state);
    474 
    475    M4OSA_DEBUG_IF2(context == M4OSA_NULL,
    476                    M4ERR_PARAMETER, "M4OSA_threadSyncGetState");
    477 
    478    M4OSA_DEBUG_IF2(state == M4OSA_NULL,
    479                    M4ERR_PARAMETER, "M4OSA_threadSyncGetState");
    480 
    481    M4OSA_DEBUG_IF2(threadContext->coreID != M4OSA_THREAD,
    482                    M4ERR_BAD_CONTEXT, "M4OSA_threadSyncGetState");
    483 
    484    *state = threadContext->state;
    485 
    486    return M4NO_ERROR;
    487 }
    488 
    489 
    490 
    491 
    492 /**
    493  ************************************************************************
    494  * @brief      This method asks the calling thread to sleep during "timeSleep"
    495  *             milliseconds.
    496  * @note       This function does not have any context.
    497  * @param      time:(IN) Time to sleep in milliseconds
    498  * @return     M4NO_ERROR: there is no error
    499  ************************************************************************
    500 */
    501 M4OSA_ERR M4OSA_threadSleep(M4OSA_UInt32 time)
    502 {
    503    struct timespec rqtp = { 0, 0 };
    504    struct timespec rmtp = { 0, 0 };
    505 
    506    M4OSA_TRACE1_1("M4OSA_threadSleep\t\tM4OSA_UInt32 %d", time);
    507 
    508    rqtp.tv_sec = (time_t)time/1000;
    509    rqtp.tv_nsec = (time%1000) * 1000000;
    510    nanosleep(&rqtp, &rmtp);
    511 
    512    return M4NO_ERROR;
    513 }
    514 
    515 #if(M4OSA_OPTIONID_THREAD_PRIORITY == M4OSA_TRUE)
    516 
    517 M4OSA_ERR M4OSA_SetThreadSyncPriority(M4OSA_Context context,
    518                                   M4OSA_DataOption optionValue)
    519 {
    520    M4OSA_ThreadContext* threadContext = (M4OSA_ThreadContext*)context;
    521    M4OSA_ThreadPriorityLevel priority
    522                                  = (M4OSA_ThreadPriorityLevel)(optionValue);
    523 
    524    M4OSA_TRACE2_2("M4OSA_SetThreadSyncPriority\t\tM4OSA_Context 0x%x\t"
    525                   "M4OSA_DataOption 0x%x", context, optionValue);
    526 
    527    if((M4OSA_UInt32)optionValue>M4OSA_kThreadLowestPriority)
    528    {
    529       return M4ERR_PARAMETER;
    530    }
    531 
    532    threadContext->priority = priority;
    533 
    534    return M4NO_ERROR;
    535 }
    536 
    537 #endif /*M4OSA_OPTIONID_THREAD_PRIORITY*/
    538 
    539 
    540 
    541 
    542 #if(M4OSA_OPTIONID_THREAD_NAME == M4OSA_TRUE)
    543 
    544 M4OSA_ERR M4OSA_SetThreadSyncName(M4OSA_Context context,
    545                               M4OSA_DataOption optionValue)
    546 {
    547    M4OSA_ThreadContext* threadContext = (M4OSA_ThreadContext*)context;
    548    M4OSA_Char* name = (M4OSA_Char*)optionValue;
    549    M4OSA_UInt32 nameSize ;
    550 
    551    M4OSA_TRACE2_2("M4OSA_SetThreadSyncName\t\tM4OSA_Context 0x%x\t"
    552                   "M4OSA_DataOption 0x%x", context, optionValue);
    553 
    554    if(threadContext->name != NULL)
    555    {
    556       free(threadContext->name);
    557       threadContext->name = M4OSA_NULL;
    558    }
    559 
    560    if(optionValue != M4OSA_NULL)
    561    {
    562       nameSize = strlen((const char *)name)+1;
    563 
    564       threadContext->name =
    565          (M4OSA_Char*)M4OSA_32bitAlignedMalloc(nameSize, M4OSA_THREAD,
    566          (M4OSA_Char*)"M4OSA_SetThreadSyncName: thread name");
    567 
    568       if(threadContext == M4OSA_NULL)
    569       {
    570          return M4ERR_ALLOC;
    571       }
    572 
    573       memcpy((void *)threadContext->name, (void *)name,
    574                    nameSize);
    575    }
    576 
    577    return M4NO_ERROR;
    578 }
    579 
    580 #endif /*M4OSA_OPTIONID_THREAD_NAME*/
    581 
    582 
    583 #if(M4OSA_OPTIONID_THREAD_STACK_SIZE == M4OSA_TRUE)
    584 
    585 M4OSA_ERR M4OSA_SetThreadSyncStackSize(M4OSA_Context context,
    586                                    M4OSA_DataOption optionValue)
    587 {
    588    M4OSA_ThreadContext* threadContext = (M4OSA_ThreadContext*)context;
    589 
    590    M4OSA_TRACE2_2("M4OSA_SetThreadSyncStackSize\t\tM4OSA_Context 0x%x\t"
    591                   "M4OSA_DataOption 0x%x", context, optionValue);
    592 
    593    threadContext->stackSize = (M4OSA_UInt32)optionValue;
    594 
    595    return M4NO_ERROR;
    596 }
    597 
    598 #endif /*M4OSA_OPTIONID_THREAD_STACK_SIZE*/
    599 
    600 /**
    601  ************************************************************************
    602  * @brief      This method asks the core OSAL-Thread component to set the value
    603  *             associated with the optionID. The caller is responsible for
    604  *             allocating/deallocating the memory of the value field.
    605  * @note       As the caller is responsible of allocating/de-allocating the
    606  *             "value" field, the callee must copy this field to its internal
    607  *             variable.
    608  * @param      context:(IN/OUT) Context of the thread
    609  * @param      optionID:(IN) ID of the option
    610  * @param      optionValue:(IN) Value of the option
    611  * @return     M4NO_ERROR: there is no error
    612  * @return     M4ERR_PARAMETER: at least one parameter is NULL
    613  * @return     M4ERR_BAD_CONTEXT: provided context is not a valid one
    614  * @return     M4ERR_BAD_OPTION_ID: the optionID is not a valid one
    615  * @return     M4ERR_STATE: this option is not available now
    616  * @return     M4ERR_READ_ONLY: this option is a read only one
    617  * @return     M4ERR_NOT_IMPLEMENTED: this option is not implemented
    618  ************************************************************************
    619 */
    620 M4OSA_ERR M4OSA_threadSyncSetOption(M4OSA_Context context,
    621                                     M4OSA_ThreadOptionID optionID,
    622                                     M4OSA_DataOption optionValue)
    623 {
    624    M4OSA_ThreadContext* threadContext = (M4OSA_ThreadContext*)context;
    625    M4OSA_ERR err_code;
    626 
    627    M4OSA_TRACE1_3("M4OSA_threadSyncSetOption\t\tM4OSA_Context 0x%x\t"
    628                   "M4OSA_OptionID %d\tM4OSA_DataOption 0x%x",
    629                   context, optionID, optionValue);
    630 
    631    M4OSA_DEBUG_IF2(context == M4OSA_NULL,
    632                    M4ERR_PARAMETER, "M4OSA_threadSyncSetOption");
    633 
    634    M4OSA_DEBUG_IF2(optionID == M4OSA_NULL,
    635                    M4ERR_PARAMETER, "M4OSA_threadSyncSetOption");
    636 
    637    M4OSA_DEBUG_IF2(threadContext->coreID != M4OSA_THREAD,
    638                    M4ERR_BAD_CONTEXT, "M4OSA_threadSyncSetOption");
    639 
    640    M4OSA_DEBUG_IF2(!M4OSA_OPTION_ID_IS_COREID(optionID, M4OSA_THREAD),
    641                    M4ERR_BAD_OPTION_ID, "M4OSA_threadSyncSetOption");
    642 
    643    M4OSA_DEBUG_IF2(!M4OSA_OPTION_ID_IS_WRITABLE(optionID),
    644                    M4ERR_READ_ONLY, "M4OSA_threadSyncSetOption");
    645 
    646 
    647    M4OSA_mutexLock(threadContext->stateMutex, M4OSA_WAIT_FOREVER);
    648 
    649    if(threadContext->state != M4OSA_kThreadOpened)
    650    {
    651       M4OSA_mutexUnlock(threadContext->stateMutex);
    652 
    653       M4OSA_DEBUG(M4ERR_STATE, "M4OSA_threadSyncSetOption");
    654 
    655       return M4ERR_STATE;
    656    }
    657 
    658    switch(optionID)
    659    {
    660 
    661 #if(M4OSA_OPTIONID_THREAD_PRIORITY == M4OSA_TRUE)
    662       case M4OSA_ThreadPriority:
    663       {
    664          err_code = M4OSA_SetThreadSyncPriority(context, optionValue);
    665 
    666          break;
    667       }
    668 #endif /*M4OSA_OPTIONID_THREAD_PRIORITY*/
    669 
    670 #if(M4OSA_OPTIONID_THREAD_NAME == M4OSA_TRUE)
    671       case M4OSA_ThreadName:
    672       {
    673          err_code = M4OSA_SetThreadSyncName(context, optionValue);
    674 
    675          break;
    676       }
    677 #endif /*M4OSA_OPTIONID_THREAD_NAME*/
    678 
    679 #if(M4OSA_OPTIONID_THREAD_STACK_SIZE == M4OSA_TRUE)
    680       case M4OSA_ThreadStackSize:
    681       {
    682          err_code = M4OSA_SetThreadSyncStackSize(context, optionValue);
    683 
    684          break;
    685       }
    686 #endif /*M4OSA_OPTIONID_THREAD_STACK_SIZE*/
    687 
    688       default:
    689       {
    690          M4OSA_DEBUG(M4ERR_NOT_IMPLEMENTED, "M4OSA_threadSyncSetOption");
    691 
    692          err_code = M4ERR_NOT_IMPLEMENTED;
    693       }
    694    }
    695 
    696    M4OSA_mutexUnlock(threadContext->stateMutex);
    697 
    698    return err_code;
    699 }
    700 
    701 
    702 
    703 /**
    704  ************************************************************************
    705  * @brief      This method asks the OSAL-Thread to return the value associated
    706  *             with the optionID. The caller is responsible for
    707  *             allocating/deallocating the memory of the value field.
    708  * @note       "optionValue" must be cast according to the type related to the
    709  *             optionID.
    710  * @note       As the caller is responsible for de-allocating the "value"
    711  *             field, the core OSAL-Thread component must perform a copy of its
    712  *             internal value to the value field.
    713  * @param      context:(IN) Context of the thread
    714  * @param      optionID:(IN) ID of the option
    715  * @param      optionValue:(OUT) Value of the option
    716  * @return     M4NO_ERROR: there is no error
    717  * @return     M4ERR_PARAMETER: at least one parameter is NULL
    718  * @return     M4ERR_BAD_CONTEXT: provided context is not a valid one
    719  * @return     M4ERR_BAD_OPTION_ID: the optionID is not a valid one
    720  * @return     M4ERR_WRITE_ONLY: this option is a write only one
    721  * @return     M4ERR_NOT_IMPLEMENTED: this option is not implemented
    722  ************************************************************************
    723 */
    724 M4OSA_ERR M4OSA_threadSyncGetOption(M4OSA_Context context,
    725                                     M4OSA_ThreadOptionID optionID,
    726                                     M4OSA_DataOption* optionValue)
    727 {
    728    M4OSA_ThreadContext* threadContext = (M4OSA_ThreadContext*)context;
    729 
    730    M4OSA_TRACE1_3("M4OSA_threadSyncGetOption\t\tM4OSA_Context 0x%x\t"
    731                   "M4OSA_OptionID %d\tM4OSA_DataOption* 0x%x",
    732                   context, optionID, optionValue);
    733 
    734    M4OSA_DEBUG_IF2(context == M4OSA_NULL,
    735                    M4ERR_PARAMETER, "M4OSA_threadSyncGetOption");
    736 
    737    M4OSA_DEBUG_IF2(optionID == M4OSA_NULL,
    738                    M4ERR_PARAMETER, "M4OSA_threadSyncGetOption");
    739 
    740    M4OSA_DEBUG_IF2(optionValue == M4OSA_NULL,
    741                    M4ERR_PARAMETER, "M4OSA_threadSyncGetOption");
    742 
    743    M4OSA_DEBUG_IF2(threadContext->coreID != M4OSA_THREAD,
    744                    M4ERR_BAD_CONTEXT, "M4OSA_threadSyncGetOption");
    745 
    746    M4OSA_DEBUG_IF2(!M4OSA_OPTION_ID_IS_COREID(optionID, M4OSA_THREAD),
    747                    M4ERR_BAD_OPTION_ID, "M4OSA_threadSyncGetOption");
    748 
    749    M4OSA_DEBUG_IF2(!M4OSA_OPTION_ID_IS_READABLE(optionID),
    750                    M4ERR_WRITE_ONLY, "M4OSA_threadSyncGetOption");
    751 
    752    switch(optionID)
    753    {
    754 
    755 #if(M4OSA_OPTIONID_THREAD_PRIORITY == M4OSA_TRUE)
    756       case M4OSA_ThreadPriority:
    757       {
    758          M4OSA_ThreadPriorityLevel* priority =
    759                                     (M4OSA_ThreadPriorityLevel*)optionValue;
    760 
    761          *priority = threadContext->priority;
    762 
    763          return M4NO_ERROR;
    764       }
    765 #endif /*M4OSA_OPTIONID_THREAD_PRIORITY*/
    766 
    767 #if(M4OSA_OPTIONID_THREAD_NAME == M4OSA_TRUE)
    768       case M4OSA_ThreadName:
    769       {
    770          M4OSA_Char** name = (M4OSA_Char**)optionValue;
    771 
    772          *name = threadContext->name;
    773 
    774          return M4NO_ERROR;
    775       }
    776 #endif /*M4OSA_OPTIONID_THREAD_NAME*/
    777 
    778 #if(M4OSA_OPTIONID_THREAD_STACK_SIZE == M4OSA_TRUE)
    779       case M4OSA_ThreadStackSize:
    780       {
    781          M4OSA_UInt32* stackSize = (M4OSA_UInt32*)optionValue;
    782 
    783          *stackSize = threadContext->stackSize;
    784 
    785          return M4NO_ERROR;
    786       }
    787 #endif /*M4OSA_OPTIONID_THREAD_STACK_SIZE*/
    788 
    789       default:
    790         break;
    791    }
    792 
    793    M4OSA_DEBUG(M4ERR_NOT_IMPLEMENTED, "M4OSA_threadSyncGetOption");
    794 
    795    return M4ERR_NOT_IMPLEMENTED;
    796 }
    797 
    798