Archive

Archive for August, 2006

win32: Threadsafe initialization of mutexes

August 15th, 2006

The $64-question: is the following function thread safe?


static HANDLE mutex=0;   

void
lock(void)
{
    if (mutex==0)
        mutex=CreateMutex(0, FALSE, 0);
    WaitForSingleObject(mutex, INFINITE);
}

void
unlock(void)
{
    ReleaseMutex(mutex);
} 

void
foo(void)
{
    lock();
    do_something();
    unlock();
} 

foo() is called by several threads. foo creates a mutex, if it wasn’t yet created, locks it, does something and then unlocks the mutex.

The dangerous code is in lock(), when the mutex is created. When two threads call the function simultaneously, and the mutex handle is NULL, both threads create their own mutex, instead of using the same mutex. And then both threads call do_something() in parallel. (This is not just a theoretical case – it has happened in an application i wrote, and it was a reproducable bug.)

To avoid this problem (which actually happened to me a few weeks ago), we have to synchronize the call to CreateMutex(). There are several options, but the fastest should be an atomic “test-and-modify” operation. The win32 SDK offers a function called InterlockedCompareExchangePointer(). It tests, if a pointer has a certain value; if yes, the pointer is exchanged with another value. Here is the new code for lock():


void
lock(void)
{
    if (mutex==0) {
        HANDLE mutex2=CreateMutex(0, FALSE, 0);
        InterlockedCompareExchangePointer(&mutex, mutex2, NULL);
        if (mutex!=mutex2)
             CloseHandle(mutex2);
    }
} 

If the mutex was not yet created, we create a second (temporary) mutex mutex2. InterlockedCompareExchangePointer() replaces mutex with mutex2, but only if mutex is NULL (the third parameter). Otherwise, we release mutex2, to avoid a resource leak.

Since InterlockedCompare-functions use atomic CPU opcodes, the “compare and exchange” will not be interrupted.

On linux this problem doesn’t exist – pthread-mutexes can be initialized statically:

 pthread_mutex_t mutex=PTHREAD_MUTEX_INITIALIZER; 

But that’s impossible for win32 handles, since they are pointers to pointers, and therefore have to be allocated at runtime.

chris Coding, Howto's

Library: getopts-0.1 (stable)

August 13th, 2006

getopts is a C library for reading and parsing command line parameters (argc and argv).

More information and download links: http://www.crupp.de/?page_id=6

chris Coding, Libraries

Welcome to my new blog!

August 9th, 2006

The stuff i’m writing about won’t be interesting for you unless you’re a geek or you like to cook. I know that programming and cooking is a strange mixture, but these are two of my hobbies, so i’ll write about them.

And while i like cooking, and i don’t have an area of expertise when it’s about food, my programming is mostly restricted to C, sometimes C++, php, python and perl. My favourite topics are linux system programming, server/network programming and database engines.

I will write about the things i learn at my job, and from time to time i will post updates about the work on my database engine.

Since i’m not a native English speaker, some entries will be German – especially recipes are really hard to translate.

Have fun, and feel free to leave a comment!

chris Uncategorized