On Wed, Nov 06, 2002 at 08:59:30PM -0500, Neal H. Walfield wrote:
> > I tried to make it return errno and be async-cancel resistant.
>
> Why do you want it to be async-cancel resistant? The functions are
> not defined as being async-cancel safe; only pthread_cancel,
> pthread_setcancelstate and pthread_setcanceltype are.
I see, async cancellation is even uglier than I thught..
>
> > Anyway the header should be basically the same, just the implementation
> > changes a bit.
>
> The macros are incredibly ugly; please remove them. Your code does
removed the uglier part
> not conform to the GNU coding standards; this will have to be fixed.
> You did not implement most of my suggestions in my previous emails on
> this subject.
It was intended as an improvemenet of the previos code, not complete rewrite :)
The nice part about this implementation is
- you have priorities handled in the condition (perhaps __thread_wakeup does
it too, I do not know)
- it can be used anywhere (modulo cancellation modes) not only on the Hurd :)
Of cource, it's probably slow.
I do not understand what is exported about the mutex_t.
The bits/semaphore.h is not easy to attach, had to change to diff for that.
--
Michal Suchanek
[EMAIL PROTECTED]
diff -Nur -x CVS libpthread.org/Makefile libpthread/Makefile
--- libpthread.org/Makefile 2002-10-11 01:05:06.000000000 +0200
+++ libpthread/Makefile 2002-11-07 13:04:22.000000000 +0100
@@ -120,6 +120,8 @@
\
pt-getschedparam.c pt-setschedparam.c pt-setschedprio.c \
\
+ semaphore.c \
+ \
cthreads-compat.c \
$(SYSDEPS)
@@ -131,7 +133,9 @@
sysdeps_headers = \
pthread.h \
+ semaphore.h \
pthread/pthread.h \
+ bits/semaphore.h \
\
bits/pthread.h \
bits/mutex.h \
diff -Nur -x CVS libpthread.org/include/bits/semaphore.h
libpthread/include/bits/semaphore.h
--- libpthread.org/include/bits/semaphore.h 1970-01-01 01:00:00.000000000 +0100
+++ libpthread/include/bits/semaphore.h 2002-11-07 14:02:01.000000000 +0100
@@ -0,0 +1,44 @@
+/* Copyright (C) 2000,02 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Written by Ga�l Le Mignot <[EMAIL PROTECTED]>
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with the GNU C Library; see the file COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+/*
+ * POSIX Threads Extension: Semaphores <semaphore.h>
+ */
+
+#ifndef _BITS_SEMAPHORE_H
+#define _BITS_SEMAPHORE_H 1
+
+#include <pthread.h>
+#include <limits.h>
+
+#define SEM_FAILED NULL
+
+#define SEM_VALUE_MAX (UINT_MAX - 1)
+#define SEM_VALUE_INVALID UINT_MAX
+
+struct __sem_t
+{
+ unsigned int count;
+ pthread_mutex_t count_lock;
+ pthread_cond_t count_cond;
+ char * ID; /* may be used in future to store semaphore name */
+};
+
+#endif /* bits/semaphore.h */
+
diff -Nur -x CVS libpthread.org/include/semaphore.h libpthread/include/semaphore.h
--- libpthread.org/include/semaphore.h 1970-01-01 01:00:00.000000000 +0100
+++ libpthread/include/semaphore.h 2002-11-07 14:04:11.000000000 +0100
@@ -0,0 +1,59 @@
+/* Copyright (C) 2000,02 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Written by Ga�l Le Mignot <[EMAIL PROTECTED]>
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with the GNU C Library; see the file COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+/*
+ * POSIX Threads Extension: Semaphores <semaphore.h>
+ */
+
+#ifndef _SEMAPHORE_H
+#define _SEMAPHORE_H 1
+
+#include <bits/semaphore.h>
+
+
+typedef struct __sem_t sem_t;
+
+__BEGIN_DECLS
+
+/* Initialize the semaphore and set the initial value - as in LinuxThreads
+ pshared must be zero right now. */
+extern int sem_init (sem_t *sem, int pshared, unsigned int value);
+
+/* Destroys the semaphore */
+extern int sem_destroy (sem_t *sem);
+
+/* Wait until the count is > 0, and then decrease it */
+extern int sem_wait (sem_t *sem);
+
+/* Non-blocking variant of sem_wait. Returns -1 if count == 0. */
+extern int sem_trywait (sem_t *sem);
+
+/* Increments the count */
+extern int sem_post (sem_t *sem);
+
+/* Return the value of the semaphore */
+extern int sem_getvalue (sem_t *sem, int *sval);
+
+/* Operate named semaphores - not implemented yet */
+extern int sem_close(sem_t *);
+extern sem_t *sem_open(const char *, int, ...);
+
+__END_DECLS
+
+#endif /* semaphore.h */
diff -Nur -x CVS libpthread.org/semaphore.c libpthread/semaphore.c
--- libpthread.org/semaphore.c 1970-01-01 01:00:00.000000000 +0100
+++ libpthread/semaphore.c 2002-11-07 14:05:38.000000000 +0100
@@ -0,0 +1,202 @@
+/* Copyright (C) 2000,02 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Written by Ga�l Le Mignot <[EMAIL PROTECTED]>
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with the GNU C Library; see the file COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+/*
+ * POSIX Threads Extension: Semaphores <semaphore.c>
+ */
+
+#include <semaphore.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <assert.h>
+
+static void pmut_unlock(void * pmutex) {
+ pthread_mutex_unlock((pthread_mutex_t *)pmutex);
+}
+
+#define pmutex_safe_lock(pmut) \
+{ \
+ int __pmutex_safe_lock_old_state; \
+ pthread_mutex_t *__pmutext_safe_lock_pmut_test = pmut; \
+ pthread_setcanceltype (PTHREAD_CANCEL_DEFERRED, \
+ &__pmutex_safe_lock_old_state); \
+ pthread_cleanup_push (&pmut_unlock, (pmut)); \
+ pthread_mutex_lock (pmut)
+
+#define pmutex_safe_unlock(pmut) \
+ pthread_cleanup_pop (1); \
+ assert (__pmutext_safe_lock_pmut_test == pmut); \
+ pthread_setcanceltype (__pmutex_safe_lock_old_state, NULL); \
+}
+
+/* Initialize the semaphore and set the initial value - as in LinuxThreads
+ pshared must be zero right now. */
+int
+sem_init (sem_t *sem, int pshared, unsigned int value)
+{
+ int res = 0;
+ if (pshared) {
+ errno = ENOTSUP;
+ return -1;
+ }
+ if (value > SEM_VALUE_MAX) {
+ errno = ERANGE;
+ return -1;
+ }
+
+ sem->count = SEM_VALUE_INVALID;
+ sem->ID = NULL;
+ if (pthread_cond_init (&sem->count_cond, NULL))
+ res = -1;
+ else
+ {
+ if(pthread_mutex_init (&sem->count_lock, NULL))
+ {
+ res = -1;
+ pthread_cond_destroy(&sem->count_cond);
+ }
+ else
+ sem->count = value;
+ }
+ return res;
+}
+
+
+/* Destroys the semaphore */
+int
+sem_destroy (sem_t *sem)
+{
+ int res = 0;
+ pthread_mutex_lock (&sem->count_lock);
+ sem->count = SEM_VALUE_INVALID;
+ pthread_cond_broadcast (&sem->count_cond);
+ if (pthread_cond_destroy (&sem->count_cond))
+ res = -1;
+ pthread_mutex_unlock(&sem->count_lock);
+ if (pthread_mutex_destroy (&sem->count_lock))
+ res = -1;
+ return res;
+}
+
+/* Wait until the count is > 0, and then decrease it */
+int
+sem_wait (sem_t *sem)
+{
+ int res = 0;
+ pmutex_safe_lock (&sem->count_lock);
+ if (sem->count == SEM_VALUE_INVALID)
+ {
+ errno = EINVAL;
+ res = -1;
+ }
+ else
+ {
+ while (!sem->count)
+ pthread_cond_wait (&sem->count_cond, &sem->count_lock);
+ if (sem->count == SEM_VALUE_INVALID)
+ {
+ res = -1;
+ errno = EINVAL;
+ }
+ else
+ sem->count--;
+ }
+ pmutex_safe_unlock (&sem->count_lock);
+ return res;
+}
+
+/* Non-blocking variant of sem_wait. Returns -1 if count == 0. */
+int
+sem_trywait (sem_t *sem)
+{
+ int res = 0;
+ pthread_mutex_lock (&sem->count_lock);
+ if (sem->count == SEM_VALUE_INVALID)
+ {
+ res = -1;
+ errno = EINVAL;
+ }
+ else
+ if (sem->count)
+ {
+ sem->count--;
+ }
+ else
+ {
+ res = -1;
+ errno = EAGAIN;
+ }
+ pthread_mutex_unlock (&sem->count_lock);
+ return res;
+}
+
+/* Increments the count */
+int
+sem_post (sem_t *sem)
+{
+ int res = 0;
+ pthread_mutex_lock (&sem->count_lock);
+ if (sem->count == SEM_VALUE_INVALID)
+ {
+ res = -1;
+ errno = EINVAL;
+ }
+ else
+ if (sem->count < SEM_VALUE_MAX)
+ {
+ sem->count++;
+ pthread_cond_signal (&sem->count_cond);
+ }
+ else
+ {
+ errno = ERANGE;
+ res = -1;
+ }
+ pthread_mutex_unlock (&sem->count_lock);
+ return res;
+}
+
+/* Return the value of the semaphore */
+int
+sem_getvalue (sem_t *sem, int *sval)
+{
+ int res = 0;
+ pthread_mutex_lock (&sem->count_lock);
+ if (sem->count == SEM_VALUE_INVALID)
+ {
+ res = -1;
+ errno = EINVAL;
+ }
+ else
+ *sval = sem->count;
+ pthread_mutex_unlock (&sem->count_lock);
+ return res;
+}
+
+sem_t *sem_open(const char * foo, int bar, ...)
+{
+ errno = ENOSYS;
+ return SEM_FAILED;
+}
+
+int sem_close(sem_t * foo)
+{
+ errno = ENOSYS;
+ return -1;
+}