• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
M4OSA_threadSyncForEverDo(void * context)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 */
M4OSA_threadSyncOpen(M4OSA_Context * context,M4OSA_ThreadDoIt func)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 */
M4OSA_threadSyncStart(M4OSA_Context context,M4OSA_Void * param)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 */
M4OSA_threadSyncStop(M4OSA_Context context)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 */
M4OSA_threadSyncClose(M4OSA_Context context)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 */
M4OSA_threadSyncGetState(M4OSA_Context context,M4OSA_ThreadState * state)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 */
M4OSA_threadSleep(M4OSA_UInt32 time)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 
M4OSA_SetThreadSyncPriority(M4OSA_Context context,M4OSA_DataOption optionValue)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 
M4OSA_SetThreadSyncName(M4OSA_Context context,M4OSA_DataOption optionValue)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 
M4OSA_SetThreadSyncStackSize(M4OSA_Context context,M4OSA_DataOption optionValue)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 */
M4OSA_threadSyncSetOption(M4OSA_Context context,M4OSA_ThreadOptionID optionID,M4OSA_DataOption optionValue)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 */
M4OSA_threadSyncGetOption(M4OSA_Context context,M4OSA_ThreadOptionID optionID,M4OSA_DataOption * optionValue)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