Equivalent of PTHREAD_MUTEX_INITIALIZER on Windows? - c

Is it possible to initialise CRITICAL_SECTION statically, as in pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER?
In other words, is it possible in C to initialize a global CRITICAL_SECTION inside a library without having to mess with DllMain etc.?

Yes, simply initialize in DLL_PROCESS_ATTACH and delete in DLL_PROCESS_DETACH
CRITICAL_SECTION g_cs = {0};
BOOL WINAPI DllMain(
HINSTANCE hinstDLL, // handle to DLL module
DWORD fdwReason, // reason for calling function
LPVOID lpReserved ) // reserved
{
// Perform actions based on the reason for calling.
switch( fdwReason )
{
case DLL_PROCESS_ATTACH:
// Initialize once for each new process.
// Return FALSE to fail DLL load.
InitializeCriticalSection(&g_cs);
break;
case DLL_THREAD_ATTACH:
// Do thread-specific initialization.
break;
case DLL_THREAD_DETACH:
// Do thread-specific cleanup.
break;
case DLL_PROCESS_DETACH:
// Perform any necessary cleanup.
DeleteCriticalSection(&g_cs);
break;
}
return TRUE; // Successful DLL_PROCESS_ATTACH.
}
References:
InitializeCriticalSection
DeleteCriticalSection

Yes! But you have to make sure that it's only done once per process.
But this is typically easiest to achieve by using the DLL_PROCESS_ATTACH case of the DLLMain
switch( fdwReason ) statement.

Another possibility in earlier versions is to instruct the linker to set a pointer to your initialization function as a user-defined global initializer. There is some discussion of this here:
http://msdn.microsoft.com/en-us/library/bb918180.aspx
Here is an example:
CRITICAL_SECTION criticalSection;
static void __cdecl Initialize(void) {
InitializeCriticalSection(&criticalSection);
}
#pragma section(".CRT$XCU", read)
__declspec(allocate(".CRT$XCU"))
const void (__cdecl *pInitialize)(void) = Initialize;

The answer above from Raymond Chen solves the problem: "You can use InitOnceExecuteOnce to initialize the critical section on first use. That's what PTHREAD_MUTEX_INITIALIZER does under the covers."
note that this will work on Vista and above only --- #rkosegi
You can do it for older versions of Windows by writing your own InitOnceExecuteOnce function using InterlockedCompareExchange. --- #RaymondChen

Related

Critical Sections and Memory Fences / Barriers on a multi-processor system

