Mutex: Difference between revisions

Content added Content deleted
m (→‎global mutexes: no promotion)
Line 26: Line 26:


=Sample implementations / APIs=
=Sample implementations / APIs=
=={{header|6502 Assembly}}==
There isn't any hardware support for mutexes, but a simple flag in memory will do. This implementation is more akin to a "starting pistol" for some time-critical process such as the Nintendo Entertainment System's vBlank NMI (Non-Maskable Interrupt) which is typically used to update video memory. The function's parameters are pre-loaded in global memory, but the function that uses them won't be called unless the lock is released. Once all the parameters are ready, the main procedure can wait for the interrupt, after which it releases the lock and waits for the interrupt again. This time, the interrupt routine that needs those parameters is run, and when it's finished, the flag is locked again. For simplicity, most of the hardware-specific routines are omitted (and in reality would require additional mutexes since it usually takes more than one frame to print a long string to the screen.)

''Side note: During a 6502's NMI, other interrupts cannot occur, not even another NMI. Therefore there is no chance that an IRQ will happen while executing NMI code.''

<lang 6502asm>;assume that the NES's screen is active and NMI occurs at the end of every frame.

mutex equ $01 ;these addresses in zero page memory will serve as the global variables.
vblankflag equ $02

main:

;if your time-sensitive function has parameters, pre-load them into global memory here.
;The only thing the NMI should have to do is write the data to the hardware registers.
jsr waitframe
LDA #$01 ;there's not enough time for a second vblank to occur between these two calls to waitframe().
STA mutex ;release the mutex. the next NMI will service the function we just unlocked.
jsr waitframe

halt:
jmp halt

nmi: ;every 1/60th of a second the CPU jumps here automatically.
pha
txa
pha
tya
pha ;pushAll

;for simplicity's sake the needs of the hardware are going to be omitted. A real NES game would perform sprite DMA here.

LDA mutex
BEQ exit_nmi

; whatever you wanted to gatekeep behind your mutex goes here.
; typically it would be something like a text box printer, etc.
; Something that needs to update the video RAM and do so ASAP.

LDA #$00
STA mutex ;lock the mutex again.

exit_nmi:
LDA #$01
STA vblankflag ;allow waitframe() to exit


pla
tay
pla
tax
pla ;popAll
rti

waitframe:
pha
LDA #0
sta vblankflag
.again:
LDA vblankflag
BEQ again ;this would loop infinitely if it weren't for vblankflag being set during NMI
pla
rts</lang>
=={{header|8086 Assembly}}==
=={{header|8086 Assembly}}==
<code>LOCK</code> is a prefix that can be added to instructions that read a value then write back to it, such as <code>INC</code> and <code>DEC</code>. This prefix "locks" the memory bus, preventing other CPUs (if any) from accessing the same memory location at the same time as the CPU executing the "locked" instruction. The lock lasts until the locked instruction is complete, at which point the lock is released. This isn't used much on the original 8086, and there are a few limitations to the usage of the <code>LOCK</code> prefix:
<code>LOCK</code> is a prefix that can be added to instructions that read a value then write back to it, such as <code>INC</code> and <code>DEC</code>. This prefix "locks" the memory bus, preventing other CPUs (if any) from accessing the same memory location at the same time as the CPU executing the "locked" instruction. The lock lasts until the locked instruction is complete, at which point the lock is released. This isn't used much on the original 8086, and there are a few limitations to the usage of the <code>LOCK</code> prefix: