freeswitch/libs/sipcc/cpr/android/cpr_android_locks.c

210 lines
5.8 KiB
C
Raw Normal View History

2012-12-18 01:14:30 +00:00
/* 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 <errno.h>
#include <pthread.h>
#include <sys/time.h>
/**
* @defgroup MutexIPCAPIs The Mutex/Semaphore IPC APIs
* @ingroup IPC
* @brief The module related to Mutex/Sempahore abstraction for the pSIPCC
* @{
*/
/**
* cprCreateMutex
*
* @brief Creates a mutual exclusion block
*
* The cprCreateMutex function is called to allow the OS to perform whatever
* work is needed to create a mutex.
*
* @param[in] name - name of the mutex. If present, CPR assigns this name to
* the mutex to assist in debugging.
*
* @return Mutex handle or NULL if creation failed. If NULL, set errno
*/
cprMutex_t
cprCreateMutex (const char *name)
{
static const char fname[] = "cprCreateMutex";
static uint16_t id = 0;
int32_t returnCode;
cpr_mutex_t *cprMutexPtr;
pthread_mutex_t *pthreadMutexPtr;
/*
* Malloc memory for a new mutex. CPR has its' own
* set of mutexes so malloc one for the generic
* CPR view and one for the CNU specific version.
*/
cprMutexPtr = (cpr_mutex_t *) cpr_malloc(sizeof(cpr_mutex_t));
pthreadMutexPtr = (pthread_mutex_t *) cpr_malloc(sizeof(pthread_mutex_t));
if ((cprMutexPtr != NULL) && (pthreadMutexPtr != NULL)) {
/* Assign name */
cprMutexPtr->name = name;
/*
* Use default mutex attributes. TBD: if we do not
* need cnuMutexAttributes global get rid of it
*/
returnCode = pthread_mutex_init(pthreadMutexPtr, NULL);
if (returnCode != 0) {
CPR_ERROR("%s - Failure trying to init Mutex %s: %d\n",
fname, name, returnCode);
cpr_free(pthreadMutexPtr);
cpr_free(cprMutexPtr);
return (cprMutex_t)NULL;
}
/*
* TODO - It would be nice for CPR to keep a linked
* list of active mutexes for debugging purposes
* such as a show command or walking the list to ensure
* that an application does not attempt to create
* the same mutex twice.
*/
cprMutexPtr->u.handlePtr = pthreadMutexPtr;
cprMutexPtr->lockId = ++id;
return (cprMutex_t)cprMutexPtr;
}
/*
* Since the code malloced two pointers ensure both
* are freed since one malloc call could have worked
* and the other failed.
*/
if (pthreadMutexPtr != NULL) {
cpr_free(pthreadMutexPtr);
} else if (cprMutexPtr != NULL) {
cpr_free(cprMutexPtr);
}
/* Malloc failed */
CPR_ERROR("%s - Malloc for mutex %s failed.\n", fname, name);
errno = ENOMEM;
return (cprMutex_t)NULL;
}
/**
* cprDestroyMutex
*
* @brief Destroys the mutex passed in.
*
* The cprDestroyMutex function is called to destroy a mutex. It is the
* application's responsibility to ensure that the mutex is unlocked when
* destroyed. Unpredictiable behavior will occur if an application
* destroys a locked mutex.
*
* @param[in] mutex - mutex to destroy
*
* @return CPR_SUCCESS or CPR_FAILURE. errno should be set for CPR_FAILURE.
*/
cprRC_t
cprDestroyMutex (cprMutex_t mutex)
{
static const char fname[] = "cprDestroyMutex";
cpr_mutex_t *cprMutexPtr;
int32_t rc;
cprMutexPtr = (cpr_mutex_t *) mutex;
if (cprMutexPtr != NULL) {
rc = pthread_mutex_destroy(cprMutexPtr->u.handlePtr);
if (rc != 0) {
CPR_ERROR("%s - Failure destroying Mutex %s: %d\n",
fname, cprMutexPtr->name, rc);
return CPR_FAILURE;
}
cprMutexPtr->lockId = 0;
cpr_free(cprMutexPtr->u.handlePtr);
cpr_free(cprMutexPtr);
return CPR_SUCCESS;
}
/* Bad application! */
CPR_ERROR("%s - NULL pointer passed in.\n", fname);
errno = EINVAL;
return CPR_FAILURE;
}
/**
* cprGetMutex
*
* @brief Acquire ownership of a mutex
*
* This function locks the mutex referenced by the mutex parameter. If the mutex
* is locked by another thread, the calling thread will block until the mutex is
* released.
*
* @param[in] mutex - Which mutex to acquire
*
* @return CPR_SUCCESS or CPR_FAILURE
*/
cprRC_t
cprGetMutex (cprMutex_t mutex)
{
static const char fname[] = "cprGetMutex";
cpr_mutex_t *cprMutexPtr;
int32_t rc;
cprMutexPtr = (cpr_mutex_t *) mutex;
if (cprMutexPtr != NULL) {
rc = pthread_mutex_lock((pthread_mutex_t *) cprMutexPtr->u.handlePtr);
if (rc != 0) {
CPR_ERROR("%s - Error acquiring mutex %s: %d\n",
fname, cprMutexPtr->name, rc);
return CPR_FAILURE;
}
return CPR_SUCCESS;
}
/* Bad application! */
CPR_ERROR("%s - NULL pointer passed in.\n", fname);
errno = EINVAL;
return CPR_FAILURE;
}
/**
* cprReleaseMutex
*
* @brief Release ownership of a mutex
*
* This function unlocks the mutex referenced by the mutex parameter.
* @param[in] mutex - Which mutex to release
*
* @return CPR_SUCCESS or CPR_FAILURE
*/
cprRC_t
cprReleaseMutex (cprMutex_t mutex)
{
static const char fname[] = "cprReleaseMutex";
cpr_mutex_t *cprMutexPtr;
int32_t rc;
cprMutexPtr = (cpr_mutex_t *) mutex;
if (cprMutexPtr != NULL) {
rc = pthread_mutex_unlock((pthread_mutex_t *) cprMutexPtr->u.handlePtr);
if (rc != 0) {
CPR_ERROR("%s - Error releasing mutex %s: %d\n",
fname, cprMutexPtr->name, rc);
return CPR_FAILURE;
}
return CPR_SUCCESS;
}
/* Bad application! */
CPR_ERROR("%s - NULL pointer passed in.\n", fname);
errno = EINVAL;
return CPR_FAILURE;
}