diff options
| author | rpj <rpj> | 2001-10-25 13:24:58 +0000 | 
|---|---|---|
| committer | rpj <rpj> | 2001-10-25 13:24:58 +0000 | 
| commit | 222a76c37c89ee37eebecd53dd32fd481245e6fa (patch) | |
| tree | 160ed8d069da4d9e94b16c436943def676e355c5 /private.c | |
| parent | 7b714286cfd65e797364fbdc583e13adba71a2ee (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.c | 68 | 
1 files changed, 68 insertions, 0 deletions
| @@ -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; +} | 
