summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog16
-rw-r--r--Nmakefile.tests2
-rw-r--r--pthread.h61
-rw-r--r--sem_getvalue.c25
-rw-r--r--sem_init.c75
-rw-r--r--tests/ChangeLog4
-rw-r--r--tests/GNUmakefile3
-rw-r--r--tests/Makefile5
-rw-r--r--tests/semaphore2.c105
9 files changed, 218 insertions, 78 deletions
diff --git a/ChangeLog b/ChangeLog
index 9a2413d..693e04d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,19 @@
+2002-06-03 Ross Johnson <rpj@digit.ise.canberra.edu.au>
+
+ * sem_init.c (sem_init): Initialise Win32 semaphores
+ to _POSIX_SEM_VALUE_MAX (which this implementation
+ defines in pthread.h) so that sem_getvalue() can use
+ the trick described in the comments in sem_getvalue().
+ * pthread.h (_POSIX_SEM_VALUE_MAX): Defined.
+ (_POSIX_SEM_NSEMS_MAX): Defined - not used but may be
+ useful for source code portability.
+
+2002-06-03 Rob Fanner <rfanner@stonethree.com>
+
+ * sem_getvalue.c (sem_getvalue): Did not work on NT.
+ Use approach suggested by Johnson M. Hart in his book
+ "Win32 System Programming".
+
2002-02-28 Ross Johnson <rpj@setup1.ise.canberra.edu.au>
* errno.c: Compiler directive was incorrectly including code.
diff --git a/Nmakefile.tests b/Nmakefile.tests
index 5e1b37a..e914305 100644
--- a/Nmakefile.tests
+++ b/Nmakefile.tests
@@ -86,6 +86,7 @@ rwlock5_t:: rwlock5_t.c
rwlock6_t:: rwlock6_t.c
rwlock6_t2:: rwlock6_t2.c
semaphore1:: semaphore1.c
+semaphore2:: semaphore2.c
context1:: context1.c
cancel3:: cancel3.c
cancel4:: cancel4.c
@@ -119,6 +120,7 @@ benchtest5:: benchtest5.c
loadfree: :test:
semaphore1 :test: loadfree
+semaphore2 :test: loadfree
mutex5 :test: loadfree
mutex1 :test: loadfree
mutex2 :test: loadfree
diff --git a/pthread.h b/pthread.h
index 3e37f81..253888b 100644
--- a/pthread.h
+++ b/pthread.h
@@ -1,4 +1,4 @@
-/* This is the POSIX thread API (POSIX 1003).
+/* This is an implementation of the threads API of POSIX 1003.1-2001.
*
* --------------------------------------------------------------------------
*
@@ -76,12 +76,14 @@
* Provides an implementation of PThreads based upon the
* standard:
*
- * POSIX 1003.1c-1995 (POSIX.1c)
+ * POSIX 1003.1-2001
+ * and
+ * The Single Unix Specification version 3
*
- * Parts of the implementation also comply with the
- * Open Group Unix 98 specification in order to enhance
- * code portability between Windows, various commercial
- * Unix implementations, and Linux.
+ * (these two are equivalent)
+ *
+ * in order to enhance code portability between Windows,
+ * various commercial Unix implementations, and Linux.
*
* See the ANNOUNCE file for a full list of conforming
* routines and defined constants, and a list of missing
@@ -283,8 +285,8 @@ extern "C"
/*
* -------------------------------------------------------------
*
- * POSIX 1003.1c-1995 Options
- * ===========================
+ * POSIX 1003.1-2001 Options
+ * =========================
*
* _POSIX_THREADS (set)
* If set, you can use threads
@@ -350,11 +352,20 @@ extern "C"
* If set you can use the special *_r library
* functions that provide thread-safe behaviour
*
+ * _POSIX_READER_WRITER_LOCKS (set)
+ * If set, you can use read/write locks
+ *
+ * _POSIX_SPIN_LOCKS (set)
+ * If set, you can use spin locks
+ *
+ * _POSIX_BARRIERS (set)
+ * If set, you can use barriers
+ *
* + These functions provide both 'inherit' and/or
* 'protect' protocol, based upon these macro
* settings.
*
- * POSIX 1003.1c-1995 Limits
+ * POSIX 1003.1-2001 Limits
* ===========================
*
* PTHREAD_DESTRUCTOR_ITERATIONS
@@ -373,18 +384,13 @@ extern "C"
* Maximum number of threads supported per
* process (must be at least 64).
*
+ * _POSIX_SEM_NSEMS_MAX
+ * The maximum number of semaphores a process can have.
+ * (only defined if not already defined)
*
- * POSIX 1003.1j/D10-1999 Options
- * ==============================
- *
- * _POSIX_READER_WRITER_LOCKS (set)
- * If set, you can use read/write locks
- *
- * _POSIX_SPIN_LOCKS (set)
- * If set, you can use spin locks
- *
- * _POSIX_BARRIERS (set)
- * If set, you can use barriers
+ * _POSIX_SEM_VALUE_MAX
+ * The maximum value a semaphore can have.
+ * (only defined if not already defined)
*
* -------------------------------------------------------------
*/
@@ -452,11 +458,16 @@ extern "C"
* constant should be set at DLL load time.
*
*/
-#define PTHREAD_DESTRUCTOR_ITERATIONS 4
-#define PTHREAD_KEYS_MAX 64
-#define PTHREAD_STACK_MIN 0
-#define PTHREAD_THREADS_MAX 2019
-
+#define PTHREAD_DESTRUCTOR_ITERATIONS 4
+#define PTHREAD_KEYS_MAX 64
+#define PTHREAD_STACK_MIN 0
+#define PTHREAD_THREADS_MAX 2019
+#ifndef _POSIX_SEM_NSEMS_MAX
+# define _POSIX_SEM_NSEMS_MAX (INT_MAX)
+#endif
+#ifndef _POSIX_SEM_VALUE_MAX
+# define _POSIX_SEM_VALUE_MAX (INT_MAX - 1)
+#endif
#if __GNUC__ && ! defined (__declspec)
# error Please upgrade your GNU compiler to one that supports __declspec.
diff --git a/sem_getvalue.c b/sem_getvalue.c
index abc76c0..b3033d3 100644
--- a/sem_getvalue.c
+++ b/sem_getvalue.c
@@ -4,15 +4,13 @@
* Module: sem_getvalue.c
*
* Purpose:
- * Semaphores aren't actually part of the PThreads standard.
+ * Semaphores aren't actually part of PThreads.
* They are defined by the POSIX Standard:
*
- * POSIX 1003.1b-1993 (POSIX.1b)
+ * POSIX 1003.1-2001
*
* -------------------------------------------------------------
*
- * --------------------------------------------------------------------------
- *
* Pthreads-win32 - POSIX Threads Library for Win32
* Copyright(C) 1998 John E. Bossom
* Copyright(C) 1999,2002 Pthreads-win32 contributors
@@ -93,19 +91,24 @@ sem_getvalue(sem_t * sem, int * sval)
#else
long value = *sval;
- /* Note:
- * The windows NT documentation says that the increment must be
- * greater than zero, but it is set to zero here. If this works,
- * the function will return true. If not, we can't do it this way
- * so flag it as not implemented.
- */
+ /* From "Win32 System Programming - Second Edition"
+ * by Johnson M Hart, chapter 9, page 256 :
+ *
+ * "The release count must be greater than zero, but if it
+ * would cause the semaphore count to exceed the maximum,
+ * the call will fail, returning FALSE, and the count will
+ * remain unchanged. Releasing a semaphore with a large count
+ * is a method used to obtain the current count atomically
+ * (of course, another thread might change the value immediately)."
+ */
- if ( ReleaseSemaphore( (*sem)->sem, 0L, &value) )
+ if ( ! ReleaseSemaphore( (*sem)->sem, _POSIX_SEM_VALUE_MAX + 1, &value) )
{
*sval = value;
}
else
{
+ /* This should NEVER occur. */
result = ENOSYS;
}
diff --git a/sem_init.c b/sem_init.c
index e36678c..78e9770 100644
--- a/sem_init.c
+++ b/sem_init.c
@@ -4,15 +4,13 @@
* Module: sem_init.c
*
* Purpose:
- * Semaphores aren't actually part of the PThreads standard.
+ * Semaphores aren't actually part of PThreads.
* They are defined by the POSIX Standard:
*
- * POSIX 1003.1b-1993 (POSIX.1b)
+ * POSIX 1003.1-2001
*
* -------------------------------------------------------------
*
- * --------------------------------------------------------------------------
- *
* Pthreads-win32 - POSIX Threads Library for Win32
* Copyright(C) 1998 John E. Bossom
* Copyright(C) 1999,2002 Pthreads-win32 contributors
@@ -49,14 +47,12 @@
#include "semaphore.h"
#include "implement.h"
-#include <limits.h>
-
int
sem_init (sem_t * sem, int pshared, unsigned int value)
/*
* ------------------------------------------------------
* DOCPUBLIC
- * This function initializes an unnamed semaphore. the
+ * This function initializes a semaphore. The
* initial value of the semaphore is 'value'
*
* PARAMETERS
@@ -73,7 +69,7 @@ sem_init (sem_t * sem, int pshared, unsigned int value)
* initial value of the semaphore counter
*
* DESCRIPTION
- * This function initializes an unnamed semaphore. The
+ * This function initializes a semaphore. The
* initial value of the semaphore is set to 'value'.
*
* RESULTS
@@ -106,45 +102,46 @@ sem_init (sem_t * sem, int pshared, unsigned int value)
s = (sem_t) calloc (1, sizeof (*s));
if (NULL == s)
- {
- result = ENOMEM;
- }
+ {
+ result = ENOMEM;
+ }
#ifdef NEED_SEM
else
- {
- s->value = value;
- s->event = CreateEvent (NULL,
- FALSE, /* manual reset */
- FALSE, /* initial state */
- NULL);
- if (0 == s->event)
- {
- result = ENOSPC;
- }
- else
- {
- if (value != 0)
- {
- SetEvent(s->event);
- }
-
- InitializeCriticalSection(&s->sem_lock_cs);
- }
- }
-
+ {
+ s->value = value;
+ s->event = CreateEvent (NULL,
+ FALSE, /* manual reset */
+ FALSE, /* initial state */
+ NULL);
+
+ if (0 == s->event)
+ {
+ result = ENOSPC;
+ }
+ else
+ {
+ if (value != 0)
+ {
+ SetEvent(s->event);
+ }
+
+ InitializeCriticalSection(&s->sem_lock_cs);
+ }
+ }
+
#else /* NEED_SEM */
s->sem = CreateSemaphore (NULL, /* Always NULL */
- value, /* Initial value */
- INT_MAX, /* Maximum value */
- NULL); /* Name */
-
+ value, /* Initial value */
+ _POSIX_SEM_VALUE_MAX, /* Maximum value */
+ NULL); /* Name */
+
if (0 == s->sem)
- {
- result = ENOSPC;
- }
+ {
+ result = ENOSPC;
+ }
#endif /* NEED_SEM */
diff --git a/tests/ChangeLog b/tests/ChangeLog
index 6c8deed..e9266a5 100644
--- a/tests/ChangeLog
+++ b/tests/ChangeLog
@@ -1,3 +1,7 @@
+2002-06-03 Ross Johnson <rpj@digit.ise.canberra.edu.au>
+
+ * semaphore2.c: New test.
+
2002-03-02 Ross Johnson <rpj@special.ise.canberra.edu.au>
* Makefile (CFLAGS): Changed /MT to /MD to link with
diff --git a/tests/GNUmakefile b/tests/GNUmakefile
index cdae2d9..15b77b6 100644
--- a/tests/GNUmakefile
+++ b/tests/GNUmakefile
@@ -65,7 +65,7 @@ COPYFILES = $(HDR) $(LIB) $(DLL)
# stop.
TESTS = loadfree \
- semaphore1 self1 mutex5 mutex1 mutex1e mutex1n mutex1r \
+ semaphore1 semaphore2 self1 mutex5 mutex1 mutex1e mutex1n mutex1r \
condvar1 condvar1_1 condvar1_2 condvar2 condvar2_1 exit1 create1 equal1 \
exit2 exit3 \
join0 join1 join2 \
@@ -221,6 +221,7 @@ rwlock6_t2.pass: rwlock6_t.pass
self1.pass:
self2.pass: create1.pass
semaphore1.pass:
+semaphore2.pass:
spin1.pass:
spin2.pass: spin1.pass
spin3.pass: spin2.pass
diff --git a/tests/Makefile b/tests/Makefile
index a3fa7f3..014b767 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -71,7 +71,7 @@ EHFLAGS =
# stop.
PASSES= loadfree.pass \
- semaphore1.pass self1.pass mutex5.pass \
+ semaphore1.pass semaphore2.pass self1.pass mutex5.pass \
mutex1.pass mutex1n.pass mutex1e.pass mutex1r.pass mutex2.pass mutex3.pass \
condvar1.pass condvar1_1.pass condvar1_2.pass condvar2.pass condvar2_1.pass \
exit1.pass create1.pass equal1.pass \
@@ -286,7 +286,8 @@ rwlock6_t.pass: rwlock5_t.pass
rwlock6_t2.pass: rwlock6_t.pass
self1.pass:
self2.pass: create1.pass
-semaphore.pass:
+semaphore1.pass:
+semaphore2.pass:
spin1.pass:
spin2.pass: spin1.pass
spin3.pass: spin2.pass
diff --git a/tests/semaphore2.c b/tests/semaphore2.c
new file mode 100644
index 0000000..133443c
--- /dev/null
+++ b/tests/semaphore2.c
@@ -0,0 +1,105 @@
+/*
+ * File: semaphore2.c
+ *
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Pthreads-win32 - POSIX Threads Library for Win32
+ * Copyright(C) 1998 John E. Bossom
+ * Copyright(C) 1999,2002 Pthreads-win32 contributors
+ *
+ * Contact Email: rpj@ise.canberra.edu.au
+ *
+ * The current list of contributors is contained
+ * in the file CONTRIBUTORS included with the source
+ * code distribution. The list can also be seen at the
+ * following World Wide Web location:
+ * http://sources.redhat.com/pthreads-win32/contributors.html
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library in the file COPYING.LIB;
+ * if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ *
+ * --------------------------------------------------------------------------
+ *
+ * Test Synopsis: Verify sem_getvalue returns the correct value.
+ * -
+ *
+ * Test Method (Validation or Falsification):
+ * - Validation
+ *
+ * Requirements Tested:
+ * -
+ *
+ * Features Tested:
+ * -
+ *
+ * Cases Tested:
+ * -
+ *
+ * Description:
+ * -
+ *
+ * Environment:
+ * -
+ *
+ * Input:
+ * - None.
+ *
+ * Output:
+ * - File name, Line number, and failed expression on failure.
+ * - No output on success.
+ *
+ * Assumptions:
+ * -
+ *
+ * Pass Criteria:
+ * - Process returns zero exit status.
+ *
+ * Fail Criteria:
+ * - Process returns non-zero exit status.
+ */
+
+#include "test.h"
+
+#define BIG_NUM 10000
+
+int
+main()
+{
+ sem_t s;
+ int value = 0;
+ int result;
+
+ assert(sem_init(&s, PTHREAD_PROCESS_PRIVATE, BIG_NUM) == 0);
+ assert((result = sem_getvalue(&s, &value)) == 0);
+ assert(value == BIG_NUM);
+
+ for (i = BIG_NUM - 1; i >= 0; i--)
+ {
+ assert(sem_wait(&s) == 0);
+ assert((result = sem_getvalue(&s, &value)) == 0);
+ assert(value == i);
+ }
+
+ for (i = 1; i <= BIG_NUM; i--)
+ {
+ assert(sem_post(&s) == 0);
+ assert((result = sem_getvalue(&s, &value)) == 0);
+ assert(value == i);
+ }
+
+ return 0;
+}
+