Index: arch/parisc/Kconfig =================================================================== RCS file: /var/cvs/linux-2.5/arch/parisc/Kconfig,v retrieving revision 1.23 diff -u -p -r1.23 Kconfig --- arch/parisc/Kconfig 14 Jul 2003 12:32:20 -0000 1.23 +++ arch/parisc/Kconfig 25 Jul 2003 04:48:34 -0000 @@ -136,9 +136,16 @@ config SMP If you don't know what to do here, say N. config PREEMPT - bool -# bool "Preemptible Kernel" - default n + bool "Preemptible Kernel" + help + This option reduces the latency of the kernel when reacting to + real-time or interactive events by allowing a low priority process to + be preempted even if it is in kernel mode executing a system call. + This allows applications to run more reliably even when the system is + under load. + + Say Y here if you are building a kernel for a desktop, embedded + or real-time system. Say N if you are unsure. config COMPAT bool Index: arch/parisc/kernel/irq.c =================================================================== RCS file: /var/cvs/linux-2.5/arch/parisc/kernel/irq.c,v retrieving revision 1.19 diff -u -p -r1.19 irq.c --- arch/parisc/kernel/irq.c 5 May 2003 21:34:24 -0000 1.19 +++ arch/parisc/kernel/irq.c 25 Jul 2003 04:48:34 -0000 @@ -329,9 +329,11 @@ unsigned long txn_alloc_addr(int virt_irq) { static int next_cpu = -1; + unsigned long ret; next_cpu++; /* assign to "next" CPU we want this bugger on */ + preempt_disable(); /* validate entry */ while ((next_cpu < NR_CPUS) && !cpu_data[next_cpu].txn_addr) next_cpu++; @@ -339,7 +341,10 @@ txn_alloc_addr(int virt_irq) if (next_cpu >= NR_CPUS) next_cpu = 0; /* nothing else, assign monarch */ - return cpu_data[next_cpu].txn_addr; + ret = cpu_data[next_cpu].txn_addr; + preempt_enable(); + + return ret; } @@ -380,7 +385,7 @@ txn_alloc_data(int virt_irq, unsigned in void do_irq(struct irqaction *action, int irq, struct pt_regs * regs) { - int cpu = smp_processor_id(); + int cpu = get_cpu(); irq_enter(); ++kstat_cpu(cpu).irqs[irq]; @@ -421,6 +426,8 @@ void do_irq(struct irqaction *action, in } irq_exit(); + + put_cpu(); } Index: arch/parisc/kernel/pa7300lc.c =================================================================== RCS file: /var/cvs/linux-2.5/arch/parisc/kernel/pa7300lc.c,v retrieving revision 1.4 diff -u -p -r1.4 pa7300lc.c --- arch/parisc/kernel/pa7300lc.c 1 Nov 2002 01:04:30 -0000 1.4 +++ arch/parisc/kernel/pa7300lc.c 25 Jul 2003 04:48:34 -0000 @@ -29,7 +29,7 @@ static u32 cpu_hpa(void) static void pa7300lc_lpmc(int code, struct pt_regs *regs) { u32 hpa; - printk(KERN_WARNING "LPMC on CPU %d\n", smp_processor_id()); + printk(KERN_WARNING "LPMC on CPU %d\n", get_cpu()); show_regs(regs); @@ -41,6 +41,8 @@ static void pa7300lc_lpmc(int code, stru gsc_readl(hpa+MIOC_CONTROL), gsc_readl(hpa+MIOC_STATUS), gsc_readl(hpa+MDERRADD), gsc_readl(hpa+DMAERR), gsc_readl(hpa+DIOERR), gsc_readl(hpa+HIDMAMEM)); + + put_cpu(); } void pa7300lc_init(void) Index: arch/parisc/kernel/perf.c =================================================================== RCS file: /var/cvs/linux-2.5/arch/parisc/kernel/perf.c,v retrieving revision 1.11 diff -u -p -r1.11 perf.c --- arch/parisc/kernel/perf.c 5 Mar 2003 21:15:38 -0000 1.11 +++ arch/parisc/kernel/perf.c 25 Jul 2003 04:48:34 -0000 @@ -529,9 +529,11 @@ static int __init perf_init(void) spin_lock_init(&perf_lock); /* TODO: this only lets us access the first cpu.. what to do for SMP? */ + preempt_disable(); cpu_device = cpu_data[0].dev; printk("Performance monitoring counters enabled for %s\n", cpu_data[0].dev->name); + preempt_enable(); return 0; } Index: arch/parisc/kernel/processor.c =================================================================== RCS file: /var/cvs/linux-2.5/arch/parisc/kernel/processor.c,v retrieving revision 1.5 diff -u -p -r1.5 processor.c --- arch/parisc/kernel/processor.c 23 Mar 2003 20:14:52 -0000 1.5 +++ arch/parisc/kernel/processor.c 25 Jul 2003 04:48:34 -0000 @@ -139,6 +139,7 @@ static int __init processor_probe(struct } #endif + preempt_disable(); p = &cpu_data[cpuid]; boot_cpu_data.cpu_count++; @@ -187,6 +188,7 @@ static int __init processor_probe(struct cpu_irq_actions[cpuid] = actions; } #endif + preempt_enable(); return 0; } @@ -248,8 +250,10 @@ void __init collect_boot_cpu_data(void) static inline void __init init_percpu_prof(int cpunum) { + preempt_disable(); cpu_data[cpunum].prof_counter = 1; cpu_data[cpunum].prof_multiplier = 1; + preempt_enable(); } @@ -284,8 +288,10 @@ int __init init_per_cpu(int cpunum) /* FWIW, FP rev/model is a more accurate way to determine ** CPU type. CPU rev/model has some ambiguous cases. */ + preempt_disable(); cpu_data[cpunum].fp_rev = coproc_cfg.revision; cpu_data[cpunum].fp_model = coproc_cfg.model; + preempt_enable(); printk(KERN_INFO "FP[%d] enabled: Rev %ld Model %ld\n", cpunum, coproc_cfg.revision, coproc_cfg.model); @@ -323,6 +329,7 @@ show_cpuinfo (struct seq_file *m, void * { int n; + preempt_disable(); for(n=0; nlock),flags); p->pending_ipi |= 1 << op; __raw_writel(IRQ_OFFSET(IPI_IRQ), cpu_data[cpu].hpa); spin_unlock_irqrestore(&(p->lock),flags); + preempt_enable(); } @@ -290,9 +296,10 @@ send_IPI_allbutself(enum ipi_message_typ int i; for (i = 0; i < smp_num_cpus; i++) { - if (i != smp_processor_id()) + if (i != get_cpu()) send_IPI_single(i, op); } + put_cpu(); } inline void @@ -361,7 +368,8 @@ smp_call_function (void (*func) (void *i smp_call_function_data = NULL; if (atomic_read (&data.unstarted_count) > 0) { printk(KERN_CRIT "SMP CALL FUNCTION TIMED OUT! (cpu=%d)\n", - smp_processor_id()); + get_cpu()); + put_cpu(); return -ETIMEDOUT; } @@ -417,13 +425,14 @@ smp_flush_tlb_all(void) void smp_do_timer(struct pt_regs *regs) { - int cpu = smp_processor_id(); + int cpu = get_cpu(); struct cpuinfo_parisc *data = &cpu_data[cpu]; if (!--data->prof_counter) { data->prof_counter = data->prof_multiplier; update_process_times(user_mode(regs)); } + put_cpu(); } /* @@ -527,6 +536,7 @@ static int __init smp_boot_one_cpu(int c struct task_struct *idle; long timeout; + preempt_disable(); /* * Create an idle task for this CPU. Note the address wed* give * to kernel_thread is irrelevant -- it's going to start @@ -586,6 +596,7 @@ static int __init smp_boot_one_cpu(int c idle = NULL; printk(KERN_CRIT "SMP: CPU:%d is stuck.\n", cpuid); + preempt_enable(); return -1; alive: @@ -597,6 +608,7 @@ alive: #ifdef ENTRY_SYS_CPUS cpu_data[cpunum].state = STATE_RUNNING; #endif + preempt_enable(); return 0; } @@ -615,11 +627,13 @@ alive: void __init smp_boot_cpus(void) { int i, cpu_count = 1; - unsigned long bogosum = cpu_data[0].loops_per_jiffy; /* Count Monarch */ - + unsigned long bogosuml; /* REVISIT - assumes first CPU reported by PAT PDC is BSP */ int bootstrap_processor=cpu_data[0].cpuid; /* CPU ID of BSP */ + preempt_disable(); + bogosuml = cpu_data[0].loops_per_jiffy; /* Count Monarch */ + bootstrap_processor=cpu_data[0].cpuid; /* CPU ID of BSP */ /* Setup BSP mappings */ printk(KERN_DEBUG "SMP: bootstrap CPU ID is %d\n",bootstrap_processor); init_task.thread_info->cpu = bootstrap_processor; @@ -635,6 +649,7 @@ void __init smp_boot_cpus(void) /* Nothing to do when told not to. */ if (max_cpus == 0) { printk(KERN_INFO "SMP mode deactivated.\n"); + preempt_enable(); return; } @@ -680,6 +695,7 @@ void __init smp_boot_cpus(void) #ifdef PER_CPU_IRQ_REGION ipi_init(); #endif + preempt_enable(); return; } @@ -709,8 +725,10 @@ void __init smp_prepare_cpus(unsigned in void __devinit smp_prepare_boot_cpu(void) { + preempt_disable(); set_bit(smp_processor_id(), &cpu_online_map); set_bit(smp_processor_id(), &cpu_present_mask); + preempt_enable(); } int __devinit __cpu_up(unsigned int cpu) Index: arch/parisc/kernel/time.c =================================================================== RCS file: /var/cvs/linux-2.5/arch/parisc/kernel/time.c,v retrieving revision 1.14 diff -u -p -r1.14 time.c --- arch/parisc/kernel/time.c 14 Jul 2003 12:32:21 -0000 1.14 +++ arch/parisc/kernel/time.c 25 Jul 2003 04:48:38 -0000 @@ -81,7 +81,7 @@ irqreturn_t timer_interrupt(int irq, voi long now; long next_tick; int nticks; - int cpu = smp_processor_id(); + int cpu = get_cpu(); parisc_do_profile(regs); @@ -128,6 +128,7 @@ irqreturn_t timer_interrupt(int irq, voi if (cpu == 0 && !atomic_read(&power_tasklet.count)) tasklet_schedule(&power_tasklet); + put_cpu(); return IRQ_HANDLED; } @@ -149,6 +150,7 @@ gettimeoffset (void) long last_tick; long elapsed_cycles; + preempt_disable(); /* it_value is the intended time of the next tick */ last_tick = cpu_data[smp_processor_id()].it_value; @@ -160,6 +162,7 @@ gettimeoffset (void) elapsed_cycles = mfctl(16) - last_tick; /* the precision of this math could be improved */ + preempt_enable(); return elapsed_cycles / (PAGE0->mem_10msec / 10000); #else return 0; @@ -236,7 +239,7 @@ void __init time_init(void) next_tick = mfctl(16); next_tick += clocktick; - cpu_data[smp_processor_id()].it_value = next_tick; + cpu_data[get_cpu()].it_value = next_tick; /* kick off Itimer (CR16) */ mtctl(next_tick, 16); @@ -253,5 +256,6 @@ void __init time_init(void) xtime.tv_sec = 0; xtime.tv_nsec = 0; } + put_cpu(); } Index: arch/parisc/kernel/traps.c =================================================================== RCS file: /var/cvs/linux-2.5/arch/parisc/kernel/traps.c,v retrieving revision 1.26 diff -u -p -r1.26 traps.c --- arch/parisc/kernel/traps.c 19 Jul 2003 07:41:09 -0000 1.26 +++ arch/parisc/kernel/traps.c 25 Jul 2003 04:48:38 -0000 @@ -325,8 +325,9 @@ int handle_toc(void) static void default_trap(int code, struct pt_regs *regs) { - printk(KERN_ERR "Trap %d on CPU %d\n", code, smp_processor_id()); + printk(KERN_ERR "Trap %d on CPU %d\n", code, get_cpu()); show_regs(regs); + put_cpu(); } void (*cpu_lpmc) (int code, struct pt_regs *regs) = default_trap; Index: include/asm-parisc/hardirq.h =================================================================== RCS file: /var/cvs/linux-2.5/include/asm-parisc/hardirq.h,v retrieving revision 1.10 diff -u -p -r1.10 hardirq.h --- include/asm-parisc/hardirq.h 27 May 2003 17:28:21 -0000 1.10 +++ include/asm-parisc/hardirq.h 25 Jul 2003 04:48:48 -0000 @@ -34,18 +34,18 @@ typedef struct { * * - bits 0-7 are the preemption count (max preemption depth: 256) * - bits 8-15 are the softirq count (max # of softirqs: 256) - * - bits 16-31 are the hardirq count (max # of hardirqs: 65536) + * - bits 16-29 are the hardirq count (max # of hardirqs: 16384) * * - (bit 63 is the PREEMPT_ACTIVE flag---not currently implemented.) * * PREEMPT_MASK: 0x000000ff * SOFTIRQ_MASK: 0x0000ff00 - * HARDIRQ_MASK: 0xffff0000 + * HARDIRQ_MASK: 0x3fff0000 */ #define PREEMPT_BITS 8 #define SOFTIRQ_BITS 8 -#define HARDIRQ_BITS 16 +#define HARDIRQ_BITS 14 #define PREEMPT_SHIFT 0 #define SOFTIRQ_SHIFT (PREEMPT_SHIFT + PREEMPT_BITS) @@ -88,8 +88,7 @@ typedef struct { #define irq_enter() (preempt_count() += HARDIRQ_OFFSET) #ifdef CONFIG_PREEMPT -# error CONFIG_PREEMT currently not supported. -# define in_atomic() BUG() +# define in_atomic() ((preempt_count() & ~PREEMPT_ACTIVE) != kernel_locked()) # define IRQ_EXIT_OFFSET (HARDIRQ_OFFSET-1) #else # define in_atomic() (preempt_count() != 0) Index: include/asm-parisc/thread_info.h =================================================================== RCS file: /var/cvs/linux-2.5/include/asm-parisc/thread_info.h,v retrieving revision 1.9 diff -u -p -r1.9 thread_info.h --- include/asm-parisc/thread_info.h 14 Jun 2003 22:15:58 -0000 1.9 +++ include/asm-parisc/thread_info.h 25 Jul 2003 04:48:48 -0000 @@ -49,7 +49,8 @@ struct thread_info { #endif /* !__ASSEMBLY */ -#define PREEMPT_ACTIVE 0x4000000 +#define PREEMPT_ACTIVE_BIT 30 +#define PREEMPT_ACTIVE (1<