From 222a76c37c89ee37eebecd53dd32fd481245e6fa Mon Sep 17 00:00:00 2001 From: rpj Date: Thu, 25 Oct 2001 13:24:58 +0000 Subject: * 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. --- private.c | 68 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) (limited to 'private.c') 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; +} -- cgit v1.2.3