For errors, return -1 and set errno to indicate the error type, rather than

returning the error directly.

For sem_post(), make sure that the correct thread is woken up.  This has
unfortunate performance implications, but is necessary for POSIX compliance.

Approved by:	jkh
This commit is contained in:
Jason Evans 2000-02-16 19:34:53 +00:00
parent b0a1b4f809
commit 8a668b9049
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=57261
3 changed files with 99 additions and 48 deletions

View File

@ -37,7 +37,8 @@
#define _SEM_CHECK_VALIDITY(sem) \
if ((*(sem))->magic != SEM_MAGIC) { \
retval = EINVAL; \
errno = EINVAL; \
retval = -1; \
goto RETURN; \
}
@ -55,34 +56,39 @@ sem_init(sem_t *sem, int pshared, unsigned int value)
* processes, which this implementation can't do. Sounds like a
* permissions problem to me (yeah right).
*/
retval = EPERM;
errno = EPERM;
retval = -1;
goto RETURN;
}
if (value > SEM_VALUE_MAX) {
retval = EINVAL;
errno = EINVAL;
retval = -1;
goto RETURN;
}
*sem = (sem_t)malloc(sizeof(struct sem));
if (*sem == NULL) {
retval = ENOSPC;
errno = ENOSPC;
retval = -1;
goto RETURN;
}
/*
* Initialize the semaphore.
*/
retval = pthread_mutex_init(&(*sem)->lock, NULL);
if (retval != 0) {
if (pthread_mutex_init(&(*sem)->lock, NULL) != 0) {
free(*sem);
errno = ENOSPC;
retval = -1;
goto RETURN;
}
retval = pthread_cond_init(&(*sem)->gtzero, NULL);
if (retval != 0) {
if (pthread_cond_init(&(*sem)->gtzero, NULL) != 0) {
pthread_mutex_destroy(&(*sem)->lock);
free(*sem);
errno = ENOSPC;
retval = -1;
goto RETURN;
}
@ -90,6 +96,7 @@ sem_init(sem_t *sem, int pshared, unsigned int value)
(*sem)->nwaiters = 0;
(*sem)->magic = SEM_MAGIC;
retval = 0;
RETURN:
return retval;
}
@ -105,7 +112,8 @@ sem_destroy(sem_t *sem)
pthread_mutex_lock(&(*sem)->lock);
if ((*sem)->nwaiters > 0) {
pthread_mutex_unlock(&(*sem)->lock);
retval = EBUSY;
errno = EBUSY;
retval = -1;
goto RETURN;
}
pthread_mutex_unlock(&(*sem)->lock);
@ -122,7 +130,7 @@ sem_destroy(sem_t *sem)
}
sem_t *
sem_open(const char * name, int oflag, ...)
sem_open(const char *name, int oflag, ...)
{
errno = ENOSYS;
return SEM_FAILED;
@ -146,7 +154,7 @@ int
sem_wait(sem_t *sem)
{
int retval;
_thread_enter_cancellation_point();
_SEM_CHECK_VALIDITY(sem);
@ -180,9 +188,11 @@ sem_trywait(sem_t *sem)
if ((*sem)->count > 0) {
(*sem)->count--;
retval = 0;
} else
retval = EAGAIN;
} else {
errno = EAGAIN;
retval = -1;
}
pthread_mutex_unlock(&(*sem)->lock);
RETURN:
@ -199,8 +209,15 @@ sem_post(sem_t *sem)
pthread_mutex_lock(&(*sem)->lock);
(*sem)->count++;
if ((*sem)->nwaiters > 0)
pthread_cond_signal(&(*sem)->gtzero);
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);

View File

