Jump to content

  • Log In with Google      Sign In   
  • Create Account

Mutex creation in multithreaded library


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
9 replies to this topic

#1 codingJoe   Members   -  Reputation: 171

Like
0Likes
Like

Posted 30 May 2013 - 10:26 AM

Hello,

 

I think I have a kind of chicken-egg problem:

 

I have a library (dll) that is pure C and that is supposed to be thread-safe.

How do I initialize it? I mean, at some point I need to call

 

globalMutex=CreateMutex(0,FALSE,0);
do some other initializations here

The above section of code should be run only the very first time someone calls a function in the library. But what if several threads call the library at the same time? Best would be to have a mutex to make sure the initialization happens only once, but mutexes need to be initialized...

Any idea?



Sponsor:

#2 Zaoshi Kaba   Crossbones+   -  Reputation: 4376

Like
2Likes
Like

Posted 30 May 2013 - 10:59 AM

Doesn't it get called only once, when you load library? So just load it before creating any threads.


Edited by Zaoshi Kaba, 30 May 2013 - 02:03 PM.


#3 ApochPiQ   Moderators   -  Reputation: 15832

Like
4Likes
Like

Posted 30 May 2013 - 12:51 PM

Most libraries solve this by requiring you to explicitly call some kind of init() function.



#4 Yourself   Crossbones+   -  Reputation: 1135

Like
1Likes
Like

Posted 30 May 2013 - 03:01 PM

If you target windows,  you could use DllMain

for other platform there are alternatives (see this for example)



#5 frob   Moderators   -  Reputation: 21488

Like
5Likes
Like

Posted 30 May 2013 - 03:42 PM

globalMutex=CreateMutex(0,FALSE,0);

Do you really need a Windows Mutex?
 
Yes, the Windows Mutex will always work, but it introduces a kernel-level stall every time you create it.  The thing takes about a full microsecond just to lock.  And heaven help your app if there is lock contention.
 
It is like installing a stop sign in the middle of a race track.  It will work at ensuring every process running on the computer obeys the lock, but at a terrible system-wide performance cost.
 
Wherever possible use a lockless solution or design around it.  Don't get in the problem to begin with.  
If you need to share data, don't lock and instead use atomic primitives.
If you need to share locked data, use an interlocked variable.
If you need to share more data than an interlocked variable can handle, use a critical section.
If you absolutely must coordinate data between many processes, use a system mutex.
 
The atomic operations and lockless solutions have no additional cost.
Interlocked operations cost around 5-10 nanoseconds, potentially a few more if there is contention.
Critical sections cost around 20-50 nanoseconds to enter and lock, plus potentially many microseconds (or worse) if there is contention.
A Windows Mutex costs around 500-1000 nanoseconds to enter and lock because it is done at the kernel level.  It can take many milliseconds (or worse) if there is contention.
 
Choose the right synchronization objects for your needs.  A full kernel-level Mutex object is usually the wrong selection.

Edited by frob, 30 May 2013 - 03:44 PM.

Check out my personal indie blog at bryanwagstaff.com.

#6 codingJoe   Members   -  Reputation: 171

Like
0Likes
Like

Posted 30 May 2013 - 03:56 PM

Thanks for all the replies.

The library can actually be compiled for many different platforms (also microcontrollers), and is allready in use. For that reason I cannot use an additional function that initializes everything.

I was just wondering if there is an extremely lightweight lock one can build, that is not OS dependent?

Or at least a random/timed mechanism that will reduce the chance for 2 threads entering the initialization section?



#7 frob   Moderators   -  Reputation: 21488

Like
2Likes
Like

Posted 30 May 2013 - 04:01 PM

I was just wondering if there is an extremely lightweight lock one can build, that is not OS dependent?

Boost has a pretty good collection of synchronization tools, although it may not be supported on your microcontrollers.


Check out my personal indie blog at bryanwagstaff.com.

#8 ApochPiQ   Moderators   -  Reputation: 15832

Like
3Likes
Like

Posted 30 May 2013 - 05:11 PM

You can build an atomic one-time lock on any CPU that supports atomic compare and swap:
 
 
// Some global
int counter = 0;
 
if (CompareAndSwap(counter, 1) == 0) {
   // Do initialization
}
 
// Carry on
[edit] For completeness: you also need a spinlock that waits until initialization is completed:
// Another global
int initdone = 0;

if (CompareAndSwap(counter, 1)) {
// init
// atomic set initdone to 1
}

while (AtomicCompare(initdone, 0)) {
// No-op
}

// Carry on

Edited by ApochPiQ, 30 May 2013 - 05:13 PM.


#9 codingJoe   Members   -  Reputation: 171

Like
0Likes
Like

Posted 31 May 2013 - 03:08 AM

Thanks again!

 

I also found a platform-independent way of doing it: the Peterson's algorithm



#10 Hodgman   Moderators   -  Reputation: 30433

Like
4Likes
Like

Posted 31 May 2013 - 03:35 AM

I also found a platform-independent way of doing it: the Peterson's algorithm

Don't try and implement that unless you're aware of the memory/cache/atomicity/reordering behaviours of your target CPU and compiler.

If you implement that code as-is on any modern CPU, it simply will not work correctly as a critical section... You'd have to insert memory fences, etc, in order to make it function correctly.

e.g. your compiler or CPU might change the order in which the writes to flag[n] and turn actually occur, or the setting of flag[n] to false at the end might actually be committed to RAM before the changes performed inside the critical section are committed!






Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS