210 lines
5.8 KiB
C
210 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 <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;
|
|
}
|
|
|