#ifndef _NSPR_PORT_X_H_
#define _NSPR_PORT_X_H_
#include "prmem.h"
#include "prlock.h"
#include "prerror.h"
#include "prinit.h"
#include "prbit.h"
#include <stdlib.h>
#include <pthread.h>
#include <string.h>
#pragma mark *** Memory ***
NSPR_API(void *) PR_Malloc(PRSize size)
{
return malloc(size ? size : 1);
}
NSPR_API(void *) PR_Calloc(PRSize nelem, PRSize elsize)
{
return calloc(nelem, elsize);
}
NSPR_API(void *) PR_Realloc(void *ptr, PRSize size)
{
return realloc(ptr, size);
}
NSPR_API(void) PR_Free(void *ptr)
{
return free(ptr);
}
#pragma mark *** locks ***
NSPR_API(PRLock*) PR_NewLock(void)
{
pthread_mutex_t *pm = PR_Malloc(sizeof(pthread_mutex_t));
if(pm == NULL) {
return NULL;
}
if(pthread_mutex_init(pm, NULL)) {
PR_Free(pm);
return NULL;
}
return (PRLock*)pm;
}
NSPR_API(void) PR_DestroyLock(PRLock *lock)
{
if(lock == NULL) {
return;
}
pthread_mutex_destroy((pthread_mutex_t *)lock);
PR_Free(lock);
}
NSPR_API(void) PR_Lock(PRLock *lock)
{
if(lock == NULL) {
return;
}
pthread_mutex_lock((pthread_mutex_t *)lock);
}
NSPR_API(PRStatus) PR_Unlock(PRLock *lock)
{
if(lock == NULL) {
return PR_FAILURE;
}
pthread_mutex_unlock((pthread_mutex_t *)lock);
return PR_SUCCESS;
}
#pragma mark *** get/set error ***
static pthread_key_t PR_threadKey;
static int PR_threadKeyInitFlag; static int PR_threadKeyErrorFlag; static pthread_mutex_t PR_threadKeyLock = PTHREAD_MUTEX_INITIALIZER;
typedef struct {
PRInt32 osError;
PRErrorCode prError;
} PR_threadErrInfo;
static PRInt32 PR_initThreadKey(
int doCreate)
{
PRInt32 prtn = 0;
if(PR_threadKeyInitFlag) {
return 0;
}
pthread_mutex_lock(&PR_threadKeyLock);
if(PR_threadKeyErrorFlag && !doCreate) {
prtn = PR_IO_ERROR;
}
else if(!PR_threadKeyInitFlag) {
prtn = pthread_key_create(&PR_threadKey, free);
if(prtn) {
PR_threadKeyErrorFlag = 1;
}
else {
PR_threadKeyErrorFlag = 0; PR_threadKeyInitFlag = 1; }
}
pthread_mutex_unlock(&PR_threadKeyLock);
return prtn;
}
static PR_threadErrInfo *PR_getThreadErrInfo(
int doCreate,
PRInt32 *threadKeyError) {
*threadKeyError = PR_initThreadKey(doCreate);
if(*threadKeyError) {
return NULL;
}
PR_threadErrInfo *errInfo = pthread_getspecific(PR_threadKey);
if((errInfo == NULL) && doCreate) {
errInfo = (PR_threadErrInfo *)malloc(sizeof(*errInfo));
if(errInfo == NULL) {
*threadKeyError = PR_OUT_OF_MEMORY_ERROR;
}
else {
memset(errInfo, 0, sizeof(*errInfo));
pthread_setspecific(PR_threadKey, errInfo);
}
}
return errInfo;
}
PR_IMPLEMENT(PRErrorCode) PR_GetError(void)
{
PRInt32 prtn;
PR_threadErrInfo *errInfo = PR_getThreadErrInfo(0, &prtn);
if(errInfo == NULL) {
if(prtn) {
return PR_INSUFFICIENT_RESOURCES_ERROR;
}
else {
return 0;
}
}
else {
return errInfo->prError;
}
}
PR_IMPLEMENT(PRInt32) PR_GetOSError(void)
{
PRInt32 prtn;
PR_threadErrInfo *errInfo = PR_getThreadErrInfo(0, &prtn);
if(errInfo == NULL) {
return prtn;
}
else {
return errInfo->osError;
}
}
PR_IMPLEMENT(void) PR_SetError(PRErrorCode code, PRInt32 osErr)
{
PRInt32 prtn;
PR_threadErrInfo *errInfo = PR_getThreadErrInfo(1, &prtn);
if(errInfo != NULL) {
errInfo->osError = osErr;
errInfo->prError = code;
}
}
#pragma mark *** misc. ***
NSPR_API(PRIntn) PR_CeilingLog2(PRUint32 i)
{
PRIntn r;
PR_CEILING_LOG2(r,i);
return r;
}
#endif