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