Are pthreads' semaphores supposed to do this or is it a Linux bug?

Are pthreads' semaphores supposed to do this or is it a Linux bug?

Post by Norm Dresne » Wed, 07 Nov 2001 01:24:59



By mistake, I had coded (in pseudo code)

Program Initialization
    Initialize semaphore with sem_init()
    acquire semaphore with sem_wait()
    if( Optional Test )
        {
        ...
        release semaphore with sem_post()
        }
    ...

Program Processing
    ...

Program Termination
    acquire semaphore with sem_wait()
    ...

And didn't execute the optional test and the program hung.  Fine, I
understand that.  But then I changed the last sem_wait() to sem_trywait()
and the program still hung.  That I don't understand.  Is this a bug or is
there something in these semaphores that hangs when a program tries to wait
on a semaphore that it already has acquired?

FWIW, It's gcc-2.95.3 & libc-5.3.12-31.

    TIA
        Norm

 
 
 

Are pthreads' semaphores supposed to do this or is it a Linux bug?

Post by Eric P. McC » Wed, 07 Nov 2001 03:02:28



> By mistake, I had coded (in pseudo code)

[skip code]

Quote:> And didn't execute the optional test and the program hung.  Fine, I
> understand that.  

I'm not sure you do.  sem_wait() does not "acquire" semaphores, not
does sem_post() "release" them.  sem_wait() blocks the calling thread
until the semaphore has a nonzero value.  sem_post() increments the
value of the semaphore.

Maybe your code is doing that properly, but it's not at all evident
from the pseudocode you posted.

Typically you would want to use semaphores like this:

  /* assume these are all initialized properly before they're used */
  sem_t do_action;
  pthread_mutex_t action_lock;
  queue action_stack;

  void *thread1(void *arg) {
    action_t *this_action;

    while(1) {
      sem_wait(&do_action);
      pthread_mutex_lock(&action_lock);
      this_action = shift(&action_stack);
      pthread_mutex_unlock(&action_lock);

      action_handler(this_action);
    }

    return NULL;
  }

  void *thread2(void *arg) {
    /* Runs through process until it discovers some sort of "action"
     * that needs to be handled by the other thread.  Then...
     */

    pthread_mutex_lock(&action_lock);
    unshift(&action_stack, &this_action);
    sem_post(&do_action);
    pthread_mutex_unlock(&action_lock);

    /* Then continue processing as normal. */
  }

The above code snippet is most useful for using non-reentrant
libraries like Guile in multithreaded programs.  Which means that I
have used it in the past and it's worked fine.

Quote:> But then I changed the last sem_wait() to sem_trywait() and the
> program still hung.  That I don't understand.

Well, you don't seem to be using the semaphores properly.  If the
semaphore is zero and the only thread which can increment its value
calls sem_wait(), your program will deadlock.

Quote:> Is this a bug or is there something in these semaphores that hangs
> when a program tries to wait on a semaphore that it already has
> acquired?
> FWIW, It's gcc-2.95.3 & libc-5.3.12-31.

My God, you're using libc5?  That might be your problem right there.
The C library _has_ to be reentrant or you will get all sorts of
creeping errors.  While it's certainly possible that someone
backpatched libc5 to make it reentrant, it's also possible that they
didn't.

Have you got a _really, really_ compelling reason you can't use libc6?

--

"I woke up this morning and realized what the game needed: pirates,
pimps, and gay furries."  - Rich "Lowtax" Kyanka

 
 
 

Are pthreads' semaphores supposed to do this or is it a Linux bug?

Post by Norm Dresne » Wed, 07 Nov 2001 05:07:56





> > By mistake, I had coded (in pseudo code)

> [skip code]

> > And didn't execute the optional test and the program hung.  Fine, I
> > understand that.

> I'm not sure you do.  sem_wait() does not "acquire" semaphores, not
> does sem_post() "release" them.  sem_wait() blocks the calling thread
> until the semaphore has a nonzero value.  sem_post() increments the
> value of the semaphore.

> Maybe your code is doing that properly, but it's not at all evident
> from the pseudocode you posted.

