home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / fastmutx.zip / os2SysLib.pas < prev    next >
Pascal/Delphi Source File  |  1996-07-11  |  6KB  |  137 lines

  1. {$A-,B-,D+,E-,F-,G-,I-,L+,N-,O-,P-,Q-,R-,S-,T-,V-,X+,Y+}
  2. {&AlignCode-,AlignData-,AlignRec-,Asm-,Cdecl-,Delphi+,W-,Frame-,G3+}
  3. {&LocInfo+,Optimise+,OrgName-,SmartLink+,Speed-,Z-,ZD-}
  4. Unit os2SysLib;
  5.  
  6. Interface uses os2def, os2base;
  7.  
  8. type
  9.     { Fast MUTEX semaphore type }
  10.       tMutexSem = record
  11.        Next  : Pointer;                { Next thread ID requesting ownership }
  12.        Owner : TID;     { Current semaphore owner; bit 31 = semaphore in use }
  13.        Count : Longint;                   { For recursive semaphore requests }
  14.       end;
  15.  
  16. { Initialize an [F]ast [M]utex [S]emaphore }
  17.  Function  fmsInit(var Sem : tMutexSem) : boolean;
  18. { Request a semaphore; wait until semaphore is available }
  19.  Function  fmsRequest(var Sem : tMutexSem) : boolean;
  20. { Release semaphore; return TRUE if o.k.; FALSE if caller is not owner }
  21.  Function  fmsRelease(var Sem : tMutexSem) : boolean;
  22. { Check if semaphore is owned; DO NOT RELY ON THIS! }
  23.  Function  fmsCheck(var Sem : tMutexSem) : boolean;
  24.  
  25. Implementation
  26.  
  27. function fmsInit; assembler {&uses none};
  28. asm             mov     ecx,Sem
  29.            lock bts     [ecx].tMutexSem.Owner,31      {Lock semaphore updates}
  30.                 jnc     @@ok
  31.                 mov     al,0
  32.                 ret     4
  33. @@ok:           xor     eax,eax
  34.                 mov     [ecx].tMutexSem.Next,eax
  35.            lock xchg    [ecx].tMutexSem.Owner,eax
  36.                 mov     al,1
  37. end;
  38.  
  39. function fmsRequest; assembler {&uses none};
  40. asm             mov     eax,fs:[12]            {Get ^Thread Information Block}
  41.                 push    dword ptr [eax]                      {Owner : Longint}
  42.                 push    eax                                   {Next : Pointer}
  43. @@testSem:      mov     ecx,Sem[4+4]                      {+4+4 since &frame-}
  44.            lock bts     [ecx].tMutexSem.Owner,31
  45.                 jnc     @@semFree
  46.                 push    0          {There is no hurry since semaphore is busy}
  47.                 call    DosSleep                  {Go to sleep for a while...}
  48.                 add     esp,4
  49.                 jmp     @@testSem
  50.  
  51. @@semFree:      mov     edx,[ecx].tMutexSem.Owner        {Get semaphore owner}
  52.                 btr     edx,31                     {Reset `semaphor busy` bit}
  53.                 cmp     edx,[esp+4]                     {Owner = current TID?}
  54.                 jne     @@notOur
  55.                 inc     [ecx].tMutexSem.Count
  56.            lock btr     [ecx].tMutexSem.Owner,31           {Release semaphore}
  57.                 add     esp,4+4
  58.                 mov     al,1
  59.                 ret     4
  60.  
  61. @@notOur:       mov     eax,esp
  62.                 xchg    eax,[ecx].tMutexSem.Next
  63.                 test    edx,edx                                   {Owner = 0?}
  64.                 jz      @@notBusy
  65.                 mov     [esp],eax                              {Save ^nextTID}
  66.            lock btr     [ecx].tMutexSem.Owner,31           {Release semaphore}
  67.                 push    dword ptr [esp+4]                            {Our TID}
  68.                 call    SuspendThread                     {Sleep until wakeup}
  69.                 add     esp,4+4
  70.                 mov     al,1
  71.                 ret     4
  72.  
  73. @@notBusy:      xchg    eax,[ecx].tMutexSem.Next
  74.                 inc     edx
  75.                 mov     [ecx].tMutexSem.Count,edx          {Request count = 1}
  76.                 pop     eax                                    {Skip ^nextTID}
  77.                 pop     eax
  78.            lock xchg    [ecx].tMutexSem.Owner,eax {Set owner&unlock semaphore}
  79.                 mov     al,1
  80. end;
  81.  
  82. function fmsRelease; assembler {&uses none};
  83. asm
  84. @@testSem:      mov     ecx,Sem
  85.            lock bts     [ecx].tMutexSem.Owner,31      {Lock semaphore updates}
  86.                 jnc     @@semFree
  87.                 push    0
  88.                 call    DosSleep
  89.                 add     esp,4
  90.                 jmp     @@testSem
  91. @@semFree:      mov     eax,fs:[12]
  92.                 mov     eax,[eax]
  93.                 bts     eax,31              {Set bit 31 in EAX for comparison}
  94.                 cmp     eax,[ecx].tMutexSem.Owner
  95.                 je      @@isOur
  96.            lock btr     [ecx].tMutexSem.Owner,31           {Release semaphore}
  97.                 mov     al,0
  98.                 ret     4
  99.  
  100. @@isOur:        dec     [ecx].tMutexSem.Count             {Request count = 1?}
  101.                 jz      @@scanChain
  102.            lock btr     [ecx].tMutexSem.Owner,31           {Release semaphore}
  103.                 mov     al,1
  104.                 ret     4
  105.  
  106. @@scanChain:    mov     edx,eax
  107.                 mov     eax,ecx
  108.                 mov     ecx,[ecx].tMutexSem.Next                    {^nextTID}
  109.                 test    ecx,ecx
  110.                 jnz     @@scanChain
  111.                 mov     ecx,Sem
  112.                 cmp     eax,ecx
  113.                 je      @@onlyOwner                  {Thread is only in chain}
  114.                 mov     [edx].tMutexSem.Next,0      {Remove thread from chain}
  115.                 mov     [ecx].tMutexSem.Count,1       {Set request count to 1}
  116.                 mov     eax,[eax].tMutexSem.Owner
  117.                 push    eax                          {ResumeThread(TID = EAX)}
  118.            lock xchg    [ecx].tMutexSem.Owner,eax{Make thread semaphore owner}
  119.                 call    ResumeThread                          {Wake up thread}
  120.                 mov     al,1
  121.                 ret     4
  122.  
  123. @@onlyOwner:    xor     eax,eax
  124.            lock xchg    eax,[ecx].tMutexSem.Owner
  125.                 mov     al,1
  126. end;
  127.  
  128. function fmsCheck; assembler {&uses none};
  129. asm             mov     eax,Sem
  130.                 mov     eax,[eax].tMutexSem.Owner
  131.                 and     eax,7FFFFFFFh
  132.                 setz    al
  133. end;
  134.  
  135. end.
  136.  
  137.