Skip to content

Instantly share code, notes, and snippets.

@t3rmin4t0r
Created December 3, 2010 19:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save t3rmin4t0r/727468 to your computer and use it in GitHub Desktop.
Save t3rmin4t0r/727468 to your computer and use it in GitHub Desktop.
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;
}
#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