summaryrefslogtreecommitdiff
path: root/schulung_tools/notes/deferred-work.txt
blob: 5ff5846c3861fa972831fdc23e08c92ffc7ff341 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
(time units)
- jiffies (1 jiffy = 1 "heartbeat")
- "jiffies" is a global variable

(delaying/sleeping)
- ndelay, udelay, mdelay (busy waiting)
- msleep, ssleep (sleeping)

(deferred work methods)
wait queues
- declare wait queue
- task 1 will wait on the wait queue (i.e. worker kernel thread)
- task 2 will notify the wait queue to wake up (i.e. interrupt handler)
- wait_event_timeout(waitqueue, time_in_jiffies)
  - HZ is defined to 1 second of jiffies
  - example of 5 seconds:    wait_event_timeout(wq, 5 * HZ)
  - example of 0.01 seconds: wait_event_timeout(wq, HZ / 100)

scheduling
- set_current_state(TASK_UNINTERRUPTIBLE);
- schedule_timeout(time_in_jiffies);
  - give the cpu to someone else
  - I want the cpu back at time_in_jiffies (as a maximum)

timers
- add_timer, mod_timer, del_timer, timer_pending
- specify a function callback and private data (with add_timer)
- specify a delay when it should be called
  (with add_timer, specified in jiffies)
- softirq context (this is atomic!)
- run on whatever cpu called add_timer
- in_softirq()
- hrtimer: net/can/bcm.c:970 hrtimer_init / hrtimer_start / hrtimer_cancel
- jiffie:  drivers/pcmcia/soc_common.c:802 timer_setup / mod_timer / del_timer_sync
- ndelay, udelay, mdelay (busy waiting)
- msleep, ssleep (sleeping)

tasklets
- tasklets run atomically in a run-to-complete fashion, but HW interrupts are
    enabled!
- tasklet_enable, tasklet_disable, tasklet_schedule, tasklet_kill
- specify a function callback and private data (with tasklet creation)
- runs on whatever cpu called tasklet_schedule
- softirq context (this is atomic!)
    -> scheduled function isn't allowed to use sleep
- serialized with itself
- https://linux-kernel-labs.github.io/master/labs/deferred_work.html#tasklets
- drivers/firewire/ohci.c:993 tasklet_init / tasklet_kill / tasklet_disable / tasklet_schedule

workqueues
- schedule a function to be executed in a different context
- PREPARE_WORK, queue_work, queue_work_delayed (in jiffies),
  cancel_delayed_work, flush_workqueue
- specify a function callback and private data (with PREPARE_WORK)
- runs on whatever cpu called queue_work
  (unless WQ_UNBOUND is used, then runs on any cpu)
- execution can be delayed (queue_work_delayed)
- runs in a kernel thread
- can use shared/system workqueues (you do not need to create your own)
- serialized with itself
- scheduled function can use sleep
- Documentation/core-api/workqueue.rst
- include/linux/workqueue.h
- net/rfkill/core.c:
  INIT_WORK - schedule_work, cancel_work_sync
  INIT_DELAYED_WORK - queue_delayed_work, cancel_delayed_work_sync
      delayed* enables to specify delay while queuing
      schedule_ vs. queue_ : schedule_* uses a global queue, queue_*
      requires us to specify a specific queue


threaded interrupt handlers
- useful for handling interrupts in a non-atomic context

completions
- Documentation/scheduler/completion.txt
- wait_for_completion() is not usable in atomic, preempt_disabled or irq_off
    situations, use try_wait_for_completion() there
- fs/btrfs/qgroup.c:3288:
    init_completion / wait_for_completion / complete_all done in rescan_worker