johnc@rtmvax.UUCP (John Connin) (07/19/88)
I thought the following "critial section" code from Thomas Wagner's excellent public domain "Ctask" package, might be of interest. In addition to the clean notation, note that the 'lock' and 'restore' routines only operate on the psw interrupt bit -- leaving all other flags unaltered. Though restoring the whole psw as done currently in Minix and Xinu seems to work, only changing the interrupt flag seems to me like a better way of doing business. #define CRITICAL int crit_save #define C_ENTER crit_save = lock() #define C_LEAVE restore(crit_save) foo() { CRTIICAL; C_ENTER; while( .... ) { .... if ( .... ) { C_LEAVE: return; .... } C_LEAVE; } ;-------------------------------------------------------------------- ; ; int lock(void) ; ; Returns current state of the interrupt flag (1 if ints were ; enabled), then disables interrupts. ; _lock proc ; pushf ; cli ; pop ax ; extract and return the flag mov cl,9 ; interrupt bit. shr ax,cl ; and ax,1 ; ret ; ; ; _lock endp ; ;-------------------------------------------------------------------- ; ; void restore(int state) ; ; Enables interrupts if 'state' is nonzero. ; _restore proc ; push bp ; mov bp,sp ; mov ax,4[bp] ; ax - state pop bp ; or ax,ax ; if (state) sti jz _rstend ; sti ; _rstend: ; ret ; ; _restore endp ; BTW: Ctask is a public domain software package which enables multi-tasking within MSDOS programs. Ctask is available on BIX and is authored by Thomas Wagner, Patschkauer Weg 31, D-1000 Berlin 33, West Germany.
Leisner.Henr@xerox.com (marty) (07/23/88)
John, I've been using the following similar functions and their equivalents on a number of processor architectures (including National 32xxx, TI34010, 8085/Z80, 80[12]86. Lock() returns the old PSW (processor status word) and disables interrupts. Restore(psw) sets the psw. Restore can also be used from C to do other things to the PSW. If anything I think the CTASK implementation is less advantageous. The following is easier and faster to implement since no bit shifting/twiddling is involved. Generally programs don't care about the PSW. But simple disable/enable doesn't work because you don't know what the interrupts were doing on the way in. It fits into the CTASK structure, since the data returned is not used by the program. I do like the syntax. The following is the Aztec assembler code for 80286 (procdef just provides convenient ways to pass arguments): ; File: int80286.asm - created by Marty Leisner ; leisner.Henr 20-Jul-88 14:53:05 ; Copyright (C) 1987, 1988 by Martin Leisner. All rights reserved. include lmacros.h ; C callable routines to handle critical sections similar to the Xinu ; approach. ; ; C program would execute ; ps = disable(); ; .... ; restore(ps) ; to alter disable interrupts without changing them at the outcome. procdef disable pushf cli pop ax pret pend disable procdef restore, <<proc_status, word>> push proc_status popf ; flags are according to proc_status pret pend restore finish end For a TI34010 (to see another example), it looks like this: unsigned disable() { asm(" getst a8"); /* save status to a8, TI GSP C compiler returns answers * in a8 */ asm(" dint"); } void restore(ps) register unsigned ps; /* force C compiler to shove ps into A9 (!?! check) */ { asm(" putst a9"); } marty ARPA: leisner.henr@xerox.com GV: leisner.henr NS: martin leisner:wbst139:xerox UUCP: nsc!nscimg!amps!marty, hplabs!parcvax!leisner
ast@cs.vu.nl (Andy Tanenbaum) (07/23/88)
I changed the locking in V1.3. The two calls are now: old_value = lock(); . . . restore(old_value) These nest properly and you can build critical sections more easily. I am leaving for a month today. I may get a chance to see news around the beginning of August, but I won't be reading my mail until Aug 24. I hope no other postings have been garbled. Maybe I will mail Vincent Broman all the postings so he can verify them against the archive. Andy Tanenbaum (ast@cs.vu.nl)