I have a Windows DLL (in C) that uses Critical Sections. A specific routine, which is called numerous times, needs to perform some initialization code the first time it is called, so I am using a Critical Section. However, since it is called so many times I am trying to avoid the overhead of entering the section each time it is called. It seems to be working, but I am wondering if there is a flaw considering memory barriers / fences when running on a multi-processor (Intel) system with an x64 OS? Here is the stripped down code:
int _isInitialized = FALSE;
CRITICAL_SECTION _InitLock = {0};
BOOL APIENTRY DllMain( HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved )
{
ARM_SECTION_BEGIN(ul_reason_for_call)
switch (ul_reason_for_call)
{
case (DLL_PROCESS_ATTACH):
InitializeCriticalSection(&_InitLock);
break;
case (DLL_THREAD_ATTACH):
break;
case (DLL_THREAD_DETACH):
break;
case (DLL_PROCESS_DETACH):
DeleteCriticalSection(&_InitLock);
break;
}
return (TRUE);
}
int myproc(parameters...)
{
if (!_isInitialized) // check first time
{
EnterCriticalSection(&_InitLock);
if (_isInitialized) // check it again
{
LeaveCriticalSection(&_InitLock);
goto initialized;
}
... do stuff ...
_isInitialized = TRUE;
LeaveCriticalSection(&_InitLock);
}
initialized:
... do more stuff ...
return(something)
}
... if there is a flaw considering memory barriers / fences ... ?
Use volatile
Code certainly appears to risk using a stale value for _isInitialized in the 2nd test.
if (!_isInitialized) {
EnterCriticalSection(&_InitLock);
if (_isInitialized) // Risk
To insure a re-read of _isInitialized, use volatile. #JimmyB
// int _isInitialized = FALSE;
volatile int _isInitialized = FALSE;
Other Shared Data
Other data than _isInitialized assigned in the ... do stuff ... and used in the later ... do more stuff ... code risks the same problem due to an optimization may read other_data before the the first if (!_isInitialized).
Code could use volatile other_data. Unfortunately that may incur an unacceptable performance drag. Alternatives depend on what is inside stuff.
Style
I'd make _isInitialized local to the function, drop the _ and avoid the goto.
int myproc(parameters...) {
static volatile int isInitialized = FALSE;
if (!isInitialized) {
EnterCriticalSection(&_InitLock);
if (!isInitialized) {
// ... do stuff ...
isInitialized = TRUE;
}
LeaveCriticalSection(&_InitLock);
}
// ... do more stuff ...
return(something)
}

Exception handling in C - making try catch work across functions

I am writing an exception handling library in C and i ran into a bump:
#define TRY do{ jmp_buf ex_buf__; switch( setjmp(ex_buf__) ){ case 0:
#define FINALLY break; } default:
#define CATCH(x) break; case x:
#define ETRY } }while(0)
#define THROW(x) longjmp(ex_buf__, x)
In my current implementation of try catch throw, I won't be able to throw an exception from inside a method called from inside the try block because the jmp_buf variable is local. How would i make that possible?
I thought about a global variable but that would not allow me to have nested try catch blocks.
You need to use a global jump buffer, because it needs to be visible to your "clients". You could, for example, save the old jump buffer in a try block, and restore it after its use.
In general, I would not recommend this approach at all, though. Trying to retrofit features into a language is fraught with peril, not the least of which would be the following code:
for ;; {
TRY {
if (someVar) {
break;
}
}
FINALLY {
doIt()
}
ETRY
}
Use a stack of jmp_buf's. Or better yet, use the existing CII library, which has been designed, built, and tested for this purpose.

One time Hook DLL initialization

My program uses SetWindowsHookEx to set a global hook function in my DLL. However I want the DLL to work with a file so I need it a file to be opened once. I can't use DllMain's DLL_PROCESS_ATTACH because it's called multiple times. What is the best solution to my problem?
Use a static flag to tell whether you've initialized already or not.
void DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) {
static BOOL initialized = FALSE;
switch(dwReason) {
case DLL_PROCESS_ATTACH:
if(!initialized) {
// Perform initialization here...ex: open your file.
initialized = TRUE;
}
break;
case DLL_PROCESS_DETACH:
if(initialized) {
// Perform cleanup here...ex: close your file.
initialized = FALSE;
}
break;
};
}

Switch/case without break inside DllMain

