On Wed, 1 Sep 2004, Andy Fiddaman wrote:
The application is threaded so I was looking to see how thread-safe the
library is.

The real issue is your C library. A common problem is that many C libraries do not have a thread-safe strtok (meaning that it keeps the state per-thread), select(), or host name routines. Many C library implementors weasel their way out of it by making you use other calls such as strtok_r().


In general, it looks as if it will be okay if I'm careful
(e.g. don't manipulate driver parameters from a thread),

It has been said that "threads are the crack cocaine of programming";
they are powerful, poorly-understood by many of their users, and have a substantial mythology.


There is *nothing* wrong with altering a global in threaded code as long as you accept that that alteration affects every thread. This is a very useful attribute (beloved of those of us who wrote multi-forked code with shareable writable pages on TOPS-20). It is something that must be thoroughly understood; but it is not something to fear.

In general, when you change a driver parameter, the desired effect is to change the global behavior of the driver. What this means in general is that if you want to change a driver parameter, you go ahead and do it. Usually, you'll be doing this at startup or under control of the user interface, instead of deep within some thread.

but there are a couple of places where race conditions could occur. For
example, there is code at the start of unix_header() which populates a
global STRINGLIST if it hasn't been done before.

This is an excellent example. That global STRINGLIST is global for a reason. It should be a global constant, but it's complex enough to need code to build it.


The only concern is whether another thread can run and join that code while the STRINGLIST is being built. For this, you need to understand how your thread library works. If thread switching only happens on I/O, you are safe since the only thing that code does is assignment and malloc().

If the threads really are separate kernel processes running in the same address space (as in Linux), then a simple mutex will do the trick. Here's one that will build even on systems which don't have threading:
static long lock = -1;
. . .
if (++lock) sleep (1);
. . . protected code . . .
lock = -1;
It'll take over 100 years for the lock to overflow with that sleep() there, so it's alright to keep testing it. On the other hand, this may not work if prefix increment is non-atomic; the C specification implies that it is, but it makes no definite statement.


I'm not adverse to adding this sort of a mutex to this and the other places that initialize globals that are intended to be constants once set.

-- Mark --

http://staff.washington.edu/mrc
Science does not emerge from voting, party politics, or public debate.
Si vis pacem, para bellum.

Reply via email to