[parisc-linux] Progress - Update
Mark Klein
mklein@dis.com
Tue, 30 Nov 1999 12:14:59 -0800
At 07:31 PM 11/30/99 +0000, Alan Cox wrote:
> > to use spin_lock_irqsave / spin_unlock_irqrestore on an array of spinlocks
> > indexed by a hash of the address - x86istic code expecting xchg() to be
> > fast is going to suck I'd guess.
>
>You can catch the suitably aligned case. I don't think anyone will have a
>problem
>if you submit patches over time so that critical xchg()'d objects are 16byte
>aligned where it doesnt impact other platforms.
You also have another option:
Create the xchg more as a "compare and swap" and separate the semaphore(s) from
the data. You can always keep the semaphores paragraph aligned and not worry
about where the data falls. Here's a sample of something I've used successfully
for many years:
;
; function CompareSwap(var Semaphore : integer;
; CellAddress : localanyptr;
; OldValue : integer;
; NewValue : integer) : integer;
;
;
; Local Register Use Declarations
;
Semaphore .EQU arg0
CellAddress .EQU arg1
OldValue .EQU arg2
NewValue .EQU arg3
;
; Pause Time Declaration
;
PauseTime .EQU 0x3f4cc800
compareswap .proc
.export compareswap, entry
.import PAUSE,code
ldw 0(0,CellAddress),r20 ; dummy load to avoid page fault
ldcws 0(0,Semaphore),ret0 ; load & clear shared memory
ldw 0(0,CellAddress),r20 ; load contents of Cell into reg20
comibf,=,n 1,ret0,spin ; if sem. locked, go to sleep
combf,=,n r20,OldValue,noteq ; go to noteq if Cell <> OldValue
stw NewValue,0(0,CellAddress) ; save new value into cell
bv r0(rp) ; return from whence we came
stw ret0,0(0,Semaphore) ; reset semaphore to avail
noteq ; the case of Cell <> OldValue
stw ret0,0(0,Semaphore) ; reset semaphore to avail
bv r0(rp) ; return from whence we came
or r0,r0,ret0 ; return false
spin
ldi -50,r19 ; Initialize counter
ldw 0(0,Semaphore),r31 ; Prime the pump
spinagain
comibt,= 1,r31,compareswap ; If so, do it again
ldw 0(0,Semaphore),r31 ; Load Semaphore again
addibt,<=,n 1,r19,spinagain ; Try again if needed.
nop
wait
stw rp,-20(sp) ; .ENTER
ldo 56(sp),sp ; .ENTER
stw arg0, -92(0,sp) ; save var Semaphore
stw arg1, -96(0,sp) ; save CellAddress
stw arg2,-100(0,sp) ; save OldValue
stw arg3,-104(0,sp) ; save NewValue
; prepare to call PAUSE
ldil L'PauseTime,r1 ; build sleep time value
ldo R'PauseTime(r1),r31
stw r31,-52(0,sp); ; save it
ldo -52(sp),arg0 ; fetch address of time value
ldil L'PAUSE,r31 ; construct link to PAUSE
.CALL
ble R'PAUSE(sr4,r31); ; sleep
COPY r31,r2 ; set return address
ldw -92(0,sp),arg0 ; restore var Semaphore
ldw -96(0,sp),arg1 ; restore CellAddress
ldw -100(0,sp),arg2 ; restore OldValue
ldw -104(0,sp),arg3 ; restore NewValue
ldw -76(sp),rp ; restore return pointer
b compareswap ; try lock the semaphore again
ldo -56(sp),sp ; pop stack ptr back to previous one
nop
nop
nop
.callinfo caller, save_rp
.exit
.procend
--
Mark Klein DIS International, Ltd.
http://www.dis.com 415-892-8400
PGP Public Key Available
--