int xp_sem_timedwait(xp_sem_t *sem, const struct timespec *abs_timeout) { int retval=0; _SEM_CHECK_VALIDITY(sem); pthread_mutex_lock(&(*sem)->lock); while ((*sem)->count == 0) { (*sem)->nwaiters++; retval=pthread_cond_timedwait(&(*sem)->gtzero, &(*sem)->lock, abs_timeout); (*sem)->nwaiters--; if(retval) { errno=retval; retval=-1; break; } } if(retval==0) (*sem)->count--; pthread_mutex_unlock(&(*sem)->lock); RETURN: return retval; }
int xp_sem_post(xp_sem_t *sem) { int retval; _SEM_CHECK_VALIDITY(sem); pthread_mutex_lock(&(*sem)->lock); (*sem)->count++; if ((*sem)->nwaiters > 0) { /* * We must use pthread_cond_broadcast() rather than * pthread_cond_signal() in order to assure that the highest * priority thread is run by the scheduler, since * pthread_cond_signal() signals waiting threads in FIFO order. */ pthread_cond_broadcast(&(*sem)->gtzero); } pthread_mutex_unlock(&(*sem)->lock); retval = 0; RETURN: return retval; }
int xp_sem_destroy(xp_sem_t *sem) { int retval; _SEM_CHECK_VALIDITY(sem); /* Make sure there are no waiters. */ pthread_mutex_lock(&(*sem)->lock); if ((*sem)->nwaiters > 0) { pthread_mutex_unlock(&(*sem)->lock); errno = EBUSY; retval = -1; goto RETURN; } pthread_mutex_unlock(&(*sem)->lock); while(pthread_mutex_destroy(&(*sem)->lock)==EBUSY) SLEEP(1); while(pthread_cond_destroy(&(*sem)->gtzero)==EBUSY) SLEEP(1); (*sem)->magic = 0; free(*sem); retval = 0; RETURN: return retval; }
int _sem_post(sem_t *sem) { int retval; _SEM_CHECK_VALIDITY(sem); /* * sem_post() is required to be safe to call from within signal * handlers. Thus, we must defer signals. */ _thread_kern_sig_defer(); pthread_mutex_lock(&(*sem)->lock); (*sem)->count++; if ((*sem)->nwaiters > 0) pthread_cond_signal(&(*sem)->gtzero); pthread_mutex_unlock(&(*sem)->lock); _thread_kern_sig_undefer(); retval = 0; RETURN: return retval; }
int _sem_wait(sem_t *sem) { int retval; _thread_enter_cancellation_point(); _SEM_CHECK_VALIDITY(sem); pthread_mutex_lock(&(*sem)->lock); while ((*sem)->count == 0) { (*sem)->nwaiters++; pthread_cond_wait(&(*sem)->gtzero, &(*sem)->lock); (*sem)->nwaiters--; } (*sem)->count--; pthread_mutex_unlock(&(*sem)->lock); retval = 0; RETURN: _thread_leave_cancellation_point(); return retval; }
int sem_wait(sem_t *sem) { int retval; pthread_testcancel(); _SEM_CHECK_VALIDITY(sem); pthread_mutex_lock(&(*sem)->lock); while ((*sem)->count == 0) { (*sem)->nwaiters++; pthread_cond_wait(&(*sem)->gtzero, &(*sem)->lock); (*sem)->nwaiters--; } (*sem)->count--; pthread_mutex_unlock(&(*sem)->lock); retval = 0; RETURN: pthread_testcancel(); return retval; }
int xp_sem_getvalue(xp_sem_t *sem, int *sval) { int retval; _SEM_CHECK_VALIDITY(sem); pthread_mutex_lock(&(*sem)->lock); *sval = (int)(*sem)->count; pthread_mutex_unlock(&(*sem)->lock); retval = 0; RETURN: return retval; }
int xp_sem_trywait(xp_sem_t *sem) { int retval; _SEM_CHECK_VALIDITY(sem); pthread_mutex_lock(&(*sem)->lock); if ((*sem)->count > 0) { (*sem)->count--; retval = 0; } else { errno = EAGAIN; retval = -1; } pthread_mutex_unlock(&(*sem)->lock); RETURN: return retval; }