mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-23 19:09:49 +00:00
Add "fast RAM semaphore" support.
Thanks to Mike Kaply <mkaply@us.ibm.com> for the patch. Bug #125123 r=wtc
This commit is contained in:
parent
98bb38ac3e
commit
5aa65e3ac5
@ -47,6 +47,33 @@
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#define USE_RAMSEM
|
||||
|
||||
#ifdef USE_RAMSEM
|
||||
#pragma pack(4)
|
||||
|
||||
#pragma pack(2)
|
||||
typedef struct _RAMSEM
|
||||
{
|
||||
ULONG ulTIDPID;
|
||||
ULONG hevSem;
|
||||
ULONG cLocks;
|
||||
USHORT cWaiting;
|
||||
USHORT cPosts;
|
||||
} RAMSEM, *PRAMSEM;
|
||||
|
||||
typedef struct _CRITICAL_SECTION
|
||||
{
|
||||
ULONG ulReserved[4]; /* Same size as RAMSEM */
|
||||
} CRITICAL_SECTION, *PCRITICAL_SECTION, *LPCRITICAL_SECTION;
|
||||
#pragma pack(4)
|
||||
|
||||
VOID APIENTRY DeleteCriticalSection(PCRITICAL_SECTION);
|
||||
VOID APIENTRY EnterCriticalSection(PCRITICAL_SECTION);
|
||||
VOID APIENTRY InitializeCriticalSection(PCRITICAL_SECTION);
|
||||
VOID APIENTRY LeaveCriticalSection(PCRITICAL_SECTION);
|
||||
#endif
|
||||
|
||||
#ifdef XP_OS2_EMX
|
||||
/*
|
||||
* EMX-specific tweaks:
|
||||
@ -162,7 +189,11 @@ struct _MDNotified {
|
||||
};
|
||||
|
||||
struct _MDLock {
|
||||
HMTX mutex; /* this is recursive on NT */
|
||||
#ifdef USE_RAMSEM
|
||||
CRITICAL_SECTION mutex; /* this is recursive on NT */
|
||||
#else
|
||||
HMTX mutex; /* this is recursive on NT */
|
||||
#endif
|
||||
|
||||
/*
|
||||
* When notifying cvars, there is no point in actually
|
||||
|
@ -48,6 +48,40 @@
|
||||
|
||||
#include "primpl.h"
|
||||
|
||||
#ifdef USE_RAMSEM
|
||||
ULONG _Far16 _Pascal Dos16GetInfoSeg(PSEL pselGlobal, PSEL pselLocal);
|
||||
APIRET _Optlink SemRequest486(PRAMSEM, ULONG);
|
||||
APIRET _Optlink SemReleasex86(PRAMSEM, ULONG);
|
||||
|
||||
typedef struct _LINFOSEG
|
||||
{
|
||||
USHORT pidCurrent;
|
||||
USHORT pidParent;
|
||||
USHORT prtyCurrent;
|
||||
USHORT tidCurrent;
|
||||
USHORT sgCurrent;
|
||||
UCHAR rfProcStatus;
|
||||
UCHAR dummy1;
|
||||
BOOL16 fForeground;
|
||||
UCHAR typProcess;
|
||||
UCHAR dummy2;
|
||||
SEL selEnvironment;
|
||||
USHORT offCmdLine;
|
||||
USHORT cbDataSegment;
|
||||
USHORT cbStack;
|
||||
USHORT cbHeap;
|
||||
USHORT hmod;
|
||||
SEL selDS;
|
||||
SEL selPack;
|
||||
SEL selPackShr;
|
||||
SEL selPackPck;
|
||||
ULONG ulReserved;
|
||||
} LINFOSEG;
|
||||
typedef LINFOSEG FAR *PLINFOSEG;
|
||||
|
||||
PLINFOSEG plisCurrent = NULL;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* AddThreadToCVWaitQueueInternal --
|
||||
*
|
||||
@ -163,7 +197,11 @@ md_UnlockAndPostNotifies(
|
||||
}
|
||||
|
||||
/* Release the lock before notifying */
|
||||
DosReleaseMutexSem(lock->mutex);
|
||||
#ifdef USE_RAMSEM
|
||||
SemReleasex86(&lock->mutex, 0);
|
||||
#else
|
||||
DosReleaseMutexSem(lock->mutex);
|
||||
#endif
|
||||
|
||||
notified = &post; /* this is where we start */
|
||||
do {
|
||||
@ -270,7 +308,11 @@ _PR_MD_WAIT_CV(_MDCVar *cv, _MDLock *lock, PRIntervalTime timeout )
|
||||
md_UnlockAndPostNotifies(lock, thred, cv);
|
||||
} else {
|
||||
AddThreadToCVWaitQueueInternal(thred, cv);
|
||||
#ifdef USE_RAMSEM
|
||||
SemReleasex86( &lock->mutex, 0 );
|
||||
#else
|
||||
DosReleaseMutexSem(lock->mutex);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Wait for notification or timeout; don't really care which */
|
||||
@ -279,7 +321,11 @@ _PR_MD_WAIT_CV(_MDCVar *cv, _MDLock *lock, PRIntervalTime timeout )
|
||||
DosResetEventSem(thred->md.blocked_sema, &count);
|
||||
}
|
||||
|
||||
#ifdef USE_RAMSEM
|
||||
SemRequest486(&(lock->mutex), -1);
|
||||
#else
|
||||
DosRequestMutexSem((lock->mutex), SEM_INDEFINITE_WAIT);
|
||||
#endif
|
||||
|
||||
PR_ASSERT(rv == NO_ERROR || rv == ERROR_TIMEOUT);
|
||||
|
||||
@ -336,27 +382,70 @@ _PR_MD_NOTIFY_CV(_MDCVar *cv, _MDLock *lock)
|
||||
PRStatus
|
||||
_PR_MD_NEW_LOCK(_MDLock *lock)
|
||||
{
|
||||
#ifdef USE_RAMSEM
|
||||
// It's better if this API traps when pCriticalSect is not a valid
|
||||
// pointer, because we can't return an error code and if we just return
|
||||
// the API caller will have nasty bugs that are hard to find.
|
||||
|
||||
PRAMSEM pramsem = (PRAMSEM)(&(lock->mutex));
|
||||
/* First time, set up addresses of processor specific functions
|
||||
*/
|
||||
if (plisCurrent == NULL)
|
||||
{
|
||||
SEL selGlobal = 0, selLocal = 0;
|
||||
|
||||
/* Convert 16 bit global information segment to 32 bit address
|
||||
* by performing CRMA on the 16 bit address: "shift" operation
|
||||
* to convert sel to flat, "and" operation to mask the address
|
||||
* to 32-bit
|
||||
*/
|
||||
Dos16GetInfoSeg(&selGlobal, &selLocal);
|
||||
plisCurrent = (PLINFOSEG)(((ULONG)selLocal << 13) &
|
||||
(ULONG)0x1fff0000);
|
||||
|
||||
}
|
||||
|
||||
memset(pramsem, 0, sizeof(pramsem));
|
||||
DosCreateEventSem(0, &pramsem->hevSem, DC_SEM_SHARED, 0);
|
||||
|
||||
lock->notified.length=0;
|
||||
lock->notified.link=NULL;
|
||||
return PR_SUCCESS;
|
||||
#else
|
||||
DosCreateMutexSem(0, &(lock->mutex), 0, 0);
|
||||
(lock)->notified.length=0;
|
||||
(lock)->notified.link=NULL;
|
||||
return PR_SUCCESS;
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
_PR_MD_FREE_LOCK(_MDLock *lock)
|
||||
{
|
||||
#ifdef USE_RAMSEM
|
||||
DosCloseEventSem(((PRAMSEM)(&(lock->mutex)))->hevSem);
|
||||
#else
|
||||
DosCloseMutexSem(lock->mutex);
|
||||
#endif
|
||||
}
|
||||
|
||||
void _PR_MD_LOCK(_MDLock *lock)
|
||||
{
|
||||
#ifdef USE_RAMSEM
|
||||
SemRequest486(&(lock->mutex), -1);
|
||||
#else
|
||||
DosRequestMutexSem(lock->mutex, SEM_INDEFINITE_WAIT);
|
||||
#endif
|
||||
}
|
||||
|
||||
PRIntn
|
||||
_PR_MD_TEST_AND_LOCK(_MDLock *lock)
|
||||
{
|
||||
#ifdef USE_RAMSEM
|
||||
SemRequest486(&(lock->mutex), -1);
|
||||
#else
|
||||
DosRequestMutexSem(lock->mutex, SEM_INDEFINITE_WAIT);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -373,7 +462,11 @@ _PR_MD_UNLOCK(_MDLock *lock)
|
||||
if (0 != lock->notified.length) {
|
||||
md_UnlockAndPostNotifies(lock, NULL, NULL);
|
||||
} else {
|
||||
#ifdef USE_RAMSEM
|
||||
SemReleasex86( &lock->mutex, 0 );
|
||||
#else
|
||||
DosReleaseMutexSem(lock->mutex);
|
||||
#endif
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -30,20 +30,258 @@ COMMENT | -*- Mode: asm; tab-width: 8; c-basic-offset: 4 -*-
|
||||
GPL.
|
||||
|
||||
Windows uses inline assembly for their atomic functions, so we have
|
||||
created an assembly file for VACPP on OS/2
|
||||
created an assembly file for VACPP on OS/2.
|
||||
|
||||
This assembly file also contains an implementation of RAM semaphores.
|
||||
|
||||
Notes:
|
||||
The ulTIDPID element of the RAMSEM structure is overloaded in the 386
|
||||
implementation to hold the TID:PID in the lower 31 bits and the lock
|
||||
bit in the high bit
|
||||
|
|
||||
page ,132
|
||||
|
||||
.486P
|
||||
.MODEL FLAT, OPTLINK
|
||||
.STACK
|
||||
ASSUME CS:FLAT, DS:FLAT, SS:FLAT, ES:FLAT, FS:FLAT
|
||||
|
||||
.CODE
|
||||
EXTRN Dos32PostEventSem:PROC
|
||||
EXTRN Dos32WaitEventSem:PROC
|
||||
EXTRN Dos32ResetEventSem:PROC
|
||||
|
||||
ramsem STRUC
|
||||
ramsem_ulTIDPID DD ?
|
||||
ramsem_hevSem DD ?
|
||||
ramsem_cLocks DD ?
|
||||
ramsem_cWaiting DW ?
|
||||
ramsem_cPosts DW ?
|
||||
ramsem ENDS
|
||||
|
||||
ERROR_SEM_TIMEOUT equ 121
|
||||
ERROR_NOT_OWNER equ 288
|
||||
SEM_RELEASE_UNOWNED equ 1
|
||||
SEM_RELEASE_ALL equ 2
|
||||
TS_LOCKBIT equ 31
|
||||
|
||||
|
||||
DATA SEGMENT DWORD USE32 PUBLIC 'DATA'
|
||||
|
||||
EXTRN plisCurrent:DWORD
|
||||
|
||||
DATA ENDS
|
||||
|
||||
CODE32 SEGMENT DWORD USE32 PUBLIC 'CODE'
|
||||
|
||||
PUBLIC SemRequest386
|
||||
PUBLIC SemRequest486
|
||||
PUBLIC SemReleasex86
|
||||
|
||||
PUBLIC _PR_MD_ATOMIC_SET
|
||||
PUBLIC _PR_MD_ATOMIC_ADD
|
||||
PUBLIC _PR_MD_ATOMIC_INCREMENT
|
||||
PUBLIC _PR_MD_ATOMIC_DECREMENT
|
||||
|
||||
;;; RAM Semaphores
|
||||
|
||||
;;;---------------------------------------------------------------------------
|
||||
;;; APIRET _Optlink SemRequest(PRAMSEM pramsem, ULONG ulTimeout);
|
||||
;;;
|
||||
;;; Registers:
|
||||
;;; EAX - packed TID:PID word
|
||||
;;; ECX - address of RAMSEM structure
|
||||
;;; EDX - length of timeout in milli-seconds
|
||||
;;;---------------------------------------------------------------------------
|
||||
|
||||
ALIGN 04H
|
||||
SemRequest386 PROC
|
||||
mov ecx, eax ; For consistency use ecx
|
||||
; for PRAMSEM (see 486 imp)
|
||||
|
||||
push ebx ; Save ebx (volatile)
|
||||
mov ebx, dword ptr [plisCurrent]
|
||||
mov eax, dword ptr [ebx+4] ; Place thread id in high
|
||||
; word, process id in low
|
||||
mov ax, word ptr [ebx] ; word
|
||||
pop ebx ; Restore ebx
|
||||
|
||||
req386_test:
|
||||
push eax
|
||||
sub eax, (ramsem PTR [ecx]).ramsem_ulTIDPID ; This thread the owner?
|
||||
shl eax,1 ; Don't compare top bit
|
||||
pop eax
|
||||
jz req386_inc_exit ; increment the use count
|
||||
|
||||
lock inc (ramsem PTR [ecx]).ramsem_cWaiting ; inc waiting flag
|
||||
|
||||
; lock ; Uncomment for SMP
|
||||
lock bts (ramsem PTR [ecx]).ramsem_ulTIDPID, 31 ; Use the high bit as the
|
||||
jc req386_sleep ; semaphore
|
||||
or (ramsem PTR [ecx]).ramsem_ulTIDPID, eax ; Copy the rest of the bits
|
||||
|
||||
req386_inc_exit:
|
||||
lock inc (ramsem PTR [ecx]).ramsem_cLocks
|
||||
xor eax,eax
|
||||
|
||||
req386_exit:
|
||||
ret
|
||||
|
||||
req386_sleep:
|
||||
push eax ; Save eax (volatile)
|
||||
push ecx ; Save ecx (volatile)
|
||||
push edx ; Save edx (volatile)
|
||||
push edx ; timeout
|
||||
push (ramsem PTR [ecx]).ramsem_hevSem
|
||||
call Dos32WaitEventSem
|
||||
add esp, 8
|
||||
pop edx ; restore edx
|
||||
pop ecx ; restore ecx
|
||||
or eax, eax
|
||||
je req386_reset ; If no error, reset
|
||||
pop edx ; junk stored eax
|
||||
jmp req386_exit ; Exit, timed out
|
||||
|
||||
req386_reset:
|
||||
push ecx ; Save ecx (volatile)
|
||||
push edx ; Save edx (volatile)
|
||||
sub esp, 4 ; Use stack space for
|
||||
push esp ; dummy pulPostCt
|
||||
push (ramsem PTR [ecx]).ramsem_hevSem
|
||||
call Dos32ResetEventSem
|
||||
add esp, 12
|
||||
pop edx ; restore edx
|
||||
pop ecx ; restore ecx
|
||||
pop eax ; restore eax
|
||||
jmp req386_test ; Retry the semaphore
|
||||
SemRequest386 ENDP
|
||||
|
||||
ALIGN 04H
|
||||
SemRequest486 PROC
|
||||
push ebx ; Save ebx (volatile)
|
||||
mov ecx, eax ; PRAMSEM must be in ecx,
|
||||
; not eax, for cmpxchg
|
||||
|
||||
mov ebx, dword ptr [plisCurrent]
|
||||
mov eax, dword ptr [ebx+4] ; Place thread id in high
|
||||
; word, process id in low
|
||||
mov ax, word ptr [ebx] ; word
|
||||
mov ebx,eax
|
||||
|
||||
req486_test:
|
||||
xor eax,eax
|
||||
cmp (ramsem PTR [ecx]).ramsem_ulTIDPID, ebx ; If we own the sem, just
|
||||
jz req486_inc_exit ; increment the use count
|
||||
|
||||
lock inc (ramsem PTR [ecx]).ramsem_cWaiting ; inc waiting flag
|
||||
|
||||
; lock ; Uncomment for SMP
|
||||
DB 0F0h
|
||||
; cmpxchg (ramsem PTR [ecx]).ramsem_ulTIDPID, ebx
|
||||
; (byte 3 is the offset of ulProcessThread into the RAMSEM structure)
|
||||
DB 00Fh
|
||||
DB 0B1h
|
||||
DB 019h
|
||||
jnz req486_sleep
|
||||
|
||||
req486_inc_exit:
|
||||
lock inc (ramsem PTR [ecx]).ramsem_cLocks
|
||||
|
||||
req486_exit:
|
||||
pop ebx ; Restore ebx
|
||||
ret
|
||||
|
||||
req486_sleep:
|
||||
push ecx ; Save ecx (volatile)
|
||||
push edx ; Save edx (volatile)
|
||||
push edx ; timeout
|
||||
push (ramsem PTR [ecx]).ramsem_hevSem
|
||||
call Dos32WaitEventSem
|
||||
add esp, 8
|
||||
pop edx ; restore edx
|
||||
pop ecx ; restore ecx
|
||||
or eax, eax
|
||||
jne req486_exit ; Exit, if error
|
||||
|
||||
push ecx ; Save ecx (volatile)
|
||||
push edx ; Save edx (volatile)
|
||||
sub esp, 4 ; Use stack space for
|
||||
push esp ; dummy pulPostCt
|
||||
push (ramsem PTR [ecx]).ramsem_hevSem
|
||||
call Dos32ResetEventSem
|
||||
add esp, 12
|
||||
pop edx ; restore edx
|
||||
pop ecx ; restore ecx
|
||||
jmp req486_test ; Retry the semaphore
|
||||
|
||||
SemRequest486 ENDP
|
||||
|
||||
;;;---------------------------------------------------------------------
|
||||
;;; APIRET _Optlink SemReleasex86(PRAMSEM pramsem, ULONG flFlags);
|
||||
;;;
|
||||
;;; Registers:
|
||||
;;; EAX - address of RAMSEM structure
|
||||
;;; ECX - temporary variable
|
||||
;;; EDX - flags
|
||||
;;;---------------------------------------------------------------------
|
||||
|
||||
ALIGN 04H
|
||||
SemReleasex86 PROC
|
||||
test edx, SEM_RELEASE_UNOWNED ; If set, don't bother
|
||||
jnz rel_ownerok ; getting/checking PID/TID
|
||||
|
||||
push ebx ; Save ebx (volatile)
|
||||
mov ebx, dword ptr [plisCurrent]
|
||||
mov ecx, dword ptr [ebx+4] ; Place thread id in high
|
||||
; word, process id in low
|
||||
mov cx, word ptr [ebx] ; word
|
||||
pop ebx ; Restore ebx
|
||||
|
||||
sub ecx, (ramsem PTR [eax]).ramsem_ulTIDPID ; This thread the owner?
|
||||
shl ecx,1 ; Don't compare top bit
|
||||
jnz rel_notowner
|
||||
|
||||
rel_ownerok:
|
||||
test edx, SEM_RELEASE_ALL
|
||||
jnz rel_clear
|
||||
|
||||
lock dec (ramsem PTR [eax]).ramsem_cLocks
|
||||
jnz rel_exit
|
||||
|
||||
rel_disown:
|
||||
mov (ramsem PTR [eax]).ramsem_ulTIDPID, 0
|
||||
|
||||
lock inc (ramsem PTR [eax]).ramsem_cPosts
|
||||
mov cx, (ramsem PTR [eax]).ramsem_cWaiting
|
||||
cmp (ramsem PTR [eax]).ramsem_cPosts, cx
|
||||
jne rel_post
|
||||
|
||||
rel_exit:
|
||||
xor eax, eax
|
||||
ret
|
||||
|
||||
rel_clear:
|
||||
lock mov (ramsem PTR [eax]).ramsem_cLocks,0
|
||||
jmp rel_disown
|
||||
|
||||
rel_notowner:
|
||||
mov eax, ERROR_NOT_OWNER
|
||||
ret
|
||||
|
||||
rel_post:
|
||||
mov (ramsem PTR [eax]).ramsem_cPosts, cx
|
||||
push (ramsem PTR [eax]).ramsem_hevSem
|
||||
call Dos32PostEventSem
|
||||
add esp,4
|
||||
xor eax,eax
|
||||
ret
|
||||
|
||||
SemReleasex86 ENDP
|
||||
|
||||
;;; Atomic functions
|
||||
|
||||
;;;---------------------------------------------------------------------
|
||||
;;; PRInt32 _Optlink _PR_MD_ATOMIC_SET(PRInt32* val, PRInt32 newval)
|
||||
;;;---------------------------------------------------------------------
|
||||
_PR_MD_ATOMIC_SET PROC OPTLINK EXPORT
|
||||
lock xchg dword ptr [eax],edx
|
||||
_PR_MD_ATOMIC_SET proc
|
||||
lock xchg dword ptr [eax],edx
|
||||
mov eax, edx;
|
||||
|
||||
ret
|
||||
@ -52,7 +290,7 @@ _PR_MD_ATOMIC_SET endp
|
||||
;;;---------------------------------------------------------------------
|
||||
;;; PRInt32 _Optlink _PR_MD_ATOMIC_ADD(PRInt32* ptr, PRInt32 val)
|
||||
;;;---------------------------------------------------------------------
|
||||
_PR_MD_ATOMIC_ADD PROC OPTLINK EXPORT
|
||||
_PR_MD_ATOMIC_ADD proc
|
||||
mov ecx, edx
|
||||
lock xadd dword ptr [eax], edx
|
||||
mov eax, edx
|
||||
@ -64,7 +302,7 @@ _PR_MD_ATOMIC_ADD endp
|
||||
;;;---------------------------------------------------------------------
|
||||
;;; PRInt32 _Optlink _PR_MD_ATOMIC_INCREMENT(PRInt32* val)
|
||||
;;;---------------------------------------------------------------------
|
||||
_PR_MD_ATOMIC_INCREMENT PROC OPTLINK EXPORT
|
||||
_PR_MD_ATOMIC_INCREMENT proc
|
||||
mov edx, 1
|
||||
lock xadd dword ptr [eax], edx
|
||||
mov eax, edx
|
||||
@ -76,7 +314,7 @@ _PR_MD_ATOMIC_INCREMENT endp
|
||||
;;;---------------------------------------------------------------------
|
||||
;;; PRInt32 _Optlink _PR_MD_ATOMIC_DECREMENT(PRInt32* val)
|
||||
;;;---------------------------------------------------------------------
|
||||
_PR_MD_ATOMIC_DECREMENT PROC OPTLINK EXPORT
|
||||
_PR_MD_ATOMIC_DECREMENT proc
|
||||
mov edx, 0ffffffffh
|
||||
lock xadd dword ptr [eax], edx
|
||||
mov eax, edx
|
||||
@ -85,4 +323,5 @@ _PR_MD_ATOMIC_DECREMENT PROC OPTLINK EXPORT
|
||||
ret
|
||||
_PR_MD_ATOMIC_DECREMENT endp
|
||||
|
||||
END
|
||||
CODE32 ENDS
|
||||
END
|
||||
|
Loading…
x
Reference in New Issue
Block a user