From: jurlwin@gandalf.UMCS.Maine.EDU (Jeff Urlwin)
Subject: Re: OS/2 libraries thread-safe ?
Organization: University of Maine, Department of Computer Science
Date: Thu, 17 Dec 1992 17:00:43 GMT

In article <1992Dec17.094108.12612@eua.ericsson.se> etxabju@eua.ericsson.se writes:
>In article 26031@cs.tu-berlin.de, ernst@opal.cs.tu-berlin.de (Ernst Kloecker) writes:
>>Hi,
>>
>>what precautions do I have to take when calling C-library functions from
>>different threads in one process ?
>>
>What C library? I can only speek for Microsoft C 6.0. I not quite sure 
>about IBM Cset/2 yet, but I think the answers are applicable for that
>library as well.
>
>There are (at least) two versions of the library - one "normal" and one 
>thread safe.  In MSC you invoke the thread safe library with -MT.

When you compile with the option /Gm+ and link with the multithreaded library,
you should be OK.  You should use _beginthread() to start your thread.  It
sets up the correct behavior of the library routines.
(NOTE: if you use /Gm+ and have ICC call the linker for you, it will grab
the multithreaded libs for you...)

>>What happens to static variables like 'errno' ?
>
>No problem. errno is redefined with the preprocessor to a thread-safe function:
>#define errno thread_safe_errno_function() or something like that.

errno is actually a function call with the CSet/2.  It will properly deal
with the multiple threads.  I forget, but I think it's defined as:
extern _Optlink int *_errno(void); 
#define errno  (*_errno())

Don't quote me on this, but I know I've seen this somewhere...
>

>>
>>Can I safely call '...printf()' from different threads ?
>
>Not quite sure, but I think so. printf/sprintf etc uses (in MSC) a static
>result array. This array is guarded with semaphores. However, there can 
>be a small risk that the output from several threads are mixed with each 
>other (but only one of them calls printf() of course).

Well sprintf shouldn't be a problem, because you supply the buffer.
(just don't call it with the same buffer...).  printf could either:
guard the use by semaphores or dynamically allocate the memory.  Either
way you *should* be OK with the call.  Where you might run into problems
is when looking at the info.  If your stdout (or your FILE) is buffered
in any way, you could be seeing some messed up stuff...or at least the
info will be interleaved...

If this is for debugging, let me tell you what I've done in the past 
(on Transputers, where you have multiple threads AND multiple processors -- 
non shared memory across the processors) is to have the notion of a timestamp
and do a fprintf from each thread with the timestamp, thread id (and 
processor, in that case) and debugging message.  Then you can have a program
merge the info into one file, based upon time.  So you might see.
in file 1:
1 In thread1
4 start calculating pi
10 finished first approx

in file 2:
2 finished setup of thread 1
5 got user input
11 got finished pi...

etc.

It's pretty simple at this point to concatenate the files and sort them
by time...this way you can see what's really going on...somewhat realtime.

You have to be careful, though, that you're not putting in too much
printing in one thread and changing the timing of the threads and how
they interact.  I've seen it happen most of the time where introducing
debugging printfs, etc actually "solves" the problem....you're in for
a fun hunt then!
>>
>>Or are the only safe functions the OS-functions in 'bsedos.h' ?
>
>Sorry.
>
>>Or are even those functions not completely thread-safe ?
>>
>Not absolutly sure how they are implemented, but functions like strtok(),
>localtime(), gmtime() etc seems a bit dangerous - I guard them with a semaphore
>when I use them.
>
I agree.  It's better to be careful, until you can see somewhere that they
ARE re-entrant.  Maybe someone at IBM can tell us which calls are re-entrant
and which aren't.  I would have to assume (until I could test further) that
the Dos, Win, etc calls are re-entrant, but I would check that...

>>
>>Thanks for any info, Ernst.
>>--
>
>No problem. Hope it helped. Can someone with experience from Cset/2 and emx
>tell how it's done there?

I hope someone who is more "in the know" than I am could continue this...

Does anyone have any neat tricks/techniques for debugging this stuff?
Maybe the fact that my background is more in parallel processing, I don't
see how people are using it here...maybe I go a little overboard...

Jeff
-- 
--------------------------------------
jurlwin@gandalf.umcs.maine.edu