@ -37,7 +37,8 @@
#define _SEM_CHECK_VALIDITY(sem) \
if ((*(sem))->magic != SEM_MAGIC) { \
retval = EINVAL; \
errno = EINVAL; \
retval = -1; \
goto RETURN; \
}
@ -55,34 +56,39 @@ sem_init(sem_t *sem, int pshared, unsigned int value)
* processes, which this implementation can't do. Sounds like a
* permissions problem to me (yeah right).
*/
retval = EPERM;
errno = EPERM;
retval = -1;
goto RETURN;
}
if (value > SEM_VALUE_MAX) {
retval = EINVAL;
errno = EINVAL;
retval = -1;
goto RETURN;
}
*sem = (sem_t)malloc(sizeof(struct sem));
if (*sem == NULL) {
retval = ENOSPC;
errno = ENOSPC;
retval = -1;
goto RETURN;
}
/*
* Initialize the semaphore.
*/
retval = pthread_mutex_init(&(*sem)->lock, NULL);
if (retval != 0) {
if (pthread_mutex_init(&(*sem)->lock, NULL) != 0) {
free(*sem);
errno = ENOSPC;
retval = -1;
goto RETURN;
}
retval = pthread_cond_init(&(*sem)->gtzero, NULL);
if (retval != 0) {
if (pthread_cond_init(&(*sem)->gtzero, NULL) != 0) {
pthread_mutex_destroy(&(*sem)->lock);
free(*sem);
errno = ENOSPC;
retval = -1;
goto RETURN;
}
@ -90,6 +96,7 @@ sem_init(sem_t *sem, int pshared, unsigned int value)
(*sem)->nwaiters = 0;
(*sem)->magic = SEM_MAGIC;
retval = 0;
RETURN:
return retval;
}
@ -105,7 +112,8 @@ sem_destroy(sem_t *sem)
pthread_mutex_lock(&(*sem)->lock);
if ((*sem)->nwaiters > 0) {
pthread_mutex_unlock(&(*sem)->lock);
retval = EBUSY;
errno = EBUSY;
retval = -1;
goto RETURN;
}
pthread_mutex_unlock(&(*sem)->lock);
@ -122,7 +130,7 @@ sem_destroy(sem_t *sem)
}
sem_t *
sem_open(const char * name, int oflag, ...)
sem_open(const char *name, int oflag, ...)
{
errno = ENOSYS;
return SEM_FAILED;
@ -146,7 +154,7 @@ int
sem_wait(sem_t *sem)
{
int retval;
_thread_enter_cancellation_point();
_SEM_CHECK_VALIDITY(sem);
@ -180,9 +188,11 @@ sem_trywait(sem_t *sem)
if ((*sem)->count > 0) {
(*sem)->count--;
retval = 0;
} else
retval = EAGAIN;
} else {
errno = EAGAIN;
retval = -1;
}
pthread_mutex_unlock(&(*sem)->lock);
RETURN:
@ -199,8 +209,15 @@ sem_post(sem_t *sem)
pthread_mutex_lock(&(*sem)->lock);
(*sem)->count++;
if ((*sem)->nwaiters > 0)
pthread_cond_signal(&(*sem)->gtzero);
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);

View File

@ -37,7 +37,8 @@
#define _SEM_CHECK_VALIDITY(sem) \
if ((*(sem))->magic != SEM_MAGIC) { \
retval = EINVAL; \
errno = EINVAL; \
retval = -1; \
goto RETURN; \
}
@ -55,34 +56,39 @@ sem_init(sem_t *sem, int pshared, unsigned int value)
* processes, which this implementation can't do. Sounds like a
* permissions problem to me (yeah right).
*/
retval = EPERM;
errno = EPERM;
retval = -1;
goto RETURN;
}
if (value > SEM_VALUE_MAX) {
retval = EINVAL;
errno = EINVAL;
retval = -1;
goto RETURN;
}
*sem = (sem_t)malloc(sizeof(struct sem));
if (*sem == NULL) {
retval = ENOSPC;
errno = ENOSPC;
retval = -1;
goto RETURN;
}
/*
* Initialize the semaphore.
*/
retval = pthread_mutex_init(&(*sem)->lock, NULL);
if (retval != 0) {
if (pthread_mutex_init(&(*sem)->lock, NULL) != 0) {
free(*sem);
errno = ENOSPC;
retval = -1;
goto RETURN;
}
retval = pthread_cond_init(&(*sem)->gtzero, NULL);
if (retval != 0) {
if (pthread_cond_init(&(*sem)->gtzero, NULL) != 0) {
pthread_mutex_destroy(&(*sem)->lock);
free(*sem);
errno = ENOSPC;
retval = -1;
goto RETURN;
}
@ -90,6 +96,7 @@ sem_init(sem_t *sem, int pshared, unsigned int value)
(*sem)->nwaiters = 0;
(*sem)->magic = SEM_MAGIC;
retval = 0;
RETURN:
return retval;
}
@ -105,7 +112,8 @@ sem_destroy(sem_t *sem)
pthread_mutex_lock(&(*sem)->lock);
if ((*sem)->nwaiters > 0) {
pthread_mutex_unlock(&(*sem)->lock);
retval = EBUSY;
errno = EBUSY;
retval = -1;
goto RETURN;
}
pthread_mutex_unlock(&(*sem)->lock);
@ -122,7 +130,7 @@ sem_destroy(sem_t *sem)
}
sem_t *
sem_open(const char * name, int oflag, ...)
sem_open(const char *name, int oflag, ...)
{
errno = ENOSYS;
return SEM_FAILED;
@ -146,7 +154,7 @@ int
sem_wait(sem_t *sem)
{
int retval;
_thread_enter_cancellation_point();
_SEM_CHECK_VALIDITY(sem);
@ -180,9 +188,11 @@ sem_trywait(sem_t *sem)
if ((*sem)->count > 0) {
(*sem)->count--;
retval = 0;
} else
retval = EAGAIN;
} else {
errno = EAGAIN;
retval = -1;
}
pthread_mutex_unlock(&(*sem)->lock);
RETURN:
@ -199,8 +209,15 @@ sem_post(sem_t *sem)
pthread_mutex_lock(&(*sem)->lock);
(*sem)->count++;
if ((*sem)->nwaiters > 0)
pthread_cond_signal(&(*sem)->gtzero);
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);