OpenCores
URL https://opencores.org/ocsvn/test_project/test_project/trunk

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [Documentation/] [cli-sti-removal.txt] - Blame information for rev 62

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
 
2
#### cli()/sti() removal guide, started by Ingo Molnar 
3
 
4
 
5
as of 2.5.28, five popular macros have been removed on SMP, and
6
are being phased out on UP:
7
 
8
 cli(), sti(), save_flags(flags), save_flags_cli(flags), restore_flags(flags)
9
 
10
until now it was possible to protect driver code against interrupt
11
handlers via a cli(), but from now on other, more lightweight methods
12
have to be used for synchronization, such as spinlocks or semaphores.
13
 
14
for example, driver code that used to do something like:
15
 
16
        struct driver_data;
17
 
18
        irq_handler (...)
19
        {
20
                ....
21
                driver_data.finish = 1;
22
                driver_data.new_work = 0;
23
                ....
24
        }
25
 
26
        ...
27
 
28
        ioctl_func (...)
29
        {
30
                ...
31
                cli();
32
                ...
33
                driver_data.finish = 0;
34
                driver_data.new_work = 2;
35
                ...
36
                sti();
37
                ...
38
        }
39
 
40
was SMP-correct because the cli() function ensured that no
41
interrupt handler (amongst them the above irq_handler()) function
42
would execute while the cli()-ed section is executing.
43
 
44
but from now on a more direct method of locking has to be used:
45
 
46
        spinlock_t driver_lock = SPIN_LOCK_UNLOCKED;
47
        struct driver_data;
48
 
49
        irq_handler (...)
50
        {
51
                unsigned long flags;
52
                ....
53
                spin_lock_irqsave(&driver_lock, flags);
54
                ....
55
                driver_data.finish = 1;
56
                driver_data.new_work = 0;
57
                ....
58
                spin_unlock_irqrestore(&driver_lock, flags);
59
                ....
60
        }
61
 
62
        ...
63
 
64
        ioctl_func (...)
65
        {
66
                ...
67
                spin_lock_irq(&driver_lock);
68
                ...
69
                driver_data.finish = 0;
70
                driver_data.new_work = 2;
71
                ...
72
                spin_unlock_irq(&driver_lock);
73
                ...
74
        }
75
 
76
the above code has a number of advantages:
77
 
78
- the locking relation is easier to understand - actual lock usage
79
  pinpoints the critical sections. cli() usage is too opaque.
80
  Easier to understand means it's easier to debug.
81
 
82
- it's faster, because spinlocks are faster to acquire than the
83
  potentially heavily-used IRQ lock. Furthermore, your driver does
84
  not have to wait eg. for a big heavy SCSI interrupt to finish,
85
  because the driver_lock spinlock is only used by your driver.
86
  cli() on the other hand was used by many drivers, and extended
87
  the critical section to the whole IRQ handler function - creating
88
  serious lock contention.
89
 
90
 
91
to make the transition easier, we've still kept the cli(), sti(),
92
save_flags(), save_flags_cli() and restore_flags() macros defined
93
on UP systems - but their usage will be phased out until 2.6 is
94
released.
95
 
96
drivers that want to disable local interrupts (interrupts on the
97
current CPU), can use the following five macros:
98
 
99
  local_irq_disable(), local_irq_enable(), local_save_flags(flags),
100
  local_irq_save(flags), local_irq_restore(flags)
101
 
102
but beware, their meaning and semantics are much simpler, far from
103
that of the old cli(), sti(), save_flags(flags) and restore_flags(flags)
104
SMP meaning:
105
 
106
    local_irq_disable()       => turn local IRQs off
107
 
108
    local_irq_enable()        => turn local IRQs on
109
 
110
    local_save_flags(flags)   => save the current IRQ state into flags. The
111
                                 state can be on or off. (on some
112
                                 architectures there's even more bits in it.)
113
 
114
    local_irq_save(flags)     => save the current IRQ state into flags and
115
                                 disable interrupts.
116
 
117
    local_irq_restore(flags)  => restore the IRQ state from flags.
118
 
119
(local_irq_save can save both irqs on and irqs off state, and
120
local_irq_restore can restore into both irqs on and irqs off state.)
121
 
122
another related change is that synchronize_irq() now takes a parameter:
123
synchronize_irq(irq). This change too has the purpose of making SMP
124
synchronization more lightweight - this way you can wait for your own
125
interrupt handler to finish, no need to wait for other IRQ sources.
126
 
127
 
128
why were these changes done? The main reason was the architectural burden
129
of maintaining the cli()/sti() interface - it became a real problem. The
130
new interrupt system is much more streamlined, easier to understand, debug,
131
and it's also a bit faster - the same happened to it that will happen to
132
cli()/sti() using drivers once they convert to spinlocks :-)
133
 

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.