tasklet
이란? 일전에 살펴본 Soft IRQ
는 커널 내에 하드코딩(이미 정의)된 후반부 핸들러였다면, tasklet
은 동적으로 Soft IRQ
서비스를 쓸 수 있게 하는 인터페이스이다. 따라서 드라이버 레벨에서 태스크릿을 자주 활용하게 된다.
tasklet
서비스 tasklet
또한 Soft IRQ
의 한 종류이다. 따라서 open_softirq()
함수를 통해 핸들러를 등록하게 된다.
tasklet
등록 tasklet
의 등록은 tasklet_schedule()
함수로 가능하며,
tasklet
을 등록하게 되면 tasklet_struct
를 자료구조(단방향 연결 리스트)에 삽입하고 raise_softirq_irqoff()
함수를 호출하여 Soft IRQ
를 요청하게 된다. 일단 tasklet_vec
(headp
의 인자) 자체는 percpu
객체이므로 프로세서간 경쟁은 없으나, 동일한 프로세서 내에서 선점될 가능성은 있으므로 local_irq_save/restore()
함수를 호출해서 인터럽트를 차단한다.
tasklet
실행 Soft IRQ
핸들러인 tasklet_action()
함수는 tasklet_action_common()
함수로 이어지고 여기에서 등록한 tasklet
을 수행하게 된다. 가장 먼저 tl_head->head
로 연결 리스트를 빼낸 뒤에 아예 NULL
로 초기화한다. 이 함수에 들어온 순간 모든 tasklet
은 처리될 예정이므로 저 순간에만 인터럽트를 차단해서 빠르게 받아온다.
그 이후에는 tasklet_trylock()
함수는 Preempt RT
에서만 유효한데 일단 tasklet
자체는 등록한 CPU 에서 처리되지만 동일한 tasklet
이 서로 다른 CPU 에서 등록될 수도 있다. 따라서 tasklet_trylock()
함수는 taslet_struct
의 state
값을 TASKLET_STATE_RUN
으로 바꾸는데 이미 TASKLET_STATE_RUN
이라면 false
를 반환하게 된다.
843 번째 라인부터 848 번째 라인은 처리되지 않은 tasklet
구조체를 다시 head
에 삽입하는 과정을 수행한다. task_trylock()
함수에서 실패했거나, 혹은 tasklet_struct
의 count
값이 0
(비활성화 상태)이 아닌 경우에 수행된다.
tasklet
활성화 / 비활성화 tasklet
은 비활성화 되어질 수 있는데 이는 tasklet_struct
의 count
값으로 결정된다. tasklet_disable()
함수를 호출하게 되면 count
값을 증가시키게 되고, _enable()
함수를 호출하면 값을 감소시키게 된다.