    include infoseg.inc
; static struct InfoSegLDT _Seg16 *pLIS;
    Public	Init_pLIS, CaptureSemaphore, TestSemaphore, ReleaseSemaphore
Init_pLIS	PROC
    push    ebx
    mov     al,DOSVAR_LocInfoSeg      ; get local info seg
    @DevHlp32 DevHlp_GetDOSVar    ; Get index value
    mov	fs,ax
    mov	eax,dword ptr fs:[bx]
    mov [pLIS],eax
    pop    ebx
    ret
Init_pLIS	ENDP
;ULONG CaptureSemaphore( PULONG pSemaphore)
;{
;   ULONG  this_thread = ((ULONG)pLIS->LIS_CurProcID <<16) + pLIS->LIS_CurThrdID;
;
;   if (*pSemaphore == this_thread)
;      _interrupt(3);		// we already own this sem!
;   while(*pSemaphore)
;	ProcBlock(pSemaphore, -1);
;   *pSemaphore == this_thread;
;   return NO_ERROR;
;}

CaptureSemaphore	PROC
   push ebx
   lea	ecx,[eax+edx*4]			; ecx = pboolSemaphore
   push	edi
   lfs  di,pLIS
   mov	dx,fs:[di].LIS_CurProcID
   shl	edx,10h
   mov	dx,fs:[di].LIS_CurThrdID
   ; now edx = (pid <<16) | tid
cap1:
   ; lock cmpxchg [ecx],edx does this:
   ;     ULONG eax, edx, *ecx;
   ;	 if(*ecx == eax) {
   ;		*ecx = edx;
   ;		zf = 1;		//zf is the "zero flag"
   ;	 }
   ;	 else {
   ;  		eax = *ecx;
   ;		zf = 0;
   ;	 }
   xor	eax,eax				; eax = 0
   db	0f0h, 0fh, 0b1h, 11h		; lock cmpxchg [ecx],edx
   jnz	short cap2
   pop	edi
   pop  ebx
   ret
deadlock:
   int  3
cap2:
   cmp  eax,edx
   je   deadlock
   push	ecx
   push	edx
   mov	dh,1			; WAIT_IS_NOT_INTERRUPTIBLE
   mov	ebx,ecx			; AX:BX is blockid, which is now in ecx
   mov	eax,ecx
   shr	eax,10h
   mov	edi,-1
   mov	ecx,edi			; no timeout
   @DevHlp32 DevHlp_ProcBlock
   pop	edx
   pop	ecx
   jmp	cap1
CaptureSemaphore	ENDP

;*--------------------------------------------------------------------------*/
;* Function: test and set semaphore
;       ULONG TestSemaphore(ULONG *pSemaphore, ULONG this_thread)
;  EAX -> pSemaphore
;  EDX -> this_thread
;  return: *pSemaphore (prior to the set)
;pseudo-code:
;ULONG TestSemaphore(PULONG eax, ULONG edx)
;{
;   ULONG  ecx = ((ULONG)pLIS->LIS_CurProcID <<16) + pLIS->LIS_CurThrdID;
;
;   eax += edx;
;   owner = *eax;
;   if (owner == ecx)
;      BreakPoint320();
;
;   if (!owner)
;      *eax = ecx;
;   return owner;
;}
;*--------------------------------------------------------------------------*/
TestSemaphore	PROC
   lea	ecx,[eax+4*edx]
   push	edi
   lfs  di,pLIS
   mov	dx,fs:[di].LIS_CurProcID
   shl	edx,10h
   mov	dx,fs:[di].LIS_CurThrdID
   pop	edi
   ; now edx = (pid <<16) | tid
   xor	eax,eax
   db	0f0h, 0fh, 0b1h, 11h		; lock cmpxchg [ecx],edx (see above)
   jz	short @f			; if it was zero, just return
   cmp	eax,edx				; were we the old owner?
   jne  short @f			; if so, stop here!
   int	3
@@:ret
TestSemaphore	ENDP

;ULONG ReleaseSemaphore( PULONG pSemaphore)
;{
;   ULONG  this_thread =((ULONG)pLIS->LIS_CurProcID <<16) + pLIS->LIS_CurThrdID;
;   
;   if (*pSemaphore != this_thread) {
;      BreakPoint320();
;      return SES_GENERAL_FAILURE;
;   }
;
;   *pboolSemaphore = 0;
;   // there might be no waiters, but do the run, regardldes.
;   devhlp32_Run((ULONG)pboolSemaphore);
;   return SES_NO_ERROR;
;}
;*--------------------------------------------------------------------------*/

ReleaseSemaphore	PROC
   lea	eax,[eax+edx*4]
   push	edi
   lfs  di,pLIS
   mov	dx,fs:[di].LIS_CurProcID
   shl	edx,10h
   mov	dx,fs:[di].LIS_CurThrdID
   pop	edi
   ; now edx = (pid <<16) | tid
   cmp	[eax],edx
   je	short @f
   int	3
@@:
   push	ebx
   mov	dword ptr [eax],0
   mov	ebx,eax
   shr	eax,10H
   @DevHlp32 DevHlp_ProcRun
   xor	eax,eax
   pop	ebx
   ret
ReleaseSemaphore	ENDP
