home *** CD-ROM | disk | FTP | other *** search
/ Troubleshooting Netware Systems / CSTRIAL0196.BIN / attach / msj / v10n05 / dynvxd.exe / VCYCLE.EXE / VCYCLE.C next >
C/C++ Source or Header  |  1995-05-10  |  5KB  |  179 lines

  1. // VCYCLE.c - main module for VxD VCYCLE
  2.  
  3. #define   DEVICE_MAIN
  4. #include  "vcycle.h"
  5. #undef    DEVICE_MAIN
  6.  
  7. Declare_Virtual_Device(VCYCLE)
  8.  
  9. DefineControlHandler(SYS_DYNAMIC_DEVICE_INIT, OnSysDynamicDeviceInit);
  10. DefineControlHandler(SYS_DYNAMIC_DEVICE_EXIT, OnSysDynamicDeviceExit);
  11. DefineControlHandler(CREATE_THREAD, OnCreateThread);
  12. DefineControlHandler(DESTROY_THREAD, OnDestroyThread);
  13. DefineControlHandler(W32_DEVICEIOCONTROL, OnW32Deviceiocontrol);
  14.  
  15. DWORD tcounter = 0xFFFFFFFF;// offset to virtual cell pointer
  16. int nvirtual;               // number of locked virtual timer cells
  17.  
  18. VOID unlockcounter(THREADHANDLE hThread);
  19. VOID threadswitch(THREADHANDLE old, THREADHANDLE new);
  20. THREADHANDLE Get_Next_Thread_Handle_Correctly(THREADHANDLE hThread);
  21.  
  22. BOOL ControlDispatcher(
  23.     DWORD dwControlMessage,
  24.     DWORD EBX,
  25.     DWORD EDX,
  26.     DWORD ESI,
  27.     DWORD EDI)
  28. {
  29.     START_CONTROL_DISPATCH
  30.  
  31.         ON_SYS_DYNAMIC_DEVICE_INIT(OnSysDynamicDeviceInit);
  32.         ON_SYS_DYNAMIC_DEVICE_EXIT(OnSysDynamicDeviceExit);
  33.         ON_CREATE_THREAD(OnCreateThread);
  34.         ON_DESTROY_THREAD(OnDestroyThread);
  35.         ON_W32_DEVICEIOCONTROL(OnW32Deviceiocontrol);
  36.  
  37.     END_CONTROL_DISPATCH
  38.  
  39.     return TRUE;
  40. }
  41.  
  42.  
  43. BOOL OnSysDynamicDeviceInit()
  44. {
  45.     MACHINE_INFO mi;
  46.     Get_Machine_Info(&mi);
  47.     if (!(mi.MI_Type & (GMIF_CPUID >> 16)))
  48.         return FALSE;
  49.     if (!(tcounter = _AllocateThreadDataSlot()))
  50.         return FALSE;
  51.     Call_When_Thread_Switched((PTHREADSWITCH_HANDLER) threadswitch, NULL);
  52.     return TRUE;
  53. }
  54.  
  55. BOOL OnSysDynamicDeviceExit()
  56. {
  57.     if (!Cancel_Call_When_Thread_Switched((PTHREADSWITCH_HANDLER)threadswitch))
  58.         return FALSE;
  59.     if (nvirtual)
  60.         {                   // cleanup locked counter cells
  61.         THREADHANDLE first, thread;
  62.         first = thread = Get_Sys_Thread_Handle();
  63.         do  {               // for each thread
  64.             unlockcounter(thread);
  65.             thread = Get_Next_Thread_Handle_Correctly(thread);
  66.             }               // for each thread
  67.         while (thread != first);
  68.         }                   // cleanup locked counter cells
  69.     _FreeThreadDataSlot(tcounter);
  70.     tcounter = 0xFFFFFFFF;
  71.     return TRUE;
  72. }
  73.  
  74. BOOL OnCreateThread(THREADHANDLE hThread)
  75. {
  76.     if (tcounter != 0xFFFFFFFF)
  77.         *(PDWORD) (hThread + tcounter) = 0;
  78.     return TRUE;
  79. }
  80.  
  81. VOID OnDestroyThread(THREADHANDLE hThread)
  82. {
  83.     if (tcounter != 0xFFFFFFFF)
  84.         unlockcounter(hThread);
  85. }
  86.  
  87. VOID unlockcounter(THREADHANDLE hThread)
  88. {
  89.     PDWORD slot = (PDWORD) (hThread + tcounter);
  90.     if (*slot)
  91.         {                   // unvirtualize timer
  92.         --nvirtual;
  93.         _LinPageUnLock((*slot) >> 12, 1, PAGEMAPGLOBAL);
  94.         *slot = 0;
  95.         }                   // unvirtualize timer
  96. }
  97.  
  98. DWORD OnW32Deviceiocontrol(PIOCTLPARAMS p)
  99. {
  100.     switch (p->dioc_IOCtlCode)
  101.         {                   // select on control code
  102.  
  103.     case DIOC_CLOSEHANDLE:
  104.         return 0;
  105.  
  106.     case DIOC_GETVERSION:
  107.         return 0;
  108.  
  109.     case 1:
  110.         {                   // GETAPPVERSION
  111.         PDWORD pversion = p->dioc_OutBuf;
  112.         PDDB ddb = (PDDB) p->dioc_VxdDDB;
  113.  
  114.         if (p->dioc_cbOutBuf < 4 || !pversion)
  115.             break;          // invalid parameters
  116.         *pversion = (ddb->DDB_Dev_Major_Version << 8) |
  117.             ddb->DDB_Dev_Minor_Version;
  118.         if (p->dioc_bytesret)
  119.             *p->dioc_bytesret = 4;
  120.         return 0;
  121.         }                   // GETAPPVERSION
  122.  
  123.     case 2:
  124.         {                   // VIRTUALIZECOUNTER
  125.         PDWORD pcounter = p->dioc_InBuf;
  126.  
  127.         if (p->dioc_cbInBuf < 4)
  128.             break;          // invalid parameter
  129.         unlockcounter(Get_Cur_Thread_Handle());
  130.         if (*pcounter)
  131.             {               // virtualize timer
  132.             DWORD alias = _LinPageLock(*pcounter >> 12, 1, PAGEMAPGLOBAL);
  133.             PDWORD slot = (PDWORD) (Get_Cur_Thread_Handle() + tcounter);
  134.  
  135.             if (!alias)
  136.                 break;      // couldn't lock page
  137.             *slot = (alias & ~4095) | (*pcounter & 4095);
  138.             }               // virtualize timer
  139.         return 0;
  140.         }                   // VIRTUALIZECOUNTER
  141.  
  142.         }                   // select on control code
  143.  
  144.     return 50;              // ERROR_NOT_SUPPORTED
  145. }
  146.  
  147. VOID __declspec(naked) threadswitch(THREADHANDLE old, THREADHANDLE new)
  148. {
  149. _asm
  150.     {                       // handle thread switch
  151.     mov     ecx, eax        ; save outgoing THCB in safe register
  152.     _emit   0Fh             ; RDTSC
  153.     _emit   31h
  154.  
  155.     add     ecx, tcounter   ; locate outgoing & incoming apps' counters
  156.     add     edi, tcounter   ;   ..
  157.     mov     ecx, [ecx]      ;   ..
  158.     mov     edi, [edi]      ;   ..
  159.  
  160.     test    ecx, ecx        ; update old thread's counter
  161.     jz      junk1           ;   ..
  162.     sub     [ecx], eax      ;   ..
  163.     sbb     [ecx+4], edx    ;   ..
  164. junk1:
  165.     test    edi, edi        ; update new thread's counter
  166.     jz      junk2           ;   ..
  167.     add     [edi], eax      ;   ..
  168.     adc     [edi], edx      ;   ..
  169. junk2:
  170.     ret                     ; return to scheduler
  171.     }                       // handle thread switch
  172. }
  173.  
  174. THREADHANDLE Get_Next_Thread_Handle_Correctly(THREADHANDLE hThread)
  175. {
  176.     _asm mov edi, hThread
  177.     return Get_Next_Thread_Handle();
  178. }
  179.