I have a Dllmain that allocates Thread local storage when a thread attaches to this DLL. Code as below:
BOOL APIENTRY DllMain(HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved)
{
LPVOID lpvData;
BOOL fIgnore;
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
onProcessAttachDLL();
// Allocate a TLS index.
if ((dwTlsIndex = TlsAlloc()) == TLS_OUT_OF_INDEXES)
return FALSE;
// how can it jump to next case???
case DLL_THREAD_ATTACH:
// Initialize the TLS index for this thread.
lpvData = (LPVOID) LocalAlloc(LPTR, MAX_BUFFER_SIZE);
if (lpvData != NULL)
fIgnore = TlsSetValue(dwTlsIndex, lpvData);
break;
...
}
I know that for the main thread, the DLL_THREAD_ATTACH is not entered, as per Microsoft Documentation. However, the above code worked. I am using VC2005. When I entered the debugger, I saw that after it entered DLL_THREAD_ATTACH case when ul_reason_for_call = 1! How can that happen? If I add `break' at the end of DLL_PROCESS_ATTACH block, the DLL failed to work.
How can this happen?
If I understand you correctly, you are wondering why, after entering the DLL_PROCESS_ATTACH case, the execution continues on the DLL_THREAD_ATTACH case, instead of after the end of the switch.
This behaviour is called "fall through", and it is standard C. Without an explicit break statement, the execution continues on the next case.
Of course, it is quite counterintuitive for programmers who see it the first time, so it is a constant source of misunderstanding and even bugs (you may not always know whether the break was left out intentionally, or by mistake). It is considered good practice, therefore, when using this construct, to mark it explicitly with a comment, like:
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
onProcessAttachDLL();
// Allocate a TLS index.
if ((dwTlsIndex = TlsAlloc()) == TLS_OUT_OF_INDEXES)
return FALSE;
// fall through
case DLL_THREAD_ATTACH:
// Initialize the TLS index for this thread.
lpvData = (LPVOID) LocalAlloc(LPTR, MAX_BUFFER_SIZE);
if (lpvData != NULL)
fIgnore = TlsSetValue(dwTlsIndex, lpvData);
break;
...
Do you understand how switch statements work? if you do NOT put a break at the end of the case, then the code just continues into the next case:
switch (3)
{
case 3:
cout << "3";
case 4:
cout << "4";
}
prints both 3 and 4.

Library initialization -- pthread_once in Win32 implementation

Hello. I am trying to make a fully thread-safe initialization function for my library and I couldn't easily find an alternative to pthread_once, which should solve the problem very easily. I've come to this code:
void libInit (void)
{
#ifdef WIN32
static volatile int initialized = 0;
static HANDLE mtx;
if (!initialized)
{
if (!mtx)
{
HANDLE mymtx;
mymtx = CreateMutex(NULL, 0, NULL);
if (InterlockedCompareExchangePointer(&mtx, mymtx, NULL) != NULL)
CloseHandle(mymtx);
}
WaitForSingleObject(mtx);
if (!initialized)
{
libInitInternal();
initialized = 1;
}
ReleaseMutex(mtx);
}
#else
static pthread_once_t initialized = PTHREAD_ONCE_INIT;
pthread_once(&initialized, libInitInternal);
#endif
}
The libInitInternal() call leads to a thread-unsafe function, that initializes the library.
I would like to hear any suggestions on what I could be doing wrong or whether you know about a better solution.
I think you want to use the One-Time Initialization functionality. In synchronous mode, all threads block until the first thread to call it completes. Seems analogous to pthread_once().
There is sample code here.
So in your case, you would say:
BOOL CALLBACK CallLibInitInternal(PINIT_ONCE InitOnce, PVOID Parameter, PVOID *lpContex) {
libInitInternal();
return TRUE;
}
void libInit() {
#ifdef WIN32
static INIT_ONCE s_init_once;
InitOnceExecuteOnce(&s_init_once, CallLibInitInternal, NULL, NULL);
#else
...
#endif
}
You might want to check what pthreads-win32 does in its pthread_once() implementaion. or just use that, if that proves to be easier.
After looking at the following source code for pthread_once() (from here), It looks like you're on the right track.
int pthread_once(pthread_once_t *once_control, void (*init_routine)(void))
{
/* Check first for speed */
if (once_control->state == PTHREAD_NEEDS_INIT) {
pthread_mutex_lock(&(once_control->mutex));
if (once_control->state == PTHREAD_NEEDS_INIT) {
init_routine();
once_control->state = PTHREAD_DONE_INIT;
}
pthread_mutex_unlock(&(once_control->mutex));
}
return(OK);
}
btw, I'll be using pthread_once() to replace some rather convoluted functions in my code.
When using GCC or clang, you can use constructor and destructor attributes. These work for both shared and static libraries, and execute code before and after main is run, respectively. Additionally, you can specify multiple constructor and destructor functions. Much cleaner than the singleton approach, and doesn't require you to remember to call libInit() from your main().
static void __attribute__((constructor))
your_lib_init(void)
{
fprintf(stderr, "library init\n");
}
static void __attribute__((destructor))
vensim_ctx_destroy(void)
{
fprintf(stderr, "library destroy\n");
}
I would check out this article. It is a solution for C++ singletons, but I believe you can use the solution for your code as well: http://www.ddj.com/cpp/199203083?pgno=1
Sadly the listing for the QLock itself is missing, it looks as if they are trying to sell the CD, but there appears to be enough description of it to write one yourself.

Resources