TIP: Click on subject to list as thread! ANSI
echo: os2prog
to: Jonathan de Boyne Pollard
from: Herbert Rosenau
date: 1999-09-03 12:43:15
subject: Terminating threads clean

 HR>> Most (but not all) OS/2 APIs calls DosExitCritSec() under cover.
 HR>> So you should not use any API (system, runtime, library) unless
 HR>> you know that this function would never call a system API.

 JdBP> Actually, that's not quite the right explanation.  

 JdBP> The reason not to call APIs is as explained in the CP Guide and
 JdBP> Reference.  (The CPREF talks about "dynamic link library
 JdBP> calls", but it is really talking about APIs in any arbitrary
 JdBP> libraries.  Even statically linked libraries can be a problem
 JdBP> if they use semaphores internally.)  If a second thread had
 JdBP> been already in that API when it was blocked by the first
 JdBP> thread entering the criticical section, then that second thread
 JdBP> will possibly be holding a mutex semaphore that restricts
 JdBP> access to the internals of that API.  If the first thread then
 JdBP> attempts to use that API, it will block on the mutex whilst
 JdBP> holding the critical section, and the two threads will be
 JdBP> deadlocked.

In redbooks is declared that most (but not all) OS/2 API will enter
DosExitCritSec() before entering ring 0. So any API to a runtime library my
call it. 

This is since OS/2 1.3. In OS/2 1.2 and earlier there was NO unlck and a
restriction not to use more than 10 assembler statements.

I'd had in OS/2 2.0 exactly that problem: In production environment a
multithreaded process crashed mostly (not always) in case of exit. The
DosWaitThread() API doesn't exist. Depending on memory amount the program
crashed or even crashed NOT.

To fix that bug I had to terminate other threads clean and before thread 1
itself terminates. For that I foun DosEnterCritSec() as friend of me. On
thread exit:

DosEnterCritSec();
death = 1;		/* signal to thread 1 thread is deed */
_endthread();		/* clean up C environment and die    */
			/* thred was started with _beginthread */

in thread 1

while (!death) DosSleep(0);	/* give up timeslice */

With DosWaitThread() this would be much simpler. A simple DosWaitThread() for
all threads in thread 1 would do the whole work.

DosEnterCritSec()/DosExitCritSec() pair is also a probate way to block other
threads for shorthand manipulation of process internal but thread shared
variables. It would save the overhead of semaphore handling. But it's always
unsuitable for longer code sequences (with/without any API).

--- Sqed/32 1.14/development
102
* Origin: Schont die Umwelt: Vermeidet DOSen (2:2476/493)

SOURCE: echoes via The OS/2 BBS

Email questions or comments to sysop@ipingthereforeiam.com
All parts of this website painstakingly hand-crafted in the U.S.A.!
IPTIA BBS/MUD/Terminal/Game Server List, © 2025 IPTIA Consulting™.