summaryrefslogtreecommitdiff
path: root/private.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 /private.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 'private.c')
-rw-r--r--private.c68
1 files changed, 68 insertions, 0 deletions
diff --git a/private.c b/private.c
index a332385..f97d9f4 100644
--- a/private.c
+++ b/private.c
@@ -1020,3 +1020,71 @@ ptw32_pop_cleanup_all(int execute)
while( NULL != ptw32_pop_cleanup(execute) ) {
}
}
+
+
+/*
+ * ptw32_InterlockedCompareExchange --
+ *
+ * Needed because W95 doesn't support InterlockedCompareExchange.
+ * It is only used when running the dll on W95. Other versions of
+ * Windows use the Win32 supported version, which may be running on
+ * different processor types.
+ *
+ * This can't be inlined because we need to know it's address so that
+ * we can call it through a pointer.
+ */
+PTW32_INTERLOCKED_LONG
+ptw32_InterlockedCompareExchange(PTW32_INTERLOCKED_LPLONG ptr,
+ PTW32_INTERLOCKED_LONG value,
+ PTW32_INTERLOCKED_LONG comparand)
+{
+ PTW32_INTERLOCKED_LONG result;
+
+#if defined(_M_IX86) || defined(_X86_)
+
+#if defined(__MSVCRT__)
+
+ _asm {
+ PUSH ecx
+ PUSH edx
+ MOV ecx,dword ptr [ptr] ; Load ECX with plTarget
+ MOV edx,dword ptr [value] ; Load EDX with lValue
+ MOV eax,dword ptr [comparand]
+ LOCK CMPXCHG dword ptr [ecx],edx ; if (EAX == [ECX]),
+ ; [ECX] = EDX
+ ; else
+ ; EAX = [ECX]
+ MOV dword ptr [result], eax
+ POP edx
+ POP ecx
+ }
+
+#elif defined(__GNUC__)
+
+ __asm__
+ (
+ "lock\n\t"
+ "cmpxchgl %3,(%0)" /* if (EAX == [ptr]), */
+ /* [ptr] = value */
+ /* else */
+ /* EAX = [ptr] */
+ :"=r" (ptr), "=a" (result)
+ :"0" (ptr), "q" (value), "a" (comparand)
+ : "memory" );
+
+#endif
+
+#else
+
+ /*
+ * If we get to here then we should be running on a Win95 system but either
+ * running on something other than an X86 processor, or a compiler other
+ * than MSVC or GCC. Pthreads-win32 doesn't support that platform (yet).
+ */
+
+ result = 0;
+
+#endif
+
+ return result;
+}