summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorManuel Traut <manut@linutronix.de>2019-01-11 08:35:12 +0100
committerJohn Ogness <john.ogness@linutronix.de>2019-01-28 19:59:32 +0106
commit0f2bdbda59d69191eb80ee223bbbbf2f8061e891 (patch)
treede351ab3f8191079bb1a425f07fd303f5c72821c
parent2268f2b2371e02762bf511cf1db1e3609b58f849 (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.txt2
-rw-r--r--schulung_tools/notes/deferred-work.txt81
-rw-r--r--schulung_tools/notes/interrupts.txt8
-rw-r--r--schulung_tools/notes/kernel-locking.txt50
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
+