Messages in this thread | | | Date | Sun, 2 Mar 1997 19:06:41 -0500 (EST) | From | "Richard B. Johnson" <> | Subject | Re: cli() and sti() |
| |
On Sun, 2 Mar 1997, Duan Zhenhai wrote:
> Hello, > Can anybody tell me more information about cli() > and sti()? Does both of them be used together? > I read some code that like: > > save_flags(..); > cli(); > ............. > restore_flags(..); > > and did not find they use sti. > > Thank you!
Some kernel code gets called with the interrupts turned OFF and some of the same code gets called with the interrupts turned ON. You never want to turn ON the interrupts in the section of code that was called with the interrupts OFF. The section of code doesn't "Know" if the interrupts were ON or OFF when it was called. The code does know, however that for certain operations, the interrupts must be OFF because the state of the object being tested might change as a result of an interrupt if the interrupts were not disabled.
Therefore, the bits in the EFLAGS register that control interrupts and other things, are first saved in a register using a macro save_flags(). The interrupt bit is then cleared using the cli() macro which emits the single byte CLI instruction. After the critical section of code, where you don't care if the interrupts are enabled, the restore_flags() macro is executed instead of sti(). This will turn back ON the interrupts if they were ON when the procedure was called, and they will be left OFF if they were OFF when the procedure was called. The Intel ASM version of what is happening is:
PUSHF ; Save EFLAGS onto stack POP DWORD PTR [_old_flags] ; POP into _old_flags CLI ; No interrupts ...... ; Critical section of code starts ...... ; Critical section of code ends PUSH DWORD PTR [_old_flags] ; Get old EFLAGS onto stack POPF ; Old EFLAGS into EFLAGS
Now, it would be NICE if the GCC compiler actually produced code like this. Unfortunately, "_old_flags" is allocated on the stack so there are many more instructions emitted under GCC than are actually required. If fact, if you were writing such code in assembly, you would just do:
PUSHF ; Save old flags CLI ; No interrupts ...... ; Critical code POPF ; Restore flags.
A pushf() macro could be easily written as could popf(). However, GCC doesn't "like" user code to perform stack operations so it "levels" the stack after such code, destroying what you want to do.
Cheers, Dick Johnson -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- Richard B. Johnson Project Engineer Analogic Corporation Voice : (508) 977-3000 ext. 3754 Fax : (508) 532-6097 Modem : (508) 977-6870 Ftp : ftp@boneserver.analogic.com Email : rjohnson@analogic.com, johnson@analogic.com Penguin : Linux version 2.1.27 on an i586 machine (66.15 BogoMips). Warning : It's hard to remain at the trailing edge of technology. -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
| |