두 함수를 비교하고, local_irq_disable()대신 local_irq_save(flags)를 쓰는 이유를 알아보자.
local_irq_disable
#define local_irq_disable() \
do { raw_local_irq_disable(); trace_hardirqs_off(); } while (0)
#define raw_local_irq_disable() arch_local_irq_disable()
static inline void arch_local_irq_disable(void)
{
unsigned long temp;
asm volatile(
" mrs %0, cpsr @ arch_local_irq_disable\n" // cpsr 을 읽어서 %0 에 저장
" orr %0, %0, #128\n" // 7번째비트(128)를 or 시킴
" msr cpsr_c, %0" // %0 값을 다시 cpsr_c 에 저장
: "=r" (temp) // %0 은 temp 를 사용 (확실치 않음)
:
: "memory", "cc");
}
local_irq_save(flags)
#define local_irq_save(flags) \
do { \
raw_local_irq_save(flags); \
trace_hardirqs_off(); \
} while (0)
#define raw_local_irq_save(flags) \
do { \
typecheck(unsigned long, flags); \
flags = arch_local_irq_save(); \
} while (0)
static inline unsigned long arch_local_irq_save(void)
{
unsigned long flags, temp;
asm volatile(
" mrs %0, cpsr @ arch_local_irq_save\n" // cpsr 을 읽어서 %0 에 저장
" orr %1, %0, #128\n" // 7번째비트(128)를 or 시킨 값을 %1에 저장
" msr cpsr_c, %1" // %1의 값을 cpsr_c 에 저장
: "=r" (flags), "=r" (temp) // %0 은 flags 를 사용, %1 은 temp 를 사용
:
: "memory", "cc");
return flags;
}
쓰는 이유에 대해 설명한 글
원문 : http://kldp.org/node/29163
질문 1의 답변임다. 혹 틀리더라도 비난은 자제 -.-
local_irq_save() 함수를 알기전에 cli()라는 함수를 알아야 합니다.
cli 는 clear Interrupt 의 약자로서 CPU 가 interrupt signal을 받더라도
이를 무시하도록 하는 것입니다. 하드웨어 인터럽트와 소프트웨어 모두다
입니다.
이를 통해 synchronization 문제를 해결합니다.
data corruption 을 막는 거죠.
cli 로 critical region 을 보호한 후 sti 로 interrupt signal 받아들이도록
세팅해주어야 합니다.
문제는 sti 로 인터럽트를 받아들이기로 세팅하면 cli 호출
전에 인터럽트를 받아
들이기로 한것인지 아닌지를 깡그리 무시한채 sti 세팅합니다.
cli 호출 전에 인터럽트를 받아들이는 상태였다면 다행이지만
인터럽트 무시 상태였다면 sti 호출후 상태가 틀려지게 되죠.
즉 cli 함수 사용전의 인터럽트 관련 세팅 상태가 원상복귀
되지 않는거죠.
그래서 사용하는 것이 local_irq_save() 함수 입니다.
패러미터로 들어가는
flag 변수(스택에 존재)에
현재 인터럽트 관련 플래그를 저장하는 IF 라는 레지스터
정보를 저장합니다.
cli 가 sti 와 짝을 이루듯 local_irq_save 는 local_irq_restore 와
짝을 이룹니다. local_irq_restore 함수가 호출되면서
flag 변수에 저장되었던 것을
다시 IF 레지스터에 넣는거죠.
그러면 local_irq_save 전의 인터럽트 관련 세팅 상태로 원상복귀됩니다.
—
즉, irq 를 disable 했다가 다시 enable 할건데,
그전의 상태로 원복해야 하기 때문에, enable/disable 상태를 cpsr 로 부터 read 해서 flags 에 저장한 후 원복시킴
'Programming > Linux_Kernel' 카테고리의 다른 글
__builtin_return_address(0) (0) | 2013.11.28 |
---|---|
kernel log back ground 로 저장하기 (0) | 2013.11.27 |
CPSR (0) | 2013.10.31 |
arm 에서의 linux process 와 thread (0) | 2013.10.23 |
linux process memory usage (0) | 2013.10.22 |