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
41void* 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*/
121M4OSA_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*/
206M4OSA_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*/
338M4OSA_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*/
393M4OSA_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*/
467M4OSA_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*/
501M4OSA_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
517M4OSA_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
544M4OSA_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
585M4OSA_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*/
620M4OSA_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*/
724M4OSA_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