204 lines
5.8 KiB
C
204 lines
5.8 KiB
C
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||
|
|
||
|
#include "cpr.h"
|
||
|
#include "cpr_stdlib.h"
|
||
|
#include "cpr_stdio.h"
|
||
|
#include <pthread.h>
|
||
|
#include <errno.h>
|
||
|
#include <unistd.h>
|
||
|
#include <sys/resource.h>
|
||
|
|
||
|
#define ANDROID_MIN_THREAD_PRIORITY (-20) /* tbd: check MV linux: current val from Larry port */
|
||
|
#define ANDROID_MAX_THREAD_PRIORITY (+19) /* tbd: check MV linux. current val from Larry port */
|
||
|
|
||
|
|
||
|
/**
|
||
|
* cprCreateThread
|
||
|
*
|
||
|
* @brief Create a thread
|
||
|
*
|
||
|
* The cprCreateThread function creates another execution thread within the
|
||
|
* current process. If the input parameter "name" is present, then this is used
|
||
|
* for debugging purposes. The startRoutine is the address of the function where
|
||
|
* the thread execution begins. The start routine prototype is defined as
|
||
|
* follows
|
||
|
* @code
|
||
|
* int32_t (*cprThreadStartRoutine)(void* data)
|
||
|
* @endcode
|
||
|
*
|
||
|
* @param[in] name - name of the thread created (optional)
|
||
|
* @param[in] startRoutine - function where thread execution begins
|
||
|
* @param[in] stackSize - size of the thread's stack
|
||
|
* @param[in] priority - thread's execution priority
|
||
|
* @param[in] data - parameter to pass to startRoutine
|
||
|
*
|
||
|
* Return Value: Thread handle or NULL if creation failed.
|
||
|
*/
|
||
|
cprThread_t
|
||
|
cprCreateThread (const char *name,
|
||
|
cprThreadStartRoutine startRoutine,
|
||
|
uint16_t stackSize,
|
||
|
uint16_t priority,
|
||
|
void *data)
|
||
|
{
|
||
|
static const char fname[] = "cprCreateThread";
|
||
|
static uint16_t id = 0;
|
||
|
cpr_thread_t *threadPtr;
|
||
|
pthread_t threadId;
|
||
|
pthread_attr_t attr;
|
||
|
|
||
|
CPR_INFO("%s: creating '%s' thread\n", fname, name);
|
||
|
|
||
|
/* Malloc memory for a new thread */
|
||
|
threadPtr = (cpr_thread_t *)cpr_malloc(sizeof(cpr_thread_t));
|
||
|
if (threadPtr != NULL) {
|
||
|
if (pthread_attr_init(&attr) != 0) {
|
||
|
|
||
|
CPR_ERROR("%s - Failed to init attribute for thread %s\n",
|
||
|
fname, name);
|
||
|
cpr_free(threadPtr);
|
||
|
return (cprThread_t)NULL;
|
||
|
}
|
||
|
|
||
|
if (pthread_attr_setstacksize(&attr, stackSize) != 0) {
|
||
|
CPR_ERROR("%s - Invalid stacksize %d specified for thread %s\n",
|
||
|
fname, stackSize, name);
|
||
|
cpr_free(threadPtr);
|
||
|
return (cprThread_t)NULL;
|
||
|
}
|
||
|
|
||
|
if (pthread_create(&threadId, &attr, startRoutine, data) != 0) {
|
||
|
CPR_ERROR("%s - Creation of thread %s failed: %d\n",
|
||
|
fname, name, errno);
|
||
|
cpr_free(threadPtr);
|
||
|
return (cprThread_t)NULL;
|
||
|
}
|
||
|
|
||
|
/* Assign name to CPR if one was passed in */
|
||
|
if (name != NULL) {
|
||
|
threadPtr->name = name;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* TODO - It would be nice for CPR to keep a linked
|
||
|
* list of running threads for debugging purposes
|
||
|
* such as a show command or walking the list to ensure
|
||
|
* that an application does not attempt to create
|
||
|
* the same thread twice.
|
||
|
*/
|
||
|
threadPtr->u.handleInt = threadId;
|
||
|
threadPtr->threadId = ++id;
|
||
|
return (cprThread_t)threadPtr;
|
||
|
}
|
||
|
|
||
|
/* Malloc failed */
|
||
|
CPR_ERROR("%s - Malloc for thread %s failed.\n", fname, name);
|
||
|
errno = ENOMEM;
|
||
|
return (cprThread_t)NULL;
|
||
|
}
|
||
|
|
||
|
|
||
|
/**
|
||
|
* cprDestroyThread
|
||
|
*
|
||
|
* @brief Destroys the thread passed in.
|
||
|
*
|
||
|
* The cprDestroyThread function is called to destroy a thread. The thread
|
||
|
* parameter may be any valid thread including the calling thread itself.
|
||
|
*
|
||
|
* @param[in] thread - thread to destroy.
|
||
|
*
|
||
|
* @return CPR_SUCCESS or CPR_FAILURE. errno should be set for FAILURE case.
|
||
|
*
|
||
|
* @note In Linux there will never be a success indication as the
|
||
|
* calling thread will have been terminated.
|
||
|
*/
|
||
|
cprRC_t
|
||
|
cprDestroyThread (cprThread_t thread)
|
||
|
{
|
||
|
static const char fname[] = "cprDestroyThread";
|
||
|
cpr_thread_t *cprThreadPtr;
|
||
|
|
||
|
cprThreadPtr = (cpr_thread_t *) thread;
|
||
|
if (cprThreadPtr != NULL) {
|
||
|
/*
|
||
|
* Make sure thread is trying to destroy itself.
|
||
|
*/
|
||
|
if ((pthread_t) cprThreadPtr->u.handleInt == pthread_self()) {
|
||
|
cprThreadPtr->threadId = 0;
|
||
|
cpr_free(cprThreadPtr);
|
||
|
pthread_exit(NULL);
|
||
|
return CPR_SUCCESS;
|
||
|
}
|
||
|
|
||
|
CPR_ERROR("%s: Thread attempted to destroy another thread, not itself.\n",
|
||
|
fname);
|
||
|
errno = EINVAL;
|
||
|
return CPR_FAILURE;
|
||
|
}
|
||
|
|
||
|
/* Bad application! */
|
||
|
CPR_ERROR("%s - NULL pointer passed in.\n", fname);
|
||
|
errno = EINVAL;
|
||
|
return CPR_FAILURE;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* cprAdjustRelativeThreadPriority
|
||
|
*
|
||
|
* @brief The function sets the relative thread priority up or down by the given value.
|
||
|
*
|
||
|
* This function is used pSIPCC to set up the thread priority. The values of the
|
||
|
* priority range from -20 (Maximum priority) to +19 (Minimum priority).
|
||
|
*
|
||
|
* @param[in] relPri - nice value of the thread -20 is MAX and 19 is MIN
|
||
|
*
|
||
|
* @return CPR_SUCCESS or CPR_FAILURE
|
||
|
*/
|
||
|
cprRC_t
|
||
|
cprAdjustRelativeThreadPriority (int relPri)
|
||
|
{
|
||
|
const char *fname = "cprAdjustRelativeThreadPriority";
|
||
|
|
||
|
if (setpriority(PRIO_PROCESS, 0, relPri) == -1) {
|
||
|
CPR_ERROR("%s: could not set the nice..err=%d\n",
|
||
|
fname, errno);
|
||
|
return CPR_FAILURE;
|
||
|
}
|
||
|
return CPR_SUCCESS;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @}
|
||
|
* @addtogroup ThreadInternal Helper functions for implementing threads in CPR
|
||
|
* @ingroup Threads
|
||
|
* @brief Helper functions used by CPR for thread implementation
|
||
|
*
|
||
|
* @{
|
||
|
*/
|
||
|
|
||
|
/**
|
||
|
* cprGetThreadId
|
||
|
*
|
||
|
* @brief Return the pthread ID for the given CPR thread.
|
||
|
*
|
||
|
* @param[in] thread - thread to query
|
||
|
*
|
||
|
* @return Thread's Id or zero(0)
|
||
|
*
|
||
|
*/
|
||
|
pthread_t
|
||
|
cprGetThreadId (cprThread_t thread)
|
||
|
{
|
||
|
if (thread) {
|
||
|
return ((cpr_thread_t *)thread)->u.handleInt;
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @}
|
||
|
*/
|