Created
December 3, 2010 19:59
-
-
Save t3rmin4t0r/727468 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
pthread_ulock_t *apc_pthreadulock_create(pthread_ulock_t *lock TSRMLS_DC) | |
{ | |
int result; | |
pthread_rwlockattr_t* attr; | |
attr = malloc(sizeof(pthread_rwlockattr_t)); | |
pthread_mutexattr_t* mutex_attr; | |
mutex_attr = malloc(sizeof(pthread_mutexattr_t)); | |
result = pthread_rwlockattr_init(attr); | |
if(result == ENOMEM) { | |
apc_error("pthread rwlock error: Insufficient memory exists to create the rwlock attribute object." TSRMLS_CC); | |
} else if(result == EINVAL) { | |
apc_error("pthread rwlock error: attr does not point to writeable memory." TSRMLS_CC); | |
} else if(result == EFAULT) { | |
apc_error("pthread rwlock error: attr is an invalid pointer." TSRMLS_CC); | |
} | |
#ifdef __USE_UNIX98 | |
pthread_rwlockattr_setkind_np(attr, PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP); | |
#endif | |
result = pthread_rwlockattr_setpshared(attr, PTHREAD_PROCESS_SHARED); | |
if(result == EINVAL) { | |
apc_error("pthread rwlock error: attr is not an initialized rwlock attribute object, or pshared is not a valid process-shared state setting." TSRMLS_CC); | |
} else if(result == EFAULT) { | |
apc_error("pthread rwlock error: attr is an invalid pointer." TSRMLS_CC); | |
} else if(result == ENOTSUP) { | |
apc_error("pthread rwlock error: pshared was set to PTHREAD_PROCESS_SHARED." TSRMLS_CC); | |
} | |
if(pthread_rwlock_init(&lock->rwlock, attr)) { | |
apc_error("unable to initialize pthread rwlock" TSRMLS_CC); | |
} | |
/* initialize upgrade mutex lock */ | |
result = pthread_mutexattr_init(mutex_attr); | |
if(result == ENOMEM) { | |
apc_error("pthread mutex error: Insufficient memory exists to create the mutex attribute object." TSRMLS_CC); | |
} else if(result == EINVAL) { | |
apc_error("pthread mutex error: attr does not point to writeable memory." TSRMLS_CC); | |
} else if(result == EFAULT) { | |
apc_error("pthread mutex error: attr is an invalid pointer." TSRMLS_CC); | |
} | |
#ifdef PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP | |
result = pthread_mutexattr_settype(mutex_attr, PTHREAD_MUTEX_ADAPTIVE_NP); | |
if (result == EINVAL) { | |
apc_error("pthread_mutexattr_settype: unable to set adaptive mutexes" TSRMLS_CC); | |
} | |
#endif | |
/* pthread_mutexattr_settype(attr, PTHREAD_MUTEX_ERRORCHECK); */ | |
result = pthread_mutexattr_setpshared(mutex_attr, PTHREAD_PROCESS_SHARED); | |
if(result == EINVAL) { | |
apc_error("pthread mutex error: attr is not an initialized mutex attribute object, or pshared is not a valid process-shared state setting." TSRMLS_CC); | |
} else if(result == EFAULT) { | |
apc_error("pthread mutex error: attr is an invalid pointer." TSRMLS_CC); | |
} else if(result == ENOTSUP) { | |
apc_error("pthread mutex error: pshared was set to PTHREAD_PROCESS_SHARED." TSRMLS_CC); | |
} | |
if(pthread_mutex_init(&lock->mutex, mutex_attr)) { | |
apc_error("unable to initialize pthread lock" TSRMLS_CC); | |
} | |
return lock; | |
} | |
void apc_pthreadulock_destroy(pthread_ulock_t *lock) | |
{ | |
return; /* we don't actually destroy the rwlock, as it would destroy it for all processes */ | |
} | |
void apc_pthreadulock_lock(pthread_ulock_t *lock TSRMLS_DC) | |
{ | |
int result; | |
if(pthread_mutex_lock(&lock->mutex) == 0) { | |
result = pthread_rwlock_wrlock(&lock->rwlock); | |
if(result == EINVAL) { | |
apc_error("unable to obtain pthread wrlock (EINVAL)" TSRMLS_CC); | |
} else if(result == EDEADLK) { | |
apc_error("unable to obtain pthread wrlock (EDEADLK)" TSRMLS_CC); | |
} | |
pthread_mutex_unlock(&lock->mutex); | |
} | |
} | |
void apc_pthreadulock_rdlock(pthread_ulock_t *lock TSRMLS_DC) | |
{ | |
int result; | |
result = pthread_rwlock_rdlock(&lock->rwlock); | |
if(result == EINVAL) { | |
apc_error("unable to obtain pthread lock (EINVAL)" TSRMLS_CC); | |
} else if(result == EDEADLK) { | |
apc_error("unable to obtain pthread lock (EDEADLK)" TSRMLS_CC); | |
} | |
} | |
void apc_pthreadulock_unlock(pthread_ulock_t *lock TSRMLS_DC) | |
{ | |
if(pthread_rwlock_unlock(&lock->rwlock)) { | |
apc_error("unable to unlock pthread lock" TSRMLS_CC); | |
} | |
} | |
zend_bool apc_pthreadulock_nonblocking_lock(pthread_ulock_t *lock TSRMLS_DC) | |
{ | |
int rval; | |
if(pthread_mutex_trylock(&lock->mutex) == 0) { | |
rval = pthread_rwlock_trywrlock(&lock->rwlock); | |
pthread_mutex_unlock(&lock->mutex); | |
if(rval == EBUSY) { /* Lock is already held */ | |
return 0; | |
} else if(rval == 0) { /* Obtained lock */ | |
return 1; | |
} else { /* Other error */ | |
apc_error("unable to obtain pthread trylock" TSRMLS_CC); | |
return 0; | |
} | |
} | |
return 0; | |
} | |
zend_bool apc_pthreadulock_tryupgrade(pthread_ulock_t *lock TSRMLS_DC) | |
{ | |
int result; | |
if(pthread_mutex_trylock(&lock->mutex) == 0) { | |
if(pthread_rwlock_unlock(&lock->rwlock)) { | |
apc_error("unable to upgrade read lock" TSRMLS_CC); | |
} | |
result = pthread_rwlock_wrlock(&lock->rwlock); | |
if(result == EINVAL) { | |
apc_error("unable to upgrade to wrlock (EINVAL)" TSRMLS_CC); | |
} else if(result == EDEADLK) { | |
apc_error("unable to upgrade to wrlock (EDEADLK)" TSRMLS_CC); | |
} | |
pthread_mutex_unlock(&lock->mutex); | |
} | |
return 0; | |
} | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <pthread.h> | |
typedef struct _pthread_ulock_t { | |
unsigned :0; | |
pthread_mutex_t mutex; | |
unsigned :0; | |
pthread_rwlock_t rwlock; | |
} pthread_ulock_t; | |
pthread_ulock_t *apc_pthreadulock_create(pthread_ulock_t *lock TSRMLS_DC); | |
void apc_pthreadulock_destroy(pthread_ulock_t *lock); | |
void apc_pthreadulock_lock(pthread_ulock_t *lock TSRMLS_DC); | |
void apc_pthreadulock_rdlock(pthread_ulock_t *lock TSRMLS_DC); | |
void apc_pthreadulock_unlock(pthread_ulock_t *lock TSRMLS_DC); | |
zend_bool apc_pthreadulock_nonblocking_lock(pthread_ulock_t *lock TSRMLS_DC); | |
zend_bool apc_pthreadulock_tryupgrade(pthread_ulock_t *lock TSRMLS_DC); | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment