선점 관련. 0이 아닌 상태에서는 선점 불가능한 프로세스가 됨
컨텍스트
1.프로세스 컨텍스트
- 특정 프로세스 또는 쓰레드가 CPU에서 실행될 때 해당 프로세스의 상태, 메모리, 레지스터, 시스템 리소스 사용 정보 등 포함
- 즉, 현재 실행 중인 프로세스의 실행 환경 전체를 의미 -> 프로세스의 집합 정도..?
- 프로세스 관련 정보가 프로세스 컨텍스트고, 태스크에 관련된 정보가 다른 태스크로 넘어가기 위해 바뀌는 과정을 컨텍스트 스위치라 부름
- 중요성 : 이 컨텍스트는 시스템에서 프로세스가 전환될 때(Context Switch) 저장되고 복원됨. 이를 통해 다중 프로세스 시스템에서 각 프로세스가 마치 독립적인 환경에서 실행되는 것처럼 관리됨
2.인터럽트 컨텍스트
인터럽트 : ex) 키보드 누르기 -> 이때 기존 실행되던 것을 저장 -> 특별한 처리를 위한 루틴 진입 -> 다시 복귀
- 시스템이 인터럽트 또는 예외 상황에 응답할 때의 실행 상황을 의미
- 이때, 커널은 사용자 프로세스의 컨텍스트를 잠시 중단하고 인터럽트 처리 루틴을 실행ㄹ함
- 인터럽트 컨텍스트는 프로세스 컨텍스트에 비해 훨씬 간소화되어 있으며, 전환 시 저장해야 하는 정보도 상대적으로 적음
- 커널에서 인터럽트가 발생해서 인터럽트 서비스 루틴을 실행하는 동작을 인터럽트 컨텍스트라 함
프로세스 컨텍스트는 프로그램과 프로그램 사이에 일어남 -> 프로세스가 완전히 바뀜 -> 오버헤드 큼
Preempt_count의 값은 여러 상태를 나타낼 수 있음
- 인터럽트 컨텍스트가 실행중이다 / 종료되었다
- Soft IRQ 컨텍스트가 실행중이다 / 종료중이다
- 프로세스 선점 스케줄링이 가능한가
인터럽트 컨텍스트 실행 표기
- preempt_count 필드에 인터럽트가 실행 중인 상태를 나타내는 비트를 설정. 이 비트를 읽어 인터럽트 컨텍스트 유무 식벽
- in_interrupt 함수를 통해 현재 실행 중인 코드가 인터럽트 컨텍스트 내에 있는지 알려줌

irq_enter에서 preempt_count 값을 0x10000 추가하는 부분이 있다 -> 이 부분에서 in_interrupt가 true로 바뀐다
131 # define in_interrupt() (irq_count()) -> true == 인터럽트 컨텍스트 중
108 # define irq_count() (mmi_count() | hardirq_count() | softirq_count())
101 # define nmi_count() (prrempt_count & NIM_MASK)
102 # define hardirq_count() (preempt_count() & HARDIRQ_MASK)
preempt.h 열기

우측의 thread_info.h를 활용하는 것을 알 수 있음

hardirq.h 열기

irq_enter() 부분의 preempt_count_add 부분에서 preempt_count 값이 바뀐다

linux/arch/arm64/include/asm/preempt.h의 preempt_count_add 부분

val에 들어가는 값을 아래에 정의되어 있음


Hard IRQ중이면 필드를 0x10000으로 설정
인터럽트 컨텍스트가 종료하는 부분은?

irq_exit -> __irq_exit_rcu

__irq_exit_rcu를 보면 660에 sub하는 부분이 보임

linux/arch/arm64/include/asm/preempt.h를 보면 더한 값을 다시 빼주는 걸 알 수 있음

지금까지 인터럽트 컨텍스트가 실행중이다 / 종료되었다 부분을 확인한 것
이제 Soft IRQ 컨텍스트가 실행중이다 / 종료중이다를 확인할 차례
Soft IRQ란?
- 하드웨어 인터럽트는 즉각적인 처리가 필요한 작업에 사용되므로 우선순위가 높음
- 소프트웨어 인터럽트는 하드웨어 인터럽트에 의해 예약된 작업을 나중에 처리하기 위해 발생하므로 우선순위가 상대적으로 낮음
- 소프트웨어 인터럽트는 커널 스케줄링에 의해 관리됨
- 급하면 Hard IRQ(하드웨어 인터럽트), 안 급하면 Soft IRQ(소프트웨어 인터럽트)로 넘김
Soft IRQ중인지는 in_interrumpt()가 아닌 in_softirq()로 할 수 있음
-> true면 soft irq중, 필드를 0x100으로 설정
softirq.c 열기

__do_softirq -> handle_softirqs

아래 부분에서 preempt_count값을 변화시킴

softirq_handle_begin -> __local_bh_disable_ip인데, 2번째 인자에 값이 들어감

__local_bh_disable_ip의 cnt로 들어가게 되고, __preept_count_add(cnt)를 통해 호출

preempt.h의

__preempt_count_add함수

값을 되돌리는 부분은 607, softirq_handle_end()

softirq_handle_end -> __local_bh_enable

__local_bh_enable을 보면 값을 되돌리는 부분이 보임

__preempt_count_sub 부분

이렇게 Soft_IRQ 시작/종료부분을 확인함
마지막으로 프로세스 선점 스케줄링 가능 여부 확인하기

주석으로 preempt_count 값이 0이면 선점 가능, 0보다 작으면 버그라 적혀 있음
그러려면 need_resched과 count 둘 다 0이 되어야 함

30, set_preempt_need_resched

preempt.need_resched값을 0으로 설정 -> count 값도 0이면 선점 가능
35, clear_preempt_need_resched

preempt.need_resched값을 1로 설정 -> count 값에 상관없이 0이 아니므로 선점 불가능
core.c 열기

should_resched과 irq_disabled를 조건으로 사용


should_resched

선점이 가능하면 1을 반환함
core.c로 돌아와서

7246, 1(선점 가능) && !irqs_disabled니까 인터럽트가 활성화중일 때만 선점 스케줄링 진행?
7247, 선점 스케줄링이 가능한 상태니까 스케줄러가 작업을 하도록 만드는 함수
'커널' 카테고리의 다른 글
| 17. 라즈베리파이 - 프로세스(current) (0) | 2025.07.14 |
|---|---|
| 16. 라즈베리파이 - thread_info 구조체 초기화 코드 (0) | 2025.07.13 |
| 14. 라즈베리파이 - 프로세스 스택 (0) | 2025.07.13 |
| 13. 라즈베리파이 - 아키텍처 별 thread_info 구조체 (0) | 2025.07.12 |
| 12. 라즈베리파이 - 태스크 디스크립터(2) (0) | 2025.07.12 |