public inbox for
 help / color / mirror / Atom feed
From: Ross Johnson <>
To: Shantanu Gogate <>,
Subject: Re: help: weird behaviour of sem_getvalue
Date: Tue, 09 Dec 2003 13:56:00 -0000	[thread overview]
Message-ID: <> (raw)
In-Reply-To: <>

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.


Shantanu Gogate wrote:

>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

       reply	other threads:[~2003-12-09 13:56 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <>
2003-12-09 13:56 ` Ross Johnson [this message]
2003-12-08  7:59 Shantanu Gogate

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \ \ \ \ \

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).