diff options
| -rw-r--r-- | GNUmakefile | 3 | ||||
| -rw-r--r-- | pthread.h | 20 | ||||
| -rw-r--r-- | pthread_mutex_timedlock.c | 340 | ||||
| -rw-r--r-- | sem_getvalue.c | 116 | ||||
| -rw-r--r-- | sem_init.c | 54 | ||||
| -rw-r--r-- | tests/semaphore2.c | 29 | 
6 files changed, 300 insertions, 262 deletions
| diff --git a/GNUmakefile b/GNUmakefile index c205458..44fc4d7 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -458,6 +458,7 @@ clean:  	-$(RM) *~  	-$(RM) *.i  	-$(RM) *.o +	-$(RM) *.obj  	-$(RM) *.exe  	-$(RM) $(PTHREAD_DEF) @@ -466,6 +467,8 @@ realclean: clean  	-$(RM) $(GCE_LIB)  	-$(RM) $(GC_DLL)  	-$(RM) $(GCE_DLL) +	-$(RM) $(GC_INLINED_STAMP) +	-$(RM) $(GCE_INLINED_STAMP)  attr.o:		attr.c $(ATTR_SRCS) $(INCL)  barrier.o:	barrier.c $(BARRIER_SRCS) $(INCL) @@ -198,6 +198,7 @@  #endif /* HAVE_SIGNAL_H */  #include <setjmp.h> +#include <limits.h>  /*   * This is a duplicate of what is in the autoconf config.h, @@ -385,12 +386,12 @@ extern "C"   *			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) + *	The maximum number of semaphores a process can have. + *	(only defined if not already defined)   *   * _POSIX_SEM_VALUE_MAX - *      The maximum value a semaphore can have. - *      (only defined if not already defined) + *	The maximum value a semaphore can have. + *	(only defined if not already defined)   *   * -------------------------------------------------------------   */ @@ -459,14 +460,15 @@ extern "C"   *   */  #define PTHREAD_DESTRUCTOR_ITERATIONS			       4 -#define PTHREAD_KEYS_MAX                        64 -#define PTHREAD_STACK_MIN                        0 -#define PTHREAD_THREADS_MAX                   2019 +#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) +/* Not used and only an arbitrary value. */ +#  define _POSIX_SEM_NSEMS_MAX		      1024  #endif  #ifndef _POSIX_SEM_VALUE_MAX -#  define _POSIX_SEM_VALUE_MAX       (INT_MAX - 1) +#  define _POSIX_SEM_VALUE_MAX	       (INT_MAX/2)  #endif  #if __GNUC__ && ! defined (__declspec) diff --git a/pthread_mutex_timedlock.c b/pthread_mutex_timedlock.c index ec1caa9..da03c03 100644 --- a/pthread_mutex_timedlock.c +++ b/pthread_mutex_timedlock.c @@ -99,58 +99,58 @@ ptw32_timed_semwait (sem_t * sem, const struct timespec * abstime)    else      {        if (abstime == NULL) -	{ -	  milliseconds = INFINITE; -	} +				{ +					milliseconds = INFINITE; +				}        else -	{ -	  /*  -	   * Calculate timeout as milliseconds from current system time.  -	   */ - -	  /* get current system time */ - +				{ +					/*  +					 * Calculate timeout as milliseconds from current system time.  +					 */ +					 +					/* get current system time */ +					  #ifdef NEED_FTIME - -	  { -	    FILETIME ft; -	    SYSTEMTIME st; - -	    GetSystemTime(&st); -	    SystemTimeToFileTime(&st, &ft); -	    /* -	     * GetSystemTimeAsFileTime(&ft); would be faster, -	     * but it does not exist on WinCE -	     */ - -	    ptw32_filetime_to_timespec(&ft, &currSysTime); -	  } - -	  /* -	   * subtract current system time from abstime -	   */ -	  milliseconds = (abstime->tv_sec - currSysTime.tv_sec) * MILLISEC_PER_SEC; -	  milliseconds += ((abstime->tv_nsec - currSysTime.tv_nsec) -                           + (NANOSEC_PER_MILLISEC/2)) / NANOSEC_PER_MILLISEC; +					 +					{ +						FILETIME ft; +						SYSTEMTIME st; +						 +						GetSystemTime(&st); +						SystemTimeToFileTime(&st, &ft); +						/* +						 * GetSystemTimeAsFileTime(&ft); would be faster, +						 * but it does not exist on WinCE +						 */ +						 +						ptw32_filetime_to_timespec(&ft, &currSysTime); +					} +					 +					/* +					 * subtract current system time from abstime +					 */ +					milliseconds = (abstime->tv_sec - currSysTime.tv_sec) * MILLISEC_PER_SEC; +					milliseconds += ((abstime->tv_nsec - currSysTime.tv_nsec) +						+ (NANOSEC_PER_MILLISEC/2)) / NANOSEC_PER_MILLISEC;  #else /* NEED_FTIME */ -	  _ftime(&currSysTime); +					_ftime(&currSysTime); -	  /* -	   * subtract current system time from abstime -	   */ -	  milliseconds = (abstime->tv_sec - currSysTime.time) * MILLISEC_PER_SEC; -	  milliseconds += ((abstime->tv_nsec + (NANOSEC_PER_MILLISEC/2)) / NANOSEC_PER_MILLISEC) +					/* +					 * subtract current system time from abstime +					 */ +					milliseconds = (abstime->tv_sec - currSysTime.time) * MILLISEC_PER_SEC; +					milliseconds += ((abstime->tv_nsec + (NANOSEC_PER_MILLISEC/2)) / NANOSEC_PER_MILLISEC)              - currSysTime.millitm;  #endif /* NEED_FTIME */ -	  if (((int) milliseconds) < 0) -	    { -	      return 2; -	    } -	} +					if (((int) milliseconds) < 0) +						{ +							return 2; +						} +				}  #ifdef NEED_SEM @@ -163,24 +163,24 @@ ptw32_timed_semwait (sem_t * sem, const struct timespec * abstime)  #endif        if (status == WAIT_OBJECT_0) -	{ +				{  #ifdef NEED_SEM -	  ptw32_decrease_semaphore(sem); +					ptw32_decrease_semaphore(sem);  #endif /* NEED_SEM */ -	  return 0; -	} +					return 0; +				}        else if (status == WAIT_TIMEOUT) -	{ -	  return 1; -	} +				{ +					return 1; +				}        else -	{ -	  result = EINVAL; -	} +				{ +					result = EINVAL; +				}      }    if (result != 0) @@ -219,9 +219,9 @@ pthread_mutex_timedlock(pthread_mutex_t *mutex, const struct timespec *abstime)    if (*mutex == PTHREAD_MUTEX_INITIALIZER)      {        if ((result = ptw32_mutex_check_need_init(mutex)) != 0) -	{ -	  return(result); -	} +				{ +					return(result); +				}      }    mx = *mutex; @@ -230,126 +230,126 @@ pthread_mutex_timedlock(pthread_mutex_t *mutex, const struct timespec *abstime)      {        mx->recursive_count = 1;        mx->ownerThread = (mx->kind != PTHREAD_MUTEX_FAST_NP -			 ? pthread_self() -			 : (pthread_t) PTW32_MUTEX_OWNER_ANONYMOUS); +				? pthread_self() +				: (pthread_t) PTW32_MUTEX_OWNER_ANONYMOUS);      }    else      {        if( mx->kind != PTHREAD_MUTEX_FAST_NP && -	  pthread_equal( mx->ownerThread, pthread_self() ) ) -	{ -	  (void) InterlockedDecrement( &mx->lock_idx ); - -	  if( mx->kind == PTHREAD_MUTEX_RECURSIVE_NP ) -	    { -	      mx->recursive_count++; -	    } -	  else -	    { -	      result = EDEADLK; -	    } -	} +				pthread_equal( mx->ownerThread, pthread_self() ) ) +				{ +					(void) InterlockedDecrement( &mx->lock_idx ); + +					if( mx->kind == PTHREAD_MUTEX_RECURSIVE_NP ) +						{ +							mx->recursive_count++; +						} +					else +						{ +							result = EDEADLK; +						} +				}        else -	{ -	  if (abstime == NULL) -	    { -	      result = EINVAL; -	    } -	  else -	    { -	      switch (ptw32_timed_semwait( &mx->wait_sema, abstime )) -		{ -		  case 0: /* We got the mutex. */ -		    { -		      mx->recursive_count = 1; -		      mx->ownerThread = (mx->kind != PTHREAD_MUTEX_FAST_NP -					 ? pthread_self() -					 : (pthread_t) PTW32_MUTEX_OWNER_ANONYMOUS); -		      break; -		    } -		  case 1: /* Timedout, try a second grab. */ -		    { -		      EnterCriticalSection(&mx->wait_cs); - -		      /* -		       * If we timeout, it is up to us to adjust lock_idx to say -		       * we're no longer waiting. If the mutex was also unlocked -		       * while we were timing out, and we simply return ETIMEDOUT, -		       * then wait_sema would be left in a state that is not consistent -		       * with the state of lock_idx. -		       * -		       * We must check to see if wait_sema has just been posted -		       * but we can't just call sem_getvalue - we must compete for -		       * the semaphore using sem_trywait(), otherwise we would need -		       * additional critical sections elsewhere, which would make the -		       * logic too inefficient. -		       * -		       * If sem_trywait returns EAGAIN then either wait_sema -		       * was given directly to another waiting thread or -		       * another thread has called sem_*wait() before us and -		       * taken the lock. Then we MUST decrement lock_idx and return -		       * ETIMEDOUT. -		       * -		       * Otherwise we MUST return success (because we have effectively -		       * acquired the lock that would have been ours had we not -		       * timed out), and NOT decrement lock_idx. -		       * -		       * We can almost guarrantee that EAGAIN is the only -		       * possible error, so no need to test errno. -		       */ - -		      if ( -1 == sem_trywait( &mx->wait_sema ) ) -			{ -			  (void) InterlockedDecrement( &mx->lock_idx ); -			  result = ETIMEDOUT; -			} - -		      LeaveCriticalSection(&mx->wait_cs); -		      break; -		    } -		  case 2: /* abstime passed before we started to wait. */ -		    { -		      /* -		       * If we timeout, it is up to us to adjust lock_idx to say -		       * we're no longer waiting. -                       * -                       * The owner thread may still have posted wait_sema thinking -                       * we were waiting. I believe we must check but then NOT do any -                       * programmed work if we have acquired the mutex because -                       * we don't how long ago abstime was. We MUST just release it -                       * immediately. -		       */ -		      EnterCriticalSection(&mx->wait_cs); - -		      result = ETIMEDOUT; - -		      if ( -1 == sem_trywait( &mx->wait_sema ) ) -			{ -			  (void) InterlockedDecrement( &mx->lock_idx ); -			} -                      else -                        { -                          if ( InterlockedDecrement( &mx->lock_idx ) >= 0 ) -                            { -                              /* Someone else is waiting on that mutex */ -                              if ( sem_post( &mx->wait_sema ) != 0 ) -                                { -                                  result = errno; -                                } -                            } -                        } - -		      LeaveCriticalSection(&mx->wait_cs); -		      break; -		    } -		  default: -		    { -		      result = errno; -		      break; -		    } -		} -	    } -	} +				{ +					if (abstime == NULL) +						{ +							result = EINVAL; +						} +					else +						{ +							switch (ptw32_timed_semwait( &mx->wait_sema, abstime )) +								{ +									case 0: /* We got the mutex. */ +									{ +										mx->recursive_count = 1; +										mx->ownerThread = (mx->kind != PTHREAD_MUTEX_FAST_NP +											? pthread_self() +											: (pthread_t) PTW32_MUTEX_OWNER_ANONYMOUS); +										break; +									} +									case 1: /* Timedout, try a second grab. */ +									{ +										EnterCriticalSection(&mx->wait_cs); + +										/* +										 * If we timeout, it is up to us to adjust lock_idx to say +										 * we're no longer waiting. If the mutex was also unlocked +										 * while we were timing out, and we simply return ETIMEDOUT, +										 * then wait_sema would be left in a state that is not consistent +										 * with the state of lock_idx. +										 * +										 * We must check to see if wait_sema has just been posted +										 * but we can't just call sem_getvalue - we must compete for +										 * the semaphore using sem_trywait(), otherwise we would need +										 * additional critical sections elsewhere, which would make the +										 * logic too inefficient. +										 * +										 * If sem_trywait returns EAGAIN then either wait_sema +										 * was given directly to another waiting thread or +										 * another thread has called sem_*wait() before us and +										 * taken the lock. Then we MUST decrement lock_idx and return +										 * ETIMEDOUT. +										 * +										 * Otherwise we MUST return success (because we have effectively +										 * acquired the lock that would have been ours had we not +										 * timed out), and NOT decrement lock_idx. +										 * +										 * We can almost guarrantee that EAGAIN is the only +										 * possible error, so no need to test errno. +										 */ + +										if ( -1 == sem_trywait( &mx->wait_sema ) ) +											{ +												(void) InterlockedDecrement( &mx->lock_idx ); +												result = ETIMEDOUT; +											} + +										LeaveCriticalSection(&mx->wait_cs); +										break; +									} +									case 2: /* abstime passed before we started to wait. */ +									{ +										/* +										 * If we timeout, it is up to us to adjust lock_idx to say +										 * we're no longer waiting. +										 * +										 * The owner thread may still have posted wait_sema thinking +										 * we were waiting. I believe we must check but then NOT do any +										 * programmed work if we have acquired the mutex because +										 * we don't how long ago abstime was. We MUST just release it +										 * immediately. +										 */ +										EnterCriticalSection(&mx->wait_cs); + +										result = ETIMEDOUT; + +										if ( -1 == sem_trywait( &mx->wait_sema ) ) +											{ +												(void) InterlockedDecrement( &mx->lock_idx ); +											} +										else +											{ +												if ( InterlockedDecrement( &mx->lock_idx ) >= 0 ) +													{ +														/* Someone else is waiting on that mutex */ +														if ( sem_post( &mx->wait_sema ) != 0 ) +															{ +																result = errno; +															} +													} +											} + +										LeaveCriticalSection(&mx->wait_cs); +										break; +									} +									default: +									{ +										result = errno; +										break; +									} +								} +						} +				}      }    return(result); diff --git a/sem_getvalue.c b/sem_getvalue.c index 297bc6c..9d37c38 100644 --- a/sem_getvalue.c +++ b/sem_getvalue.c @@ -11,32 +11,32 @@   *   * -------------------------------------------------------------   * - *      Pthreads-win32 - POSIX Threads Library for Win32 - *      Copyright(C) 1998 John E. Bossom - *      Copyright(C) 1999,2002 Pthreads-win32 contributors + *	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 + *	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 + *	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 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. + *	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 + *	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   */  #include "pthread.h" @@ -55,20 +55,20 @@ sem_getvalue(sem_t * sem, int * sval)        *        * Return value        * -      *       0                  sval has been set. -      *      -1                  failed, error in errno +      *       0 		 sval has been set. +      *      -1 		 failed, error in errno        *        *  in global errno        * -      *      EINVAL              'sem' is not a valid semaphore, -      *      ENOSYS              this function is not supported, +      *      EINVAL		 'sem' is not a valid semaphore, +      *      ENOSYS		 this function is not supported,        *        *        * PARAMETERS        * -      *      sem                 pointer to an instance of sem_t +      *      sem		 pointer to an instance of sem_t        * -      *      sval                pointer to int. +      *      sval		 pointer to int.        *        * DESCRIPTION        *      This function stores the current count value of the semaphore @@ -86,27 +86,57 @@ sem_getvalue(sem_t * sem, int * sval)      {  #ifdef NEED_SEM -  +        result = ENOSYS; -  +  #else -			 + +      /* +       * There appears to be NO atomic means of determining the +       * value of the semaphore. Using only ReleaseSemaphore() +       * with either a zero or oversized count parameter has been +       * suggested but this trick doesn't produce consistent results +       * across Windows versions (the technique uses values that are +       * knowingly illegal but hopes to extract the current value +       * anyway - the zero parameter appears to work for Win9x but +       * neither work reliably for WinNT). +       * +       * The intrusive method below will give false results +       * at times but it at least errs on the side of +       * caution. Competing threads might occasionally believe +       * the semaphore has a count of one less than it actually +       * would have and possibly block momentarily unecessarily, +       * but they will never see a higher semaphore value than +       * there should be. +       * +       * +       * Multiple threads calling sem_getvalue() at the same time +       * may not all return the same value (assuming no calls to +       * other semaphore routines). They will always return the +       * correct value or a lesser value. This problem could be fixed +       * with a global or a per-semaphore critical section here. +       * +       * An equally approximate but IMO slightly riskier approach +       * would be to keep a separate per-semaphore counter and +       * decrement/increment it inside of sem_wait() and sem_post() +       * etc using the Interlocked* functions. +       */        if ( WaitForSingleObject( (*sem)->sem, 0 ) == WAIT_TIMEOUT ) -        { -					/* Failed - must be zero. */ -          value = 0; -        } +				{ +					/* Failed - must be zero */ +					value = 0; +				}        else -        { -					/* Decremented sema - release it and note the value. */ -					(void) ReleaseSemaphore( (*sem)->sem, 1L, &value ); -          value++; -        } -  +				{ +					/* Decremented semaphore - release it and note the value */ +					(void) ReleaseSemaphore( (*sem)->sem, 1L, &value); +					value++; +				} +  #endif      } -  -  + +    if ( result != 0 )      {        errno = result; @@ -115,5 +145,5 @@ sem_getvalue(sem_t * sem, int * sval)  	*sval = value;    return 0; -  +  }   /* sem_getvalue */ @@ -11,32 +11,32 @@   *   * -------------------------------------------------------------   * - *      Pthreads-win32 - POSIX Threads Library for Win32 - *      Copyright(C) 1998 John E. Bossom - *      Copyright(C) 1999,2002 Pthreads-win32 contributors + *	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 + *	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 + *	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 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. + *	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 + *	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   */  #ifndef _UWIN @@ -126,17 +126,17 @@ sem_init (sem_t * sem, int pshared, unsigned int value)  								{  									SetEvent(s->event);  								} -							 +  							InitializeCriticalSection(&s->sem_lock_cs);  						}  				} -			 +  #else /* NEED_SEM */ -      s->sem = CreateSemaphore (NULL,	     /* Always NULL */ -				value,	              /* Initial value */ -				_POSIX_SEM_VALUE_MAX, /* Maximum value */ -				NULL);	              /* Name */ +      s->sem = CreateSemaphore (NULL,			     /* Always NULL */ +				(long) value,		     /* Initial value */ +				(long) _POSIX_SEM_VALUE_MAX, /* Maximum value */ +				NULL);			     /* Name */        if (0 == s->sem)  				{ diff --git a/tests/semaphore2.c b/tests/semaphore2.c index 133443c..855662f 100644 --- a/tests/semaphore2.c +++ b/tests/semaphore2.c @@ -46,13 +46,13 @@   * -    *   * Cases Tested: - * -  + * -   *   * Description: - * -  + * -   *   * Environment: - * -  + * -   *   * Input:   * - None. @@ -62,7 +62,7 @@   * - No output on success.   *   * Assumptions: - * -  + * -   *   * Pass Criteria:   * - Process returns zero exit status. @@ -73,30 +73,33 @@  #include "test.h" -#define BIG_NUM 10000 +#define MAX_COUNT 100000  int  main()  {    sem_t s;  	int value = 0; -  int result; +	int i; -  assert(sem_init(&s, PTHREAD_PROCESS_PRIVATE, BIG_NUM) == 0); -	assert((result = sem_getvalue(&s, &value)) == 0); -	assert(value == BIG_NUM); +  assert(sem_init(&s, PTHREAD_PROCESS_PRIVATE, MAX_COUNT) == 0); +	assert(sem_getvalue(&s, &value) == 0); +	assert(value == MAX_COUNT); +//	  printf("Value = %ld\n", value); -	for (i = BIG_NUM - 1; i >= 0; i--) +	for (i = MAX_COUNT - 1; i >= 0; i--)  		{  			assert(sem_wait(&s) == 0); -			assert((result = sem_getvalue(&s, &value)) == 0); +			assert(sem_getvalue(&s, &value) == 0); +//			  printf("Value = %ld\n", value);  			assert(value == i);  		} -	for (i = 1; i <= BIG_NUM; i--) +	for (i = 1; i <= MAX_COUNT; i++)  		{  			assert(sem_post(&s) == 0); -			assert((result = sem_getvalue(&s, &value)) == 0); +			assert(sem_getvalue(&s, &value) == 0); +//			  printf("Value = %ld\n", value);  			assert(value == i);  		} | 
