$NetBSD: patch-ah,v 1.4 2008/10/28 11:32:07 markd Exp $ --- mcop_mt/threads_posix.cc.orig 2005-09-10 20:13:32.000000000 +1200 +++ mcop_mt/threads_posix.cc @@ -27,13 +27,158 @@ /* only compile this if we have libpthread available */ #ifdef HAVE_LIBPTHREAD +#include #include #include #include #include #include +#include +#ifdef _POSIX_SEMAPHORES #include +#else + +#include +#include + +struct sem_t { + pthread_mutex_t lock; + pthread_cond_t gtzero; + unsigned int count; + unsigned int nwaiters; +}; + +static int sem_init(sem_t *, int, unsigned int); +static int sem_destroy(sem_t *); +static int sem_wait(sem_t *); +static int sem_trywait(sem_t *); +static int sem_post(sem_t *); +static int sem_getvalue(sem_t *, int *); + +static int +sem_init(sem_t *sem, int pshared, unsigned int value) +{ + + /* + * Range check the arguments. + */ + if (pshared != 0) { + errno = EPERM; + return -1; + } + + if (value > INT_MAX) { + errno = EINVAL; + return -1; + } + + /* + * Initialize the semaphore. + */ + if (pthread_mutex_init(&sem->lock, NULL) != 0) { + errno = ENOMEM; + return -1; + } + + if (pthread_cond_init(&sem->gtzero, NULL) != 0) { + pthread_mutex_destroy(&sem->lock); + errno = ENOMEM; + return -1; + } + + sem->count = value; + sem->nwaiters = 0; + + return 0; +} + +static int +sem_destroy(sem_t *sem) +{ + + /* Make sure there are no waiters. */ + pthread_mutex_lock(&sem->lock); + if (sem->nwaiters > 0) { + pthread_mutex_unlock(&sem->lock); + errno = EBUSY; + return -1; + } + pthread_mutex_unlock(&sem->lock); + + pthread_mutex_destroy(&sem->lock); + pthread_cond_destroy(&sem->gtzero); + + return 0; +} + +static int +sem_wait(sem_t *sem) +{ + pthread_testcancel(); + + pthread_mutex_lock(&sem->lock); + + while (sem->count == 0) { + sem->nwaiters++; + pthread_cond_wait(&sem->gtzero, &sem->lock); + } + sem->count--; + + pthread_mutex_unlock(&sem->lock); + + pthread_testcancel(); + return 0; +} + +static int +sem_trywait(sem_t *sem) +{ + int retval; + + pthread_mutex_lock(&sem->lock); + + if (sem->count > 0) { + sem->count--; + retval = 0; + } else { + errno = EAGAIN; + retval = -1; + } + + pthread_mutex_unlock(&sem->lock); + + return retval; +} + +static int +sem_post(sem_t *sem) +{ + pthread_mutex_lock(&sem->lock); + + sem->count++; + if (sem->nwaiters > 0) { + pthread_cond_broadcast(&sem->gtzero); + } + + pthread_mutex_unlock(&sem->lock); + + return 0; +} + +static int +sem_getvalue(sem_t *sem, int *sval) +{ + + pthread_mutex_lock(&sem->lock); + *sval = sem->count; + pthread_mutex_unlock(&sem->lock); + + return 0; +} +#endif + + #include #include @@ -186,10 +331,12 @@ public: Thread_impl(Thread *thread) : thread(thread) { } void setPriority(int priority) { +#ifdef _POSIX_THREAD_PRIORITY_SCHEDULING struct sched_param sp; sp.sched_priority = priority; if (pthread_setschedparam(pthread, SCHED_FIFO, &sp)) arts_debug("Thread::setPriority: sched_setscheduler failed"); +#endif } static pthread_key_t privateDataKey; static void *threadStartInternal(void *impl)