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;
+}

Reply via email to