238 lines
7.6 KiB
C
238 lines
7.6 KiB
C
/*++
|
|
|
|
Copyright (c) 1995-2000 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
synlock.c
|
|
|
|
Abstract:
|
|
|
|
Implementation of the intel locked instructions. All locked instructions
|
|
wait on a single global mutex (shared between processes). This takes care
|
|
of any synchronization problem between intel processes. Instructions which
|
|
access aligned 32bit memory are also synchronized with native processes
|
|
via the functions in lock.c.
|
|
|
|
Author:
|
|
|
|
22-Aug-1995 t-orig (Ori Gershony)
|
|
|
|
Revision History:
|
|
|
|
24-Aug-1999 [askhalid] copied from 32-bit wx86 directory and make work for 64bit.
|
|
|
|
--*/
|
|
|
|
#include <nt.h>
|
|
#include <ntrtl.h>
|
|
#include <nturtl.h>
|
|
#include <windows.h>
|
|
#include <stdio.h>
|
|
#include "fragp.h"
|
|
#include "cpumain.h"
|
|
#include "lock.h"
|
|
#include "synlock.h"
|
|
|
|
//
|
|
// The following two variables are used to synchronize intel instructions
|
|
// with the LOCK prefix. The critical section is a lot faster, but it does
|
|
// not guarantee synchronization in shared memory. Eventually we should use
|
|
// the critical section by default, and the mutex for certain applications which
|
|
// need it (maybe get a list from the registry).
|
|
//
|
|
HANDLE Wx86LockSynchMutexHandle;
|
|
RTL_CRITICAL_SECTION Wx86LockSynchCriticalSection;
|
|
|
|
//
|
|
// The following variable decided which synchronization object is used
|
|
// Remove the '#define' below to allow runtime selection of whether
|
|
// x86 LOCK: prefixes on 8-bit and 16-bit instructions and unaligned
|
|
// 32-bit instructions are synchronized across the entire machine
|
|
// or only within the current process. With the '#define' present,
|
|
// LOCK: prefixes imply only per-process synchronization.
|
|
//
|
|
SYNCHOBJECTTYPE SynchObjectType;
|
|
#define SynchObjectType USECRITICALSECTION
|
|
|
|
#define GET_SYNCHOBJECT \
|
|
if (SynchObjectType == USECRITICALSECTION){ \
|
|
RtlEnterCriticalSection(&Wx86LockSynchCriticalSection); \
|
|
} else { \
|
|
WaitForSingleObject(Wx86LockSynchMutexHandle, INFINITE);\
|
|
}
|
|
|
|
#define RELEASE_SYNCHOBJECT \
|
|
if (SynchObjectType == USECRITICALSECTION){ \
|
|
RtlLeaveCriticalSection(&Wx86LockSynchCriticalSection); \
|
|
} else { \
|
|
ReleaseMutex(Wx86LockSynchMutexHandle); \
|
|
}
|
|
|
|
//
|
|
// Macros for 8 bit fragments
|
|
//
|
|
#define SLOCKFRAG1_8(x) \
|
|
FRAG1(SynchLock ## x ## Frag8, unsigned char) \
|
|
{ \
|
|
GET_SYNCHOBJECT \
|
|
x ## Frag8 (cpu, pop1); \
|
|
RELEASE_SYNCHOBJECT \
|
|
}
|
|
|
|
#define SLOCKFRAG2_8(x) \
|
|
FRAG2(SynchLock ## x ## Frag8, unsigned char) \
|
|
{ \
|
|
GET_SYNCHOBJECT \
|
|
x ## Frag8 (cpu, pop1, op2); \
|
|
RELEASE_SYNCHOBJECT \
|
|
}
|
|
|
|
#define SLOCKFRAG2REF_8(x) \
|
|
FRAG2REF(SynchLock ## x ## Frag8, unsigned char) \
|
|
{ \
|
|
GET_SYNCHOBJECT \
|
|
x ## Frag8 (cpu, pop1, pop2); \
|
|
RELEASE_SYNCHOBJECT \
|
|
}
|
|
|
|
|
|
//
|
|
// Macros for 16 bit fragments
|
|
//
|
|
#define SLOCKFRAG1_16(x) \
|
|
FRAG1(SynchLock ## x ## Frag16, unsigned short) \
|
|
{ \
|
|
GET_SYNCHOBJECT \
|
|
x ## Frag16 (cpu, pop1); \
|
|
RELEASE_SYNCHOBJECT \
|
|
}
|
|
|
|
#define SLOCKFRAG2_16(x) \
|
|
FRAG2(SynchLock ## x ## Frag16, unsigned short) \
|
|
{ \
|
|
GET_SYNCHOBJECT \
|
|
x ## Frag16 (cpu, pop1, op2); \
|
|
RELEASE_SYNCHOBJECT \
|
|
}
|
|
|
|
#define SLOCKFRAG2REF_16(x) \
|
|
FRAG2REF(SynchLock ## x ## Frag16, unsigned short) \
|
|
{ \
|
|
GET_SYNCHOBJECT \
|
|
x ## Frag16 (cpu, pop1, pop2); \
|
|
RELEASE_SYNCHOBJECT \
|
|
}
|
|
|
|
|
|
//
|
|
// Macros for 32 bit fragments
|
|
// Note: in the 32bit case, we check if pop1 is aligned and
|
|
// call the lock version if it is.
|
|
//
|
|
|
|
|
|
#define SLOCKFRAG1_32(x) \
|
|
FRAG1(SynchLock ## x ## Frag32, unsigned long) \
|
|
{ \
|
|
GET_SYNCHOBJECT \
|
|
if (((ULONG)(ULONGLONG)pop1 & 0x3) == 0){ \
|
|
Lock ## x ## Frag32 (cpu, pop1); \
|
|
} else { \
|
|
x ## Frag32 (cpu, pop1); \
|
|
} \
|
|
RELEASE_SYNCHOBJECT \
|
|
}
|
|
|
|
|
|
#define SLOCKFRAG2_32(x) \
|
|
FRAG2(SynchLock ## x ## Frag32, unsigned long) \
|
|
{ \
|
|
GET_SYNCHOBJECT \
|
|
if (((ULONG) (ULONGLONG)pop1 & 0x3) == 0){ \
|
|
Lock ## x ## Frag32 (cpu, pop1, op2); \
|
|
} else { \
|
|
x ## Frag32 (cpu, pop1, op2); \
|
|
} \
|
|
RELEASE_SYNCHOBJECT \
|
|
}
|
|
|
|
#define SLOCKFRAG2REF_32(x) \
|
|
FRAG2REF(SynchLock ## x ## Frag32, unsigned long) \
|
|
{ \
|
|
GET_SYNCHOBJECT \
|
|
if (((ULONG)(ULONGLONG)pop1 & 0x3) == 0){ \
|
|
Lock ## x ## Frag32 (cpu, pop1, pop2); \
|
|
} else { \
|
|
x ## Frag32 (cpu, pop1, pop2); \
|
|
} \
|
|
RELEASE_SYNCHOBJECT \
|
|
}
|
|
|
|
//
|
|
// Monster macros!
|
|
//
|
|
#define SLOCKFRAG1(x) \
|
|
SLOCKFRAG1_8(x) \
|
|
SLOCKFRAG1_16(x) \
|
|
SLOCKFRAG1_32(x)
|
|
|
|
#define SLOCKFRAG2(x) \
|
|
SLOCKFRAG2_8(x) \
|
|
SLOCKFRAG2_16(x) \
|
|
SLOCKFRAG2_32(x)
|
|
|
|
#define SLOCKFRAG2REF(x) \
|
|
SLOCKFRAG2REF_8(x) \
|
|
SLOCKFRAG2REF_16(x) \
|
|
SLOCKFRAG2REF_32(x)
|
|
|
|
|
|
//
|
|
// Now finally the actual fragments
|
|
//
|
|
|
|
|
|
|
|
SLOCKFRAG2(Add)
|
|
SLOCKFRAG2(Or)
|
|
SLOCKFRAG2(Adc)
|
|
SLOCKFRAG2(Sbb)
|
|
SLOCKFRAG2(And)
|
|
SLOCKFRAG2(Sub)
|
|
SLOCKFRAG2(Xor)
|
|
SLOCKFRAG1(Not)
|
|
SLOCKFRAG1(Neg)
|
|
SLOCKFRAG1(Inc)
|
|
SLOCKFRAG1(Dec)
|
|
SLOCKFRAG2REF(Xchg)
|
|
SLOCKFRAG2REF(Xadd)
|
|
SLOCKFRAG2REF(CmpXchg)
|
|
FRAG2REF(SynchLockCmpXchg8bFrag32, ULONGLONG)
|
|
{
|
|
GET_SYNCHOBJECT
|
|
if (((ULONG)(ULONGLONG)pop1 & 0x7) == 0){
|
|
LockCmpXchg8bFrag32 (cpu, pop1, pop2);
|
|
} else {
|
|
CmpXchg8bFrag32 (cpu, pop1, pop2);
|
|
}
|
|
RELEASE_SYNCHOBJECT
|
|
}
|
|
|
|
//
|
|
// Bts, Btr and Btc only come in 16bit and 32bit flavors
|
|
//
|
|
SLOCKFRAG2_16(BtsMem)
|
|
SLOCKFRAG2_16(BtsReg)
|
|
SLOCKFRAG2_16(BtrMem)
|
|
SLOCKFRAG2_16(BtrReg)
|
|
SLOCKFRAG2_16(BtcMem)
|
|
SLOCKFRAG2_16(BtcReg)
|
|
|
|
SLOCKFRAG2_32(BtsMem)
|
|
SLOCKFRAG2_32(BtsReg)
|
|
SLOCKFRAG2_32(BtrMem)
|
|
SLOCKFRAG2_32(BtrReg)
|
|
SLOCKFRAG2_32(BtcMem)
|
|
SLOCKFRAG2_32(BtcReg)
|