home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Troubleshooting Netware Systems
/
CSTRIAL0196.BIN
/
attach
/
msj
/
v10n05
/
dynvxd.exe
/
VCYCLE.EXE
/
VCYCLE.C
next >
Wrap
C/C++ Source or Header
|
1995-05-10
|
5KB
|
179 lines
// VCYCLE.c - main module for VxD VCYCLE
#define DEVICE_MAIN
#include "vcycle.h"
#undef DEVICE_MAIN
Declare_Virtual_Device(VCYCLE)
DefineControlHandler(SYS_DYNAMIC_DEVICE_INIT, OnSysDynamicDeviceInit);
DefineControlHandler(SYS_DYNAMIC_DEVICE_EXIT, OnSysDynamicDeviceExit);
DefineControlHandler(CREATE_THREAD, OnCreateThread);
DefineControlHandler(DESTROY_THREAD, OnDestroyThread);
DefineControlHandler(W32_DEVICEIOCONTROL, OnW32Deviceiocontrol);
DWORD tcounter = 0xFFFFFFFF;// offset to virtual cell pointer
int nvirtual; // number of locked virtual timer cells
VOID unlockcounter(THREADHANDLE hThread);
VOID threadswitch(THREADHANDLE old, THREADHANDLE new);
THREADHANDLE Get_Next_Thread_Handle_Correctly(THREADHANDLE hThread);
BOOL ControlDispatcher(
DWORD dwControlMessage,
DWORD EBX,
DWORD EDX,
DWORD ESI,
DWORD EDI)
{
START_CONTROL_DISPATCH
ON_SYS_DYNAMIC_DEVICE_INIT(OnSysDynamicDeviceInit);
ON_SYS_DYNAMIC_DEVICE_EXIT(OnSysDynamicDeviceExit);
ON_CREATE_THREAD(OnCreateThread);
ON_DESTROY_THREAD(OnDestroyThread);
ON_W32_DEVICEIOCONTROL(OnW32Deviceiocontrol);
END_CONTROL_DISPATCH
return TRUE;
}
BOOL OnSysDynamicDeviceInit()
{
MACHINE_INFO mi;
Get_Machine_Info(&mi);
if (!(mi.MI_Type & (GMIF_CPUID >> 16)))
return FALSE;
if (!(tcounter = _AllocateThreadDataSlot()))
return FALSE;
Call_When_Thread_Switched((PTHREADSWITCH_HANDLER) threadswitch, NULL);
return TRUE;
}
BOOL OnSysDynamicDeviceExit()
{
if (!Cancel_Call_When_Thread_Switched((PTHREADSWITCH_HANDLER)threadswitch))
return FALSE;
if (nvirtual)
{ // cleanup locked counter cells
THREADHANDLE first, thread;
first = thread = Get_Sys_Thread_Handle();
do { // for each thread
unlockcounter(thread);
thread = Get_Next_Thread_Handle_Correctly(thread);
} // for each thread
while (thread != first);
} // cleanup locked counter cells
_FreeThreadDataSlot(tcounter);
tcounter = 0xFFFFFFFF;
return TRUE;
}
BOOL OnCreateThread(THREADHANDLE hThread)
{
if (tcounter != 0xFFFFFFFF)
*(PDWORD) (hThread + tcounter) = 0;
return TRUE;
}
VOID OnDestroyThread(THREADHANDLE hThread)
{
if (tcounter != 0xFFFFFFFF)
unlockcounter(hThread);
}
VOID unlockcounter(THREADHANDLE hThread)
{
PDWORD slot = (PDWORD) (hThread + tcounter);
if (*slot)
{ // unvirtualize timer
--nvirtual;
_LinPageUnLock((*slot) >> 12, 1, PAGEMAPGLOBAL);
*slot = 0;
} // unvirtualize timer
}
DWORD OnW32Deviceiocontrol(PIOCTLPARAMS p)
{
switch (p->dioc_IOCtlCode)
{ // select on control code
case DIOC_CLOSEHANDLE:
return 0;
case DIOC_GETVERSION:
return 0;
case 1:
{ // GETAPPVERSION
PDWORD pversion = p->dioc_OutBuf;
PDDB ddb = (PDDB) p->dioc_VxdDDB;
if (p->dioc_cbOutBuf < 4 || !pversion)
break; // invalid parameters
*pversion = (ddb->DDB_Dev_Major_Version << 8) |
ddb->DDB_Dev_Minor_Version;
if (p->dioc_bytesret)
*p->dioc_bytesret = 4;
return 0;
} // GETAPPVERSION
case 2:
{ // VIRTUALIZECOUNTER
PDWORD pcounter = p->dioc_InBuf;
if (p->dioc_cbInBuf < 4)
break; // invalid parameter
unlockcounter(Get_Cur_Thread_Handle());
if (*pcounter)
{ // virtualize timer
DWORD alias = _LinPageLock(*pcounter >> 12, 1, PAGEMAPGLOBAL);
PDWORD slot = (PDWORD) (Get_Cur_Thread_Handle() + tcounter);
if (!alias)
break; // couldn't lock page
*slot = (alias & ~4095) | (*pcounter & 4095);
} // virtualize timer
return 0;
} // VIRTUALIZECOUNTER
} // select on control code
return 50; // ERROR_NOT_SUPPORTED
}
VOID __declspec(naked) threadswitch(THREADHANDLE old, THREADHANDLE new)
{
_asm
{ // handle thread switch
mov ecx, eax ; save outgoing THCB in safe register
_emit 0Fh ; RDTSC
_emit 31h
add ecx, tcounter ; locate outgoing & incoming apps' counters
add edi, tcounter ; ..
mov ecx, [ecx] ; ..
mov edi, [edi] ; ..
test ecx, ecx ; update old thread's counter
jz junk1 ; ..
sub [ecx], eax ; ..
sbb [ecx+4], edx ; ..
junk1:
test edi, edi ; update new thread's counter
jz junk2 ; ..
add [edi], eax ; ..
adc [edi], edx ; ..
junk2:
ret ; return to scheduler
} // handle thread switch
}
THREADHANDLE Get_Next_Thread_Handle_Correctly(THREADHANDLE hThread)
{
_asm mov edi, hThread
return Get_Next_Thread_Handle();
}