When the semaphore has an initial value of 1, the action of wait is
equivalent to "acquiring" the semaphore and post "releases" it in the sense
that by waiting,  that section acquired the rights to sole access to the
area(s) of memory protected by the mutex and by posting, that section of the
program releases the memory for other parts to access.

    Since I was working on the skeleton of the program, there really wasn't
much more to it than what I posted.  The initialization routine was supposed
to create the semaphore with a value of 1, acquire the rights to it,
optionally write some data into shared memory, and then post to the
semaphore to "release" it.   In this version of the program, there wasn't
anything at all in the processing section so there weren't any other threads
competing for the semaphore.  The termination section was designed to wait
on the semaphore until it was free, terminate all threads and then destroy
the semaphore and then end the program.
    What did happen is that in the initialization section the post never got
executed -- I did say that I'd made a  mistake -- and then the termination
section went to wait on it again.  Regardless of the version of libc, I'd
expect that to hang and it did.  But when I replaced the wait in the
termination section with trywait, I expected that to fail and the program to
continue from there -- but that hung too.  That's what I suspect is an
implementation bug and that's what I was questioning.

- Show quoted text -

> Typically you would want to use semaphores like this:

>   /* assume these are all initialized properly before they're used */
>   sem_t do_action;
>   pthread_mutex_t action_lock;
>   queue action_stack;

>   void *thread1(void *arg) {
>     action_t *this_action;

>     while(1) {
>       sem_wait(&do_action);
>       pthread_mutex_lock(&action_lock);
>       this_action = shift(&action_stack);
>       pthread_mutex_unlock(&action_lock);

>       action_handler(this_action);
>     }

>     return NULL;
>   }

>   void *thread2(void *arg) {
>     /* Runs through process until it discovers some sort of "action"
>      * that needs to be handled by the other thread.  Then...
>      */

>     pthread_mutex_lock(&action_lock);
>     unshift(&action_stack, &this_action);
>     sem_post(&do_action);
>     pthread_mutex_unlock(&action_lock);

>     /* Then continue processing as normal. */
>   }

> The above code snippet is most useful for using non-reentrant
> libraries like Guile in multithreaded programs.  Which means that I
> have used it in the past and it's worked fine.

> > But then I changed the last sem_wait() to sem_trywait() and the
> > program still hung.  That I don't understand.

> Well, you don't seem to be using the semaphores properly.  If the
> semaphore is zero and the only thread which can increment its value
> calls sem_wait(), your program will deadlock.

> > Is this a bug or is there something in these semaphores that hangs
> > when a program tries to wait on a semaphore that it already has
> > acquired?

> > FWIW, It's gcc-2.95.3 & libc-5.3.12-31.

> My God, you're using libc5?  That might be your problem right there.
> The C library _has_ to be reentrant or you will get all sorts of
> creeping errors.  While it's certainly possible that someone
> backpatched libc5 to make it reentrant, it's also possible that they
> didn't.

> Have you got a _really, really_ compelling reason you can't use libc6?

> --

> "I woke up this morning and realized what the game needed: pirates,
> pimps, and gay furries."  - Rich "Lowtax" Kyanka

 
 
 

1. Can't find iostream.h... what rpm pagckages am I suppose to install?

I have installed the gcc version 2.something
for C and C++ and the preprocessors
but when I tried to compile a c++ program that uses iostream.h
the compiler can't find it!
where should I look for it?
it is not in my linux partitions.
but i have iostream.h from Microsoft VC++
thanks for your help!

* Sent from RemarQ http://www.remarq.com The Internet's Discussion Network *
The fastest and easiest way to search and participate in Usenet - Free!

2. Resolution is to low!

3. How do I get 'w' to say that i am doing something else

4. Kernel compiled with PCI and Adaptec 1540CP

5. What am I doing wrong with 'chat'?

6. Monitor blanking out in Gnome

7. Solaris 2.6 Am I suppose to have libs -ldes & -lcrypt ???

8. Help! Installation goes fine, but won't boot!

9. Now what am I supposed to do?

10. What I am Suppose to do ? WD9033 driver

11. OK, so how am I supposed to know my support contract info?

12. Whcih files from the XFree863.3.1 distrib am I supposed to install?

13. how do I use DHCP or whatever I am supposed to use with my network card