]> git.pld-linux.org Git - packages/kernel.git/blame - preempt-kernel-rml-2.4.20-1.patch
- obsolete
[packages/kernel.git] / preempt-kernel-rml-2.4.20-1.patch
CommitLineData
da373bdb 1 CREDITS | 2
2 Documentation/Configure.help | 11 ++++
3 Documentation/preempt-locking.txt | 104 ++++++++++++++++++++++++++++++++++++++
4 MAINTAINERS | 8 ++
5 arch/arm/config.in | 2
6 arch/arm/kernel/entry-armv.S | 40 ++++++++++++++
7 arch/arm/tools/getconstants.c | 6 ++
8 arch/i386/config.in | 8 ++
9 arch/i386/kernel/entry.S | 49 +++++++++++++++++
10 arch/i386/kernel/i387.c | 3 +
11 arch/i386/kernel/smp.c | 24 ++++++--
12 arch/i386/kernel/traps.c | 2
13 arch/i386/lib/dec_and_lock.c | 1
14 arch/mips/config-shared.in | 1
15 arch/mips/kernel/i8259.c | 1
16 arch/mips/kernel/irq.c | 29 ++++++++++
17 arch/mips/mm/extable.c | 1
18 arch/ppc/config.in | 2
19 arch/ppc/kernel/entry.S | 35 ++++++++++++
20 arch/ppc/kernel/irq.c | 28 ++++++++++
21 arch/ppc/kernel/mk_defs.c | 3 +
22 arch/ppc/kernel/setup.c | 14 +++++
23 arch/ppc/lib/dec_and_lock.c | 1
24 arch/sh/config.in | 1
25 arch/sh/kernel/entry.S | 104 +++++++++++++++++++++++++++++++++++---
26 arch/sh/kernel/irq.c | 17 ++++++
27 drivers/ieee1394/csr.c | 1
28 drivers/sound/sound_core.c | 1
29 fs/adfs/map.c | 1
30 fs/exec.c | 2
31 fs/fat/cache.c | 1
32 fs/nls/nls_base.c | 1
33 include/asm-arm/dma.h | 1
34 include/asm-arm/hardirq.h | 1
35 include/asm-arm/pgalloc.h | 8 ++
36 include/asm-arm/smplock.h | 11 ++++
37 include/asm-arm/softirq.h | 8 +-
38 include/asm-arm/system.h | 7 ++
39 include/asm-i386/hardirq.h | 14 +++--
40 include/asm-i386/highmem.h | 7 ++
41 include/asm-i386/hw_irq.h | 19 +++++-
42 include/asm-i386/i387.h | 3 -
43 include/asm-i386/pgalloc.h | 12 ++++
44 include/asm-i386/smplock.h | 14 +++++
45 include/asm-i386/softirq.h | 8 +-
46 include/asm-i386/spinlock.h | 18 +++---
47 include/asm-i386/system.h | 7 ++
48 include/asm-mips/smplock.h | 15 +++++
49 include/asm-mips/softirq.h | 3 +
50 include/asm-mips/system.h | 14 +++++
51 include/asm-ppc/dma.h | 1
52 include/asm-ppc/hardirq.h | 1
53 include/asm-ppc/highmem.h | 6 +-
54 include/asm-ppc/hw_irq.h | 6 ++
55 include/asm-ppc/mmu_context.h | 4 +
56 include/asm-ppc/pgalloc.h | 9 +++
57 include/asm-ppc/smplock.h | 14 +++++
58 include/asm-ppc/softirq.h | 10 +++
59 include/asm-sh/hardirq.h | 2
60 include/asm-sh/smplock.h | 85 ++++++++++++++++++++++++++++---
61 include/asm-sh/softirq.h | 3 +
62 include/asm-sh/system.h | 13 ++++
63 include/linux/brlock.h | 10 +--
64 include/linux/dcache.h | 56 +++++++++++---------
65 include/linux/fs_struct.h | 13 +++-
66 include/linux/sched.h | 12 ++++
67 include/linux/smp_lock.h | 2
68 include/linux/spinlock.h | 82 +++++++++++++++++++++++++++--
69 include/linux/tqueue.h | 31 ++++++-----
70 kernel/exit.c | 7 ++
71 kernel/fork.c | 7 ++
72 kernel/ksyms.c | 3 +
73 kernel/sched.c | 48 ++++++++++++++++-
74 lib/dec_and_lock.c | 1
75 mm/slab.c | 3 -
76 net/core/dev.c | 6 ++
77 net/core/skbuff.c | 30 ++++++----
78 net/socket.c | 2
79 net/sunrpc/pmap_clnt.c | 1
80 79 files changed, 1011 insertions(+), 131 deletions(-)
81
82
83diff -urN linux-2.4.20/arch/arm/config.in linux/arch/arm/config.in
84--- linux-2.4.20/arch/arm/config.in 2002-11-28 18:53:09.000000000 -0500
85+++ linux/arch/arm/config.in 2002-12-11 02:34:47.000000000 -0500
86@@ -372,7 +372,7 @@
87 else
88 define_bool CONFIG_DISCONTIGMEM n
89 fi
90-
91+dep_bool 'Preemptible Kernel' CONFIG_PREEMPT $CONFIG_CPU_32
92 endmenu
93
94 mainmenu_option next_comment
95diff -urN linux-2.4.20/arch/arm/kernel/entry-armv.S linux/arch/arm/kernel/entry-armv.S
96--- linux-2.4.20/arch/arm/kernel/entry-armv.S 2002-08-02 20:39:42.000000000 -0400
97+++ linux/arch/arm/kernel/entry-armv.S 2002-12-11 02:34:47.000000000 -0500
98@@ -697,6 +697,12 @@
99 add r4, sp, #S_SP
100 mov r6, lr
101 stmia r4, {r5, r6, r7, r8, r9} @ save sp_SVC, lr_SVC, pc, cpsr, old_ro
102+#ifdef CONFIG_PREEMPT
103+ get_current_task r9
104+ ldr r8, [r9, #TSK_PREEMPT]
105+ add r8, r8, #1
106+ str r8, [r9, #TSK_PREEMPT]
107+#endif
108 1: get_irqnr_and_base r0, r6, r5, lr
109 movne r1, sp
110 @
111@@ -704,6 +710,25 @@
112 @
113 adrsvc ne, lr, 1b
114 bne do_IRQ
115+#ifdef CONFIG_PREEMPT
116+2: ldr r8, [r9, #TSK_PREEMPT]
117+ subs r8, r8, #1
118+ bne 3f
119+ ldr r7, [r9, #TSK_NEED_RESCHED]
120+ teq r7, #0
121+ beq 3f
122+ ldr r6, .LCirqstat
123+ ldr r0, [r6, #IRQSTAT_BH_COUNT]
124+ teq r0, #0
125+ bne 3f
126+ mov r0, #MODE_SVC
127+ msr cpsr_c, r0 @ enable interrupts
128+ bl SYMBOL_NAME(preempt_schedule)
129+ mov r0, #I_BIT | MODE_SVC
130+ msr cpsr_c, r0 @ disable interrupts
131+ b 2b
132+3: str r8, [r9, #TSK_PREEMPT]
133+#endif
134 ldr r0, [sp, #S_PSR] @ irqs are already disabled
135 msr spsr, r0
136 ldmia sp, {r0 - pc}^ @ load r0 - pc, cpsr
137@@ -761,6 +786,9 @@
138 .LCprocfns: .word SYMBOL_NAME(processor)
139 #endif
140 .LCfp: .word SYMBOL_NAME(fp_enter)
141+#ifdef CONFIG_PREEMPT
142+.LCirqstat: .word SYMBOL_NAME(irq_stat)
143+#endif
144
145 irq_prio_table
146
147@@ -801,6 +829,12 @@
148 stmdb r8, {sp, lr}^
149 alignment_trap r4, r7, __temp_irq
150 zero_fp
151+ get_current_task tsk
152+#ifdef CONFIG_PREEMPT
153+ ldr r0, [tsk, #TSK_PREEMPT]
154+ add r0, r0, #1
155+ str r0, [tsk, #TSK_PREEMPT]
156+#endif
157 1: get_irqnr_and_base r0, r6, r5, lr
158 movne r1, sp
159 adrsvc ne, lr, 1b
160@@ -808,8 +842,12 @@
161 @ routine called with r0 = irq number, r1 = struct pt_regs *
162 @
163 bne do_IRQ
164+#ifdef CONFIG_PREEMPT
165+ ldr r0, [tsk, #TSK_PREEMPT]
166+ sub r0, r0, #1
167+ str r0, [tsk, #TSK_PREEMPT]
168+#endif
169 mov why, #0
170- get_current_task tsk
171 b ret_to_user
172
173 .align 5
174diff -urN linux-2.4.20/arch/arm/tools/getconstants.c linux/arch/arm/tools/getconstants.c
175--- linux-2.4.20/arch/arm/tools/getconstants.c 2001-10-11 12:04:57.000000000 -0400
176+++ linux/arch/arm/tools/getconstants.c 2002-12-11 02:34:47.000000000 -0500
177@@ -13,6 +13,7 @@
178
179 #include <asm/pgtable.h>
180 #include <asm/uaccess.h>
181+#include <asm/hardirq.h>
182
183 /*
184 * Make sure that the compiler and target are compatible.
185@@ -39,6 +40,11 @@
186 DEFN("TSS_SAVE", OFF_TSK(thread.save));
187 DEFN("TSS_FPESAVE", OFF_TSK(thread.fpstate.soft.save));
188
189+#ifdef CONFIG_PREEMPT
190+DEFN("TSK_PREEMPT", OFF_TSK(preempt_count));
191+DEFN("IRQSTAT_BH_COUNT", (unsigned long)&(((irq_cpustat_t *)0)->__local_bh_count));
192+#endif
193+
194 #ifdef CONFIG_CPU_32
195 DEFN("TSS_DOMAIN", OFF_TSK(thread.domain));
196
197diff -urN linux-2.4.20/arch/i386/config.in linux/arch/i386/config.in
198--- linux-2.4.20/arch/i386/config.in 2002-11-28 18:53:09.000000000 -0500
199+++ linux/arch/i386/config.in 2002-12-11 02:34:47.000000000 -0500
200@@ -206,6 +206,7 @@
201 bool 'Math emulation' CONFIG_MATH_EMULATION
202 bool 'MTRR (Memory Type Range Register) support' CONFIG_MTRR
203 bool 'Symmetric multi-processing support' CONFIG_SMP
204+bool 'Preemptible Kernel' CONFIG_PREEMPT
205 if [ "$CONFIG_SMP" != "y" ]; then
206 bool 'Local APIC support on uniprocessors' CONFIG_X86_UP_APIC
207 dep_bool 'IO-APIC support on uniprocessors' CONFIG_X86_UP_IOAPIC $CONFIG_X86_UP_APIC
208@@ -224,9 +225,12 @@
209 define_bool CONFIG_X86_TSC y
210 fi
211
212-if [ "$CONFIG_SMP" = "y" -a "$CONFIG_X86_CMPXCHG" = "y" ]; then
213- define_bool CONFIG_HAVE_DEC_LOCK y
214+if [ "$CONFIG_SMP" = "y" -o "$CONFIG_PREEMPT" = "y" ]; then
215+ if [ "$CONFIG_X86_CMPXCHG" = "y" ]; then
216+ define_bool CONFIG_HAVE_DEC_LOCK y
217+ fi
218 fi
219+
220 endmenu
221
222 mainmenu_option next_comment
223diff -urN linux-2.4.20/arch/i386/kernel/entry.S linux/arch/i386/kernel/entry.S
224--- linux-2.4.20/arch/i386/kernel/entry.S 2002-11-28 18:53:09.000000000 -0500
225+++ linux/arch/i386/kernel/entry.S 2002-12-11 02:34:47.000000000 -0500
226@@ -73,7 +73,7 @@
227 * these are offsets into the task-struct.
228 */
229 state = 0
230-flags = 4
231+preempt_count = 4
232 sigpending = 8
233 addr_limit = 12
234 exec_domain = 16
235@@ -81,8 +81,28 @@
236 tsk_ptrace = 24
237 processor = 52
238
239+/* These are offsets into the irq_stat structure
240+ * There is one per cpu and it is aligned to 32
241+ * byte boundry (we put that here as a shift count)
242+ */
243+irq_array_shift = CONFIG_X86_L1_CACHE_SHIFT
244+
245+irq_stat_local_irq_count = 4
246+irq_stat_local_bh_count = 8
247+
248 ENOSYS = 38
249
250+#ifdef CONFIG_SMP
251+#define GET_CPU_INDX movl processor(%ebx),%eax; \
252+ shll $irq_array_shift,%eax
253+#define GET_CURRENT_CPU_INDX GET_CURRENT(%ebx); \
254+ GET_CPU_INDX
255+#define CPU_INDX (,%eax)
256+#else
257+#define GET_CPU_INDX
258+#define GET_CURRENT_CPU_INDX GET_CURRENT(%ebx)
259+#define CPU_INDX
260+#endif
261
262 #define SAVE_ALL \
263 cld; \
264@@ -255,12 +275,30 @@
265 ALIGN
266 ENTRY(ret_from_intr)
267 GET_CURRENT(%ebx)
268+#ifdef CONFIG_PREEMPT
269+ cli
270+ decl preempt_count(%ebx)
271+#endif
272 ret_from_exception:
273 movl EFLAGS(%esp),%eax # mix EFLAGS and CS
274 movb CS(%esp),%al
275 testl $(VM_MASK | 3),%eax # return to VM86 mode or non-supervisor?
276 jne ret_from_sys_call
277+#ifdef CONFIG_PREEMPT
278+ cmpl $0,preempt_count(%ebx)
279+ jnz restore_all
280+ cmpl $0,need_resched(%ebx)
281+ jz restore_all
282+ movl SYMBOL_NAME(irq_stat)+irq_stat_local_bh_count CPU_INDX,%ecx
283+ addl SYMBOL_NAME(irq_stat)+irq_stat_local_irq_count CPU_INDX,%ecx
284+ jnz restore_all
285+ incl preempt_count(%ebx)
286+ sti
287+ call SYMBOL_NAME(preempt_schedule)
288+ jmp ret_from_intr
289+#else
290 jmp restore_all
291+#endif
292
293 ALIGN
294 reschedule:
295@@ -297,6 +335,9 @@
296 GET_CURRENT(%ebx)
297 call *%edi
298 addl $8,%esp
299+#ifdef CONFIG_PREEMPT
300+ cli
301+#endif
302 jmp ret_from_exception
303
304 ENTRY(coprocessor_error)
305@@ -316,12 +357,18 @@
306 movl %cr0,%eax
307 testl $0x4,%eax # EM (math emulation bit)
308 jne device_not_available_emulate
309+#ifdef CONFIG_PREEMPT
310+ cli
311+#endif
312 call SYMBOL_NAME(math_state_restore)
313 jmp ret_from_exception
314 device_not_available_emulate:
315 pushl $0 # temporary storage for ORIG_EIP
316 call SYMBOL_NAME(math_emulate)
317 addl $4,%esp
318+#ifdef CONFIG_PREEMPT
319+ cli
320+#endif
321 jmp ret_from_exception
322
323 ENTRY(debug)
324diff -urN linux-2.4.20/arch/i386/kernel/i387.c linux/arch/i386/kernel/i387.c
325--- linux-2.4.20/arch/i386/kernel/i387.c 2002-08-02 20:39:42.000000000 -0400
326+++ linux/arch/i386/kernel/i387.c 2002-12-11 02:34:47.000000000 -0500
327@@ -10,6 +10,7 @@
328
329 #include <linux/config.h>
330 #include <linux/sched.h>
331+#include <linux/spinlock.h>
332 #include <linux/init.h>
333 #include <asm/processor.h>
334 #include <asm/i387.h>
335@@ -89,6 +90,8 @@
336 {
337 struct task_struct *tsk = current;
338
339+ preempt_disable();
340+
341 if (tsk->flags & PF_USEDFPU) {
342 __save_init_fpu(tsk);
343 return;
344diff -urN linux-2.4.20/arch/i386/kernel/smp.c linux/arch/i386/kernel/smp.c
345--- linux-2.4.20/arch/i386/kernel/smp.c 2002-11-28 18:53:09.000000000 -0500
346+++ linux/arch/i386/kernel/smp.c 2002-12-11 02:34:47.000000000 -0500
347@@ -357,10 +357,13 @@
348
349 asmlinkage void smp_invalidate_interrupt (void)
350 {
351- unsigned long cpu = smp_processor_id();
352+ unsigned long cpu;
353+
354+ preempt_disable();
355
356+ cpu = smp_processor_id();
357 if (!test_bit(cpu, &flush_cpumask))
358- return;
359+ goto out;
360 /*
361 * This was a BUG() but until someone can quote me the
362 * line from the intel manual that guarantees an IPI to
363@@ -381,6 +384,8 @@
364 }
365 ack_APIC_irq();
366 clear_bit(cpu, &flush_cpumask);
367+out:
368+ preempt_enable();
369 }
370
371 static void flush_tlb_others (unsigned long cpumask, struct mm_struct *mm,
372@@ -430,17 +435,22 @@
373 void flush_tlb_current_task(void)
374 {
375 struct mm_struct *mm = current->mm;
376- unsigned long cpu_mask = mm->cpu_vm_mask & ~(1 << smp_processor_id());
377+ unsigned long cpu_mask;
378
379+ preempt_disable();
380+ cpu_mask = mm->cpu_vm_mask & ~(1UL << smp_processor_id());
381 local_flush_tlb();
382 if (cpu_mask)
383 flush_tlb_others(cpu_mask, mm, FLUSH_ALL);
384+ preempt_enable();
385 }
386
387 void flush_tlb_mm (struct mm_struct * mm)
388 {
389- unsigned long cpu_mask = mm->cpu_vm_mask & ~(1 << smp_processor_id());
390+ unsigned long cpu_mask;
391
392+ preempt_disable();
393+ cpu_mask = mm->cpu_vm_mask & ~(1UL << smp_processor_id());
394 if (current->active_mm == mm) {
395 if (current->mm)
396 local_flush_tlb();
397@@ -449,13 +459,16 @@
398 }
399 if (cpu_mask)
400 flush_tlb_others(cpu_mask, mm, FLUSH_ALL);
401+ preempt_enable();
402 }
403
404 void flush_tlb_page(struct vm_area_struct * vma, unsigned long va)
405 {
406 struct mm_struct *mm = vma->vm_mm;
407- unsigned long cpu_mask = mm->cpu_vm_mask & ~(1 << smp_processor_id());
408+ unsigned long cpu_mask;
409
410+ preempt_disable();
411+ cpu_mask = mm->cpu_vm_mask & ~(1UL << smp_processor_id());
412 if (current->active_mm == mm) {
413 if(current->mm)
414 __flush_tlb_one(va);
415@@ -465,6 +478,7 @@
416
417 if (cpu_mask)
418 flush_tlb_others(cpu_mask, mm, va);
419+ preempt_enable();
420 }
421
422 static inline void do_flush_tlb_all_local(void)
423diff -urN linux-2.4.20/arch/i386/kernel/traps.c linux/arch/i386/kernel/traps.c
424--- linux-2.4.20/arch/i386/kernel/traps.c 2002-11-28 18:53:09.000000000 -0500
425+++ linux/arch/i386/kernel/traps.c 2002-12-11 02:34:47.000000000 -0500
426@@ -751,6 +751,8 @@
427 *
428 * Careful.. There are problems with IBM-designed IRQ13 behaviour.
429 * Don't touch unless you *really* know how it works.
430+ *
431+ * Must be called with kernel preemption disabled.
432 */
433 asmlinkage void math_state_restore(struct pt_regs regs)
434 {
435diff -urN linux-2.4.20/arch/i386/lib/dec_and_lock.c linux/arch/i386/lib/dec_and_lock.c
436--- linux-2.4.20/arch/i386/lib/dec_and_lock.c 2000-07-07 21:20:16.000000000 -0400
437+++ linux/arch/i386/lib/dec_and_lock.c 2002-12-11 02:34:47.000000000 -0500
438@@ -8,6 +8,7 @@
439 */
440
441 #include <linux/spinlock.h>
442+#include <linux/sched.h>
443 #include <asm/atomic.h>
444
445 int atomic_dec_and_lock(atomic_t *atomic, spinlock_t *lock)
446diff -urN linux-2.4.20/arch/mips/config-shared.in linux/arch/mips/config-shared.in
447--- linux-2.4.20/arch/mips/config-shared.in 2002-11-28 18:53:09.000000000 -0500
448+++ linux/arch/mips/config-shared.in 2002-12-11 02:34:47.000000000 -0500
449@@ -615,6 +615,7 @@
450 define_bool CONFIG_HOTPLUG_PCI n
451 fi
452
453+dep_bool 'Preemptible Kernel' CONFIG_PREEMPT $CONFIG_NEW_IRQ
454 bool 'System V IPC' CONFIG_SYSVIPC
455 bool 'BSD Process Accounting' CONFIG_BSD_PROCESS_ACCT
456 bool 'Sysctl support' CONFIG_SYSCTL
457diff -urN linux-2.4.20/arch/mips/kernel/i8259.c linux/arch/mips/kernel/i8259.c
458--- linux-2.4.20/arch/mips/kernel/i8259.c 2002-11-28 18:53:10.000000000 -0500
459+++ linux/arch/mips/kernel/i8259.c 2002-12-11 02:34:47.000000000 -0500
460@@ -8,6 +8,7 @@
461 * Copyright (C) 1992 Linus Torvalds
462 * Copyright (C) 1994 - 2000 Ralf Baechle
463 */
464+#include <linux/sched.h>
465 #include <linux/delay.h>
466 #include <linux/init.h>
467 #include <linux/ioport.h>
468diff -urN linux-2.4.20/arch/mips/kernel/irq.c linux/arch/mips/kernel/irq.c
469--- linux-2.4.20/arch/mips/kernel/irq.c 2002-11-28 18:53:10.000000000 -0500
470+++ linux/arch/mips/kernel/irq.c 2002-12-11 02:34:47.000000000 -0500
471@@ -8,6 +8,8 @@
472 * Copyright (C) 1992 Linus Torvalds
473 * Copyright (C) 1994 - 2000 Ralf Baechle
474 */
475+
476+#include <linux/sched.h>
477 #include <linux/config.h>
478 #include <linux/kernel.h>
479 #include <linux/delay.h>
480@@ -19,11 +21,13 @@
481 #include <linux/slab.h>
482 #include <linux/mm.h>
483 #include <linux/random.h>
484-#include <linux/sched.h>
485+#include <linux/spinlock.h>
486+#include <linux/ptrace.h>
487
488 #include <asm/atomic.h>
489 #include <asm/system.h>
490 #include <asm/uaccess.h>
491+#include <asm/debug.h>
492
493 /*
494 * Controller mappings for all interrupt sources:
495@@ -429,6 +433,8 @@
496 struct irqaction * action;
497 unsigned int status;
498
499+ preempt_disable();
500+
501 kstat.irqs[cpu][irq]++;
502 spin_lock(&desc->lock);
503 desc->handler->ack(irq);
504@@ -490,6 +496,27 @@
505
506 if (softirq_pending(cpu))
507 do_softirq();
508+
509+#if defined(CONFIG_PREEMPT)
510+ while (--current->preempt_count == 0) {
511+ db_assert(intr_off());
512+ db_assert(!in_interrupt());
513+
514+ if (current->need_resched == 0) {
515+ break;
516+ }
517+
518+ current->preempt_count ++;
519+ sti();
520+ if (user_mode(regs)) {
521+ schedule();
522+ } else {
523+ preempt_schedule();
524+ }
525+ cli();
526+ }
527+#endif
528+
529 return 1;
530 }
531
532diff -urN linux-2.4.20/arch/mips/mm/extable.c linux/arch/mips/mm/extable.c
533--- linux-2.4.20/arch/mips/mm/extable.c 2002-11-28 18:53:10.000000000 -0500
534+++ linux/arch/mips/mm/extable.c 2002-12-11 02:34:47.000000000 -0500
535@@ -3,6 +3,7 @@
536 */
537 #include <linux/config.h>
538 #include <linux/module.h>
539+#include <linux/sched.h>
540 #include <linux/spinlock.h>
541 #include <asm/uaccess.h>
542
543diff -urN linux-2.4.20/arch/ppc/config.in linux/arch/ppc/config.in
544--- linux-2.4.20/arch/ppc/config.in 2002-11-28 18:53:11.000000000 -0500
545+++ linux/arch/ppc/config.in 2002-12-11 02:34:47.000000000 -0500
546@@ -112,6 +112,8 @@
547 bool ' Distribute interrupts on all CPUs by default' CONFIG_IRQ_ALL_CPUS
548 fi
549
550+bool 'Preemptible kernel support' CONFIG_PREEMPT
551+
552 if [ "$CONFIG_6xx" = "y" -a "$CONFIG_8260" = "n" ];then
553 bool 'AltiVec Support' CONFIG_ALTIVEC
554 bool 'Thermal Management Support' CONFIG_TAU
555diff -urN linux-2.4.20/arch/ppc/kernel/entry.S linux/arch/ppc/kernel/entry.S
556--- linux-2.4.20/arch/ppc/kernel/entry.S 2002-11-28 18:53:11.000000000 -0500
557+++ linux/arch/ppc/kernel/entry.S 2002-12-11 02:34:47.000000000 -0500
558@@ -278,6 +278,41 @@
559 */
560 cmpi 0,r3,0
561 beq restore
562+#ifdef CONFIG_PREEMPT
563+ lwz r3,PREEMPT_COUNT(r2)
564+ cmpi 0,r3,1
565+ bge ret_from_except
566+ lwz r5,_MSR(r1)
567+ andi. r5,r5,MSR_PR
568+ bne do_signal_ret
569+ lwz r5,NEED_RESCHED(r2)
570+ cmpi 0,r5,0
571+ beq ret_from_except
572+ lis r3,irq_stat@h
573+ ori r3,r3,irq_stat@l
574+ lwz r5,4(r3)
575+ lwz r3,8(r3)
576+ add r3,r3,r5
577+ cmpi 0,r3,0
578+ bne ret_from_except
579+ lwz r3,PREEMPT_COUNT(r2)
580+ addi r3,r3,1
581+ stw r3,PREEMPT_COUNT(r2)
582+ mfmsr r0
583+ ori r0,r0,MSR_EE
584+ mtmsr r0
585+ sync
586+ bl preempt_schedule
587+ mfmsr r0
588+ rlwinm r0,r0,0,17,15
589+ mtmsr r0
590+ sync
591+ lwz r3,PREEMPT_COUNT(r2)
592+ subi r3,r3,1
593+ stw r3,PREEMPT_COUNT(r2)
594+ li r3,1
595+ b ret_from_intercept
596+#endif /* CONFIG_PREEMPT */
597 .globl ret_from_except
598 ret_from_except:
599 lwz r3,_MSR(r1) /* Returning to user mode? */
600diff -urN linux-2.4.20/arch/ppc/kernel/irq.c linux/arch/ppc/kernel/irq.c
601--- linux-2.4.20/arch/ppc/kernel/irq.c 2002-11-28 18:53:11.000000000 -0500
602+++ linux/arch/ppc/kernel/irq.c 2002-12-11 02:34:47.000000000 -0500
603@@ -556,6 +556,34 @@
604 return 1; /* lets ret_from_int know we can do checks */
605 }
606
607+#ifdef CONFIG_PREEMPT
608+int
609+preempt_intercept(struct pt_regs *regs)
610+{
611+ int ret;
612+
613+ preempt_disable();
614+
615+ switch(regs->trap) {
616+ case 0x500:
617+ ret = do_IRQ(regs);
618+ break;
619+#ifndef CONFIG_4xx
620+ case 0x900:
621+#else
622+ case 0x1000:
623+#endif
624+ ret = timer_interrupt(regs);
625+ break;
626+ default:
627+ BUG();
628+ }
629+
630+ preempt_enable();
631+ return ret;
632+}
633+#endif /* CONFIG_PREEMPT */
634+
635 unsigned long probe_irq_on (void)
636 {
637 return 0;
638diff -urN linux-2.4.20/arch/ppc/kernel/mk_defs.c linux/arch/ppc/kernel/mk_defs.c
639--- linux-2.4.20/arch/ppc/kernel/mk_defs.c 2001-08-28 09:58:33.000000000 -0400
640+++ linux/arch/ppc/kernel/mk_defs.c 2002-12-11 02:34:47.000000000 -0500
641@@ -42,6 +42,9 @@
642 DEFINE(SIGPENDING, offsetof(struct task_struct, sigpending));
643 DEFINE(THREAD, offsetof(struct task_struct, thread));
644 DEFINE(MM, offsetof(struct task_struct, mm));
645+#ifdef CONFIG_PREEMPT
646+ DEFINE(PREEMPT_COUNT, offsetof(struct task_struct, preempt_count));
647+#endif
648 DEFINE(ACTIVE_MM, offsetof(struct task_struct, active_mm));
649 DEFINE(TASK_STRUCT_SIZE, sizeof(struct task_struct));
650 DEFINE(KSP, offsetof(struct thread_struct, ksp));
651diff -urN linux-2.4.20/arch/ppc/kernel/setup.c linux/arch/ppc/kernel/setup.c
652--- linux-2.4.20/arch/ppc/kernel/setup.c 2002-11-28 18:53:11.000000000 -0500
653+++ linux/arch/ppc/kernel/setup.c 2002-12-11 02:34:47.000000000 -0500
654@@ -498,6 +498,20 @@
655 strcpy(cmd_line, CONFIG_CMDLINE);
656 #endif /* CONFIG_CMDLINE */
657
658+#ifdef CONFIG_PREEMPT
659+ /* Override the irq routines for external & timer interrupts here,
660+ * as the MMU has only been minimally setup at this point and
661+ * there are no protections on page zero.
662+ */
663+ {
664+ extern int preempt_intercept(struct pt_regs *);
665+
666+ do_IRQ_intercept = (unsigned long) &preempt_intercept;
667+ timer_interrupt_intercept = (unsigned long) &preempt_intercept;
668+
669+ }
670+#endif /* CONFIG_PREEMPT */
671+
672 platform_init(r3, r4, r5, r6, r7);
673
674 if (ppc_md.progress)
675diff -urN linux-2.4.20/arch/ppc/lib/dec_and_lock.c linux/arch/ppc/lib/dec_and_lock.c
676--- linux-2.4.20/arch/ppc/lib/dec_and_lock.c 2001-11-16 13:10:08.000000000 -0500
677+++ linux/arch/ppc/lib/dec_and_lock.c 2002-12-11 02:34:47.000000000 -0500
678@@ -1,4 +1,5 @@
679 #include <linux/module.h>
680+#include <linux/sched.h>
681 #include <linux/spinlock.h>
682 #include <asm/atomic.h>
683 #include <asm/system.h>
684diff -urN linux-2.4.20/arch/sh/config.in linux/arch/sh/config.in
685--- linux-2.4.20/arch/sh/config.in 2002-11-28 18:53:11.000000000 -0500
686+++ linux/arch/sh/config.in 2002-12-11 02:34:47.000000000 -0500
687@@ -124,6 +124,7 @@
688 hex 'Physical memory start address' CONFIG_MEMORY_START 08000000
689 hex 'Physical memory size' CONFIG_MEMORY_SIZE 00400000
690 fi
691+bool 'Preemptible Kernel' CONFIG_PREEMPT
692 endmenu
693
694 if [ "$CONFIG_SH_HP690" = "y" ]; then
695diff -urN linux-2.4.20/arch/sh/kernel/entry.S linux/arch/sh/kernel/entry.S
696--- linux-2.4.20/arch/sh/kernel/entry.S 2002-08-02 20:39:43.000000000 -0400
697+++ linux/arch/sh/kernel/entry.S 2002-12-11 02:34:47.000000000 -0500
698@@ -60,10 +60,18 @@
699 /*
700 * These are offsets into the task-struct.
701 */
702-flags = 4
703+preempt_count = 4
704 sigpending = 8
705 need_resched = 20
706 tsk_ptrace = 24
707+flags = 84
708+
709+/*
710+ * These offsets are into irq_stat.
711+ * (Find irq_cpustat_t in asm-sh/hardirq.h)
712+ */
713+local_irq_count = 8
714+local_bh_count = 12
715
716 PT_TRACESYS = 0x00000002
717 PF_USEDFPU = 0x00100000
718@@ -143,7 +151,7 @@
719 mov.l __INV_IMASK, r11; \
720 stc sr, r10; \
721 and r11, r10; \
722- stc k_g_imask, r11; \
723+ stc k_g_imask, r11; \
724 or r11, r10; \
725 ldc r10, sr
726
727@@ -304,8 +312,8 @@
728 mov.l @(tsk_ptrace,r0), r0 ! Is current PTRACE_SYSCALL'd?
729 mov #PT_TRACESYS, r1
730 tst r1, r0
731- bt ret_from_syscall
732- bra syscall_ret_trace
733+ bf syscall_ret_trace
734+ bra ret_from_syscall
735 nop
736
737 .align 2
738@@ -505,8 +513,6 @@
739 .long syscall_ret_trace
740 __syscall_ret:
741 .long syscall_ret
742-__INV_IMASK:
743- .long 0xffffff0f ! ~(IMASK)
744
745
746 .align 2
747@@ -518,7 +524,84 @@
748 .align 2
749 1: .long SYMBOL_NAME(schedule)
750
751+#ifdef CONFIG_PREEMPT
752+ !
753+ ! Returning from interrupt during kernel mode: check if
754+ ! preempt_schedule should be called. If need_resched flag
755+ ! is set, preempt_count is zero, and we're not currently
756+ ! in an interrupt handler (local irq or bottom half) then
757+ ! call preempt_schedule.
758+ !
759+ ! Increment preempt_count to prevent a nested interrupt
760+ ! from reentering preempt_schedule, then decrement after
761+ ! and drop through to regular interrupt return which will
762+ ! jump back and check again in case such an interrupt did
763+ ! come in (and didn't preempt due to preempt_count).
764+ !
765+ ! NOTE: because we just checked that preempt_count was
766+ ! zero before getting to the call, can't we use immediate
767+ ! values (1 and 0) rather than inc/dec? Also, rather than
768+ ! drop through to ret_from_irq, we already know this thread
769+ ! is kernel mode, can't we go direct to ret_from_kirq? In
770+ ! fact, with proper interrupt nesting and so forth could
771+ ! the loop simply be on the need_resched w/o checking the
772+ ! other stuff again? Optimize later...
773+ !
774+ .align 2
775+ret_from_kirq:
776+ ! Nonzero preempt_count prevents scheduling
777+ stc k_current, r1
778+ mov.l @(preempt_count,r1), r0
779+ cmp/eq #0, r0
780+ bf restore_all
781+ ! Zero need_resched prevents scheduling
782+ mov.l @(need_resched,r1), r0
783+ cmp/eq #0, r0
784+ bt restore_all
785+ ! If in_interrupt(), don't schedule
786+ mov.l __irq_stat, r1
787+ mov.l @(local_irq_count,r1), r0
788+ mov.l @(local_bh_count,r1), r1
789+ or r1, r0
790+ cmp/eq #0, r0
791+ bf restore_all
792+ ! Allow scheduling using preempt_schedule
793+ ! Adjust preempt_count and SR as needed.
794+ stc k_current, r1
795+ mov.l @(preempt_count,r1), r0 ! Could replace this ...
796+ add #1, r0 ! ... and this w/mov #1?
797+ mov.l r0, @(preempt_count,r1)
798+ STI()
799+ mov.l __preempt_schedule, r0
800+ jsr @r0
801+ nop
802+ /* CLI */
803+ stc sr, r0
804+ or #0xf0, r0
805+ ldc r0, sr
806+ !
807+ stc k_current, r1
808+ mov.l @(preempt_count,r1), r0 ! Could replace this ...
809+ add #-1, r0 ! ... and this w/mov #0?
810+ mov.l r0, @(preempt_count,r1)
811+ ! Maybe should bra ret_from_kirq, or loop over need_resched?
812+ ! For now, fall through to ret_from_irq again...
813+#endif /* CONFIG_PREEMPT */
814+
815 ret_from_irq:
816+ mov #OFF_SR, r0
817+ mov.l @(r0,r15), r0 ! get status register
818+ shll r0
819+ shll r0 ! kernel space?
820+#ifndef CONFIG_PREEMPT
821+ bt restore_all ! Yes, it's from kernel, go back soon
822+#else /* CONFIG_PREEMPT */
823+ bt ret_from_kirq ! From kernel: maybe preempt_schedule
824+#endif /* CONFIG_PREEMPT */
825+ !
826+ bra ret_from_syscall
827+ nop
828+
829 ret_from_exception:
830 mov #OFF_SR, r0
831 mov.l @(r0,r15), r0 ! get status register
832@@ -564,6 +647,13 @@
833 .long SYMBOL_NAME(do_signal)
834 __irq_stat:
835 .long SYMBOL_NAME(irq_stat)
836+#ifdef CONFIG_PREEMPT
837+__preempt_schedule:
838+ .long SYMBOL_NAME(preempt_schedule)
839+#endif /* CONFIG_PREEMPT */
840+__INV_IMASK:
841+ .long 0xffffff0f ! ~(IMASK)
842+
843
844 .align 2
845 restore_all:
846@@ -679,7 +769,7 @@
847 __fpu_prepare_fd:
848 .long SYMBOL_NAME(fpu_prepare_fd)
849 __init_task_flags:
850- .long SYMBOL_NAME(init_task_union)+4
851+ .long SYMBOL_NAME(init_task_union)+flags
852 __PF_USEDFPU:
853 .long PF_USEDFPU
854 #endif
855diff -urN linux-2.4.20/arch/sh/kernel/irq.c linux/arch/sh/kernel/irq.c
856--- linux-2.4.20/arch/sh/kernel/irq.c 2001-09-08 15:29:09.000000000 -0400
857+++ linux/arch/sh/kernel/irq.c 2002-12-11 02:34:47.000000000 -0500
858@@ -229,6 +229,14 @@
859 struct irqaction * action;
860 unsigned int status;
861
862+ /*
863+ * At this point we're now about to actually call handlers,
864+ * and interrupts might get reenabled during them... bump
865+ * preempt_count to prevent any preemption while the handler
866+ * called here is pending...
867+ */
868+ preempt_disable();
869+
870 /* Get IRQ number */
871 asm volatile("stc r2_bank, %0\n\t"
872 "shlr2 %0\n\t"
873@@ -298,8 +306,17 @@
874 desc->handler->end(irq);
875 spin_unlock(&desc->lock);
876
877+
878 if (softirq_pending(cpu))
879 do_softirq();
880+
881+ /*
882+ * We're done with the handlers, interrupts should be
883+ * currently disabled; decrement preempt_count now so
884+ * as we return preemption may be allowed...
885+ */
886+ preempt_enable_no_resched();
887+
888 return 1;
889 }
890
891diff -urN linux-2.4.20/CREDITS linux/CREDITS
892--- linux-2.4.20/CREDITS 2002-11-28 18:53:08.000000000 -0500
893+++ linux/CREDITS 2002-12-11 02:34:47.000000000 -0500
894@@ -1001,8 +1001,8 @@
895
896 N: Nigel Gamble
897 E: nigel@nrg.org
898-E: nigel@sgi.com
899 D: Interrupt-driven printer driver
900+D: Preemptible kernel
901 S: 120 Alley Way
902 S: Mountain View, California 94040
903 S: USA
904diff -urN linux-2.4.20/Documentation/Configure.help linux/Documentation/Configure.help
905--- linux-2.4.20/Documentation/Configure.help 2002-11-28 18:53:08.000000000 -0500
906+++ linux/Documentation/Configure.help 2002-12-11 02:34:47.000000000 -0500
907@@ -279,6 +279,17 @@
908 If you have a system with several CPUs, you do not need to say Y
909 here: the local APIC will be used automatically.
910
911+Preemptible Kernel
912+CONFIG_PREEMPT
913+ This option reduces the latency of the kernel when reacting to
914+ real-time or interactive events by allowing a low priority process to
915+ be preempted even if it is in kernel mode executing a system call.
916+ This allows applications to run more reliably even when the system is
917+ under load.
918+
919+ Say Y here if you are building a kernel for a desktop, embedded or
920+ real-time system. Say N if you are unsure.
921+
922 Kernel math emulation
923 CONFIG_MATH_EMULATION
924 Linux can emulate a math coprocessor (used for floating point
925diff -urN linux-2.4.20/Documentation/preempt-locking.txt linux/Documentation/preempt-locking.txt
926--- linux-2.4.20/Documentation/preempt-locking.txt 1969-12-31 19:00:00.000000000 -0500
927+++ linux/Documentation/preempt-locking.txt 2002-12-11 02:34:47.000000000 -0500
928@@ -0,0 +1,104 @@
929+ Proper Locking Under a Preemptible Kernel:
930+ Keeping Kernel Code Preempt-Safe
931+ Robert Love <rml@tech9.net>
932+ Last Updated: 22 Jan 2002
933+
934+
935+INTRODUCTION
936+
937+
938+A preemptible kernel creates new locking issues. The issues are the same as
939+those under SMP: concurrency and reentrancy. Thankfully, the Linux preemptible
940+kernel model leverages existing SMP locking mechanisms. Thus, the kernel
941+requires explicit additional locking for very few additional situations.
942+
943+This document is for all kernel hackers. Developing code in the kernel
944+requires protecting these situations.
945+
946+
947+RULE #1: Per-CPU data structures need explicit protection
948+
949+
950+Two similar problems arise. An example code snippet:
951+
952+ struct this_needs_locking tux[NR_CPUS];
953+ tux[smp_processor_id()] = some_value;
954+ /* task is preempted here... */
955+ something = tux[smp_processor_id()];
956+
957+First, since the data is per-CPU, it may not have explicit SMP locking, but
958+require it otherwise. Second, when a preempted task is finally rescheduled,
959+the previous value of smp_processor_id may not equal the current. You must
960+protect these situations by disabling preemption around them.
961+
962+
963+RULE #2: CPU state must be protected.
964+
965+
966+Under preemption, the state of the CPU must be protected. This is arch-
967+dependent, but includes CPU structures and state not preserved over a context
968+switch. For example, on x86, entering and exiting FPU mode is now a critical
969+section that must occur while preemption is disabled. Think what would happen
970+if the kernel is executing a floating-point instruction and is then preempted.
971+Remember, the kernel does not save FPU state except for user tasks. Therefore,
972+upon preemption, the FPU registers will be sold to the lowest bidder. Thus,
973+preemption must be disabled around such regions.
974+
975+Note, some FPU functions are already explicitly preempt safe. For example,
976+kernel_fpu_begin and kernel_fpu_end will disable and enable preemption.
977+However, math_state_restore must be called with preemption disabled.
978+
979+
980+RULE #3: Lock acquire and release must be performed by same task
981+
982+
983+A lock acquired in one task must be released by the same task. This
984+means you can't do oddball things like acquire a lock and go off to
985+play while another task releases it. If you want to do something
986+like this, acquire and release the task in the same code path and
987+have the caller wait on an event by the other task.
988+
989+
990+SOLUTION
991+
992+
993+Data protection under preemption is achieved by disabling preemption for the
994+duration of the critical region.
995+
996+preempt_enable() decrement the preempt counter
997+preempt_disable() increment the preempt counter
998+preempt_enable_no_resched() decrement, but do not immediately preempt
999+preempt_get_count() return the preempt counter
1000+
1001+The functions are nestable. In other words, you can call preempt_disable
1002+n-times in a code path, and preemption will not be reenabled until the n-th
1003+call to preempt_enable. The preempt statements define to nothing if
1004+preemption is not enabled.
1005+
1006+Note that you do not need to explicitly prevent preemption if you are holding
1007+any locks or interrupts are disabled, since preemption is implicitly disabled
1008+in those cases.
1009+
1010+Example:
1011+
1012+ cpucache_t *cc; /* this is per-CPU */
1013+ preempt_disable();
1014+ cc = cc_data(searchp);
1015+ if (cc && cc->avail) {
1016+ __free_block(searchp, cc_entry(cc), cc->avail);
1017+ cc->avail = 0;
1018+ }
1019+ preempt_enable();
1020+ return 0;
1021+
1022+Notice how the preemption statements must encompass every reference of the
1023+critical variables. Another example:
1024+
1025+ int buf[NR_CPUS];
1026+ set_cpu_val(buf);
1027+ if (buf[smp_processor_id()] == -1) printf(KERN_INFO "wee!\n");
1028+ spin_lock(&buf_lock);
1029+ /* ... */
1030+
1031+This code is not preempt-safe, but see how easily we can fix it by simply
1032+moving the spin_lock up two lines.
1033diff -urN linux-2.4.20/drivers/ieee1394/csr.c linux/drivers/ieee1394/csr.c
1034--- linux-2.4.20/drivers/ieee1394/csr.c 2002-11-28 18:53:13.000000000 -0500
1035+++ linux/drivers/ieee1394/csr.c 2002-12-11 02:34:47.000000000 -0500
1036@@ -10,6 +10,7 @@
1037 */
1038
1039 #include <linux/string.h>
1040+#include <linux/sched.h>
1041
1042 #include "ieee1394_types.h"
1043 #include "hosts.h"
1044diff -urN linux-2.4.20/drivers/sound/sound_core.c linux/drivers/sound/sound_core.c
1045--- linux-2.4.20/drivers/sound/sound_core.c 2001-09-30 15:26:08.000000000 -0400
1046+++ linux/drivers/sound/sound_core.c 2002-12-11 02:34:47.000000000 -0500
1047@@ -37,6 +37,7 @@
1048 #include <linux/config.h>
1049 #include <linux/module.h>
1050 #include <linux/init.h>
1051+#include <linux/sched.h>
1052 #include <linux/slab.h>
1053 #include <linux/types.h>
1054 #include <linux/kernel.h>
1055diff -urN linux-2.4.20/fs/adfs/map.c linux/fs/adfs/map.c
1056--- linux-2.4.20/fs/adfs/map.c 2001-10-25 16:53:53.000000000 -0400
1057+++ linux/fs/adfs/map.c 2002-12-11 02:34:47.000000000 -0500
1058@@ -12,6 +12,7 @@
1059 #include <linux/fs.h>
1060 #include <linux/adfs_fs.h>
1061 #include <linux/spinlock.h>
1062+#include <linux/sched.h>
1063
1064 #include "adfs.h"
1065
1066diff -urN linux-2.4.20/fs/exec.c linux/fs/exec.c
1067--- linux-2.4.20/fs/exec.c 2002-11-28 18:53:15.000000000 -0500
1068+++ linux/fs/exec.c 2002-12-11 02:34:47.000000000 -0500
1069@@ -440,8 +440,8 @@
1070 active_mm = current->active_mm;
1071 current->mm = mm;
1072 current->active_mm = mm;
1073- task_unlock(current);
1074 activate_mm(active_mm, mm);
1075+ task_unlock(current);
1076 mm_release();
1077 if (old_mm) {
1078 if (active_mm != old_mm) BUG();
1079diff -urN linux-2.4.20/fs/fat/cache.c linux/fs/fat/cache.c
1080--- linux-2.4.20/fs/fat/cache.c 2001-10-12 16:48:42.000000000 -0400
1081+++ linux/fs/fat/cache.c 2002-12-11 02:34:47.000000000 -0500
1082@@ -14,6 +14,7 @@
1083 #include <linux/string.h>
1084 #include <linux/stat.h>
1085 #include <linux/fat_cvf.h>
1086+#include <linux/sched.h>
1087
1088 #if 0
1089 # define PRINTK(x) printk x
1090diff -urN linux-2.4.20/fs/nls/nls_base.c linux/fs/nls/nls_base.c
1091--- linux-2.4.20/fs/nls/nls_base.c 2002-08-02 20:39:45.000000000 -0400
1092+++ linux/fs/nls/nls_base.c 2002-12-11 02:34:47.000000000 -0500
1093@@ -18,6 +18,7 @@
1094 #ifdef CONFIG_KMOD
1095 #include <linux/kmod.h>
1096 #endif
1097+#include <linux/sched.h>
1098 #include <linux/spinlock.h>
1099
1100 static struct nls_table *tables;
1101diff -urN linux-2.4.20/include/asm-arm/dma.h linux/include/asm-arm/dma.h
1102--- linux-2.4.20/include/asm-arm/dma.h 2001-08-12 14:14:00.000000000 -0400
1103+++ linux/include/asm-arm/dma.h 2002-12-11 02:34:47.000000000 -0500
1104@@ -5,6 +5,7 @@
1105
1106 #include <linux/config.h>
1107 #include <linux/spinlock.h>
1108+#include <linux/sched.h>
1109 #include <asm/system.h>
1110 #include <asm/memory.h>
1111 #include <asm/scatterlist.h>
1112diff -urN linux-2.4.20/include/asm-arm/hardirq.h linux/include/asm-arm/hardirq.h
1113--- linux-2.4.20/include/asm-arm/hardirq.h 2001-10-11 12:04:57.000000000 -0400
1114+++ linux/include/asm-arm/hardirq.h 2002-12-11 02:34:47.000000000 -0500
1115@@ -34,6 +34,7 @@
1116 #define irq_exit(cpu,irq) (local_irq_count(cpu)--)
1117
1118 #define synchronize_irq() do { } while (0)
1119+#define release_irqlock(cpu) do { } while (0)
1120
1121 #else
1122 #error SMP not supported
1123diff -urN linux-2.4.20/include/asm-arm/pgalloc.h linux/include/asm-arm/pgalloc.h
1124--- linux-2.4.20/include/asm-arm/pgalloc.h 2001-08-12 14:14:00.000000000 -0400
1125+++ linux/include/asm-arm/pgalloc.h 2002-12-11 02:34:47.000000000 -0500
1126@@ -57,40 +57,48 @@
1127 {
1128 unsigned long *ret;
1129
1130+ preempt_disable();
1131 if ((ret = pgd_quicklist) != NULL) {
1132 pgd_quicklist = (unsigned long *)__pgd_next(ret);
1133 ret[1] = ret[2];
1134 clean_dcache_entry(ret + 1);
1135 pgtable_cache_size--;
1136 }
1137+ preempt_enable();
1138 return (pgd_t *)ret;
1139 }
1140
1141 static inline void free_pgd_fast(pgd_t *pgd)
1142 {
1143+ preempt_disable();
1144 __pgd_next(pgd) = (unsigned long) pgd_quicklist;
1145 pgd_quicklist = (unsigned long *) pgd;
1146 pgtable_cache_size++;
1147+ preempt_enable();
1148 }
1149
1150 static inline pte_t *pte_alloc_one_fast(struct mm_struct *mm, unsigned long address)
1151 {
1152 unsigned long *ret;
1153
1154+ preempt_disable();
1155 if((ret = pte_quicklist) != NULL) {
1156 pte_quicklist = (unsigned long *)__pte_next(ret);
1157 ret[0] = 0;
1158 clean_dcache_entry(ret);
1159 pgtable_cache_size--;
1160 }
1161+ preempt_enable();
1162 return (pte_t *)ret;
1163 }
1164
1165 static inline void free_pte_fast(pte_t *pte)
1166 {
1167+ preempt_disable();
1168 __pte_next(pte) = (unsigned long) pte_quicklist;
1169 pte_quicklist = (unsigned long *) pte;
1170 pgtable_cache_size++;
1171+ preempt_enable();
1172 }
1173
1174 #else /* CONFIG_NO_PGT_CACHE */
1175diff -urN linux-2.4.20/include/asm-arm/smplock.h linux/include/asm-arm/smplock.h
1176--- linux-2.4.20/include/asm-arm/smplock.h 2001-08-12 14:14:00.000000000 -0400
1177+++ linux/include/asm-arm/smplock.h 2002-12-11 02:34:47.000000000 -0500
1178@@ -3,12 +3,17 @@
1179 *
1180 * Default SMP lock implementation
1181 */
1182+#include <linux/config.h>
1183 #include <linux/interrupt.h>
1184 #include <linux/spinlock.h>
1185
1186 extern spinlock_t kernel_flag;
1187
1188+#ifdef CONFIG_PREEMPT
1189+#define kernel_locked() preempt_get_count()
1190+#else
1191 #define kernel_locked() spin_is_locked(&kernel_flag)
1192+#endif
1193
1194 /*
1195 * Release global kernel lock and global interrupt lock
1196@@ -40,8 +45,14 @@
1197 */
1198 static inline void lock_kernel(void)
1199 {
1200+#ifdef CONFIG_PREEMPT
1201+ if (current->lock_depth == -1)
1202+ spin_lock(&kernel_flag);
1203+ ++current->lock_depth;
1204+#else
1205 if (!++current->lock_depth)
1206 spin_lock(&kernel_flag);
1207+#endif
1208 }
1209
1210 static inline void unlock_kernel(void)
1211diff -urN linux-2.4.20/include/asm-arm/softirq.h linux/include/asm-arm/softirq.h
1212--- linux-2.4.20/include/asm-arm/softirq.h 2001-09-08 15:02:31.000000000 -0400
1213+++ linux/include/asm-arm/softirq.h 2002-12-11 02:34:47.000000000 -0500
1214@@ -5,20 +5,22 @@
1215 #include <asm/hardirq.h>
1216
1217 #define __cpu_bh_enable(cpu) \
1218- do { barrier(); local_bh_count(cpu)--; } while (0)
1219+ do { barrier(); local_bh_count(cpu)--; preempt_enable(); } while (0)
1220 #define cpu_bh_disable(cpu) \
1221- do { local_bh_count(cpu)++; barrier(); } while (0)
1222+ do { preempt_disable(); local_bh_count(cpu)++; barrier(); } while (0)
1223
1224 #define local_bh_disable() cpu_bh_disable(smp_processor_id())
1225 #define __local_bh_enable() __cpu_bh_enable(smp_processor_id())
1226
1227 #define in_softirq() (local_bh_count(smp_processor_id()) != 0)
1228
1229-#define local_bh_enable() \
1230+#define _local_bh_enable() \
1231 do { \
1232 unsigned int *ptr = &local_bh_count(smp_processor_id()); \
1233 if (!--*ptr && ptr[-2]) \
1234 __asm__("bl%? __do_softirq": : : "lr");/* out of line */\
1235 } while (0)
1236
1237+#define local_bh_enable() do { _local_bh_enable(); preempt_enable(); } while (0)
1238+
1239 #endif /* __ASM_SOFTIRQ_H */
1240diff -urN linux-2.4.20/include/asm-arm/system.h linux/include/asm-arm/system.h
1241--- linux-2.4.20/include/asm-arm/system.h 2000-11-27 20:07:59.000000000 -0500
1242+++ linux/include/asm-arm/system.h 2002-12-11 02:34:47.000000000 -0500
1243@@ -62,6 +62,13 @@
1244 #define local_irq_disable() __cli()
1245 #define local_irq_enable() __sti()
1246
1247+#define irqs_disabled() \
1248+({ \
1249+ unsigned long cpsr_val; \
1250+ asm ("mrs %0, cpsr" : "=r" (cpsr_val)); \
1251+ cpsr_val & 128; \
1252+})
1253+
1254 #ifdef CONFIG_SMP
1255 #error SMP not supported
1256
1257diff -urN linux-2.4.20/include/asm-i386/hardirq.h linux/include/asm-i386/hardirq.h
1258--- linux-2.4.20/include/asm-i386/hardirq.h 2001-11-22 14:46:19.000000000 -0500
1259+++ linux/include/asm-i386/hardirq.h 2002-12-11 02:34:47.000000000 -0500
1260@@ -19,12 +19,16 @@
1261
1262 /*
1263 * Are we in an interrupt context? Either doing bottom half
1264- * or hardware interrupt processing?
1265+ * or hardware interrupt processing? Note the preempt check,
1266+ * this is both a bugfix and an optimization. If we are
1267+ * preemptible, we cannot be in an interrupt.
1268 */
1269-#define in_interrupt() ({ int __cpu = smp_processor_id(); \
1270- (local_irq_count(__cpu) + local_bh_count(__cpu) != 0); })
1271+#define in_interrupt() (preempt_is_disabled() && \
1272+ ({unsigned long __cpu = smp_processor_id(); \
1273+ (local_irq_count(__cpu) + local_bh_count(__cpu) != 0); }))
1274
1275-#define in_irq() (local_irq_count(smp_processor_id()) != 0)
1276+#define in_irq() (preempt_is_disabled() && \
1277+ (local_irq_count(smp_processor_id()) != 0))
1278
1279 #ifndef CONFIG_SMP
1280
1281@@ -36,6 +40,8 @@
1282
1283 #define synchronize_irq() barrier()
1284
1285+#define release_irqlock(cpu) do { } while (0)
1286+
1287 #else
1288
1289 #include <asm/atomic.h>
1290diff -urN linux-2.4.20/include/asm-i386/highmem.h linux/include/asm-i386/highmem.h
1291--- linux-2.4.20/include/asm-i386/highmem.h 2002-08-02 20:39:45.000000000 -0400
1292+++ linux/include/asm-i386/highmem.h 2002-12-11 02:34:47.000000000 -0500
1293@@ -88,6 +88,7 @@
1294 enum fixed_addresses idx;
1295 unsigned long vaddr;
1296
1297+ preempt_disable();
1298 if (page < highmem_start_page)
1299 return page_address(page);
1300
1301@@ -109,8 +110,10 @@
1302 unsigned long vaddr = (unsigned long) kvaddr;
1303 enum fixed_addresses idx = type + KM_TYPE_NR*smp_processor_id();
1304
1305- if (vaddr < FIXADDR_START) // FIXME
1306+ if (vaddr < FIXADDR_START) { // FIXME
1307+ preempt_enable();
1308 return;
1309+ }
1310
1311 if (vaddr != __fix_to_virt(FIX_KMAP_BEGIN+idx))
1312 out_of_line_bug();
1313@@ -122,6 +125,8 @@
1314 pte_clear(kmap_pte-idx);
1315 __flush_tlb_one(vaddr);
1316 #endif
1317+
1318+ preempt_enable();
1319 }
1320
1321 #endif /* __KERNEL__ */
1322diff -urN linux-2.4.20/include/asm-i386/hw_irq.h linux/include/asm-i386/hw_irq.h
1323--- linux-2.4.20/include/asm-i386/hw_irq.h 2001-11-22 14:46:18.000000000 -0500
1324+++ linux/include/asm-i386/hw_irq.h 2002-12-11 02:34:47.000000000 -0500
1325@@ -95,6 +95,18 @@
1326 #define __STR(x) #x
1327 #define STR(x) __STR(x)
1328
1329+#define GET_CURRENT \
1330+ "movl %esp, %ebx\n\t" \
1331+ "andl $-8192, %ebx\n\t"
1332+
1333+#ifdef CONFIG_PREEMPT
1334+#define BUMP_LOCK_COUNT \
1335+ GET_CURRENT \
1336+ "incl 4(%ebx)\n\t"
1337+#else
1338+#define BUMP_LOCK_COUNT
1339+#endif
1340+
1341 #define SAVE_ALL \
1342 "cld\n\t" \
1343 "pushl %es\n\t" \
1344@@ -108,15 +120,12 @@
1345 "pushl %ebx\n\t" \
1346 "movl $" STR(__KERNEL_DS) ",%edx\n\t" \
1347 "movl %edx,%ds\n\t" \
1348- "movl %edx,%es\n\t"
1349+ "movl %edx,%es\n\t" \
1350+ BUMP_LOCK_COUNT
1351
1352 #define IRQ_NAME2(nr) nr##_interrupt(void)
1353 #define IRQ_NAME(nr) IRQ_NAME2(IRQ##nr)
1354
1355-#define GET_CURRENT \
1356- "movl %esp, %ebx\n\t" \
1357- "andl $-8192, %ebx\n\t"
1358-
1359 /*
1360 * SMP has a few special interrupts for IPI messages
1361 */
1362diff -urN linux-2.4.20/include/asm-i386/i387.h linux/include/asm-i386/i387.h
1363--- linux-2.4.20/include/asm-i386/i387.h 2002-08-02 20:39:45.000000000 -0400
1364+++ linux/include/asm-i386/i387.h 2002-12-11 02:34:47.000000000 -0500
1365@@ -12,6 +12,7 @@
1366 #define __ASM_I386_I387_H
1367
1368 #include <linux/sched.h>
1369+#include <linux/spinlock.h>
1370 #include <asm/processor.h>
1371 #include <asm/sigcontext.h>
1372 #include <asm/user.h>
1373@@ -24,7 +25,7 @@
1374 extern void restore_fpu( struct task_struct *tsk );
1375
1376 extern void kernel_fpu_begin(void);
1377-#define kernel_fpu_end() stts()
1378+#define kernel_fpu_end() do { stts(); preempt_enable(); } while(0)
1379
1380
1381 #define unlazy_fpu( tsk ) do { \
1382diff -urN linux-2.4.20/include/asm-i386/pgalloc.h linux/include/asm-i386/pgalloc.h
1383--- linux-2.4.20/include/asm-i386/pgalloc.h 2002-08-02 20:39:45.000000000 -0400
1384+++ linux/include/asm-i386/pgalloc.h 2002-12-11 02:34:47.000000000 -0500
1385@@ -75,20 +75,26 @@
1386 {
1387 unsigned long *ret;
1388
1389+ preempt_disable();
1390 if ((ret = pgd_quicklist) != NULL) {
1391 pgd_quicklist = (unsigned long *)(*ret);
1392 ret[0] = 0;
1393 pgtable_cache_size--;
1394- } else
1395+ preempt_enable();
1396+ } else {
1397+ preempt_enable();
1398 ret = (unsigned long *)get_pgd_slow();
1399+ }
1400 return (pgd_t *)ret;
1401 }
1402
1403 static inline void free_pgd_fast(pgd_t *pgd)
1404 {
1405+ preempt_disable();
1406 *(unsigned long *)pgd = (unsigned long) pgd_quicklist;
1407 pgd_quicklist = (unsigned long *) pgd;
1408 pgtable_cache_size++;
1409+ preempt_enable();
1410 }
1411
1412 static inline void free_pgd_slow(pgd_t *pgd)
1413@@ -119,19 +125,23 @@
1414 {
1415 unsigned long *ret;
1416
1417+ preempt_disable();
1418 if ((ret = (unsigned long *)pte_quicklist) != NULL) {
1419 pte_quicklist = (unsigned long *)(*ret);
1420 ret[0] = ret[1];
1421 pgtable_cache_size--;
1422 }
1423+ preempt_enable();
1424 return (pte_t *)ret;
1425 }
1426
1427 static inline void pte_free_fast(pte_t *pte)
1428 {
1429+ preempt_disable();
1430 *(unsigned long *)pte = (unsigned long) pte_quicklist;
1431 pte_quicklist = (unsigned long *) pte;
1432 pgtable_cache_size++;
1433+ preempt_enable();
1434 }
1435
1436 static __inline__ void pte_free_slow(pte_t *pte)
1437diff -urN linux-2.4.20/include/asm-i386/smplock.h linux/include/asm-i386/smplock.h
1438--- linux-2.4.20/include/asm-i386/smplock.h 2002-08-02 20:39:45.000000000 -0400
1439+++ linux/include/asm-i386/smplock.h 2002-12-11 02:34:47.000000000 -0500
1440@@ -11,7 +11,15 @@
1441 extern spinlock_cacheline_t kernel_flag_cacheline;
1442 #define kernel_flag kernel_flag_cacheline.lock
1443
1444+#ifdef CONFIG_SMP
1445 #define kernel_locked() spin_is_locked(&kernel_flag)
1446+#else
1447+#ifdef CONFIG_PREEMPT
1448+#define kernel_locked() preempt_get_count()
1449+#else
1450+#define kernel_locked() 1
1451+#endif
1452+#endif
1453
1454 /*
1455 * Release global kernel lock and global interrupt lock
1456@@ -43,6 +51,11 @@
1457 */
1458 static __inline__ void lock_kernel(void)
1459 {
1460+#ifdef CONFIG_PREEMPT
1461+ if (current->lock_depth == -1)
1462+ spin_lock(&kernel_flag);
1463+ ++current->lock_depth;
1464+#else
1465 #if 1
1466 if (!++current->lock_depth)
1467 spin_lock(&kernel_flag);
1468@@ -55,6 +68,7 @@
1469 :"=m" (__dummy_lock(&kernel_flag)),
1470 "=m" (current->lock_depth));
1471 #endif
1472+#endif
1473 }
1474
1475 static __inline__ void unlock_kernel(void)
1476diff -urN linux-2.4.20/include/asm-i386/softirq.h linux/include/asm-i386/softirq.h
1477--- linux-2.4.20/include/asm-i386/softirq.h 2002-08-02 20:39:45.000000000 -0400
1478+++ linux/include/asm-i386/softirq.h 2002-12-11 02:34:48.000000000 -0500
1479@@ -5,9 +5,9 @@
1480 #include <asm/hardirq.h>
1481
1482 #define __cpu_bh_enable(cpu) \
1483- do { barrier(); local_bh_count(cpu)--; } while (0)
1484+ do { barrier(); local_bh_count(cpu)--; preempt_enable(); } while (0)
1485 #define cpu_bh_disable(cpu) \
1486- do { local_bh_count(cpu)++; barrier(); } while (0)
1487+ do { preempt_disable(); local_bh_count(cpu)++; barrier(); } while (0)
1488
1489 #define local_bh_disable() cpu_bh_disable(smp_processor_id())
1490 #define __local_bh_enable() __cpu_bh_enable(smp_processor_id())
1491@@ -22,7 +22,7 @@
1492 * If you change the offsets in irq_stat then you have to
1493 * update this code as well.
1494 */
1495-#define local_bh_enable() \
1496+#define _local_bh_enable() \
1497 do { \
1498 unsigned int *ptr = &local_bh_count(smp_processor_id()); \
1499 \
1500@@ -45,4 +45,6 @@
1501 /* no registers clobbered */ ); \
1502 } while (0)
1503
1504+#define local_bh_enable() do { _local_bh_enable(); preempt_enable(); } while (0)
1505+
1506 #endif /* __ASM_SOFTIRQ_H */
1507diff -urN linux-2.4.20/include/asm-i386/spinlock.h linux/include/asm-i386/spinlock.h
1508--- linux-2.4.20/include/asm-i386/spinlock.h 2002-11-28 18:53:15.000000000 -0500
1509+++ linux/include/asm-i386/spinlock.h 2002-12-11 02:34:48.000000000 -0500
1510@@ -77,7 +77,7 @@
1511 :"=m" (lock->lock) : : "memory"
1512
1513
1514-static inline void spin_unlock(spinlock_t *lock)
1515+static inline void _raw_spin_unlock(spinlock_t *lock)
1516 {
1517 #if SPINLOCK_DEBUG
1518 if (lock->magic != SPINLOCK_MAGIC)
1519@@ -97,7 +97,7 @@
1520 :"=q" (oldval), "=m" (lock->lock) \
1521 :"0" (oldval) : "memory"
1522
1523-static inline void spin_unlock(spinlock_t *lock)
1524+static inline void _raw_spin_unlock(spinlock_t *lock)
1525 {
1526 char oldval = 1;
1527 #if SPINLOCK_DEBUG
1528@@ -113,7 +113,7 @@
1529
1530 #endif
1531
1532-static inline int spin_trylock(spinlock_t *lock)
1533+static inline int _raw_spin_trylock(spinlock_t *lock)
1534 {
1535 char oldval;
1536 __asm__ __volatile__(
1537@@ -123,7 +123,7 @@
1538 return oldval > 0;
1539 }
1540
1541-static inline void spin_lock(spinlock_t *lock)
1542+static inline void _raw_spin_lock(spinlock_t *lock)
1543 {
1544 #if SPINLOCK_DEBUG
1545 __label__ here;
1546@@ -179,7 +179,7 @@
1547 */
1548 /* the spinlock helpers are in arch/i386/kernel/semaphore.c */
1549
1550-static inline void read_lock(rwlock_t *rw)
1551+static inline void _raw_read_lock(rwlock_t *rw)
1552 {
1553 #if SPINLOCK_DEBUG
1554 if (rw->magic != RWLOCK_MAGIC)
1555@@ -188,7 +188,7 @@
1556 __build_read_lock(rw, "__read_lock_failed");
1557 }
1558
1559-static inline void write_lock(rwlock_t *rw)
1560+static inline void _raw_write_lock(rwlock_t *rw)
1561 {
1562 #if SPINLOCK_DEBUG
1563 if (rw->magic != RWLOCK_MAGIC)
1564@@ -197,10 +197,10 @@
1565 __build_write_lock(rw, "__write_lock_failed");
1566 }
1567
1568-#define read_unlock(rw) asm volatile("lock ; incl %0" :"=m" ((rw)->lock) : : "memory")
1569-#define write_unlock(rw) asm volatile("lock ; addl $" RW_LOCK_BIAS_STR ",%0":"=m" ((rw)->lock) : : "memory")
1570+#define _raw_read_unlock(rw) asm volatile("lock ; incl %0" :"=m" ((rw)->lock) : : "memory")
1571+#define _raw_write_unlock(rw) asm volatile("lock ; addl $" RW_LOCK_BIAS_STR ",%0":"=m" ((rw)->lock) : : "memory")
1572
1573-static inline int write_trylock(rwlock_t *lock)
1574+static inline int _raw_write_trylock(rwlock_t *lock)
1575 {
1576 atomic_t *count = (atomic_t *)lock;
1577 if (atomic_sub_and_test(RW_LOCK_BIAS, count))
1578diff -urN linux-2.4.20/include/asm-i386/system.h linux/include/asm-i386/system.h
1579--- linux-2.4.20/include/asm-i386/system.h 2002-11-28 18:53:15.000000000 -0500
1580+++ linux/include/asm-i386/system.h 2002-12-11 02:34:48.000000000 -0500
1581@@ -322,6 +322,13 @@
1582 /* used in the idle loop; sti takes one instruction cycle to complete */
1583 #define safe_halt() __asm__ __volatile__("sti; hlt": : :"memory")
1584
1585+#define irqs_disabled() \
1586+({ \
1587+ unsigned long flags; \
1588+ __save_flags(flags); \
1589+ !(flags & (1<<9)); \
1590+})
1591+
1592 /* For spinlocks etc */
1593 #define local_irq_save(x) __asm__ __volatile__("pushfl ; popl %0 ; cli":"=g" (x): /* no input */ :"memory")
1594 #define local_irq_restore(x) __restore_flags(x)
1595diff -urN linux-2.4.20/include/asm-mips/smplock.h linux/include/asm-mips/smplock.h
1596--- linux-2.4.20/include/asm-mips/smplock.h 2002-08-02 20:39:45.000000000 -0400
1597+++ linux/include/asm-mips/smplock.h 2002-12-11 02:34:48.000000000 -0500
1598@@ -5,12 +5,21 @@
1599 *
1600 * Default SMP lock implementation
1601 */
1602+#include <linux/config.h>
1603 #include <linux/interrupt.h>
1604 #include <linux/spinlock.h>
1605
1606 extern spinlock_t kernel_flag;
1607
1608+#ifdef CONFIG_SMP
1609 #define kernel_locked() spin_is_locked(&kernel_flag)
1610+#else
1611+#ifdef CONFIG_PREEMPT
1612+#define kernel_locked() preempt_get_count()
1613+#else
1614+#define kernel_locked() 1
1615+#endif
1616+#endif
1617
1618 /*
1619 * Release global kernel lock and global interrupt lock
1620@@ -42,8 +51,14 @@
1621 */
1622 extern __inline__ void lock_kernel(void)
1623 {
1624+#ifdef CONFIG_PREEMPT
1625+ if (current->lock_depth == -1)
1626+ spin_lock(&kernel_flag);
1627+ ++current->lock_depth;
1628+#else
1629 if (!++current->lock_depth)
1630 spin_lock(&kernel_flag);
1631+#endif
1632 }
1633
1634 extern __inline__ void unlock_kernel(void)
1635diff -urN linux-2.4.20/include/asm-mips/softirq.h linux/include/asm-mips/softirq.h
1636--- linux-2.4.20/include/asm-mips/softirq.h 2002-11-28 18:53:15.000000000 -0500
1637+++ linux/include/asm-mips/softirq.h 2002-12-11 02:34:48.000000000 -0500
1638@@ -15,6 +15,7 @@
1639
1640 static inline void cpu_bh_disable(int cpu)
1641 {
1642+ preempt_disable();
1643 local_bh_count(cpu)++;
1644 barrier();
1645 }
1646@@ -23,6 +24,7 @@
1647 {
1648 barrier();
1649 local_bh_count(cpu)--;
1650+ preempt_enable();
1651 }
1652
1653
1654@@ -36,6 +38,7 @@
1655 cpu = smp_processor_id(); \
1656 if (!--local_bh_count(cpu) && softirq_pending(cpu)) \
1657 do_softirq(); \
1658+ preempt_enable(); \
1659 } while (0)
1660
1661 #define in_softirq() (local_bh_count(smp_processor_id()) != 0)
1662diff -urN linux-2.4.20/include/asm-mips/system.h linux/include/asm-mips/system.h
1663--- linux-2.4.20/include/asm-mips/system.h 2002-11-28 18:53:15.000000000 -0500
1664+++ linux/include/asm-mips/system.h 2002-12-11 02:34:48.000000000 -0500
1665@@ -322,4 +322,18 @@
1666 #define die_if_kernel(msg, regs) \
1667 __die_if_kernel(msg, regs, __FILE__ ":", __FUNCTION__, __LINE__)
1668
1669+extern __inline__ int intr_on(void)
1670+{
1671+ unsigned long flags;
1672+ save_flags(flags);
1673+ return flags & 1;
1674+}
1675+
1676+extern __inline__ int intr_off(void)
1677+{
1678+ return ! intr_on();
1679+}
1680+
1681+#define irqs_disabled() intr_off()
1682+
1683 #endif /* _ASM_SYSTEM_H */
1684diff -urN linux-2.4.20/include/asm-ppc/dma.h linux/include/asm-ppc/dma.h
1685--- linux-2.4.20/include/asm-ppc/dma.h 2001-05-21 18:02:06.000000000 -0400
1686+++ linux/include/asm-ppc/dma.h 2002-12-11 02:34:48.000000000 -0500
1687@@ -14,6 +14,7 @@
1688 #include <linux/config.h>
1689 #include <asm/io.h>
1690 #include <linux/spinlock.h>
1691+#include <linux/sched.h>
1692 #include <asm/system.h>
1693
1694 /*
1695diff -urN linux-2.4.20/include/asm-ppc/hardirq.h linux/include/asm-ppc/hardirq.h
1696--- linux-2.4.20/include/asm-ppc/hardirq.h 2002-11-28 18:53:15.000000000 -0500
1697+++ linux/include/asm-ppc/hardirq.h 2002-12-11 02:34:48.000000000 -0500
1698@@ -48,6 +48,7 @@
1699 #define hardirq_exit(cpu) (local_irq_count(cpu)--)
1700
1701 #define synchronize_irq() do { } while (0)
1702+#define release_irqlock(cpu) do { } while (0)
1703
1704 #else /* CONFIG_SMP */
1705
1706diff -urN linux-2.4.20/include/asm-ppc/highmem.h linux/include/asm-ppc/highmem.h
1707--- linux-2.4.20/include/asm-ppc/highmem.h 2001-07-02 17:34:57.000000000 -0400
1708+++ linux/include/asm-ppc/highmem.h 2002-12-11 02:34:48.000000000 -0500
1709@@ -84,6 +84,7 @@
1710 unsigned int idx;
1711 unsigned long vaddr;
1712
1713+ preempt_disable();
1714 if (page < highmem_start_page)
1715 return page_address(page);
1716
1717@@ -105,8 +106,10 @@
1718 unsigned long vaddr = (unsigned long) kvaddr;
1719 unsigned int idx = type + KM_TYPE_NR*smp_processor_id();
1720
1721- if (vaddr < KMAP_FIX_BEGIN) // FIXME
1722+ if (vaddr < KMAP_FIX_BEGIN) { // FIXME
1723+ preempt_enable();
1724 return;
1725+ }
1726
1727 if (vaddr != KMAP_FIX_BEGIN + idx * PAGE_SIZE)
1728 BUG();
1729@@ -118,6 +121,7 @@
1730 pte_clear(kmap_pte+idx);
1731 flush_tlb_page(0, vaddr);
1732 #endif
1733+ preempt_enable();
1734 }
1735
1736 #endif /* __KERNEL__ */
1737diff -urN linux-2.4.20/include/asm-ppc/hw_irq.h linux/include/asm-ppc/hw_irq.h
1738--- linux-2.4.20/include/asm-ppc/hw_irq.h 2002-11-28 18:53:15.000000000 -0500
1739+++ linux/include/asm-ppc/hw_irq.h 2002-12-11 02:34:48.000000000 -0500
1740@@ -22,6 +22,12 @@
1741 #define __save_flags(flags) __save_flags_ptr((unsigned long *)&flags)
1742 #define __save_and_cli(flags) ({__save_flags(flags);__cli();})
1743
1744+#define mfmsr() ({unsigned int rval; \
1745+ asm volatile("mfmsr %0" : "=r" (rval)); rval;})
1746+#define mtmsr(v) asm volatile("mtmsr %0" : : "r" (v))
1747+
1748+#define irqs_disabled() ((mfmsr() & MSR_EE) == 0)
1749+
1750 extern void do_lost_interrupts(unsigned long);
1751
1752 #define mask_irq(irq) ({if (irq_desc[irq].handler && irq_desc[irq].handler->disable) irq_desc[irq].handler->disable(irq);})
1753diff -urN linux-2.4.20/include/asm-ppc/mmu_context.h linux/include/asm-ppc/mmu_context.h
1754--- linux-2.4.20/include/asm-ppc/mmu_context.h 2001-10-02 12:12:44.000000000 -0400
1755+++ linux/include/asm-ppc/mmu_context.h 2002-12-11 02:34:48.000000000 -0500
1756@@ -158,6 +158,10 @@
1757 static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
1758 struct task_struct *tsk, int cpu)
1759 {
1760+#ifdef CONFIG_PREEMPT
1761+ if (preempt_get_count() == 0)
1762+ BUG();
1763+#endif
1764 tsk->thread.pgdir = next->pgd;
1765 get_mmu_context(next);
1766 set_context(next->context, next->pgd);
1767diff -urN linux-2.4.20/include/asm-ppc/pgalloc.h linux/include/asm-ppc/pgalloc.h
1768--- linux-2.4.20/include/asm-ppc/pgalloc.h 2001-05-21 18:02:06.000000000 -0400
1769+++ linux/include/asm-ppc/pgalloc.h 2002-12-11 02:34:48.000000000 -0500
1770@@ -68,20 +68,25 @@
1771 {
1772 unsigned long *ret;
1773
1774+ preempt_disable();
1775 if ((ret = pgd_quicklist) != NULL) {
1776 pgd_quicklist = (unsigned long *)(*ret);
1777 ret[0] = 0;
1778 pgtable_cache_size--;
1779+ preempt_enable();
1780 } else
1781+ preempt_enable();
1782 ret = (unsigned long *)get_pgd_slow();
1783 return (pgd_t *)ret;
1784 }
1785
1786 extern __inline__ void free_pgd_fast(pgd_t *pgd)
1787 {
1788+ preempt_disable();
1789 *(unsigned long **)pgd = pgd_quicklist;
1790 pgd_quicklist = (unsigned long *) pgd;
1791 pgtable_cache_size++;
1792+ preempt_enable();
1793 }
1794
1795 extern __inline__ void free_pgd_slow(pgd_t *pgd)
1796@@ -120,19 +125,23 @@
1797 {
1798 unsigned long *ret;
1799
1800+ preempt_disable();
1801 if ((ret = pte_quicklist) != NULL) {
1802 pte_quicklist = (unsigned long *)(*ret);
1803 ret[0] = 0;
1804 pgtable_cache_size--;
1805 }
1806+ preempt_enable();
1807 return (pte_t *)ret;
1808 }
1809
1810 extern __inline__ void pte_free_fast(pte_t *pte)
1811 {
1812+ preempt_disable();
1813 *(unsigned long **)pte = pte_quicklist;
1814 pte_quicklist = (unsigned long *) pte;
1815 pgtable_cache_size++;
1816+ preempt_enable();
1817 }
1818
1819 extern __inline__ void pte_free_slow(pte_t *pte)
1820diff -urN linux-2.4.20/include/asm-ppc/smplock.h linux/include/asm-ppc/smplock.h
1821--- linux-2.4.20/include/asm-ppc/smplock.h 2001-11-02 20:43:54.000000000 -0500
1822+++ linux/include/asm-ppc/smplock.h 2002-12-11 02:34:48.000000000 -0500
1823@@ -15,7 +15,15 @@
1824
1825 extern spinlock_t kernel_flag;
1826
1827+#ifdef CONFIG_SMP
1828 #define kernel_locked() spin_is_locked(&kernel_flag)
1829+#else
1830+#ifdef CONFIG_PREEMPT
1831+#define kernel_locked() preempt_get_count()
1832+#else
1833+#define kernel_locked() 1
1834+#endif
1835+#endif
1836
1837 /*
1838 * Release global kernel lock and global interrupt lock
1839@@ -47,8 +55,14 @@
1840 */
1841 static __inline__ void lock_kernel(void)
1842 {
1843+#ifdef CONFIG_PREEMPT
1844+ if (current->lock_depth == -1)
1845+ spin_lock(&kernel_flag);
1846+ ++current->lock_depth;
1847+#else
1848 if (!++current->lock_depth)
1849 spin_lock(&kernel_flag);
1850+#endif
1851 }
1852
1853 static __inline__ void unlock_kernel(void)
1854diff -urN linux-2.4.20/include/asm-ppc/softirq.h linux/include/asm-ppc/softirq.h
1855--- linux-2.4.20/include/asm-ppc/softirq.h 2001-09-08 15:02:31.000000000 -0400
1856+++ linux/include/asm-ppc/softirq.h 2002-12-11 02:34:48.000000000 -0500
1857@@ -10,6 +10,7 @@
1858
1859 #define local_bh_disable() \
1860 do { \
1861+ preempt_disable(); \
1862 local_bh_count(smp_processor_id())++; \
1863 barrier(); \
1864 } while (0)
1865@@ -18,9 +19,10 @@
1866 do { \
1867 barrier(); \
1868 local_bh_count(smp_processor_id())--; \
1869+ preempt_enable(); \
1870 } while (0)
1871
1872-#define local_bh_enable() \
1873+#define _local_bh_enable() \
1874 do { \
1875 if (!--local_bh_count(smp_processor_id()) \
1876 && softirq_pending(smp_processor_id())) { \
1877@@ -28,6 +30,12 @@
1878 } \
1879 } while (0)
1880
1881+#define local_bh_enable() \
1882+do { \
1883+ _local_bh_enable(); \
1884+ preempt_enable(); \
1885+} while (0)
1886+
1887 #define in_softirq() (local_bh_count(smp_processor_id()) != 0)
1888
1889 #endif /* __ASM_SOFTIRQ_H */
1890diff -urN linux-2.4.20/include/asm-sh/hardirq.h linux/include/asm-sh/hardirq.h
1891--- linux-2.4.20/include/asm-sh/hardirq.h 2001-09-08 15:29:09.000000000 -0400
1892+++ linux/include/asm-sh/hardirq.h 2002-12-11 02:34:48.000000000 -0500
1893@@ -34,6 +34,8 @@
1894
1895 #define synchronize_irq() barrier()
1896
1897+#define release_irqlock(cpu) do { } while (0)
1898+
1899 #else
1900
1901 #error Super-H SMP is not available
1902diff -urN linux-2.4.20/include/asm-sh/smplock.h linux/include/asm-sh/smplock.h
1903--- linux-2.4.20/include/asm-sh/smplock.h 2001-09-08 15:29:09.000000000 -0400
1904+++ linux/include/asm-sh/smplock.h 2002-12-11 02:34:48.000000000 -0500
1905@@ -9,15 +9,88 @@
1906
1907 #include <linux/config.h>
1908
1909-#ifndef CONFIG_SMP
1910-
1911+#if !defined(CONFIG_SMP) && !defined(CONFIG_PREEMPT)
1912+/*
1913+ * Should never happen, since linux/smp_lock.h catches this case;
1914+ * but in case this file is included directly with neither SMP nor
1915+ * PREEMPT configuration, provide same dummys as linux/smp_lock.h
1916+ */
1917 #define lock_kernel() do { } while(0)
1918 #define unlock_kernel() do { } while(0)
1919-#define release_kernel_lock(task, cpu, depth) ((depth) = 1)
1920-#define reacquire_kernel_lock(task, cpu, depth) do { } while(0)
1921+#define release_kernel_lock(task, cpu) do { } while(0)
1922+#define reacquire_kernel_lock(task) do { } while(0)
1923+#define kernel_locked() 1
1924+
1925+#else /* CONFIG_SMP || CONFIG_PREEMPT */
1926+
1927+#if CONFIG_SMP
1928+#error "We do not support SMP on SH yet"
1929+#endif
1930+/*
1931+ * Default SMP lock implementation (i.e. the i386 version)
1932+ */
1933+
1934+#include <linux/interrupt.h>
1935+#include <linux/spinlock.h>
1936+
1937+extern spinlock_t kernel_flag;
1938+#define lock_bkl() spin_lock(&kernel_flag)
1939+#define unlock_bkl() spin_unlock(&kernel_flag)
1940
1941+#ifdef CONFIG_SMP
1942+#define kernel_locked() spin_is_locked(&kernel_flag)
1943+#elif CONFIG_PREEMPT
1944+#define kernel_locked() preempt_get_count()
1945+#else /* neither */
1946+#define kernel_locked() 1
1947+#endif
1948+
1949+/*
1950+ * Release global kernel lock and global interrupt lock
1951+ */
1952+#define release_kernel_lock(task, cpu) \
1953+do { \
1954+ if (task->lock_depth >= 0) \
1955+ spin_unlock(&kernel_flag); \
1956+ release_irqlock(cpu); \
1957+ __sti(); \
1958+} while (0)
1959+
1960+/*
1961+ * Re-acquire the kernel lock
1962+ */
1963+#define reacquire_kernel_lock(task) \
1964+do { \
1965+ if (task->lock_depth >= 0) \
1966+ spin_lock(&kernel_flag); \
1967+} while (0)
1968+
1969+/*
1970+ * Getting the big kernel lock.
1971+ *
1972+ * This cannot happen asynchronously,
1973+ * so we only need to worry about other
1974+ * CPU's.
1975+ */
1976+static __inline__ void lock_kernel(void)
1977+{
1978+#ifdef CONFIG_PREEMPT
1979+ if (current->lock_depth == -1)
1980+ spin_lock(&kernel_flag);
1981+ ++current->lock_depth;
1982 #else
1983-#error "We do not support SMP on SH"
1984-#endif /* CONFIG_SMP */
1985+ if (!++current->lock_depth)
1986+ spin_lock(&kernel_flag);
1987+#endif
1988+}
1989+
1990+static __inline__ void unlock_kernel(void)
1991+{
1992+ if (current->lock_depth < 0)
1993+ BUG();
1994+ if (--current->lock_depth < 0)
1995+ spin_unlock(&kernel_flag);
1996+}
1997+#endif /* CONFIG_SMP || CONFIG_PREEMPT */
1998
1999 #endif /* __ASM_SH_SMPLOCK_H */
2000diff -urN linux-2.4.20/include/asm-sh/softirq.h linux/include/asm-sh/softirq.h
2001--- linux-2.4.20/include/asm-sh/softirq.h 2001-09-08 15:29:09.000000000 -0400
2002+++ linux/include/asm-sh/softirq.h 2002-12-11 02:34:48.000000000 -0500
2003@@ -6,6 +6,7 @@
2004
2005 #define local_bh_disable() \
2006 do { \
2007+ preempt_disable(); \
2008 local_bh_count(smp_processor_id())++; \
2009 barrier(); \
2010 } while (0)
2011@@ -14,6 +15,7 @@
2012 do { \
2013 barrier(); \
2014 local_bh_count(smp_processor_id())--; \
2015+ preempt_enable(); \
2016 } while (0)
2017
2018 #define local_bh_enable() \
2019@@ -23,6 +25,7 @@
2020 && softirq_pending(smp_processor_id())) { \
2021 do_softirq(); \
2022 } \
2023+ preempt_enable(); \
2024 } while (0)
2025
2026 #define in_softirq() (local_bh_count(smp_processor_id()) != 0)
2027diff -urN linux-2.4.20/include/asm-sh/system.h linux/include/asm-sh/system.h
2028--- linux-2.4.20/include/asm-sh/system.h 2001-09-08 15:29:09.000000000 -0400
2029+++ linux/include/asm-sh/system.h 2002-12-11 02:34:48.000000000 -0500
2030@@ -285,4 +285,17 @@
2031 void disable_hlt(void);
2032 void enable_hlt(void);
2033
2034+/*
2035+ * irqs_disabled - are interrupts disabled?
2036+ */
2037+static inline int irqs_disabled(void)
2038+{
2039+ unsigned long flags;
2040+
2041+ __save_flags(flags);
2042+ if (flags & 0x000000f0)
2043+ return 1;
2044+ return 0;
2045+}
2046+
2047 #endif
2048diff -urN linux-2.4.20/include/linux/brlock.h linux/include/linux/brlock.h
2049--- linux-2.4.20/include/linux/brlock.h 2002-11-28 18:53:15.000000000 -0500
2050+++ linux/include/linux/brlock.h 2002-12-11 02:34:48.000000000 -0500
2051@@ -171,11 +171,11 @@
2052 }
2053
2054 #else
2055-# define br_read_lock(idx) ((void)(idx))
2056-# define br_read_unlock(idx) ((void)(idx))
2057-# define br_write_lock(idx) ((void)(idx))
2058-# define br_write_unlock(idx) ((void)(idx))
2059-#endif
2060+# define br_read_lock(idx) ({ (void)(idx); preempt_disable(); })
2061+# define br_read_unlock(idx) ({ (void)(idx); preempt_enable(); })
2062+# define br_write_lock(idx) ({ (void)(idx); preempt_disable(); })
2063+# define br_write_unlock(idx) ({ (void)(idx); preempt_enable(); })
2064+#endif /* CONFIG_SMP */
2065
2066 /*
2067 * Now enumerate all of the possible sw/hw IRQ protected
2068diff -urN linux-2.4.20/include/linux/dcache.h linux/include/linux/dcache.h
2069--- linux-2.4.20/include/linux/dcache.h 2002-11-28 18:53:15.000000000 -0500
2070+++ linux/include/linux/dcache.h 2002-12-11 02:34:48.000000000 -0500
2071@@ -127,31 +127,6 @@
2072
2073 extern spinlock_t dcache_lock;
2074
2075-/**
2076- * d_drop - drop a dentry
2077- * @dentry: dentry to drop
2078- *
2079- * d_drop() unhashes the entry from the parent
2080- * dentry hashes, so that it won't be found through
2081- * a VFS lookup any more. Note that this is different
2082- * from deleting the dentry - d_delete will try to
2083- * mark the dentry negative if possible, giving a
2084- * successful _negative_ lookup, while d_drop will
2085- * just make the cache lookup fail.
2086- *
2087- * d_drop() is used mainly for stuff that wants
2088- * to invalidate a dentry for some reason (NFS
2089- * timeouts or autofs deletes).
2090- */
2091-
2092-static __inline__ void d_drop(struct dentry * dentry)
2093-{
2094- spin_lock(&dcache_lock);
2095- list_del(&dentry->d_hash);
2096- INIT_LIST_HEAD(&dentry->d_hash);
2097- spin_unlock(&dcache_lock);
2098-}
2099-
2100 static __inline__ int dname_external(struct dentry *d)
2101 {
2102 return d->d_name.name != d->d_iname;
2103@@ -276,3 +251,34 @@
2104 #endif /* __KERNEL__ */
2105
2106 #endif /* __LINUX_DCACHE_H */
2107+
2108+#if !defined(__LINUX_DCACHE_H_INLINES) && defined(_TASK_STRUCT_DEFINED)
2109+#define __LINUX_DCACHE_H_INLINES
2110+
2111+#ifdef __KERNEL__
2112+/**
2113+ * d_drop - drop a dentry
2114+ * @dentry: dentry to drop
2115+ *
2116+ * d_drop() unhashes the entry from the parent
2117+ * dentry hashes, so that it won't be found through
2118+ * a VFS lookup any more. Note that this is different
2119+ * from deleting the dentry - d_delete will try to
2120+ * mark the dentry negative if possible, giving a
2121+ * successful _negative_ lookup, while d_drop will
2122+ * just make the cache lookup fail.
2123+ *
2124+ * d_drop() is used mainly for stuff that wants
2125+ * to invalidate a dentry for some reason (NFS
2126+ * timeouts or autofs deletes).
2127+ */
2128+
2129+static __inline__ void d_drop(struct dentry * dentry)
2130+{
2131+ spin_lock(&dcache_lock);
2132+ list_del(&dentry->d_hash);
2133+ INIT_LIST_HEAD(&dentry->d_hash);
2134+ spin_unlock(&dcache_lock);
2135+}
2136+#endif
2137+#endif
2138diff -urN linux-2.4.20/include/linux/fs_struct.h linux/include/linux/fs_struct.h
2139--- linux-2.4.20/include/linux/fs_struct.h 2001-07-13 18:10:44.000000000 -0400
2140+++ linux/include/linux/fs_struct.h 2002-12-11 02:34:48.000000000 -0500
2141@@ -20,6 +20,15 @@
2142 extern void exit_fs(struct task_struct *);
2143 extern void set_fs_altroot(void);
2144
2145+struct fs_struct *copy_fs_struct(struct fs_struct *old);
2146+void put_fs_struct(struct fs_struct *fs);
2147+
2148+#endif
2149+#endif
2150+
2151+#if !defined(_LINUX_FS_STRUCT_H_INLINES) && defined(_TASK_STRUCT_DEFINED)
2152+#define _LINUX_FS_STRUCT_H_INLINES
2153+#ifdef __KERNEL__
2154 /*
2155 * Replace the fs->{rootmnt,root} with {mnt,dentry}. Put the old values.
2156 * It can block. Requires the big lock held.
2157@@ -65,9 +74,5 @@
2158 mntput(old_pwdmnt);
2159 }
2160 }
2161-
2162-struct fs_struct *copy_fs_struct(struct fs_struct *old);
2163-void put_fs_struct(struct fs_struct *fs);
2164-
2165 #endif
2166 #endif
2167diff -urN linux-2.4.20/include/linux/sched.h linux/include/linux/sched.h
2168--- linux-2.4.20/include/linux/sched.h 2002-11-28 18:53:15.000000000 -0500
2169+++ linux/include/linux/sched.h 2002-12-11 02:34:48.000000000 -0500
2170@@ -91,6 +91,7 @@
2171 #define TASK_UNINTERRUPTIBLE 2
2172 #define TASK_ZOMBIE 4
2173 #define TASK_STOPPED 8
2174+#define PREEMPT_ACTIVE 0x4000000
2175
2176 #define __set_task_state(tsk, state_value) \
2177 do { (tsk)->state = (state_value); } while (0)
2178@@ -157,6 +158,9 @@
2179 #define MAX_SCHEDULE_TIMEOUT LONG_MAX
2180 extern signed long FASTCALL(schedule_timeout(signed long timeout));
2181 asmlinkage void schedule(void);
2182+#ifdef CONFIG_PREEMPT
2183+asmlinkage void preempt_schedule(void);
2184+#endif
2185
2186 extern int schedule_task(struct tq_struct *task);
2187 extern void flush_scheduled_tasks(void);
2188@@ -289,7 +293,7 @@
2189 * offsets of these are hardcoded elsewhere - touch with care
2190 */
2191 volatile long state; /* -1 unrunnable, 0 runnable, >0 stopped */
2192- unsigned long flags; /* per process flags, defined below */
2193+ int preempt_count; /* 0 => preemptable, <0 => BUG */
2194 int sigpending;
2195 mm_segment_t addr_limit; /* thread address space:
2196 0-0xBFFFFFFF for user-thead
2197@@ -331,6 +335,7 @@
2198 struct mm_struct *active_mm;
2199 struct list_head local_pages;
2200 unsigned int allocation_order, nr_local_pages;
2201+ unsigned long flags;
2202
2203 /* task state */
2204 struct linux_binfmt *binfmt;
2205@@ -955,5 +960,10 @@
2206 __cond_resched();
2207 }
2208
2209+#define _TASK_STRUCT_DEFINED
2210+#include <linux/dcache.h>
2211+#include <linux/tqueue.h>
2212+#include <linux/fs_struct.h>
2213+
2214 #endif /* __KERNEL__ */
2215 #endif
2216diff -urN linux-2.4.20/include/linux/smp_lock.h linux/include/linux/smp_lock.h
2217--- linux-2.4.20/include/linux/smp_lock.h 2001-11-22 14:46:27.000000000 -0500
2218+++ linux/include/linux/smp_lock.h 2002-12-11 02:34:48.000000000 -0500
2219@@ -3,7 +3,7 @@
2220
2221 #include <linux/config.h>
2222
2223-#ifndef CONFIG_SMP
2224+#if !defined(CONFIG_SMP) && !defined(CONFIG_PREEMPT)
2225
2226 #define lock_kernel() do { } while(0)
2227 #define unlock_kernel() do { } while(0)
2228diff -urN linux-2.4.20/include/linux/spinlock.h linux/include/linux/spinlock.h
2229--- linux-2.4.20/include/linux/spinlock.h 2002-11-28 18:53:15.000000000 -0500
2230+++ linux/include/linux/spinlock.h 2002-12-11 02:34:48.000000000 -0500
2231@@ -2,6 +2,7 @@
2232 #define __LINUX_SPINLOCK_H
2233
2234 #include <linux/config.h>
2235+#include <linux/compiler.h>
2236
2237 /*
2238 * These are the generic versions of the spinlocks and read-write
2239@@ -62,8 +63,10 @@
2240
2241 #if (DEBUG_SPINLOCKS < 1)
2242
2243+#ifndef CONFIG_PREEMPT
2244 #define atomic_dec_and_lock(atomic,lock) atomic_dec_and_test(atomic)
2245 #define ATOMIC_DEC_AND_LOCK
2246+#endif
2247
2248 /*
2249 * Your basic spinlocks, allowing only a single CPU anywhere
2250@@ -80,11 +83,11 @@
2251 #endif
2252
2253 #define spin_lock_init(lock) do { } while(0)
2254-#define spin_lock(lock) (void)(lock) /* Not "unused variable". */
2255+#define _raw_spin_lock(lock) (void)(lock) /* Not "unused variable". */
2256 #define spin_is_locked(lock) (0)
2257-#define spin_trylock(lock) ({1; })
2258+#define _raw_spin_trylock(lock) ({1; })
2259 #define spin_unlock_wait(lock) do { } while(0)
2260-#define spin_unlock(lock) do { } while(0)
2261+#define _raw_spin_unlock(lock) do { } while(0)
2262
2263 #elif (DEBUG_SPINLOCKS < 2)
2264
2265@@ -144,13 +147,78 @@
2266 #endif
2267
2268 #define rwlock_init(lock) do { } while(0)
2269-#define read_lock(lock) (void)(lock) /* Not "unused variable". */
2270-#define read_unlock(lock) do { } while(0)
2271-#define write_lock(lock) (void)(lock) /* Not "unused variable". */
2272-#define write_unlock(lock) do { } while(0)
2273+#define _raw_read_lock(lock) (void)(lock) /* Not "unused variable". */
2274+#define _raw_read_unlock(lock) do { } while(0)
2275+#define _raw_write_lock(lock) (void)(lock) /* Not "unused variable". */
2276+#define _raw_write_unlock(lock) do { } while(0)
2277
2278 #endif /* !SMP */
2279
2280+#ifdef CONFIG_PREEMPT
2281+
2282+#define preempt_get_count() (current->preempt_count)
2283+#define preempt_is_disabled() (preempt_get_count() != 0)
2284+
2285+#define preempt_disable() \
2286+do { \
2287+ ++current->preempt_count; \
2288+ barrier(); \
2289+} while (0)
2290+
2291+#define preempt_enable_no_resched() \
2292+do { \
2293+ --current->preempt_count; \
2294+ barrier(); \
2295+} while (0)
2296+
2297+#define preempt_enable() \
2298+do { \
2299+ --current->preempt_count; \
2300+ barrier(); \
2301+ if (unlikely(current->preempt_count < current->need_resched)) \
2302+ preempt_schedule(); \
2303+} while (0)
2304+
2305+#define spin_lock(lock) \
2306+do { \
2307+ preempt_disable(); \
2308+ _raw_spin_lock(lock); \
2309+} while(0)
2310+
2311+#define spin_trylock(lock) ({preempt_disable(); _raw_spin_trylock(lock) ? \
2312+ 1 : ({preempt_enable(); 0;});})
2313+#define spin_unlock(lock) \
2314+do { \
2315+ _raw_spin_unlock(lock); \
2316+ preempt_enable(); \
2317+} while (0)
2318+
2319+#define read_lock(lock) ({preempt_disable(); _raw_read_lock(lock);})
2320+#define read_unlock(lock) ({_raw_read_unlock(lock); preempt_enable();})
2321+#define write_lock(lock) ({preempt_disable(); _raw_write_lock(lock);})
2322+#define write_unlock(lock) ({_raw_write_unlock(lock); preempt_enable();})
2323+#define write_trylock(lock) ({preempt_disable();_raw_write_trylock(lock) ? \
2324+ 1 : ({preempt_enable(); 0;});})
2325+
2326+#else
2327+
2328+#define preempt_get_count() (0)
2329+#define preempt_is_disabled() (1)
2330+#define preempt_disable() do { } while (0)
2331+#define preempt_enable_no_resched() do {} while(0)
2332+#define preempt_enable() do { } while (0)
2333+
2334+#define spin_lock(lock) _raw_spin_lock(lock)
2335+#define spin_trylock(lock) _raw_spin_trylock(lock)
2336+#define spin_unlock(lock) _raw_spin_unlock(lock)
2337+
2338+#define read_lock(lock) _raw_read_lock(lock)
2339+#define read_unlock(lock) _raw_read_unlock(lock)
2340+#define write_lock(lock) _raw_write_lock(lock)
2341+#define write_unlock(lock) _raw_write_unlock(lock)
2342+#define write_trylock(lock) _raw_write_trylock(lock)
2343+#endif
2344+
2345 /* "lock on reference count zero" */
2346 #ifndef ATOMIC_DEC_AND_LOCK
2347 #include <asm/atomic.h>
2348diff -urN linux-2.4.20/include/linux/tqueue.h linux/include/linux/tqueue.h
2349--- linux-2.4.20/include/linux/tqueue.h 2001-11-22 14:46:19.000000000 -0500
2350+++ linux/include/linux/tqueue.h 2002-12-11 02:34:48.000000000 -0500
2351@@ -94,6 +94,22 @@
2352 extern spinlock_t tqueue_lock;
2353
2354 /*
2355+ * Call all "bottom halfs" on a given list.
2356+ */
2357+
2358+extern void __run_task_queue(task_queue *list);
2359+
2360+static inline void run_task_queue(task_queue *list)
2361+{
2362+ if (TQ_ACTIVE(*list))
2363+ __run_task_queue(list);
2364+}
2365+
2366+#endif /* _LINUX_TQUEUE_H */
2367+
2368+#if !defined(_LINUX_TQUEUE_H_INLINES) && defined(_TASK_STRUCT_DEFINED)
2369+#define _LINUX_TQUEUE_H_INLINES
2370+/*
2371 * Queue a task on a tq. Return non-zero if it was successfully
2372 * added.
2373 */
2374@@ -109,17 +125,4 @@
2375 }
2376 return ret;
2377 }
2378-
2379-/*
2380- * Call all "bottom halfs" on a given list.
2381- */
2382-
2383-extern void __run_task_queue(task_queue *list);
2384-
2385-static inline void run_task_queue(task_queue *list)
2386-{
2387- if (TQ_ACTIVE(*list))
2388- __run_task_queue(list);
2389-}
2390-
2391-#endif /* _LINUX_TQUEUE_H */
2392+#endif
2393diff -urN linux-2.4.20/kernel/exit.c linux/kernel/exit.c
2394--- linux-2.4.20/kernel/exit.c 2002-11-28 18:53:15.000000000 -0500
2395+++ linux/kernel/exit.c 2002-12-11 02:34:48.000000000 -0500
2396@@ -313,8 +313,8 @@
2397 /* more a memory barrier than a real lock */
2398 task_lock(tsk);
2399 tsk->mm = NULL;
2400- task_unlock(tsk);
2401 enter_lazy_tlb(mm, current, smp_processor_id());
2402+ task_unlock(tsk);
2403 mmput(mm);
2404 }
2405 }
2406@@ -435,6 +435,11 @@
2407 tsk->flags |= PF_EXITING;
2408 del_timer_sync(&tsk->real_timer);
2409
2410+ if (unlikely(preempt_get_count()))
2411+ printk(KERN_INFO "note: %s[%d] exited with preempt_count %d\n",
2412+ current->comm, current->pid,
2413+ preempt_get_count());
2414+
2415 fake_volatile:
2416 #ifdef CONFIG_BSD_PROCESS_ACCT
2417 acct_process(code);
2418diff -urN linux-2.4.20/kernel/fork.c linux/kernel/fork.c
2419--- linux-2.4.20/kernel/fork.c 2002-11-28 18:53:15.000000000 -0500
2420+++ linux/kernel/fork.c 2002-12-11 02:34:48.000000000 -0500
2421@@ -629,6 +629,13 @@
2422 if (p->binfmt && p->binfmt->module)
2423 __MOD_INC_USE_COUNT(p->binfmt->module);
2424
2425+#ifdef CONFIG_PREEMPT
2426+ /*
2427+ * Continue with preemption disabled as part of the context
2428+ * switch, so start with preempt_count set to 1.
2429+ */
2430+ p->preempt_count = 1;
2431+#endif
2432 p->did_exec = 0;
2433 p->swappable = 0;
2434 p->state = TASK_UNINTERRUPTIBLE;
2435diff -urN linux-2.4.20/kernel/ksyms.c linux/kernel/ksyms.c
2436--- linux-2.4.20/kernel/ksyms.c 2002-11-28 18:53:15.000000000 -0500
2437+++ linux/kernel/ksyms.c 2002-12-11 02:34:48.000000000 -0500
2438@@ -450,6 +450,9 @@
2439 EXPORT_SYMBOL(interruptible_sleep_on);
2440 EXPORT_SYMBOL(interruptible_sleep_on_timeout);
2441 EXPORT_SYMBOL(schedule);
2442+#ifdef CONFIG_PREEMPT
2443+EXPORT_SYMBOL(preempt_schedule);
2444+#endif
2445 EXPORT_SYMBOL(schedule_timeout);
2446 EXPORT_SYMBOL(yield);
2447 EXPORT_SYMBOL(__cond_resched);
2448diff -urN linux-2.4.20/kernel/sched.c linux/kernel/sched.c
2449--- linux-2.4.20/kernel/sched.c 2002-11-28 18:53:15.000000000 -0500
2450+++ linux/kernel/sched.c 2002-12-11 02:34:48.000000000 -0500
2451@@ -489,7 +489,7 @@
2452 task_lock(prev);
2453 task_release_cpu(prev);
2454 mb();
2455- if (prev->state == TASK_RUNNING)
2456+ if (task_on_runqueue(prev))
2457 goto needs_resched;
2458
2459 out_unlock:
2460@@ -519,7 +519,7 @@
2461 goto out_unlock;
2462
2463 spin_lock_irqsave(&runqueue_lock, flags);
2464- if ((prev->state == TASK_RUNNING) && !task_has_cpu(prev))
2465+ if (task_on_runqueue(prev) && !task_has_cpu(prev))
2466 reschedule_idle(prev);
2467 spin_unlock_irqrestore(&runqueue_lock, flags);
2468 goto out_unlock;
2469@@ -532,6 +532,7 @@
2470 asmlinkage void schedule_tail(struct task_struct *prev)
2471 {
2472 __schedule_tail(prev);
2473+ preempt_enable();
2474 }
2475
2476 /*
2477@@ -551,9 +552,10 @@
2478 struct list_head *tmp;
2479 int this_cpu, c;
2480
2481-
2482 spin_lock_prefetch(&runqueue_lock);
2483
2484+ preempt_disable();
2485+
2486 BUG_ON(!current->active_mm);
2487 need_resched_back:
2488 prev = current;
2489@@ -581,6 +583,14 @@
2490 move_last_runqueue(prev);
2491 }
2492
2493+#ifdef CONFIG_PREEMPT
2494+ /*
2495+ * entering from preempt_schedule, off a kernel preemption,
2496+ * go straight to picking the next task.
2497+ */
2498+ if (unlikely(preempt_get_count() & PREEMPT_ACTIVE))
2499+ goto treat_like_run;
2500+#endif
2501 switch (prev->state) {
2502 case TASK_INTERRUPTIBLE:
2503 if (signal_pending(prev)) {
2504@@ -591,6 +601,9 @@
2505 del_from_runqueue(prev);
2506 case TASK_RUNNING:;
2507 }
2508+#ifdef CONFIG_PREEMPT
2509+ treat_like_run:
2510+#endif
2511 prev->need_resched = 0;
2512
2513 /*
2514@@ -699,9 +712,31 @@
2515 reacquire_kernel_lock(current);
2516 if (current->need_resched)
2517 goto need_resched_back;
2518+ preempt_enable_no_resched();
2519 return;
2520 }
2521
2522+#ifdef CONFIG_PREEMPT
2523+/*
2524+ * this is is the entry point to schedule() from in-kernel preemption
2525+ */
2526+asmlinkage void preempt_schedule(void)
2527+{
2528+ if (unlikely(irqs_disabled()))
2529+ return;
2530+
2531+need_resched:
2532+ current->preempt_count += PREEMPT_ACTIVE;
2533+ schedule();
2534+ current->preempt_count -= PREEMPT_ACTIVE;
2535+
2536+ /* we could miss a preemption opportunity between schedule and now */
2537+ barrier();
2538+ if (unlikely(current->need_resched))
2539+ goto need_resched;
2540+}
2541+#endif /* CONFIG_PREEMPT */
2542+
2543 /*
2544 * The core wakeup function. Non-exclusive wakeups (nr_exclusive == 0) just wake everything
2545 * up. If it's an exclusive wakeup (nr_exclusive == small +ve number) then we wake all the
2546@@ -1327,6 +1362,13 @@
2547 sched_data->curr = current;
2548 sched_data->last_schedule = get_cycles();
2549 clear_bit(current->processor, &wait_init_idle);
2550+#ifdef CONFIG_PREEMPT
2551+ /*
2552+ * fix up the preempt_count for non-CPU0 idle threads
2553+ */
2554+ if (current->processor)
2555+ current->preempt_count = 0;
2556+#endif
2557 }
2558
2559 extern void init_timervecs (void);
2560diff -urN linux-2.4.20/lib/dec_and_lock.c linux/lib/dec_and_lock.c
2561--- linux-2.4.20/lib/dec_and_lock.c 2001-10-03 12:11:26.000000000 -0400
2562+++ linux/lib/dec_and_lock.c 2002-12-11 02:34:48.000000000 -0500
2563@@ -1,5 +1,6 @@
2564 #include <linux/module.h>
2565 #include <linux/spinlock.h>
2566+#include <linux/sched.h>
2567 #include <asm/atomic.h>
2568
2569 /*
2570diff -urN linux-2.4.20/MAINTAINERS linux/MAINTAINERS
2571--- linux-2.4.20/MAINTAINERS 2002-11-28 18:53:08.000000000 -0500
2572+++ linux/MAINTAINERS 2002-12-11 02:34:48.000000000 -0500
2573@@ -1310,6 +1310,14 @@
2574 M: mostrows@styx.uwaterloo.ca
2575 S: Maintained
2576
2577+PREEMPTIBLE KERNEL
2578+P: Robert M. Love
2579+M: rml@tech9.net
2580+L: linux-kernel@vger.kernel.org
2581+L: kpreempt-tech@lists.sourceforge.net
2582+W: http://tech9.net/rml/linux
2583+S: Supported
2584+
2585 PROMISE DC4030 CACHING DISK CONTROLLER DRIVER
2586 P: Peter Denison
2587 M: promise@pnd-pc.demon.co.uk
2588diff -urN linux-2.4.20/mm/slab.c linux/mm/slab.c
2589--- linux-2.4.20/mm/slab.c 2002-11-28 18:53:15.000000000 -0500
2590+++ linux/mm/slab.c 2002-12-11 02:34:48.000000000 -0500
2591@@ -49,7 +49,8 @@
2592 * constructors and destructors are called without any locking.
2593 * Several members in kmem_cache_t and slab_t never change, they
2594 * are accessed without any locking.
2595- * The per-cpu arrays are never accessed from the wrong cpu, no locking.
2596+ * The per-cpu arrays are never accessed from the wrong cpu, no locking,
2597+ * and local interrupts are disabled so slab code is preempt-safe.
2598 * The non-constant members are protected with a per-cache irq spinlock.
2599 *
2600 * Further notes from the original documentation:
2601diff -urN linux-2.4.20/net/core/dev.c linux/net/core/dev.c
2602--- linux-2.4.20/net/core/dev.c 2002-11-28 18:53:15.000000000 -0500
2603+++ linux/net/core/dev.c 2002-12-11 02:34:48.000000000 -0500
2604@@ -1049,9 +1049,15 @@
2605 int cpu = smp_processor_id();
2606
2607 if (dev->xmit_lock_owner != cpu) {
2608+ /*
2609+ * The spin_lock effectivly does a preempt lock, but
2610+ * we are about to drop that...
2611+ */
2612+ preempt_disable();
2613 spin_unlock(&dev->queue_lock);
2614 spin_lock(&dev->xmit_lock);
2615 dev->xmit_lock_owner = cpu;
2616+ preempt_enable();
2617
2618 if (!netif_queue_stopped(dev)) {
2619 if (netdev_nit)
2620diff -urN linux-2.4.20/net/core/skbuff.c linux/net/core/skbuff.c
2621--- linux-2.4.20/net/core/skbuff.c 2002-08-02 20:39:46.000000000 -0400
2622+++ linux/net/core/skbuff.c 2002-12-11 02:34:48.000000000 -0500
2623@@ -111,33 +111,37 @@
2624
2625 static __inline__ struct sk_buff *skb_head_from_pool(void)
2626 {
2627- struct sk_buff_head *list = &skb_head_pool[smp_processor_id()].list;
2628+ struct sk_buff_head *list;
2629+ struct sk_buff *skb = NULL;
2630+ unsigned long flags;
2631
2632- if (skb_queue_len(list)) {
2633- struct sk_buff *skb;
2634- unsigned long flags;
2635+ local_irq_save(flags);
2636
2637- local_irq_save(flags);
2638+ list = &skb_head_pool[smp_processor_id()].list;
2639+
2640+ if (skb_queue_len(list))
2641 skb = __skb_dequeue(list);
2642- local_irq_restore(flags);
2643- return skb;
2644- }
2645- return NULL;
2646+
2647+ local_irq_restore(flags);
2648+ return skb;
2649 }
2650
2651 static __inline__ void skb_head_to_pool(struct sk_buff *skb)
2652 {
2653- struct sk_buff_head *list = &skb_head_pool[smp_processor_id()].list;
2654+ struct sk_buff_head *list;
2655+ unsigned long flags;
2656
2657- if (skb_queue_len(list) < sysctl_hot_list_len) {
2658- unsigned long flags;
2659+ local_irq_save(flags);
2660+ list = &skb_head_pool[smp_processor_id()].list;
2661
2662- local_irq_save(flags);
2663+ if (skb_queue_len(list) < sysctl_hot_list_len) {
2664 __skb_queue_head(list, skb);
2665 local_irq_restore(flags);
2666
2667 return;
2668 }
2669+
2670+ local_irq_restore(flags);
2671 kmem_cache_free(skbuff_head_cache, skb);
2672 }
2673
2674diff -urN linux-2.4.20/net/socket.c linux/net/socket.c
2675--- linux-2.4.20/net/socket.c 2002-11-28 18:53:16.000000000 -0500
2676+++ linux/net/socket.c 2002-12-11 02:34:48.000000000 -0500
2677@@ -132,7 +132,7 @@
2678
2679 static struct net_proto_family *net_families[NPROTO];
2680
2681-#ifdef CONFIG_SMP
2682+#if defined(CONFIG_SMP) || defined(CONFIG_PREEMPT)
2683 static atomic_t net_family_lockct = ATOMIC_INIT(0);
2684 static spinlock_t net_family_lock = SPIN_LOCK_UNLOCKED;
2685
2686diff -urN linux-2.4.20/net/sunrpc/pmap_clnt.c linux/net/sunrpc/pmap_clnt.c
2687--- linux-2.4.20/net/sunrpc/pmap_clnt.c 2002-08-02 20:39:46.000000000 -0400
2688+++ linux/net/sunrpc/pmap_clnt.c 2002-12-11 02:34:48.000000000 -0500
2689@@ -12,6 +12,7 @@
2690 #include <linux/config.h>
2691 #include <linux/types.h>
2692 #include <linux/socket.h>
2693+#include <linux/sched.h>
2694 #include <linux/kernel.h>
2695 #include <linux/errno.h>
2696 #include <linux/uio.h>
This page took 0.52046 seconds and 4 git commands to generate.