[comp.os.os2] Threads and semaphores under OS/2

jamin@cogsci.berkeley.edu (Sugih Jamin) (10/21/89)

In article <1989Oct19.143604.21001@rpi.edu> ander@pawl.rpi.edu (Michael R. Primm) writes:
>
>Threads are easy to use and much more useful than fork()ing around :-).  
>
I am having problem dynamically creating and killing threads.  Suppose I am a 
function that gets called everytime a thread is to be spawned.  If I allocate
a stack for the thread in my own stack, then that stack is going to get
de-allocated everytime I exit.  If I using the heap space for the thread
stack, who will be freeing it?  Definitely not the thread itself?
Am I suppose to manage all those stacks also?  Such is not the case in Mach,
I think.

Another question relating to threads, do you know how to tell if you have 
any thread running?  Some API calls that serve an anologous purpose to
DosCWait(), but for threads will be nice.

According to all I have read on OS/2 semaphores, it seems like not only don't
they support counting semaphores, they don't even eliminate the problem of
race condition because any thread could be scheduled next.  OS/2 has three
different kinds of semaphores with ten(?) semaphore functions, yet none of
them are as powerful as the one defined by Dijkstra?  What I want is a counting
semaphores with a FIFO queue. Sometime ago somebody wrote an article in the
Microsoft Systems Journal showing how one could "easily" implement a counting
semaphore using the available APIs.  But the counting semaphore he showed
did not have a FIFO queue associated with it, so one still has the race
condition.  Please correct me if I am wrong.  


sugih

ejp@bohra.cpg.oz (Esmond Pitt) (10/24/89)

In article <32054@ucbvax.BERKELEY.EDU> jamin@cogsci.berkeley.edu.UUCP (Sugih Jamin) writes:
>Am I suppose to manage all those stacks also?

I'm afraid so.

>Another question relating to threads, do you know how to tell if you have 
>any thread running?  Some API calls that serve an analogous purpose to
>DosCWait(), but for threads will be nice.

You can roll your own DosTWait() (wait for thread) fairly reliably.
You just code a sleep loop which does something harmless to the thread
like, say, attempting to get its priority.  When you gets the No Such
Thread error (sorry, no manual handy), the thread has finished.

This is useful in waiting for the thread to finish so you can dispose
of its stack.

The only problem is that the threadid might be quickly re-used between
the old thread terminating and a new one starting; this problem can be
gated away.

They really should have put in a DosTWait() and automatic stack
allocation, though.

>According to all I have read on OS/2 semaphores, it seems like not only don't
>they support counting semaphores, they don't even eliminate the problem of
>race condition because any thread could be scheduled next.  OS/2 has three
>different kinds of semaphores with ten(?) semaphore functions, yet none of
>them are as powerful as the one defined by Dijkstra?  What I want is a counting
>semaphores with a FIFO queue. Sometime ago somebody wrote an article in the
>Microsoft Systems Journal showing how one could "easily" implement a counting
>semaphore using the available APIs.  But the counting semaphore he showed
>did not have a FIFO queue associated with it, so one still has the race
>condition.  Please correct me if I am wrong.  

Yes, sorry, they should have got that right too.


-- 
Esmond Pitt, Computer Power Group
ejp@bohra.cpg.oz

robertre@microsoft.UUCP (Robert Reichel ms2) (10/25/89)

In article <32054@ucbvax.BERKELEY.EDU> jamin@cogsci.berkeley.edu.UUCP (Sugih Jamin) writes:
>I am having problem dynamically creating and killing threads.  Suppose I am a 
>function that gets called everytime a thread is to be spawned.  If I allocate
>a stack for the thread in my own stack, then that stack is going to get
>de-allocated everytime I exit.  If I using the heap space for the thread
>stack, who will be freeing it?  Definitely not the thread itself?
>Am I suppose to manage all those stacks also?  Such is not the case in Mach,
>I think.

You need to manage your own stacks.  There are a couple of ways I can
think of to free a stack correctly, I'm sure there are more:

	Thread A	Thread B
			Take Sem
	Wait on Sem	
			DosEnterCritSet (turns off thread switching for
					the process)
			Release Sem
			DosExit
	Free B's stack

The key point to remember is that DosExit clears an existing critical
section.

If you don't want to do the EnterCritSec (which is a bit rude since
it pretty much shuts down your application) you can have A and B wait
on a system semaphore and have A wake up with ERROR_SEM_OWNER_DIED.

>Another question relating to threads, do you know how to tell if you have 
>any thread running?  Some API calls that serve an anologous purpose to
>DosCWait(), but for threads will be nice.

This does not currently exist, but may in the future.  Right now you
have to have to keep track of who you've spun off.  Most apps I've
written somewhere have a bit array corresponding to thread id's, so
I can scan it to see who's alive.

>According to all I have read on OS/2 semaphores, it seems like not only don't
>they support counting semaphores, they don't even eliminate the problem of
>race condition because any thread could be scheduled next.  OS/2 has three
>different kinds of semaphores with ten(?) semaphore functions, yet none of
>them are as powerful as the one defined by Dijkstra?  What I want is a counting
>semaphores with a FIFO queue. Sometime ago somebody wrote an article in the
>Microsoft Systems Journal showing how one could "easily" implement a counting
>semaphore using the available APIs.  But the counting semaphore he showed
>did not have a FIFO queue associated with it, so one still has the race
>condition.  Please correct me if I am wrong.  

I'm sure it's possible to do what you're trying to do, but I haven't
done it yet and don't have the time at the moment.  As far as FIFO
goes, the scheduler is priority based, meaning that the highest priority
thread waiting on a resource will be the first one scheduled, regardless
of when he did the wait.  This prevents low priority threads from holding
resources needed by high priority guys and gumming up the works.  As
far as threads with equal priority goes, you will probably see FIFO
response within a given priority group, but it isn't guaranteed.


Disclaimer: My opinions are my own, and do not reflect the opinions
or policies of Microsoft.  I also reserve the right to be wrong.
-- 
Robert Reichel
robertre%microsof@beaver.washington.edu or 
{decvax,uunet,uw-beaver}!microsoft!robertre

ander@pawl.rpi.edu (Michael R. Primm) (10/25/89)

   For the stack allocation problem, one user solution I've though of may be
the use of a "watchdog" thread.  Each stack that you allocate for a thread 
would have a RAM semaphore associated with it which starts off being "set".
When a threat possessing such a stack wishes to terminate, it "clears" the
semaphore and exits.  The one problem is being sure that the thread is able
to exit before the stack gets reused.  But, anyway, the watchdog would hang
out waiting for stack semaphores to "clear", and would free the storage 
after a "reasonable delay" (long enough to be sure the thread was able to 
exit after the semaphore was cleared).  Anyway, while its pretty kludgy, 
it may be a possible route to consider.
                                                  --Mike Primm  
      

bobf@lotus.com (Bob Frankston (BFrankston)) (10/25/89)

Note that semaphores are associated with a process and not a thread
and thus can't be used to detect the death of a thread.  If the
thread terminates cleanly, you can have it send a message to a queue
announcing its demise.  You can have a separate thread waiting on the
queue that frees the resources for the departed tthreads.

[Opinions are my own and do not necessarily represent Lotus]