summaryrefslogtreecommitdiff
path: root/nonportable.c
diff options
context:
space:
mode:
authorrpj <rpj>2001-10-25 13:24:58 +0000
committerrpj <rpj>2001-10-25 13:24:58 +0000
commit222a76c37c89ee37eebecd53dd32fd481245e6fa (patch)
tree160ed8d069da4d9e94b16c436943def676e355c5 /nonportable.c
parent7b714286cfd65e797364fbdc583e13adba71a2ee (diff)
* barrier.c: Move _LONG and _LPLONG defines into
implement.h; rename to PTW32_INTERLOCKED_LONG and PTW32_INTERLOCKED_LPLONG respectively. * spin.c: Likewise; ptw32_interlocked_compare_exchange used in place of InterlockedCompareExchange directly. * global.c (ptw32_interlocked_compare_exchange): Add prototype for this new routine pointer to be used when InterlockedCompareExchange isn't supported by Windows. * nonportable.c (pthread_win32_process_attach_np): Check for support of InterlockedCompareExchange in kernel32 and assign its address to ptw32_interlocked_compare_exchange if it exists, or our own ix86 specific implementation ptw32_InterlockedCompareExchange. *private.c (ptw32_InterlockedCompareExchange): An implementation of InterlockedCompareExchange() which is specific to ix86; written directly in assembler for either MSVC or GNU C; needed because Windows 95 doesn't support InterlockedCompareExchange(). * sched.c (sched_get_priority_min): Extend to return THREAD_PRIORITY_IDLE. (sched_get_priority_max): Extend to return THREAD_PRIORITY_CRITICAL.
Diffstat (limited to 'nonportable.c')
-rw-r--r--nonportable.c47
1 files changed, 47 insertions, 0 deletions
diff --git a/nonportable.c b/nonportable.c
index 5fcb1b8..de9dc07 100644
--- a/nonportable.c
+++ b/nonportable.c
@@ -179,6 +179,11 @@ pthread_getprocessors_np(int * count)
}
+/*
+ * Handle to kernel32.dll
+ */
+static HINSTANCE ptw32_h_kernel32;
+
BOOL
pthread_win32_process_attach_np ()
{
@@ -189,6 +194,43 @@ pthread_win32_process_attach_np ()
pthread_count++;
#endif
+ /*
+ * Load KERNEL32 and try to get address of InterlockedCompareExchange
+ */
+ ptw32_h_kernel32 = LoadLibrary(TEXT("KERNEL32.DLL"));
+
+ ptw32_interlocked_compare_exchange =
+ (PTW32_INTERLOCKED_LONG (PT_STDCALL *)(PTW32_INTERLOCKED_LPLONG, PTW32_INTERLOCKED_LONG, PTW32_INTERLOCKED_LONG))
+#if defined(NEED_UNICODE_CONSTS)
+ GetProcAddress(ptw32_h_kernel32,
+ (const TCHAR *)TEXT("InterlockedCompareExchange"));
+#else
+ GetProcAddress(ptw32_h_kernel32,
+ (LPCSTR) "InterlockedCompareExchange");
+#endif
+
+ if (ptw32_interlocked_compare_exchange == NULL)
+ {
+ ptw32_interlocked_compare_exchange = &ptw32_InterlockedCompareExchange;
+
+ /*
+ * If InterlockedCompareExchange is not being used, then free
+ * the kernel32.dll handle now, rather than leaving it until
+ * DLL_PROCESS_DETACH.
+ *
+ * Note: this is not a pedantic exercise in freeing unused
+ * resources! It is a work-around for a bug in Windows 95
+ * (see microsoft knowledge base article, Q187684) which
+ * does Bad Things when FreeLibrary is called within
+ * the DLL_PROCESS_DETACH code, in certain situations.
+ * Since w95 just happens to be a platform which does not
+ * provide InterlockedCompareExchange, the bug will be
+ * effortlessly avoided.
+ */
+ (void) FreeLibrary(ptw32_h_kernel32);
+ ptw32_h_kernel32 = 0;
+ }
+
return result;
}
@@ -214,6 +256,11 @@ pthread_win32_process_detach_np ()
* The DLL is being unmapped into the process's address space
*/
ptw32_processTerminate ();
+
+ if (ptw32_h_kernel32)
+ {
+ (void) FreeLibrary(ptw32_h_kernel32);
+ }
}
return TRUE;