diff options
Diffstat (limited to 'libvideoeditor/osal/src/M4OSA_Thread.c')
-rwxr-xr-x | libvideoeditor/osal/src/M4OSA_Thread.c | 954 |
1 files changed, 954 insertions, 0 deletions
diff --git a/libvideoeditor/osal/src/M4OSA_Thread.c b/libvideoeditor/osal/src/M4OSA_Thread.c new file mode 100755 index 0000000..c09b82c --- /dev/null +++ b/libvideoeditor/osal/src/M4OSA_Thread.c @@ -0,0 +1,954 @@ +/* + * Copyright (C) 2004-2011 NXP Software + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + ************************************************************************ + * @file M4OSA_Thread.c + * @ingroup OSAL + * @brief Implements and manipulate threads + * @note This file implements functions to manipulate threads + ************************************************************************ +*/ + +#include <sched.h> +#include <time.h> +#include <pthread.h> +#include <errno.h> + +#include <utils/threads.h> +#include "M4OSA_Debug.h" +#include "M4OSA_Memory.h" +#include "M4OSA_Thread.h" +#include "M4OSA_Thread_priv.h" +#include "M4OSA_Mutex.h" +#include "M4OSA_Semaphore.h" +#include "M4OSA_CharStar.h" + + +void* M4OSA_threadSyncForEverDo(void *context) +{ + M4OSA_ThreadContext* threadContext = (M4OSA_ThreadContext*)context; + M4OSA_Bool auto_kill = M4OSA_FALSE; + + /* + M4OSA_Void* userData; + */ + + M4OSA_TRACE2_1("M4OSA_threadSyncForEverDo\t\tLPVOID 0x%x", context); + + /* + userData = threadContext->userData; + */ + + M4OSA_mutexLock(threadContext->stateMutex, M4OSA_WAIT_FOREVER); + + /*if(threadContext->startCallBack != M4OSA_NULL) + { + threadContext->startCallBack(threadContext, userData); + }*/ + + threadContext->state = M4OSA_kThreadRunning; + + M4OSA_semaphorePost(threadContext->semStartStop); + + while(threadContext->state == M4OSA_kThreadRunning) + { + M4OSA_mutexUnlock(threadContext->stateMutex); + + if((threadContext->func(threadContext->param)) != M4NO_ERROR) + { + M4OSA_mutexLock(threadContext->stateMutex, M4OSA_WAIT_FOREVER); + + if(threadContext->state == M4OSA_kThreadRunning) + { + + //PR 2354 - ACO : Suppress stopping state and don't + // unlock mutex before closing the thread + threadContext->state = M4OSA_kThreadOpened; + M4OSA_mutexUnlock(threadContext->stateMutex); + return 0; + } + + M4OSA_mutexUnlock(threadContext->stateMutex); + } + + M4OSA_mutexLock(threadContext->stateMutex, M4OSA_WAIT_FOREVER); + } + + + M4OSA_semaphorePost(threadContext->semStartStop); + + + M4OSA_mutexUnlock(threadContext->stateMutex); + + + return 0; +} + + + + + +/** + ************************************************************************ + * @brief This method creates a new thread. After this call the thread is + * identified by its "context". The thread function is provided by + * the "func" parameter. This function creates & allocates a unique + * context. It's the OSAL real time responsibility for managing its + * context. It must be freed by the M4OSA_threadSyncClose function. + * The context parameter will be sent back to any OSAL core thread + * functions to allow retrieving data associated to the opened + * thread. + * @note This function creates the thread, but the thread is not running. + * @note Once the thread is created, the state is M4OSA_kThreadOpened. + * @param context:(OUT) Context of the created thread + * @param func:(IN) "doIt" function pointer to run + * @return M4NO_ERROR: there is no error + * @return M4ERR_PARAMETER: at least one parameter is NULL + * @return M4ERR_ALLOC: there is no more available memory + * @return M4ERR_CONTEXT_FAILED: the context creation failed + ************************************************************************ +*/ +M4OSA_ERR M4OSA_threadSyncOpen(M4OSA_Context* context, + M4OSA_ThreadDoIt func) +{ + M4OSA_ThreadContext* threadContext = M4OSA_NULL; + M4OSA_ERR err_code; + + M4OSA_TRACE1_2("M4OSA_threadSyncOpen\t\tM4OSA_Context* 0x%x\t" + "M4OSA_ThreadDoIt 0x%x", context, func); + + M4OSA_DEBUG_IF2(context == M4OSA_NULL, + M4ERR_PARAMETER, "M4OSA_threadSyncOpen"); + + M4OSA_DEBUG_IF2(func == M4OSA_NULL, + M4ERR_PARAMETER, "M4OSA_threadSyncOpen"); + + *context = M4OSA_NULL; + + threadContext = + (M4OSA_ThreadContext*)M4OSA_malloc(sizeof(M4OSA_ThreadContext), + M4OSA_THREAD, (M4OSA_Char*)"M4OSA_threadSyncOpen: thread context"); + + if(threadContext == M4OSA_NULL) + { + M4OSA_DEBUG(M4ERR_ALLOC, "M4OSA_threadSyncOpen"); + + return M4ERR_ALLOC; + } + + threadContext->func = func; + threadContext->stackSize = 64 * 1024; + threadContext->name = M4OSA_NULL; + threadContext->threadID = 0; + threadContext->coreID = M4OSA_THREAD; +/* + threadContext->userData = M4OSA_NULL; + threadContext->stopCallBack = M4OSA_NULL; + threadContext->startCallBack = M4OSA_NULL; +*/ + threadContext->state = M4OSA_kThreadOpened; + threadContext->priority = M4OSA_kThreadNormalPriority ; + + err_code = M4OSA_mutexOpen(&(threadContext->stateMutex)); + + if(M4OSA_ERR_IS_ERROR(err_code)) + { + M4OSA_DEBUG(err_code, "M4OSA_threadSyncOpen: M4OSA_mutexOpen"); + + return err_code; + } + + err_code = M4OSA_semaphoreOpen(&(threadContext->semStartStop), 0); + + if(M4OSA_ERR_IS_ERROR(err_code)) + { + M4OSA_DEBUG(err_code, "M4OSA_threadSyncOpen: M4OSA_semaphoreOpen"); + + return err_code; + } + + *context = threadContext; + + return M4NO_ERROR; +} + + + + + +/** + ************************************************************************ + * @brief This method runs a specified thread. The "param" parameter + * allows the application to set a specific parameter to the + * created thread. This parameter will be used as the second one of + * the "M4OSA_ThreadDoIt" function. + * @note This method is a blocking up to the thread is running. + * Before calling this method, the state is M4OSA_kThreadOpened. + * Once the method is called, the state is M4OSA_kThreadStarting. + * Once the thread is running, the state is M4OSA_kThreadRunning. + * @note This method returns immediately. If the "threadStarted" optionID + * is not NULL, the thread will call it before running the doIt + * function. + * @param context:(IN/OUT) Context of the thread + * @param param:(IN) Application data thread parameter + * @return M4NO_ERROR: there is no error + * @return M4ERR_PARAMETER: at least one parameter is NULL + * @return M4ERR_BAD_CONTEXT: provided context is not a valid one + * @return M4ERR_STATE: this function cannot be called now + * @return M4ERR_THREAD_NOT_STARTED: the thread did not start + ************************************************************************ +*/ +M4OSA_ERR M4OSA_threadSyncStart(M4OSA_Context context, + M4OSA_Void* param) +{ + M4OSA_ThreadContext* threadContext = (M4OSA_ThreadContext*)context; + pthread_attr_t attribute = { 0, 0, 0, 0, 0, 0 }; + int min = 0; + int max = 0; + int priority = 0; + struct sched_param sched = { 0 }; + + M4OSA_TRACE1_2("M4OSA_threadSyncStart\t\tM4OSA_Context 0x%x\tM4OSA_Void* " + "0x%x", context, param); + + M4OSA_DEBUG_IF2(context == M4OSA_NULL, + M4ERR_PARAMETER, "M4OSA_threadSyncStart"); + + M4OSA_DEBUG_IF2(threadContext->coreID != M4OSA_THREAD, + M4ERR_BAD_CONTEXT, "M4OSA_threadSyncStart"); + + M4OSA_mutexLock(threadContext->stateMutex, M4OSA_WAIT_FOREVER); + + if(threadContext->state != M4OSA_kThreadOpened) + { + M4OSA_mutexUnlock(threadContext->stateMutex); + + M4OSA_DEBUG(M4ERR_STATE, "M4OSA_threadSyncStart"); + + return M4ERR_STATE; + } + + threadContext->state = M4OSA_kThreadStarting; + + M4OSA_mutexUnlock(threadContext->stateMutex); + threadContext->param = param; + + if ( 0 == pthread_attr_init( &attribute ) ) + { + if ( 0 == pthread_attr_setdetachstate( &attribute, PTHREAD_CREATE_DETACHED ) ) + { + if ( 0 == pthread_attr_setstacksize( &attribute, (size_t)threadContext->stackSize ) ) + { + if ( 0 == pthread_attr_setschedpolicy( &attribute, SCHED_OTHER ) ) + { +#if 0 + min = sched_get_priority_min( SCHED_OTHER ); + max = sched_get_priority_max( SCHED_OTHER ); + + switch(threadContext->priority) + { + case M4OSA_kThreadLowestPriority: + priority = min; + break; + case M4OSA_kThreadLowPriority: + priority = min + ( max - min ) / 4; + break; + case M4OSA_kThreadNormalPriority: + priority = min + ( max - min ) / 2; + break; + case M4OSA_kThreadHighPriority: + priority = max - ( max - min ) / 4; + break; + case M4OSA_kThreadHighestPriority: + priority = max; + break; + } +#else + /* Tentative patches to handle priorities in a better way : */ + /* Use Android's predefined priorities (range +19..-20) + *rather than Linux ones (0..99)*/ + + /* Get min and max priorities */ + min = sched_get_priority_min( SCHED_FIFO ); + max = sched_get_priority_max( SCHED_FIFO ); + + M4OSA_TRACE1_2("M4OSA_threadSyncStart MAX=%d MIN=%d", max, min); + + /* tentative modification of the priorities */ + /* Set the priority based on default android priorities */ + /* This probably requires some more tuning, + * outcome of this priority settings are not yet satisfactory */ + /* Implementing thread handling based on Android's thread creation + * helpers might bring some improvement (see threads.h) */ + switch(threadContext->priority) + { + case M4OSA_kThreadLowestPriority: + priority = ANDROID_PRIORITY_NORMAL; + break; + case M4OSA_kThreadLowPriority: + priority = ANDROID_PRIORITY_DISPLAY; + break; + case M4OSA_kThreadNormalPriority: + priority = ANDROID_PRIORITY_URGENT_DISPLAY; + break; + case M4OSA_kThreadHighPriority: + priority = ANDROID_PRIORITY_AUDIO; + break; + case M4OSA_kThreadHighestPriority: + priority = ANDROID_PRIORITY_URGENT_AUDIO; + break; + } +#endif + sched.sched_priority = priority; + + if ( 0 == pthread_attr_setschedparam( &attribute, &sched ) ) + { + if ( 0 == pthread_create( &threadContext->threadID, + &attribute, + &M4OSA_threadSyncForEverDo, + (void *)threadContext ) ) + { + if ( M4OSA_FALSE == M4OSA_ERR_IS_ERROR( M4OSA_semaphoreWait( + threadContext->semStartStop, + M4OSA_WAIT_FOREVER ) ) ) + { + return M4NO_ERROR; + } + } + } + } + } + } + pthread_attr_destroy( &attribute ); + } + + M4OSA_mutexLock(threadContext->stateMutex, M4OSA_WAIT_FOREVER); + + threadContext->state = M4OSA_kThreadOpened; + + M4OSA_mutexUnlock(threadContext->stateMutex); + + M4OSA_DEBUG(M4ERR_THREAD_NOT_STARTED, "M4OSA_threadSyncStart"); + + return M4ERR_THREAD_NOT_STARTED; +} + + + + +/** + ************************************************************************ + * @brief This method stops a specified thread. + * @note This call is a blocking one up to the "M4OSA_ThreadDoIt" + * function has returned. + * Before the method is called, the state is M4OSA_kThreadRunning. + * Once the method is called, the state is M4OSA_kThreadStopping. + * Once the thread is stopped, the state is M4OSA_kThreadOpened. + * @note This method returns once the thread has been stopped. If the + * "threadStopped" optionID is not NULL, the thread will call it + * before dying. + * @param context:(IN/OUT) Context of the thread + * @return M4NO_ERROR: there is no error + * @return M4ERR_PARAMETER: at least one parameter is NULL + * @return M4ERR_STATE: this function cannot be called now + * @return M4ERR_BAD_CONTEXT: provided context is not a valid one + ************************************************************************ +*/ +M4OSA_ERR M4OSA_threadSyncStop(M4OSA_Context context) +{ + M4OSA_ThreadContext* threadContext = (M4OSA_ThreadContext*)context; + + M4OSA_TRACE1_1("M4OSA_threadSyncStop\t\tM4OSA_Context 0x%x", context); + + M4OSA_DEBUG_IF2(context == M4OSA_NULL, + M4ERR_PARAMETER, "M4OSA_threadSyncStop"); + + M4OSA_DEBUG_IF2(threadContext->coreID != M4OSA_THREAD, + M4ERR_BAD_CONTEXT, "M4OSA_threadSyncStop"); + + M4OSA_mutexLock(threadContext->stateMutex, M4OSA_WAIT_FOREVER); + + if(threadContext->state != M4OSA_kThreadRunning) + { + M4OSA_mutexUnlock(threadContext->stateMutex); + + M4OSA_DEBUG(M4ERR_STATE, "M4OSA_threadSyncStop"); + + return M4ERR_STATE; + } + + threadContext->state = M4OSA_kThreadStopping; + + M4OSA_mutexUnlock(threadContext->stateMutex); + + M4OSA_semaphoreWait(threadContext->semStartStop, M4OSA_WAIT_FOREVER); + + M4OSA_mutexLock(threadContext->stateMutex, M4OSA_WAIT_FOREVER); + + threadContext->state = M4OSA_kThreadOpened; + + M4OSA_mutexUnlock(threadContext->stateMutex); + + return M4NO_ERROR; +} + + + + +/** + ************************************************************************ + * @brief This method deletes a thread (identified by its context). After + * this call the thread and its context are no more useable. This + * function frees all the memory related to this thread. + * @note Before the method is called, the state is M4OSA_kThreadOpened. + * Once the method is called, the state is M4OSA_kThreadClosed. + * @param context:(IN/OUT) Context of the thread + * @return M4NO_ERROR: there is no error + * @return M4ERR_PARAMETER: at least one parameter is NULL + * @return M4ERR_STATE: this function cannot be called now + * @return M4ERR_BAD_CONTEXT: provided context is not a valid one + ************************************************************************ +*/ +M4OSA_ERR M4OSA_threadSyncClose(M4OSA_Context context) +{ + M4OSA_ThreadContext* threadContext = (M4OSA_ThreadContext*)context; + M4OSA_ERR err_code; + + M4OSA_TRACE1_1("M4OSA_threadSyncClose\t\tM4OSA_Context 0x%x", context); + + M4OSA_DEBUG_IF2(context == M4OSA_NULL, + M4ERR_PARAMETER, "M4OSA_threadSyncClose"); + + M4OSA_DEBUG_IF2(threadContext->coreID != M4OSA_THREAD, + M4ERR_BAD_CONTEXT, "M4OSA_threadSyncClose"); + + M4OSA_DEBUG_IF2(threadContext->state == M4OSA_kThreadClosed, + M4ERR_BAD_CONTEXT, "M4OSA_threadSyncClose"); + + M4OSA_mutexLock(threadContext->stateMutex, M4OSA_WAIT_FOREVER); + + if(threadContext->state != M4OSA_kThreadOpened) + { + M4OSA_mutexUnlock(threadContext->stateMutex); + + M4OSA_DEBUG(M4ERR_STATE, "M4OSA_threadSyncClose"); + + return M4ERR_STATE; + } + + threadContext->state = M4OSA_kThreadClosed; + + M4OSA_mutexUnlock(threadContext->stateMutex); + + err_code = M4OSA_mutexClose(threadContext->stateMutex); + + if(M4OSA_ERR_IS_ERROR(err_code)) + { + M4OSA_DEBUG(err_code, "M4OSA_threadSyncClose: M4OSA_mutexClose"); + + return err_code; + } + + err_code = M4OSA_semaphoreClose(threadContext->semStartStop); + + if(M4OSA_ERR_IS_ERROR(err_code)) + { + M4OSA_DEBUG(err_code, "M4OSA_threadSyncClose: M4OSA_semaphoreClose"); + + return err_code; + } + + if(threadContext->name != M4OSA_NULL) + { + M4OSA_free((M4OSA_MemAddr32)threadContext->name); + } + + M4OSA_free((M4OSA_MemAddr32)threadContext); + + return M4NO_ERROR; +} + + + + +/** + ************************************************************************ + * @brief This method asks the thread to return its state. + * @note The caller is responsible for allocating/deallocating the state + * field. + * @param context:(IN) Context of the thread + * @param state:(OUT) Thread state + * @return M4NO_ERROR: there is no error + * @return M4ERR_PARAMETER: at least one parameter is NULL + * @return M4ERR_BAD_CONTEXT: provided context is not a valid one + ************************************************************************ +*/ +M4OSA_ERR M4OSA_threadSyncGetState(M4OSA_Context context, + M4OSA_ThreadState* state) +{ + M4OSA_ThreadContext* threadContext = (M4OSA_ThreadContext*)context; + + M4OSA_TRACE1_2("M4OSA_threadSyncGetState\t\tM4OSA_Context 0x%x\t" + "M4OSA_ThreadState* 0x%x", context, state); + + M4OSA_DEBUG_IF2(context == M4OSA_NULL, + M4ERR_PARAMETER, "M4OSA_threadSyncGetState"); + + M4OSA_DEBUG_IF2(state == M4OSA_NULL, + M4ERR_PARAMETER, "M4OSA_threadSyncGetState"); + + M4OSA_DEBUG_IF2(threadContext->coreID != M4OSA_THREAD, + M4ERR_BAD_CONTEXT, "M4OSA_threadSyncGetState"); + + *state = threadContext->state; + + return M4NO_ERROR; +} + + + + +/** + ************************************************************************ + * @brief This method asks the calling thread to sleep during "timeSleep" + * milliseconds. + * @note This function does not have any context. + * @param time:(IN) Time to sleep in milliseconds + * @return M4NO_ERROR: there is no error + ************************************************************************ +*/ +M4OSA_ERR M4OSA_threadSleep(M4OSA_UInt32 time) +{ + struct timespec rqtp = { 0, 0 }; + struct timespec rmtp = { 0, 0 }; + + M4OSA_TRACE1_1("M4OSA_threadSleep\t\tM4OSA_UInt32 %d", time); + + rqtp.tv_sec = (time_t)time/1000; + rqtp.tv_nsec = (time%1000) * 1000000; + nanosleep(&rqtp, &rmtp); + + return M4NO_ERROR; +} + + + + +#if(M4OSA_OPTIONID_THREAD_STARTED == M4OSA_TRUE) + +/*M4OSA_ERR M4OSA_SetThreadSyncStarted(M4OSA_Context context, + M4OSA_DataOption optionValue) +{ + M4OSA_ThreadContext* threadContext = (M4OSA_ThreadContext*)context ; + + M4OSA_TRACE2_2("M4OSA_SetThreadSyncStarted\t\tM4OSA_Context 0x%x\t" + "M4OSA_DataOption 0x%x", context, optionValue); + + threadContext->startCallBack = (M4OSA_ThreadCallBack)optionValue; + + return M4NO_ERROR; +}*/ + +#endif /*M4OSA_OPTIONID_THREAD_STARTED*/ + + + + +#if(M4OSA_OPTIONID_THREAD_STOPPED == M4OSA_TRUE) + +/*M4OSA_ERR M4OSA_SetThreadSyncStopped(M4OSA_Context context, + M4OSA_DataOption optionValue) +{ + M4OSA_ThreadContext* threadContext = (M4OSA_ThreadContext*)context; + + M4OSA_TRACE2_2("M4OSA_SetThreadSyncStopped\t\tM4OSA_Context 0x%x\t" + "M4OSA_DataOption 0x%x", context, optionValue); + + threadContext->stopCallBack = (M4OSA_ThreadCallBack)optionValue; + + return M4NO_ERROR; +}*/ + +#endif /*M4OSA_OPTIONID_THREAD_STOPPED*/ + + + +#if(M4OSA_OPTIONID_THREAD_PRIORITY == M4OSA_TRUE) + +M4OSA_ERR M4OSA_SetThreadSyncPriority(M4OSA_Context context, + M4OSA_DataOption optionValue) +{ + M4OSA_ThreadContext* threadContext = (M4OSA_ThreadContext*)context; + M4OSA_ThreadPriorityLevel priority + = (M4OSA_ThreadPriorityLevel)(optionValue); + + M4OSA_TRACE2_2("M4OSA_SetThreadSyncPriority\t\tM4OSA_Context 0x%x\t" + "M4OSA_DataOption 0x%x", context, optionValue); + + if((M4OSA_UInt32)optionValue>M4OSA_kThreadLowestPriority) + { + return M4ERR_PARAMETER; + } + + threadContext->priority = priority; + + return M4NO_ERROR; +} + +#endif /*M4OSA_OPTIONID_THREAD_PRIORITY*/ + + + + +#if(M4OSA_OPTIONID_THREAD_NAME == M4OSA_TRUE) + +M4OSA_ERR M4OSA_SetThreadSyncName(M4OSA_Context context, + M4OSA_DataOption optionValue) +{ + M4OSA_ThreadContext* threadContext = (M4OSA_ThreadContext*)context; + M4OSA_Char* name = (M4OSA_Char*)optionValue; + M4OSA_UInt32 nameSize ; + + M4OSA_TRACE2_2("M4OSA_SetThreadSyncName\t\tM4OSA_Context 0x%x\t" + "M4OSA_DataOption 0x%x", context, optionValue); + + if(threadContext->name != NULL) + { + M4OSA_free((M4OSA_MemAddr32)threadContext->name); + threadContext->name = M4OSA_NULL; + } + + if(optionValue != M4OSA_NULL) + { + nameSize = M4OSA_chrLength(name)+1; + + threadContext->name = + (M4OSA_Char*)M4OSA_malloc(nameSize, M4OSA_THREAD, + (M4OSA_Char*)"M4OSA_SetThreadSyncName: thread name"); + + if(threadContext == M4OSA_NULL) + { + return M4ERR_ALLOC; + } + + M4OSA_memcpy((M4OSA_MemAddr8)threadContext->name, (M4OSA_MemAddr8)name, + nameSize); + } + + return M4NO_ERROR; +} + +#endif /*M4OSA_OPTIONID_THREAD_NAME*/ + + +#if(M4OSA_OPTIONID_THREAD_STACK_SIZE == M4OSA_TRUE) + +M4OSA_ERR M4OSA_SetThreadSyncStackSize(M4OSA_Context context, + M4OSA_DataOption optionValue) +{ + M4OSA_ThreadContext* threadContext = (M4OSA_ThreadContext*)context; + + M4OSA_TRACE2_2("M4OSA_SetThreadSyncStackSize\t\tM4OSA_Context 0x%x\t" + "M4OSA_DataOption 0x%x", context, optionValue); + + threadContext->stackSize = (M4OSA_UInt32)optionValue; + + return M4NO_ERROR; +} + +#endif /*M4OSA_OPTIONID_THREAD_STACK_SIZE*/ + + + +#if(M4OSA_OPTIONID_THREAD_USER_DATA == M4OSA_TRUE) + +/*M4OSA_ERR M4OSA_SetThreadSyncUserData(M4OSA_Context context, + M4OSA_DataOption optionValue) +{ + M4OSA_ThreadContext* threadContext = (M4OSA_ThreadContext*)context; + + M4OSA_TRACE2_2("M4OSA_SetThreadSyncUserData\t\tM4OSA_Context 0x%x\t" + "M4OSA_DataOption 0x%x", context, optionValue); + + threadContext->userData = (M4OSA_Void*)optionValue; + + return M4NO_ERROR; +}*/ + +#endif /*M4OSA_OPTIONID_THREAD_USER_DATA*/ + + + + + +/** + ************************************************************************ + * @brief This method asks the core OSAL-Thread component to set the value + * associated with the optionID. The caller is responsible for + * allocating/deallocating the memory of the value field. + * @note As the caller is responsible of allocating/de-allocating the + * "value" field, the callee must copy this field to its internal + * variable. + * @param context:(IN/OUT) Context of the thread + * @param optionID:(IN) ID of the option + * @param optionValue:(IN) Value of the option + * @return M4NO_ERROR: there is no error + * @return M4ERR_PARAMETER: at least one parameter is NULL + * @return M4ERR_BAD_CONTEXT: provided context is not a valid one + * @return M4ERR_BAD_OPTION_ID: the optionID is not a valid one + * @return M4ERR_STATE: this option is not available now + * @return M4ERR_READ_ONLY: this option is a read only one + * @return M4ERR_NOT_IMPLEMENTED: this option is not implemented + ************************************************************************ +*/ +M4OSA_ERR M4OSA_threadSyncSetOption(M4OSA_Context context, + M4OSA_ThreadOptionID optionID, + M4OSA_DataOption optionValue) +{ + M4OSA_ThreadContext* threadContext = (M4OSA_ThreadContext*)context; + M4OSA_ERR err_code; + + M4OSA_TRACE1_3("M4OSA_threadSyncSetOption\t\tM4OSA_Context 0x%x\t" + "M4OSA_OptionID %d\tM4OSA_DataOption 0x%x", + context, optionID, optionValue); + + M4OSA_DEBUG_IF2(context == M4OSA_NULL, + M4ERR_PARAMETER, "M4OSA_threadSyncSetOption"); + + M4OSA_DEBUG_IF2(optionID == M4OSA_NULL, + M4ERR_PARAMETER, "M4OSA_threadSyncSetOption"); + + M4OSA_DEBUG_IF2(threadContext->coreID != M4OSA_THREAD, + M4ERR_BAD_CONTEXT, "M4OSA_threadSyncSetOption"); + + M4OSA_DEBUG_IF2(!M4OSA_OPTION_ID_IS_COREID(optionID, M4OSA_THREAD), + M4ERR_BAD_OPTION_ID, "M4OSA_threadSyncSetOption"); + + M4OSA_DEBUG_IF2(!M4OSA_OPTION_ID_IS_WRITABLE(optionID), + M4ERR_READ_ONLY, "M4OSA_threadSyncSetOption"); + + + M4OSA_mutexLock(threadContext->stateMutex, M4OSA_WAIT_FOREVER); + + if(threadContext->state != M4OSA_kThreadOpened) + { + M4OSA_mutexUnlock(threadContext->stateMutex); + + M4OSA_DEBUG(M4ERR_STATE, "M4OSA_threadSyncSetOption"); + + return M4ERR_STATE; + } + + switch(optionID) + { +#if(M4OSA_OPTIONID_THREAD_STARTED == M4OSA_TRUE) + /*case M4OSA_ThreadStarted: + { + err_code = M4OSA_SetThreadSyncStarted(context, optionValue); + + break; + }*/ +#endif /*M4OSA_OPTIONID_THREAD_STARTED*/ + +#if(M4OSA_OPTIONID_THREAD_STOPPED == M4OSA_TRUE) + /*case M4OSA_ThreadStopped: + { + err_code = M4OSA_SetThreadSyncStopped(context, optionValue); + + break; + }*/ +#endif /*M4OSA_OPTIONID_THREAD_STOPPED*/ + +#if(M4OSA_OPTIONID_THREAD_USER_DATA == M4OSA_TRUE) + /*case M4OSA_ThreadUserData: + { + err_code = M4OSA_SetThreadSyncUserData(context, optionValue); + + break; + }*/ +#endif /*M4OSA_OPTIONID_THREAD_USER_DATA*/ + +#if(M4OSA_OPTIONID_THREAD_PRIORITY == M4OSA_TRUE) + case M4OSA_ThreadPriority: + { + err_code = M4OSA_SetThreadSyncPriority(context, optionValue); + + break; + } +#endif /*M4OSA_OPTIONID_THREAD_PRIORITY*/ + +#if(M4OSA_OPTIONID_THREAD_NAME == M4OSA_TRUE) + case M4OSA_ThreadName: + { + err_code = M4OSA_SetThreadSyncName(context, optionValue); + + break; + } +#endif /*M4OSA_OPTIONID_THREAD_NAME*/ + +#if(M4OSA_OPTIONID_THREAD_STACK_SIZE == M4OSA_TRUE) + case M4OSA_ThreadStackSize: + { + err_code = M4OSA_SetThreadSyncStackSize(context, optionValue); + + break; + } +#endif /*M4OSA_OPTIONID_THREAD_STACK_SIZE*/ + + default: + { + M4OSA_DEBUG(M4ERR_NOT_IMPLEMENTED, "M4OSA_threadSyncSetOption"); + + err_code = M4ERR_NOT_IMPLEMENTED; + } + } + + M4OSA_mutexUnlock(threadContext->stateMutex); + + return err_code; +} + + + +/** + ************************************************************************ + * @brief This method asks the OSAL-Thread to return the value associated + * with the optionID. The caller is responsible for + * allocating/deallocating the memory of the value field. + * @note "optionValue" must be cast according to the type related to the + * optionID. + * @note As the caller is responsible for de-allocating the "value" + * field, the core OSAL-Thread component must perform a copy of its + * internal value to the value field. + * @param context:(IN) Context of the thread + * @param optionID:(IN) ID of the option + * @param optionValue:(OUT) Value of the option + * @return M4NO_ERROR: there is no error + * @return M4ERR_PARAMETER: at least one parameter is NULL + * @return M4ERR_BAD_CONTEXT: provided context is not a valid one + * @return M4ERR_BAD_OPTION_ID: the optionID is not a valid one + * @return M4ERR_WRITE_ONLY: this option is a write only one + * @return M4ERR_NOT_IMPLEMENTED: this option is not implemented + ************************************************************************ +*/ +M4OSA_ERR M4OSA_threadSyncGetOption(M4OSA_Context context, + M4OSA_ThreadOptionID optionID, + M4OSA_DataOption* optionValue) +{ + M4OSA_ThreadContext* threadContext = (M4OSA_ThreadContext*)context; + + M4OSA_TRACE1_3("M4OSA_threadSyncGetOption\t\tM4OSA_Context 0x%x\t" + "M4OSA_OptionID %d\tM4OSA_DataOption* 0x%x", + context, optionID, optionValue); + + M4OSA_DEBUG_IF2(context == M4OSA_NULL, + M4ERR_PARAMETER, "M4OSA_threadSyncGetOption"); + + M4OSA_DEBUG_IF2(optionID == M4OSA_NULL, + M4ERR_PARAMETER, "M4OSA_threadSyncGetOption"); + + M4OSA_DEBUG_IF2(optionValue == M4OSA_NULL, + M4ERR_PARAMETER, "M4OSA_threadSyncGetOption"); + + M4OSA_DEBUG_IF2(threadContext->coreID != M4OSA_THREAD, + M4ERR_BAD_CONTEXT, "M4OSA_threadSyncGetOption"); + + M4OSA_DEBUG_IF2(!M4OSA_OPTION_ID_IS_COREID(optionID, M4OSA_THREAD), + M4ERR_BAD_OPTION_ID, "M4OSA_threadSyncGetOption"); + + M4OSA_DEBUG_IF2(!M4OSA_OPTION_ID_IS_READABLE(optionID), + M4ERR_WRITE_ONLY, "M4OSA_threadSyncGetOption"); + + switch(optionID) + { +#if(M4OSA_OPTIONID_THREAD_STARTED == M4OSA_TRUE) + /*case M4OSA_ThreadStarted: + { + M4OSA_ThreadCallBack* startCallBack = (M4OSA_ThreadCallBack*)optionValue; + + *startCallBack = threadContext->startCallBack; + + return M4NO_ERROR; + }*/ +#endif /*M4OSA_OPTIONID_THREAD_STARTED*/ + +#if(M4OSA_OPTIONID_THREAD_STOPPED == M4OSA_TRUE) + /*case M4OSA_ThreadStopped: + { + M4OSA_ThreadCallBack* stopCallBack = (M4OSA_ThreadCallBack*)optionValue; + + *stopCallBack = threadContext->stopCallBack; + + return M4NO_ERROR; + }*/ +#endif /*M4OSA_OPTIONID_THREAD_STOPPED*/ + +#if(M4OSA_OPTIONID_THREAD_USER_DATA == M4OSA_TRUE) + /*case M4OSA_ThreadUserData: + { + M4OSA_Void** userData = (M4OSA_Void**)optionValue; + + *userData = threadContext->userData; + + return M4NO_ERROR; + }*/ +#endif /*M4OSA_OPTIONID_THREAD_USER_DATA*/ + +#if(M4OSA_OPTIONID_THREAD_PRIORITY == M4OSA_TRUE) + case M4OSA_ThreadPriority: + { + M4OSA_ThreadPriorityLevel* priority = + (M4OSA_ThreadPriorityLevel*)optionValue; + + *priority = threadContext->priority; + + return M4NO_ERROR; + } +#endif /*M4OSA_OPTIONID_THREAD_PRIORITY*/ + +#if(M4OSA_OPTIONID_THREAD_NAME == M4OSA_TRUE) + case M4OSA_ThreadName: + { + M4OSA_Char** name = (M4OSA_Char**)optionValue; + + *name = threadContext->name; + + return M4NO_ERROR; + } +#endif /*M4OSA_OPTIONID_THREAD_NAME*/ + +#if(M4OSA_OPTIONID_THREAD_STACK_SIZE == M4OSA_TRUE) + case M4OSA_ThreadStackSize: + { + M4OSA_UInt32* stackSize = (M4OSA_UInt32*)optionValue; + + *stackSize = threadContext->stackSize; + + return M4NO_ERROR; + } +#endif /*M4OSA_OPTIONID_THREAD_STACK_SIZE*/ + + default: + break; + } + + M4OSA_DEBUG(M4ERR_NOT_IMPLEMENTED, "M4OSA_threadSyncGetOption"); + + return M4ERR_NOT_IMPLEMENTED; +} + |