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