This is the mail archive of the pthreads-win32@sources.redhat.com mailing list for the pthreas-win32 project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: help: weird behaviour of sem_getvalue


Hi Shantanu,

The sem_getvalue.c file contains the following comments:-

     /*
      * 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.
      */

The method used performs a WaitForSingleObject() call on the (underlying Win32) semaphore with a 0 timeout. If it returns WAIT_TIMEOUT then the semaphore was 0, otherwise it immediately releases the sema and gets the (value-1) through ReleaseSemaphore().

Wrapping all this in a critical section would add overhead to every other sem_*() call.

Regards.
Ross

Shantanu Gogate wrote:

Hi,
I am using pthreads-win32 package( was using pthreads-win32-2003-05-10.exe and also tried the
latest 2003-09-18.exe) but facing a weird problem using sem_getvalue. I have replicated what I am
trying to do thru this snippet of code which you can test for yourself. Basically there is a
semaphore which is set to one before the threads are launched. one or more threads continuously
check the value of this semaphore to see if it has become zero and if it has, then the thread
exits. Interestingly if you comment out the pthread_exit line then you that the sem_getvalue
returns the value of semaphore as zero for a brief period of time and then starts reporting it as
one again !! if i compile the same code on a linux box this anomaly is not observed. Is this is a
bug in win32-pthreads ? Any help would be appreciated.

Shantanu Gogate.

the code:

<<<<
#include <pthread.h>
#include <semaphore.h>
#include <stdio.h> static sem_t g_sem_ready,g_sem_queue;
void *consumer(void *args) {
int count=0,value;
while(1) {
sem_getvalue(&g_sem_ready,&value);
printf("consumer ready= %d\n",value);
if(value <= 0 ) {
sem_getvalue(&g_sem_queue,&value);
// printf("consumer exiting, with %d pending\n", value);
pthread_exit(0);
} else {
sem_wait(&g_sem_queue);
count++;
// printf("consumed %d\n",count);
}
} }


void *producer(void *args) {
       int value,count=0;
       while(1) {
               sem_getvalue(&g_sem_ready,&value);
               printf("producer ready= %d\n",value);
               if(value <= 0 ) {
                       printf("producer exiting\n");
               //      pthread_exit(0);
               }
               else {
                       count++;
               //      printf("produced %d\n",count);
                       sem_post(&g_sem_queue);
                       if(count > 200)
                               pthread_exit(0);
               }
       }
}
int main(int argc, char *argv[]) {
       pthread_t th1, th2;
       int status;

       sem_init(&g_sem_ready,0,0);
       sem_init(&g_sem_queue,0,0);

       sem_post(&g_sem_ready);
       pthread_create(&th1,NULL, consumer, NULL);
       pthread_create(&th2,NULL, producer, NULL);
       sleep(10);
       printf("going down baby\n");
       sem_wait(&g_sem_ready);
       pthread_join(th2,(void **)&status);
       pthread_join(th1,(void **)&status);
}






__________________________________
Do you Yahoo!?
Protect your identity with Yahoo! Mail AddressGuard
http://antispam.yahoo.com/whatsnewfree




Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]