This is the mail archive of the cygwin@cygwin.com mailing list for the Cygwin 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: pthread_cond_wait does not relock mutex on release


It's interesting that your system behaves so differently. (I
believe signals are supposed to interrupt condition variable
waits--perhaps you're system is being flooded by them?)

There are a few things you could try, including:

o Disabling signals in the created threads. To do this, you
  have to disable them in the parent, create the threads,
  then reenable them. It's generally worth it.

o Using a semaphore (you still have to check for a spurious
  wakeup due to a caught signal).


Here are some code snippets you might find helpful:


This creates threads, disabling signals (extracted from
Python's POSIX threads module):

    sigset_t oldmask, newmask;
    sigfillset(&newmask);
    pthread_sigmask(SIG_BLOCK, &newmask, &oldmask);
    pthread_create(...);
    pthread_sigmask(SIG_SETMASK, &oldmask, NULL);


These snippets should let you use semaphores to signal
between threads:


/*
 * As of February 2002, Cygwin thread implementations mistakenly report error
 * codes in the return value of the sem_ calls (like the pthread_ functions).
 * Correct implementations return -1 and put the code in errno. This supports
 * either.
 */
static int
fix_status(int status)
{
    return (status == -1) ? errno : status;
}

...


/* VARIABLES USED IN ALL SNIPPETS: */
    sem_t *sem;
    int status;


/* CREATE A SEMAPHORE */
    sem = (sem_t *)malloc(sizeof(sem_t));
    if (sem) {
        status = sem_init(sem,0,0); /* start "acquired" */
        if (status != 0) {
            free((void *)sem);
            sem = NULL;
        }
    }
    if (!sem) REPORT_ERROR();


/* DESTROY THE SEMAPHORE */
    if (sem) {
        status = sem_destroy(sem);
        if (status != 0) REPORT_ERROR();
        free(sem);
    }


/* WAIT FOR THE SIGNAL */
    do {
        status = fix_status(sem_wait(sem));
    } while (status == EINTR); /* Retry if interrupted by a signal */
    if (status != 0) REPORT_ERROR();


/* SIGNAL THE SEMAPHORE */
    status = sem_post(sem);
    if (status != 0) REPORT_ERROR();


I think the bug requiring the "fix_status" function has been
fixed, but you might find it easier to understand this way.
The "normal" way to wait for a semaphore is:
    do {
        status = sem_wait(sem);
    } while ((status == -1) && (errno == EINTR));


With semaphores you have to be careful to match the number of
sem_wait() and sem_post() calls (extra sem_post() calls would
cause future sem_wait()'s not to wait).


-Jerry

-O Gerald S. Williams, 55A-134A-E   : mailto:gsw@agere.com O-
-O AGERE SYSTEMS, 6755 SNOWDRIFT RD : office:610-712-8661  O-
-O ALLENTOWN, PA, USA 18106-9353    : mobile:908-672-7592  O-

> Robert and Gerald:
>
>          Both quite right.  Although adding the SAFE_PRINTF made no
> difference in the
> output, checking a condition value in a loop made all the difference.  
> Putting a printf in the loop revealed to my surprise that "spurious wakeups"
> were occurring thousands of times per second.  I had naively assumed that a
> condition would stay set until signalled.  Now I'm led to wonder if a
> condition variable is any performance improvement over a simple loop and
> short sleep.  Any thoughts?
>
>          Thanks very much for your time and effort.  It was a great help.
>
> -- Michael


--
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple
Bug reporting:         http://cygwin.com/bugs.html
Documentation:         http://cygwin.com/docs.html
FAQ:                   http://cygwin.com/faq/


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