/* A busy mutex can't be destroyed */ static __attribute__((noinline)) int mutex_ref(pthread_mutex_t *m ) { int r = 0; _spin_lite_lock(&mutex_global); if (!m || !*m) { _spin_lite_unlock(&mutex_global); return EINVAL; } if (STATIC_INITIALIZER(*m)) { _spin_lite_unlock(&mutex_global); r = mutex_static_init(m); _spin_lite_lock(&mutex_global); if (r != 0 && r != EBUSY) { _spin_lite_unlock(&mutex_global); return r; } } r = 0; if (!m || !*m || ((mutex_t *)*m)->valid != LIFE_MUTEX) r = EINVAL; else { ((mutex_t *)*m)->busy ++; } _spin_lite_unlock(&mutex_global); return r; }
static __attribute__((noinline)) int mutex_static_init(pthread_mutex_t *m) { static pthread_mutexattr_t mxattr_recursive = PTHREAD_MUTEX_RECURSIVE; static pthread_mutexattr_t mxattr_errorcheck = PTHREAD_MUTEX_ERRORCHECK; int r; _spin_lite_lock(&mutex_global_static); if (!STATIC_INITIALIZER(*m)) { /* Assume someone crept in between: */ r = 0; } else { if (*m == PTHREAD_MUTEX_INITIALIZER) r = pthread_mutex_init (m, NULL); else if (*m == PTHREAD_RECURSIVE_MUTEX_INITIALIZER) r = pthread_mutex_init (m, &mxattr_recursive); else if (*m == PTHREAD_ERRORCHECK_MUTEX_INITIALIZER) r = pthread_mutex_init (m, &mxattr_errorcheck); else if (*m == NULL) r = EINVAL; else r = pthread_mutex_init(m, NULL); } _spin_lite_unlock(&mutex_global_static); return r; }
static WINPTHREADS_ATTRIBUTE((noinline)) void barrier_ref_set (volatile pthread_barrier_t *barrier, void *v) { _spin_lite_lock(&barrier_global); *barrier = v; _spin_lite_unlock(&barrier_global); }
static __attribute__ ((noinline)) int rwl_unref(volatile pthread_rwlock_t *rwl, int res) { _spin_lite_lock(&rwl_global); #ifdef WINPTHREAD_DBG assert((((rwlock_t *)*rwl)->valid == LIFE_RWLOCK) && (((rwlock_t *)*rwl)->busy > 0)); #endif ((rwlock_t *)*rwl)->busy--; _spin_lite_unlock(&rwl_global); return res; }
static WINPTHREADS_ATTRIBUTE((noinline)) int barrier_unref(volatile pthread_barrier_t *barrier, int res) { _spin_lite_lock(&barrier_global); #ifdef WINPTHREAD_DBG assert((((barrier_t *)*barrier)->valid == LIFE_BARRIER) && (((barrier_t *)*barrier)->busy > 0)); #endif ((barrier_t *)*barrier)->busy--; _spin_lite_unlock(&barrier_global); return res; }
static __attribute__((noinline)) int mutex_ref_init(pthread_mutex_t *m ) { int r = 0; _spin_lite_lock(&mutex_global); if (!m) r = EINVAL; _spin_lite_unlock(&mutex_global); return r; }
static __attribute__((noinline)) int mutex_unref(pthread_mutex_t *m, int r) { mutex_t *m_ = (mutex_t *)*m; _spin_lite_lock(&mutex_global); #ifdef WINPTHREAD_DBG assert((m_->valid == LIFE_MUTEX) && (m_->busy > 0)); #endif m_->busy --; _spin_lite_unlock(&mutex_global); return r; }
static WINPTHREADS_ATTRIBUTE((noinline)) int mutex_ref_init (pthread_mutex_t *m ) { int r = 0; _spin_lite_lock (&mutex_global); if (!m) r = EINVAL; _spin_lite_unlock (&mutex_global); return r; }
static WINPTHREADS_ATTRIBUTE((noinline)) int barrier_ref(volatile pthread_barrier_t *barrier) { int r = 0; _spin_lite_lock(&barrier_global); if (!barrier || !*barrier || ((barrier_t *)*barrier)->valid != LIFE_BARRIER) r = EINVAL; else { ((barrier_t *)*barrier)->busy ++; } _spin_lite_unlock(&barrier_global); return r; }
static __attribute__((noinline)) int rwlock_static_init(pthread_rwlock_t *rw) { int r; _spin_lite_lock(&cond_locked); if (*rw != PTHREAD_RWLOCK_INITIALIZER) { _spin_lite_unlock(&cond_locked); return EINVAL; } r = pthread_rwlock_init (rw, NULL); _spin_lite_unlock(&cond_locked); return r; }
static __attribute__((noinline)) int rwl_ref(pthread_rwlock_t *rwl, int f ) { int r = 0; INIT_RWLOCK(rwl); _spin_lite_lock(&rwl_global); if (!rwl || !*rwl || ((rwlock_t *)*rwl)->valid != LIFE_RWLOCK) r = EINVAL; else { ((rwlock_t *)*rwl)->busy ++; } _spin_lite_unlock(&rwl_global); return r; }
static __attribute__((noinline)) int rwl_ref_unlock(pthread_rwlock_t *rwl ) { int r = 0; _spin_lite_lock(&rwl_global); if (!rwl || !*rwl || ((rwlock_t *)*rwl)->valid != LIFE_RWLOCK) r = EINVAL; else if (STATIC_RWL_INITIALIZER(*rwl)) r= EPERM; else { ((rwlock_t *)*rwl)->busy ++; } _spin_lite_unlock(&rwl_global); return r; }
static inline int spinlock_static_init (pthread_spinlock_t *l) { int ret; _spin_lite_lock(&spin_locked); if (PTHREAD_SPINLOCK_INITIALIZER != *l) { /* Check that somebody called destroy already. Otherwise assume someone crept in between. */ ret = (*l == NULL ? EINVAL : 0); } else { ret = pthread_spin_init(l, PTHREAD_PROCESS_PRIVATE); } _spin_lite_unlock(&spin_locked); return ret; }
/* An unlock can simply fail with EPERM instead of auto-init (can't be owned) */ static WINPTHREADS_ATTRIBUTE((noinline)) int mutex_ref_unlock (pthread_mutex_t *m) { int r = 0; mutex_t *m_ = (mutex_t *)*m; _spin_lite_lock (&mutex_global); if (!m || !*m || ((mutex_t *)*m)->valid != LIFE_MUTEX) r = EINVAL; else if (STATIC_INITIALIZER(*m) || !COND_LOCKED(m_)) r = EPERM; else ((mutex_t *)*m)->busy ++; _spin_lite_unlock (&mutex_global); return r; }
/* An unlock can simply fail with EPERM instead of auto-init (can't be owned) */ static __attribute__((noinline)) int mutex_ref_unlock(pthread_mutex_t *m) { int r = 0; mutex_t *m_ = (mutex_t *)*m; _spin_lite_lock(&mutex_global); if (!m || !*m || ((mutex_t *)*m)->valid != LIFE_MUTEX) r = EINVAL; else if (STATIC_INITIALIZER(*m) || !COND_LOCKED(m_)) { r= EPERM; } else { ((mutex_t *)*m)->busy ++; } _spin_lite_unlock(&mutex_global); return r; }
int pthread_rwlock_destroy (pthread_rwlock_t *rwlock_) { rwlock_t *rwlock; pthread_rwlock_t rDestroy; int r, r2; _spin_lite_lock(&cond_locked); r = rwl_ref_destroy(rwlock_,&rDestroy); _spin_lite_unlock(&cond_locked); if(r) return r; if(!rDestroy) return 0; /* destroyed a (still) static initialized rwl */ rwlock = (rwlock_t *)rDestroy; r = rwlock_gain_both_locks (rwlock); if (r != 0) { *rwlock_ = rDestroy; return r; } if (rwlock->nsh_count > rwlock->ncomplete || rwlock->nex_count > 0) { *rwlock_ = rDestroy; r = rwlock_free_both_locks(rwlock, 1); if (!r) r = EBUSY; return r; } rwlock->valid = DEAD_RWLOCK; r = rwlock_free_both_locks(rwlock, 0); if (r != 0) { *rwlock_ = rDestroy; return r; } r = pthread_cond_destroy(&rwlock->ccomplete); r2 = pthread_mutex_destroy(&rwlock->mex); if (!r) r = r2; r2 = pthread_mutex_destroy(&rwlock->mcomplete); if (!r) r = r2; rwlock->valid = DEAD_RWLOCK; free(rDestroy); return 0; }
int pthread_spin_destroy(pthread_spinlock_t *l) { spin_t *_l; if (!l || !*l) return EINVAL; _spin_lite_lock(&spin_locked); if (*l == PTHREAD_SPINLOCK_INITIALIZER) { *l = NULL; _spin_lite_unlock(&spin_locked); return 0; } _spin_lite_unlock(&spin_locked); _l = (spin_t *)*l; if (((spin_t *)(*l))->valid != (unsigned int)LIFE_SPINLOCK) return EINVAL; if (_l->l != 0) return EBUSY; *l= NULL; /* dereference first, free later */ _l->valid = DEAD_SPINLOCK; _l->l = 0; free(_l); return 0; }