typedef class mutex_lock
{
public:
mutex_lock()
: LockCount(-1)
, hEvent(0)
{
}
~mutex_lock()
{
if(NULL != this->hEvent)
{
CloseHandle(this->hEvent);
}
this->hEvent = NULL;
this->LockCount = -1;
}
long GetLock();
long ReleaseLock();
private:
mutex_lock(mutex_lock&);
long LockCount;
HANDLE hEvent;
} MUTEXLOCK, *LPMUTEXLOCK;
long mutex_lock::GetLock()
{
__asm
{
mov ebx, [this]; // 把基址保存在ebx中
lock inc dword ptr [ebx]; // 对LockCount进行加锁加,保证多CPU时的唯一性,
je LRET1; // 如果LockCount加1为0的话,表示没有人在使用资源,同时利用上面的互斥加对资源进行占用。
cmp dword ptr [ebx+4], 0; // 此时LockCount加1大于0的情况,表示已有人使用此资源,要对此资源进行加内核锁
jne L1; // 如果平常没有创建内核锁,则进行创始一个
push 0;
push 0;
push 0;
push 0;
call dword ptr [CreateEvent];
mov edx, eax; // 创建内存锁成功后,在同样对hEvent变量进行互斥比较后替换,以处理多个线程同时对此值进行替换的情况,保证只有一个能够成功替换
mov eax, 0;
lock cmpxchg dword ptr [ebx+4], edx; // 互斥比较替换
je L1;
push edx; // 如果已经被别人替换过了,需要把自己创建的内核锁释放
call dword ptr [CloseHandle];
L1:
push INFINITE;
push [ebx+4];
call dword ptr [WaitForSingleObject]; // 在内核级进行等待
LRET1:
mov eax, 0
}
}
long mutex_lock::ReleaseLock()
{
__asm
{
mov ebx, [this]; // 把基址保存在ebx中
mov eax, -1;
lock xadd dword ptr [ebx], eax; // 进行交换自减交换操作,运行后,eax中是第一操作数先前的值,此值用会返回用来判断是否多调用了ReleaseLock
jl LRET2; // 没有别的线程占用资源,直接返回,用户可以通过返回值,分析是否失败
cmp dword ptr [ebx+4], 0; // 有别的线程在等待,检查内核锁,如果没有则进行创建
jne L2;
push 0;
push 0;
push 0;
push 0;
call dword ptr [CreateEvent];
mov edx, eax;
mov eax, 0;
lock cmpxchg dword ptr [ebx+4], edx; // 互斥替换内核锁句柄
je L2; // 已经有内核锁了,把自已申请的关闭
push edx;
call dword ptr [CloseHandle];
L2:
push [ebx+4]; // 设计信号,唤醒一个线程
call dword ptr [SetEvent];
mov eax, 0;
LRET2:
}
}