1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/media/webrtc/signaling/src/sipcc/cpr/android/cpr_android_threads.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,219 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 + 1.8 +#include "cpr.h" 1.9 +#include "cpr_stdlib.h" 1.10 +#include "cpr_stdio.h" 1.11 +#include <pthread.h> 1.12 +#include <errno.h> 1.13 +#include <unistd.h> 1.14 +#include <sys/resource.h> 1.15 +#include "thread_monitor.h" 1.16 +#include "prtypes.h" 1.17 +#include "mozilla/Assertions.h" 1.18 + 1.19 +#define ANDROID_MIN_THREAD_PRIORITY (-20) /* tbd: check MV linux: current val from Larry port */ 1.20 +#define ANDROID_MAX_THREAD_PRIORITY (+19) /* tbd: check MV linux. current val from Larry port */ 1.21 + 1.22 +void CSFLogRegisterThread(const cprThread_t thread); 1.23 + 1.24 +/** 1.25 + * cprCreateThread 1.26 + * 1.27 + * @brief Create a thread 1.28 + * 1.29 + * The cprCreateThread function creates another execution thread within the 1.30 + * current process. If the input parameter "name" is present, then this is used 1.31 + * for debugging purposes. The startRoutine is the address of the function where 1.32 + * the thread execution begins. The start routine prototype is defined as 1.33 + * follows 1.34 + * @code 1.35 + * int32_t (*cprThreadStartRoutine)(void* data) 1.36 + * @endcode 1.37 + * 1.38 + * @param[in] name - name of the thread created (optional) 1.39 + * @param[in] startRoutine - function where thread execution begins 1.40 + * @param[in] stackSize - size of the thread's stack 1.41 + * @param[in] priority - thread's execution priority 1.42 + * @param[in] data - parameter to pass to startRoutine 1.43 + * 1.44 + * Return Value: Thread handle or NULL if creation failed. 1.45 + */ 1.46 +cprThread_t 1.47 +cprCreateThread (const char *name, 1.48 + cprThreadStartRoutine startRoutine, 1.49 + uint16_t stackSize, 1.50 + uint16_t priority, 1.51 + void *data) 1.52 +{ 1.53 + static const char fname[] = "cprCreateThread"; 1.54 + static uint16_t id = 0; 1.55 + cpr_thread_t *threadPtr; 1.56 + pthread_t threadId; 1.57 + pthread_attr_t attr; 1.58 + 1.59 + CPR_INFO("%s: creating '%s' thread\n", fname, name); 1.60 + 1.61 + /* Malloc memory for a new thread */ 1.62 + threadPtr = (cpr_thread_t *)cpr_malloc(sizeof(cpr_thread_t)); 1.63 + if (threadPtr != NULL) { 1.64 + if (pthread_attr_init(&attr) != 0) { 1.65 + 1.66 + CPR_ERROR("%s - Failed to init attribute for thread %s\n", 1.67 + fname, name); 1.68 + cpr_free(threadPtr); 1.69 + return (cprThread_t)NULL; 1.70 + } 1.71 + 1.72 + if (pthread_attr_setstacksize(&attr, stackSize) != 0) { 1.73 + CPR_ERROR("%s - Invalid stacksize %d specified for thread %s\n", 1.74 + fname, stackSize, name); 1.75 + cpr_free(threadPtr); 1.76 + return (cprThread_t)NULL; 1.77 + } 1.78 + 1.79 + if (pthread_create(&threadId, &attr, startRoutine, data) != 0) { 1.80 + CPR_ERROR("%s - Creation of thread %s failed: %d\n", 1.81 + fname, name, errno); 1.82 + cpr_free(threadPtr); 1.83 + return (cprThread_t)NULL; 1.84 + } 1.85 + 1.86 + /* Assign name to CPR if one was passed in */ 1.87 + if (name != NULL) { 1.88 + threadPtr->name = name; 1.89 + } 1.90 + 1.91 + /* 1.92 + * TODO - It would be nice for CPR to keep a linked 1.93 + * list of running threads for debugging purposes 1.94 + * such as a show command or walking the list to ensure 1.95 + * that an application does not attempt to create 1.96 + * the same thread twice. 1.97 + */ 1.98 + threadPtr->u.handleInt = threadId; 1.99 + threadPtr->threadId = ++id; 1.100 + CSFLogRegisterThread(threadPtr); 1.101 + return (cprThread_t)threadPtr; 1.102 + } 1.103 + 1.104 + /* Malloc failed */ 1.105 + CPR_ERROR("%s - Malloc for thread %s failed.\n", fname, name); 1.106 + errno = ENOMEM; 1.107 + return (cprThread_t)NULL; 1.108 +} 1.109 + 1.110 +/* 1.111 + * cprJoinThread 1.112 + * 1.113 + * wait for thread termination 1.114 + */ 1.115 +void cprJoinThread(cprThread_t thread) 1.116 +{ 1.117 + cpr_thread_t *cprThreadPtr; 1.118 + 1.119 + cprThreadPtr = (cpr_thread_t *) thread; 1.120 + MOZ_ASSERT(cprThreadPtr); 1.121 + pthread_join(cprThreadPtr->u.handleInt, NULL); 1.122 +} 1.123 + 1.124 +/** 1.125 + * cprDestroyThread 1.126 + * 1.127 + * @brief Destroys the thread passed in. 1.128 + * 1.129 + * The cprDestroyThread function is called to destroy a thread. The thread 1.130 + * parameter may be any valid thread including the calling thread itself. 1.131 + * 1.132 + * @param[in] thread - thread to destroy. 1.133 + * 1.134 + * @return CPR_SUCCESS or CPR_FAILURE. errno should be set for FAILURE case. 1.135 + * 1.136 + * @note In Linux there will never be a success indication as the 1.137 + * calling thread will have been terminated. 1.138 + */ 1.139 +cprRC_t 1.140 +cprDestroyThread (cprThread_t thread) 1.141 +{ 1.142 + cpr_thread_t *cprThreadPtr; 1.143 + 1.144 + cprThreadPtr = (cpr_thread_t *) thread; 1.145 + if (cprThreadPtr) { 1.146 + /* 1.147 + * Make sure thread is trying to destroy itself. 1.148 + */ 1.149 + if ((pthread_t) cprThreadPtr->u.handleInt == pthread_self()) { 1.150 + CPR_INFO("%s: Destroying Thread %d", __FUNCTION__, cprThreadPtr->threadId); 1.151 + pthread_exit(NULL); 1.152 + return CPR_SUCCESS; 1.153 + } 1.154 + 1.155 + CPR_ERROR("%s: Thread attempted to destroy another thread, not itself.", 1.156 + __FUNCTION__); 1.157 + MOZ_ASSERT(PR_FALSE); 1.158 + errno = EINVAL; 1.159 + return CPR_FAILURE; 1.160 + } 1.161 + 1.162 + CPR_ERROR("%s - NULL pointer passed in.", __FUNCTION__); 1.163 + MOZ_ASSERT(PR_FALSE); 1.164 + errno = EINVAL; 1.165 + return CPR_FAILURE; 1.166 +} 1.167 + 1.168 +/** 1.169 + * cprAdjustRelativeThreadPriority 1.170 + * 1.171 + * @brief The function sets the relative thread priority up or down by the given value. 1.172 + * 1.173 + * This function is used pSIPCC to set up the thread priority. The values of the 1.174 + * priority range from -20 (Maximum priority) to +19 (Minimum priority). 1.175 + * 1.176 + * @param[in] relPri - nice value of the thread -20 is MAX and 19 is MIN 1.177 + * 1.178 + * @return CPR_SUCCESS or CPR_FAILURE 1.179 + */ 1.180 +cprRC_t 1.181 +cprAdjustRelativeThreadPriority (int relPri) 1.182 +{ 1.183 + const char *fname = "cprAdjustRelativeThreadPriority"; 1.184 + 1.185 + if (setpriority(PRIO_PROCESS, 0, relPri) == -1) { 1.186 + CPR_ERROR("%s: could not set the nice..err=%d\n", 1.187 + fname, errno); 1.188 + return CPR_FAILURE; 1.189 + } 1.190 + return CPR_SUCCESS; 1.191 +} 1.192 + 1.193 +/** 1.194 + * @} 1.195 + * @addtogroup ThreadInternal Helper functions for implementing threads in CPR 1.196 + * @ingroup Threads 1.197 + * @brief Helper functions used by CPR for thread implementation 1.198 + * 1.199 + * @{ 1.200 + */ 1.201 + 1.202 +/** 1.203 + * cprGetThreadId 1.204 + * 1.205 + * @brief Return the pthread ID for the given CPR thread. 1.206 + * 1.207 + * @param[in] thread - thread to query 1.208 + * 1.209 + * @return Thread's Id or zero(0) 1.210 + * 1.211 + */ 1.212 +pthread_t 1.213 +cprGetThreadId (cprThread_t thread) 1.214 +{ 1.215 + if (thread) { 1.216 + return ((cpr_thread_t *)thread)->u.handleInt; 1.217 + } 1.218 + return 0; 1.219 +} 1.220 +/** 1.221 + * @} 1.222 + */