Blame view

Documentation/preempt-locking.txt 5.59 KB
9cc07df4b   Mauro Carvalho Chehab   preempt-locking.t...
1
2
3
  ===========================================================================
  Proper Locking Under a Preemptible Kernel: Keeping Kernel Code Preempt-Safe
  ===========================================================================
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4

9cc07df4b   Mauro Carvalho Chehab   preempt-locking.t...
5
6
  :Author: Robert Love <rml@tech9.net>
  :Last Updated: 28 Aug 2002
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
7

9cc07df4b   Mauro Carvalho Chehab   preempt-locking.t...
8
9
10
  
  Introduction
  ============
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
11
12
13
14
15
16
17
18
19
20
21
22
  
  
  A preemptible kernel creates new locking issues.  The issues are the same as
  those under SMP: concurrency and reentrancy.  Thankfully, the Linux preemptible
  kernel model leverages existing SMP locking mechanisms.  Thus, the kernel
  requires explicit additional locking for very few additional situations.
  
  This document is for all kernel hackers.  Developing code in the kernel
  requires protecting these situations.
   
  
  RULE #1: Per-CPU data structures need explicit protection
9cc07df4b   Mauro Carvalho Chehab   preempt-locking.t...
23
  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
24

9cc07df4b   Mauro Carvalho Chehab   preempt-locking.t...
25
  Two similar problems arise. An example code snippet::
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
  
  	struct this_needs_locking tux[NR_CPUS];
  	tux[smp_processor_id()] = some_value;
  	/* task is preempted here... */
  	something = tux[smp_processor_id()];
  
  First, since the data is per-CPU, it may not have explicit SMP locking, but
  require it otherwise.  Second, when a preempted task is finally rescheduled,
  the previous value of smp_processor_id may not equal the current.  You must
  protect these situations by disabling preemption around them.
  
  You can also use put_cpu() and get_cpu(), which will disable preemption.
  
  
  RULE #2: CPU state must be protected.
9cc07df4b   Mauro Carvalho Chehab   preempt-locking.t...
41
  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
42
43
44
45
46
47
48
49
50
51
52
53
54
  
  
  Under preemption, the state of the CPU must be protected.  This is arch-
  dependent, but includes CPU structures and state not preserved over a context
  switch.  For example, on x86, entering and exiting FPU mode is now a critical
  section that must occur while preemption is disabled.  Think what would happen
  if the kernel is executing a floating-point instruction and is then preempted.
  Remember, the kernel does not save FPU state except for user tasks.  Therefore,
  upon preemption, the FPU registers will be sold to the lowest bidder.  Thus,
  preemption must be disabled around such regions.
  
  Note, some FPU functions are already explicitly preempt safe.  For example,
  kernel_fpu_begin and kernel_fpu_end will disable and enable preemption.
3a0aee480   Ingo Molnar   x86/fpu: Rename m...
55
  However, fpu__restore() must be called with preemption disabled.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
56
57
58
  
  
  RULE #3: Lock acquire and release must be performed by same task
9cc07df4b   Mauro Carvalho Chehab   preempt-locking.t...
59
  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
60
61
62
63
64
65
66
  
  
  A lock acquired in one task must be released by the same task.  This
  means you can't do oddball things like acquire a lock and go off to
  play while another task releases it.  If you want to do something
  like this, acquire and release the task in the same code path and
  have the caller wait on an event by the other task.
9cc07df4b   Mauro Carvalho Chehab   preempt-locking.t...
67
68
  Solution
  ========
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
69
70
71
72
  
  
  Data protection under preemption is achieved by disabling preemption for the
  duration of the critical region.
9cc07df4b   Mauro Carvalho Chehab   preempt-locking.t...
73
74
75
76
77
78
79
  ::
  
    preempt_enable()		decrement the preempt counter
    preempt_disable()		increment the preempt counter
    preempt_enable_no_resched()	decrement, but do not immediately preempt
    preempt_check_resched()	if needed, reschedule
    preempt_count()		return the preempt counter
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
  
  The functions are nestable.  In other words, you can call preempt_disable
  n-times in a code path, and preemption will not be reenabled until the n-th
  call to preempt_enable.  The preempt statements define to nothing if
  preemption is not enabled.
  
  Note that you do not need to explicitly prevent preemption if you are holding
  any locks or interrupts are disabled, since preemption is implicitly disabled
  in those cases.
  
  But keep in mind that 'irqs disabled' is a fundamentally unsafe way of
  disabling preemption - any spin_unlock() decreasing the preemption count
  to 0 might trigger a reschedule. A simple printk() might trigger a reschedule.
  So use this implicit preemption-disabling property only if you know that the
  affected codepath does not do any of this. Best policy is to use this only for
  small, atomic code that you wrote and which calls no complex functions.
9cc07df4b   Mauro Carvalho Chehab   preempt-locking.t...
96
  Example::
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
97
98
99
100
101
102
103
104
105
106
107
108
  
  	cpucache_t *cc; /* this is per-CPU */
  	preempt_disable();
  	cc = cc_data(searchp);
  	if (cc && cc->avail) {
  		__free_block(searchp, cc_entry(cc), cc->avail);
  		cc->avail = 0;
  	}
  	preempt_enable();
  	return 0;
  
  Notice how the preemption statements must encompass every reference of the
9cc07df4b   Mauro Carvalho Chehab   preempt-locking.t...
109
  critical variables.  Another example::
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
110
111
112
113
114
115
116
117
118
119
  
  	int buf[NR_CPUS];
  	set_cpu_val(buf);
  	if (buf[smp_processor_id()] == -1) printf(KERN_INFO "wee!
  ");
  	spin_lock(&buf_lock);
  	/* ... */
  
  This code is not preempt-safe, but see how easily we can fix it by simply
  moving the spin_lock up two lines.
9cc07df4b   Mauro Carvalho Chehab   preempt-locking.t...
120
121
  Preventing preemption using interrupt disabling
  ===============================================
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
  
  
  It is possible to prevent a preemption event using local_irq_disable and
  local_irq_save.  Note, when doing so, you must be very careful to not cause
  an event that would set need_resched and result in a preemption check.  When
  in doubt, rely on locking or explicit preemption disabling.
  
  Note in 2.5 interrupt disabling is now only per-CPU (e.g. local).
  
  An additional concern is proper usage of local_irq_disable and local_irq_save.
  These may be used to protect from preemption, however, on exit, if preemption
  may be enabled, a test to see if preemption is required should be done.  If
  these are called from the spin_lock and read/write lock macros, the right thing
  is done.  They may also be called within a spin-lock protected region, however,
  if they are ever called outside of this context, a test for preemption should
  be made. Do note that calls from interrupt context or bottom half/ tasklets
  are also protected by preemption locks and so may use the versions which do
  not check preemption.