; -*- Mode: asm; tab-width: 8; c-basic-offset: 4 -*-
; ***** BEGIN LICENSE BLOCK *****
; Version: MPL 1.1/GPL 2.0/LGPL 2.1
;
; The contents of this file are subject to the Mozilla Public License Version
; 1.1 (the "License"); you may not use this file except in compliance with
; the License. You may obtain a copy of the License at
; http://www.mozilla.org/MPL/
;
; Software distributed under the License is distributed on an "AS IS" basis,
; WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
; for the specific language governing rights and limitations under the
; License.
;
; The Original Code is the Netscape Portable Runtime (NSPR).
;
; The Initial Developer of the Original Code is
; IBM Corporation.
; Portions created by the Initial Developer are Copyright (C) 2001
; the Initial Developer. All Rights Reserved.
;
; Contributor(s):
;
; Alternatively, the contents of this file may be used under the terms of
; either the GNU General Public License Version 2 or later (the "GPL"), or
; the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
; in which case the provisions of the GPL or the LGPL are applicable instead
; of those above. If you wish to allow use of your version of this file only
; under the terms of either the GPL or the LGPL, and not to allow others to
; use your version of this file under the terms of the MPL, indicate your
; decision by deleting the provisions above and replace them with the notice
; and other provisions required by the GPL or the LGPL. If you do not delete
; the provisions above, a recipient may use your version of this file under
; the terms of any one of the MPL, the GPL or the LGPL.
;
; ***** END LICENSE BLOCK *****
; Windows uses inline assembly for their atomic functions, so we have
; 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
ASSUME CS:FLAT, DS:FLAT, SS:FLAT, ES:FLAT, FS:FLAT
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 USE32 PUBLIC 'CODE'
PUBLIC SemRequest486
PUBLIC SemReleasex86
PUBLIC _PR_MD_ATOMIC_SET
PUBLIC _PR_MD_ATOMIC_ADD
PUBLIC _PR_MD_ATOMIC_INCREMENT
PUBLIC _PR_MD_ATOMIC_DECREMENT
;;;---------------------------------------------------------------------------
;;; 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 10H
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 short 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 short 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 10H
SemReleasex86 PROC
test edx, SEM_RELEASE_UNOWNED ; If set, don't bother
jnz short 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 short rel_notowner
rel_ownerok:
test edx, SEM_RELEASE_ALL
jnz short rel_clear
lock dec (ramsem PTR [eax]).ramsem_cLocks
jnz short 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 short 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
;;;---------------------------------------------------------------------
;;; PRInt32 _Optlink _PR_MD_ATOMIC_SET(PRInt32* val, PRInt32 newval)
;;;---------------------------------------------------------------------
ALIGN 10H
_PR_MD_ATOMIC_SET proc
lock xchg dword ptr [eax],edx
mov eax, edx;
ret
_PR_MD_ATOMIC_SET endp
;;;---------------------------------------------------------------------
;;; PRInt32 _Optlink _PR_MD_ATOMIC_ADD(PRInt32* ptr, PRInt32 val)
;;;---------------------------------------------------------------------
ALIGN 10H
_PR_MD_ATOMIC_ADD proc
mov ecx, edx
lock xadd dword ptr [eax], edx
mov eax, edx
add eax, ecx
ret
_PR_MD_ATOMIC_ADD endp
;;;---------------------------------------------------------------------
;;; PRInt32 _Optlink _PR_MD_ATOMIC_INCREMENT(PRInt32* val)
;;;---------------------------------------------------------------------
ALIGN 10H
_PR_MD_ATOMIC_INCREMENT proc
mov edx, 1
lock xadd dword ptr [eax], edx
mov eax, edx
inc eax
ret
_PR_MD_ATOMIC_INCREMENT endp
;;;---------------------------------------------------------------------
;;; PRInt32 _Optlink _PR_MD_ATOMIC_DECREMENT(PRInt32* val)
;;;---------------------------------------------------------------------
ALIGN 10H
_PR_MD_ATOMIC_DECREMENT proc
mov edx, 0ffffffffh
lock xadd dword ptr [eax], edx
mov eax, edx
dec eax
ret
_PR_MD_ATOMIC_DECREMENT endp
CODE32 ENDS
END
syntax highlighted by Code2HTML, v. 0.9.1