int _pthread_barrier_wait(pthread_barrier_t *barrier) { struct pthread *curthread = _get_curthread(); pthread_barrier_t bar; int64_t cycle; int ret; if (barrier == NULL || *barrier == NULL) return (EINVAL); bar = *barrier; THR_UMUTEX_LOCK(curthread, &bar->b_lock); if (++bar->b_waiters == bar->b_count) { /* Current thread is lastest thread */ bar->b_waiters = 0; bar->b_cycle++; _thr_ucond_broadcast(&bar->b_cv); THR_UMUTEX_UNLOCK(curthread, &bar->b_lock); ret = PTHREAD_BARRIER_SERIAL_THREAD; } else { cycle = bar->b_cycle; bar->b_refcount++; do { _thr_ucond_wait(&bar->b_cv, &bar->b_lock, NULL, 0); THR_UMUTEX_LOCK(curthread, &bar->b_lock); /* test cycle to avoid bogus wakeup */ } while (cycle == bar->b_cycle); if (--bar->b_refcount == 0 && bar->b_destroying) _thr_ucond_broadcast(&bar->b_cv); THR_UMUTEX_UNLOCK(curthread, &bar->b_lock); ret = 0; } return (ret); }
int _pthread_barrier_destroy(pthread_barrier_t *barrier) { pthread_barrier_t bar; struct pthread *curthread; int pshared; if (barrier == NULL || *barrier == NULL) return (EINVAL); if (*barrier == THR_PSHARED_PTR) { bar = __thr_pshared_offpage(barrier, 0); if (bar == NULL) { *barrier = NULL; return (0); } pshared = 1; } else { bar = *barrier; pshared = 0; } curthread = _get_curthread(); THR_UMUTEX_LOCK(curthread, &bar->b_lock); if (bar->b_destroying) { THR_UMUTEX_UNLOCK(curthread, &bar->b_lock); return (EBUSY); } bar->b_destroying = 1; do { if (bar->b_waiters > 0) { bar->b_destroying = 0; THR_UMUTEX_UNLOCK(curthread, &bar->b_lock); return (EBUSY); } if (bar->b_refcount != 0) { _thr_ucond_wait(&bar->b_cv, &bar->b_lock, NULL, 0); THR_UMUTEX_LOCK(curthread, &bar->b_lock); } else break; } while (1); bar->b_destroying = 0; THR_UMUTEX_UNLOCK(curthread, &bar->b_lock); *barrier = NULL; if (pshared) __thr_pshared_destroy(barrier); else free(bar); return (0); }
void _spinunlock(spinlock_t *lck) { struct spinlock_extra *_extra; _extra = (struct spinlock_extra *)lck->fname; THR_UMUTEX_UNLOCK(_get_curthread(), &_extra->lock); }
void __thr_spinunlock(spinlock_t *lck) { struct spinlock_extra *_extra; _extra = lck->thr_extra; THR_UMUTEX_UNLOCK(_get_curthread(), &_extra->lock); }
int _pthread_spin_unlock(pthread_spinlock_t *lock) { struct pthread_spinlock *lck; if (lock == NULL) return (EINVAL); lck = *lock == THR_PSHARED_PTR ? __thr_pshared_offpage(lock, 0) : *lock; if (lck == NULL) return (EINVAL); return (THR_UMUTEX_UNLOCK(_get_curthread(), &lck->s_lock)); }
void _thr_report_death(struct pthread *curthread) { curthread->event_buf.event = TD_DEATH; curthread->event_buf.th_p = (uintptr_t)curthread; curthread->event_buf.data = 0; THR_UMUTEX_LOCK(curthread, &_thr_event_lock); _thread_last_event = curthread; _thread_bp_death(); _thread_last_event = NULL; THR_UMUTEX_UNLOCK(curthread, &_thr_event_lock); }
void _thr_report_creation(struct pthread *curthread, struct pthread *newthread) { curthread->event_buf.event = TD_CREATE; curthread->event_buf.th_p = (uintptr_t)newthread; curthread->event_buf.data = 0; THR_UMUTEX_LOCK(curthread, &_thr_event_lock); _thread_last_event = curthread; _thread_bp_create(); _thread_last_event = NULL; THR_UMUTEX_UNLOCK(curthread, &_thr_event_lock); }
int _pthread_spin_unlock(pthread_spinlock_t *lock) { struct pthread *curthread = _get_curthread(); struct pthread_spinlock *lck; int ret; if (lock == NULL || (lck = *lock) == NULL) ret = EINVAL; else { ret = THR_UMUTEX_UNLOCK(curthread, &lck->s_lock); } return (ret); }
int _pthread_barrier_destroy(pthread_barrier_t *barrier) { pthread_barrier_t bar; struct pthread *curthread; if (barrier == NULL || *barrier == NULL) return (EINVAL); curthread = _get_curthread(); bar = *barrier; THR_UMUTEX_LOCK(curthread, &bar->b_lock); if (bar->b_destroying) { THR_UMUTEX_UNLOCK(curthread, &bar->b_lock); return (EBUSY); } bar->b_destroying = 1; do { if (bar->b_waiters > 0) { bar->b_destroying = 0; THR_UMUTEX_UNLOCK(curthread, &bar->b_lock); return (EBUSY); } if (bar->b_refcount != 0) { _thr_ucond_wait(&bar->b_cv, &bar->b_lock, NULL, 0); THR_UMUTEX_LOCK(curthread, &bar->b_lock); } else break; } while (1); bar->b_destroying = 0; THR_UMUTEX_UNLOCK(curthread, &bar->b_lock); *barrier = NULL; free(bar); return (0); }
static void init_spinlock(spinlock_t *lck) { struct pthread *curthread = _get_curthread(); THR_UMUTEX_LOCK(curthread, &spinlock_static_lock); if ((lck->thr_extra == NULL) && (spinlock_count < MAX_SPINLOCKS)) { lck->thr_extra = &extra[spinlock_count]; _thr_umutex_init(&extra[spinlock_count].lock); extra[spinlock_count].owner = lck; spinlock_count++; } THR_UMUTEX_UNLOCK(curthread, &spinlock_static_lock); if (lck->thr_extra == NULL) PANIC("Warning: exceeded max spinlocks"); }