diff options
| author | Manuel Traut <manut@linutronix.de> | 2019-01-11 08:35:12 +0100 |
|---|---|---|
| committer | John Ogness <john.ogness@linutronix.de> | 2019-01-28 19:59:32 +0106 |
| commit | 0f2bdbda59d69191eb80ee223bbbbf2f8061e891 (patch) | |
| tree | de351ab3f8191079bb1a425f07fd303f5c72821c | |
| parent | 2268f2b2371e02762bf511cf1db1e3609b58f849 (diff) | |
schulung_tools/notes add some kernel notes
they should be converted to a 'Kernel API' slideset.
Signed-off-by: Manuel Traut <manut@linutronix.de>
| -rw-r--r-- | schulung_tools/notes/cpureg.txt | 2 | ||||
| -rw-r--r-- | schulung_tools/notes/deferred-work.txt | 81 | ||||
| -rw-r--r-- | schulung_tools/notes/interrupts.txt | 8 | ||||
| -rw-r--r-- | schulung_tools/notes/kernel-locking.txt | 50 |
4 files changed, 141 insertions, 0 deletions
diff --git a/schulung_tools/notes/cpureg.txt b/schulung_tools/notes/cpureg.txt new file mode 100644 index 0000000..874e1c0 --- /dev/null +++ b/schulung_tools/notes/cpureg.txt @@ -0,0 +1,2 @@ + - most of the kernel code is architecture independent + - Don't use cpu registers in your driver / fs / .. code, just in arch/<yourarch> diff --git a/schulung_tools/notes/deferred-work.txt b/schulung_tools/notes/deferred-work.txt new file mode 100644 index 0000000..5ff5846 --- /dev/null +++ b/schulung_tools/notes/deferred-work.txt @@ -0,0 +1,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 + diff --git a/schulung_tools/notes/interrupts.txt b/schulung_tools/notes/interrupts.txt new file mode 100644 index 0000000..2f6edcc --- /dev/null +++ b/schulung_tools/notes/interrupts.txt @@ -0,0 +1,8 @@ +- programming interrupt handlers + - registering (request_irq) + - in_interrupt (check if in interrupt handler) + - in_atomic (cannot be scheduled away) + - no sleeping functions allowed + - can be shared + - handler code must check if it is the correct interrupt + - can be threaded (threadirqs) diff --git a/schulung_tools/notes/kernel-locking.txt b/schulung_tools/notes/kernel-locking.txt new file mode 100644 index 0000000..1757227 --- /dev/null +++ b/schulung_tools/notes/kernel-locking.txt @@ -0,0 +1,50 @@ + ++ locking + Documentation/kernel-hacking/locking.rst + - atomic operations + Documentation/atomic_t.txt + atomic_t atomic64_t and atomic_long_t + atomic_read(), atomic_set() + atomic[_fetch]_{add,sub,inc,dec}() + atomic[_fetch]_{and,or,xor,andnot}() + .. + - mutex + waiter can sleep, not usable in tasklets/timer/irqs + - spinlock / rwlock + spin_lock # use if lock is shared in different tasklets / only in user context + spin_lock_bh / disables softirqs # use if lock is shared in user context and softirqs (tasklets/timer) + spin_lock_irqsave / disables irqs # use if lock is shared in user context and irq context + --> Use irqsave variant if you're unsure + --> Avoid holding spinlock for more than 5 lines of code and across any + function call (except accessors like :c:func:`readb()`). + +============== ============= ============= ========= ========= ========= ========= ======= ======= ============== ============== +. IRQ Handler A IRQ Handler B Softirq A Softirq B Tasklet A Tasklet B Timer A Timer B User Context A User Context B +============== ============= ============= ========= ========= ========= ========= ======= ======= ============== ============== +IRQ Handler A None +IRQ Handler B SLIS None +Softirq A SLI SLI SL +Softirq B SLI SLI SL SL +Tasklet A SLI SLI SL SL None +Tasklet B SLI SLI SL SL SL None +Timer A SLI SLI SL SL SL SL None +Timer B SLI SLI SL SL SL SL SL None +User Context A SLI SLI SLBH SLBH SLBH SLBH SLBH SLBH None +User Context B SLI SLI SLBH SLBH SLBH SLBH SLBH SLBH MLI None +============== ============= ============= ========= ========= ========= ========= ======= ======= ============== ============== + +Table: Table of Locking Requirements + ++--------+----------------------------+ +| SLIS | spin_lock_irqsave | ++--------+----------------------------+ +| SLI | spin_lock_irq | ++--------+----------------------------+ +| SL | spin_lock | ++--------+----------------------------+ +| SLBH | spin_lock_bh | ++--------+----------------------------+ +| MLI | mutex_lock_interruptible | ++--------+----------------------------+ + +Table: Legend for Locking Requirements Table + |
