Implement call_once (C23).

This implementation includes synchronization suitable for multithreading (albeit with inefficient busy waiting), even though ORCA/C does not currently support that. This could potentially be used with forked processes under GNO.
This commit is contained in:
Stephen Heumann
2025-09-21 16:29:17 -05:00
parent 5b04986f08
commit 81e6b8b0a8
+49
View File
@@ -378,6 +378,55 @@ lb5 stz addr no match - return null
lb6 creturn 4:addr
end
****************************************************************
*
* void call_once(short *flag, void (*func)(void));
*
* Call func once, if flag indicates it has not already been
* called. Do not return until the call to func has completed,
* either from this call_once invocation or another one.
*
* Inputs:
* flag - indicating if func was called already
* func - function to call once
*
* Note: This has synchronization suitable for multithreading,
* even though ORCA/C does not currently support it.
*
****************************************************************
*
call_once start
csubroutine (4:flag,4:func)
rtl_addr equ after-1
php test and set flag
sei
lda [flag]
bne nocall if not already set
inc a flag that call is in progress
sta [flag]
plp
ldy func call func
lda func+2
and #$00ff
ora #rtl_addr|8
pea rtl_addr|-8
pha
dey
phy
rtl
after lda #-1 flag that the call is done
sta [flag]
bra ret else
nocall plp
wait lda [flag] wait for any concurrent call to finish
bpl wait
ret creturn
end
****************************************************************
*
* div_t div(n,d)