From b2bca276f0fdb43e7ba4aa6baefe835d23820164 Mon Sep 17 00:00:00 2001 From: rpj Date: Mon, 3 Jun 2002 09:19:57 +0000 Subject: An attempt to get sem_getvalue working properly. --- ChangeLog | 16 ++++++++ Nmakefile.tests | 2 + pthread.h | 61 ++++++++++++++++++------------- sem_getvalue.c | 25 +++++++------ sem_init.c | 75 ++++++++++++++++++-------------------- tests/ChangeLog | 4 ++ tests/GNUmakefile | 3 +- tests/Makefile | 5 ++- tests/semaphore2.c | 105 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 9 files changed, 218 insertions(+), 78 deletions(-) create mode 100644 tests/semaphore2.c diff --git a/ChangeLog b/ChangeLog index 9a2413d..693e04d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,19 @@ +2002-06-03 Ross Johnson + + * 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 + + * 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 * 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 - 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 + + * semaphore2.c: New test. + 2002-03-02 Ross Johnson * 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; +} + -- cgit v1.2.3