From 429383c2a6f56796aa5bafdc97009c8aeccd1967 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Fri, 23 Nov 2007 15:16:09 -0500 Subject: [PATCH] Import 2.1.114 --- Makefile | 2 +- arch/i386/kernel/bios32.c | 16 ++- arch/i386/kernel/io_apic.c | 259 ++++++++++++++++------------------ arch/i386/kernel/irq.h | 6 - arch/i386/kernel/process.c | 16 +++ arch/i386/kernel/traps.c | 4 +- arch/i386/mm/fault.c | 1 + arch/m68k/amiga/amiga_ksyms.c | 1 + arch/m68k/amiga/pcmcia.c | 1 - drivers/block/nbd.c | 8 +- drivers/net/apne.c | 1 - drivers/scsi/bvme6000.c | 1 - fs/lockd/svc.c | 30 ++-- include/asm-alpha/smplock.h | 49 +++++++ include/asm-arm/smplock.h | 49 +++++++ include/asm-generic/smplock.h | 49 +++++++ include/asm-i386/smplock.h | 59 ++++++++ include/asm-i386/spinlock.h | 14 +- include/asm-m68k/smplock.h | 49 +++++++ include/asm-mips/smplock.h | 49 +++++++ include/asm-ppc/smplock.h | 49 +++++++ include/asm-sparc/smplock.h | 49 +++++++ include/asm-sparc64/smplock.h | 49 +++++++ include/linux/sched.h | 25 ++-- include/linux/smp_lock.h | 55 +------- kernel/exit.c | 66 +++++---- kernel/fork.c | 39 +++-- kernel/sched.c | 47 +++--- 28 files changed, 751 insertions(+), 292 deletions(-) create mode 100644 include/asm-alpha/smplock.h create mode 100644 include/asm-arm/smplock.h create mode 100644 include/asm-generic/smplock.h create mode 100644 include/asm-i386/smplock.h create mode 100644 include/asm-m68k/smplock.h create mode 100644 include/asm-mips/smplock.h create mode 100644 include/asm-ppc/smplock.h create mode 100644 include/asm-sparc/smplock.h create mode 100644 include/asm-sparc64/smplock.h diff --git a/Makefile b/Makefile index b99089cb4c00..b464017c9a23 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ VERSION = 2 PATCHLEVEL = 1 -SUBLEVEL = 113 +SUBLEVEL = 114 ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/) diff --git a/arch/i386/kernel/bios32.c b/arch/i386/kernel/bios32.c index 49918c0f849f..5e56a7300ba2 100644 --- a/arch/i386/kernel/bios32.c +++ b/arch/i386/kernel/bios32.c @@ -1,7 +1,7 @@ /* * bios32.c - Low-Level PCI Access * - * $Id: bios32.c,v 1.42 1998/07/26 09:33:07 mj Exp $ + * $Id: bios32.c,v 1.43 1998/08/03 15:59:20 mj Exp $ * * Copyright 1993, 1994 Drew Eckhardt * Visionary Computing @@ -920,6 +920,13 @@ __initfunc(void pcibios_fixup_peer_bridges(void)) struct pci_bus *b = &pci_root; int i; + /* + * Don't search for peer host bridges if we use config type 2 + * since it reads bogus values for non-existent busses and + * chipsets supporting multiple primary busses use conf1 anyway. + */ + if (access_pci == &pci_direct_conf2) + return; do { int n = b->subordinate+1; u16 l; @@ -972,8 +979,13 @@ __initfunc(void pcibios_fixup_devices(void)) /* * Don't enable VGA-compatible cards since they have * fixed I/O and memory space. + * + * Don't enabled disabled IDE interfaces either because + * some BIOSes may reallocate the same address when they + * find that no devices are attached. */ - if ((dev->class >> 8) != PCI_CLASS_DISPLAY_VGA) { + if (((dev->class >> 8) != PCI_CLASS_DISPLAY_VGA) && + ((dev->class >> 8) != PCI_CLASS_STORAGE_IDE)) { pci_read_config_word(dev, PCI_COMMAND, &cmd); if (has_io && !(cmd & PCI_COMMAND_IO)) { printk("PCI: Enabling I/O for device %02x:%02x\n", diff --git a/arch/i386/kernel/io_apic.c b/arch/i386/kernel/io_apic.c index 7e160f17e38f..92472655f5f9 100644 --- a/arch/i386/kernel/io_apic.c +++ b/arch/i386/kernel/io_apic.c @@ -7,49 +7,24 @@ * patches and reporting/debugging problems patiently! */ -#include -#include -#include #include -#include -#include -#include -#include -#include -#include #include -#include #include -#include -#include -#include -#include +#include #include #include "irq.h" /* - * volatile is justified in this case, it might change - * spontaneously, GCC should not cache it + * volatile is justified in this case, IO-APIC register contents + * might change spontaneously, GCC should not cache it */ #define IO_APIC_BASE ((volatile int *)fix_to_virt(FIX_IO_APIC_BASE)) -enum mp_irq_source_types { - mp_INT = 0, - mp_NMI = 1, - mp_SMI = 2, - mp_ExtINT = 3 -}; - -enum ioapic_irq_destination_types { - dest_Fixed = 0, - dest_LowestPrio = 1, - dest_ExtINT = 7 -}; - /* * The structure of the IO-APIC: */ + struct IO_APIC_reg_00 { __u32 __reserved_2 : 24, ID : 4, @@ -69,6 +44,17 @@ struct IO_APIC_reg_02 { __reserved_1 : 4; } __attribute__ ((packed)); +/* + * # of IRQ routing registers + */ +int nr_ioapic_registers = 0; + +enum ioapic_irq_destination_types { + dest_Fixed = 0, + dest_LowestPrio = 1, + dest_ExtINT = 7 +}; + struct IO_APIC_route_entry { __u32 vector : 8, delivery_mode : 3, /* 000: FIXED @@ -97,13 +83,17 @@ struct IO_APIC_route_entry { } __attribute__ ((packed)); -#define UNEXPECTED_IO_APIC() \ - { \ - printk(" WARNING: unexpected IO-APIC, please mail\n"); \ - printk(" to linux-smp@vger.rutgers.edu\n"); \ - } +/* + * MP-BIOS irq configuration table structures: + */ + +enum mp_irq_source_types { + mp_INT = 0, + mp_NMI = 1, + mp_SMI = 2, + mp_ExtINT = 3 +}; -int nr_ioapic_registers = 0; /* # of IRQ routing registers */ int mp_irq_entries = 0; /* # of MP IRQ source entries */ struct mpc_config_intsrc mp_irqs[MAX_IRQ_SOURCES]; /* MP IRQ source entries */ @@ -116,13 +106,13 @@ int mpc_default_type = 0; /* non-0 if default (table-less) */ static int irq_2_pin[NR_IRQS]; -unsigned int io_apic_read (unsigned int reg) +static inline unsigned int io_apic_read(unsigned int reg) { *IO_APIC_BASE = reg; return *(IO_APIC_BASE+4); } -void io_apic_write (unsigned int reg, unsigned int value) +static inline void io_apic_write(unsigned int reg, unsigned int value) { *IO_APIC_BASE = reg; *(IO_APIC_BASE+4) = value; @@ -141,57 +131,57 @@ static inline void io_apic_sync(void) * We disable IO-APIC IRQs by setting their 'destination CPU mask' to * zero. Trick, trick. */ -void disable_IO_APIC_irq(unsigned int irq) +static inline void disable_IO_APIC_irq(unsigned int irq) { int pin = irq_2_pin[irq]; struct IO_APIC_route_entry entry; if (pin != -1) { - *(((int *)&entry)+1) = io_apic_read(0x11+pin*2); + *(((int *)&entry) + 1) = io_apic_read(0x11 + pin * 2); entry.dest.logical.logical_dest = 0x0; - io_apic_write(0x11+2*pin, *(((int *)&entry)+1)); + io_apic_write(0x11 + 2 * pin, *(((int *)&entry) + 1)); io_apic_sync(); } } -void enable_IO_APIC_irq(unsigned int irq) +static inline void enable_IO_APIC_irq(unsigned int irq) { int pin = irq_2_pin[irq]; struct IO_APIC_route_entry entry; if (pin != -1) { - *(((int *)&entry)+1) = io_apic_read(0x11+pin*2); + *(((int *)&entry) + 1) = io_apic_read(0x11 + pin * 2); entry.dest.logical.logical_dest = 0xff; - io_apic_write(0x11+2*pin, *(((int *)&entry)+1)); + io_apic_write(0x11 + 2 * pin, *(((int *)&entry) + 1)); } } -void mask_IO_APIC_irq(unsigned int irq) +static inline void mask_IO_APIC_irq(unsigned int irq) { int pin = irq_2_pin[irq]; struct IO_APIC_route_entry entry; if (pin != -1) { - *(((int *)&entry)+0) = io_apic_read(0x10+pin*2); + *(((int *)&entry) + 0) = io_apic_read(0x10 + pin * 2); entry.mask = 1; - io_apic_write(0x10+2*pin, *(((int *)&entry)+0)); + io_apic_write(0x10 + 2 * pin, *(((int *)&entry) + 0)); io_apic_sync(); } } -void unmask_IO_APIC_irq(unsigned int irq) +static inline void unmask_IO_APIC_irq(unsigned int irq) { int pin = irq_2_pin[irq]; struct IO_APIC_route_entry entry; if (pin != -1) { - *(((int *)&entry)+0) = io_apic_read(0x10+pin*2); + *(((int *)&entry) + 0) = io_apic_read(0x10 + pin * 2); entry.mask = 0; - io_apic_write(0x10+2*pin, *(((int *)&entry)+0)); + io_apic_write(0x10 + 2 * pin, *(((int *)&entry) + 0)); } } -void clear_IO_APIC_pin (unsigned int pin) +static void __init clear_IO_APIC_pin(unsigned int pin) { struct IO_APIC_route_entry entry; @@ -200,8 +190,8 @@ void clear_IO_APIC_pin (unsigned int pin) */ memset(&entry, 0, sizeof(entry)); entry.mask = 1; - io_apic_write(0x10+2*pin, *(((int *)&entry)+0)); - io_apic_write(0x11+2*pin, *(((int *)&entry)+1)); + io_apic_write(0x10 + 2 * pin, *(((int *)&entry) + 0)); + io_apic_write(0x11 + 2 * pin, *(((int *)&entry) + 1)); } @@ -214,30 +204,30 @@ void clear_IO_APIC_pin (unsigned int pin) int pirq_entries [MAX_PIRQS]; int pirqs_enabled; -__initfunc(void ioapic_pirq_setup(char *str, int *ints)) +void __init ioapic_pirq_setup(char *str, int *ints) { int i, max; - for (i=0; i IRQ %d\n", i, ints[i+1]); /* * PIRQs are mapped upside down, usually. */ - pirq_entries[MAX_PIRQS-i-1]=ints[i+1]; + pirq_entries[MAX_PIRQS-i-1] = ints[i+1]; } } } @@ -245,11 +235,11 @@ __initfunc(void ioapic_pirq_setup(char *str, int *ints)) /* * Find the IRQ entry number of a certain pin. */ -__initfunc(static int find_irq_entry(int pin, int type)) +static int __init find_irq_entry(int pin, int type) { int i; - for (i=0; i=16) && (pin<=23)) { + if ((pin >= 16) && (pin <= 23)) { if (pirq_entries[pin-16] != -1) { if (!pirq_entries[pin-16]) { printk("disabling PIRQ%d\n", pin-16); @@ -510,14 +499,14 @@ static int pin_2_irq (int idx, int pin) return irq; } -int IO_APIC_irq_trigger (int irq) +static inline int IO_APIC_irq_trigger(int irq) { int idx, pin; - for (pin=0; pin 0) @@ -541,14 +530,14 @@ __initfunc(static int assign_irq_vector(int irq)) return current_vector; } -__initfunc(void setup_IO_APIC_irqs (void)) +void __init setup_IO_APIC_irqs(void) { struct IO_APIC_route_entry entry; - int pin, idx, bus, irq, first_notcon=1; + int pin, idx, bus, irq, first_notcon = 1; printk("init IO_APIC IRQs\n"); - for (pin=0; pin%d ", i, irq_2_pin[i]); printk("\n"); @@ -729,15 +724,15 @@ void print_IO_APIC (void) return; } -__initfunc(static void init_sym_mode (void)) +static void __init init_sym_mode(void) { int i, pin; - for (i=0; ioem_id; table++) + for ( ; table->oem_id ; table++) if ((!strcmp(table->oem_id,ioapic_OEM_ID)) && (!strcmp(table->product_id,ioapic_Product_ID))) return 1; return 0; } -__initfunc(static int ioapic_whitelisted (void)) +static int __init ioapic_whitelisted(void) { /* * Right now, whitelist everything to see whether the new parsing @@ -818,12 +813,12 @@ __initfunc(static int ioapic_whitelisted (void)) #endif } -__initfunc(static int ioapic_blacklisted (void)) +static int __init ioapic_blacklisted(void) { return in_ioapic_list(ioapic_blacklist); } -__initfunc(static void setup_ioapic_id (void)) +static void __init setup_ioapic_id(void) { struct IO_APIC_reg_00 reg_00; @@ -857,11 +852,11 @@ __initfunc(static void setup_ioapic_id (void)) panic("could not set ID"); } -__initfunc(static void construct_default_ISA_mptable (void)) +static void __init construct_default_ISA_mptable(void) { - int i, pos=0; + int i, pos = 0; - for (i=0; i<16; i++) { + for (i = 0; i < 16; i++) { if (!IO_APIC_IRQ(i)) continue; @@ -903,14 +898,11 @@ __initfunc(static void construct_default_ISA_mptable (void)) * - if this function detects that timer IRQs are defunct, then we fall * back to ISA timer IRQs */ -__initfunc(static int timer_irq_works (void)) +static int __init timer_irq_works(void) { - unsigned int t1=jiffies; - unsigned long flags; + unsigned int t1 = jiffies; - save_flags(flags); sti(); - udelay(10*10000); if (jiffies-t1>1) @@ -919,8 +911,6 @@ __initfunc(static int timer_irq_works (void)) return 0; } -#ifdef __SMP__ - /* * In the SMP+IOAPIC case it might happen that there are an unspecified * number of pending IRQ events unhandled. These cases are very rare, @@ -928,7 +918,7 @@ __initfunc(static int timer_irq_works (void)) * better to do it this way as thus we do not have to be aware of * 'pending' interrupts in the IRQ path, except at this point. */ -static inline void self_IPI (unsigned int irq) +static inline void self_IPI(unsigned int irq) { irq_desc_t *desc = irq_desc + irq; @@ -1023,8 +1013,8 @@ static void do_edge_ioapic_IRQ(unsigned int irq, int cpu, struct pt_regs * regs) irq_exit(cpu, irq); } -static void do_level_ioapic_IRQ (unsigned int irq, int cpu, - struct pt_regs * regs) +static void do_level_ioapic_IRQ(unsigned int irq, int cpu, + struct pt_regs * regs) { irq_desc_t *desc = irq_desc + irq; struct irqaction * action; @@ -1095,7 +1085,7 @@ static struct hw_interrupt_type ioapic_level_irq_type = { disable_level_ioapic_irq }; -void init_IO_APIC_traps(void) +static inline void init_IO_APIC_traps(void) { int i; /* @@ -1124,7 +1114,6 @@ void init_IO_APIC_traps(void) } } } -#endif /* * This code may look a bit paranoid, but it's supposed to cooperate with @@ -1132,38 +1121,38 @@ void init_IO_APIC_traps(void) * is so screwy. Thanks to Brian Perkins for testing/hacking this beast * fanatically on his truly buggy board. */ -__initfunc(static void check_timer (void)) +static inline void check_timer(void) { int pin1, pin2; - pin1 = find_timer_pin (mp_INT); - pin2 = find_timer_pin (mp_ExtINT); + pin1 = find_timer_pin(mp_INT); + pin2 = find_timer_pin(mp_ExtINT); - if (!timer_irq_works ()) { + if (!timer_irq_works()) { if (pin1 != -1) printk("..MP-BIOS bug: 8254 timer not connected to IO-APIC\n"); printk("...trying to set up timer as ExtINT... "); if (pin2 != -1) { printk(".. (found pin %d) ...", pin2); - setup_ExtINT_pin (pin2); + setup_ExtINT_pin(pin2); make_8259A_irq(0); } - if (!timer_irq_works ()) { + if (!timer_irq_works()) { printk(" failed.\n"); printk("...trying to set up timer as BP IRQ..."); /* * Just in case ... */ if (pin1 != -1) - clear_IO_APIC_pin (pin1); + clear_IO_APIC_pin(pin1); if (pin2 != -1) - clear_IO_APIC_pin (pin2); + clear_IO_APIC_pin(pin2); make_8259A_irq(0); - if (!timer_irq_works ()) { + if (!timer_irq_works()) { printk(" failed.\n"); panic("IO-APIC + timer doesn't work!"); } @@ -1172,7 +1161,7 @@ __initfunc(static void check_timer (void)) } } -__initfunc(void setup_IO_APIC (void)) +void __init setup_IO_APIC(void) { init_sym_mode(); @@ -1216,7 +1205,7 @@ __initfunc(void setup_IO_APIC (void)) * Set up the IO-APIC IRQ routing table by parsing the MP-BIOS * mptable: */ - setup_IO_APIC_irqs (); + setup_IO_APIC_irqs(); init_IRQ_SMP(); check_timer(); diff --git a/arch/i386/kernel/irq.h b/arch/i386/kernel/irq.h index 99a4d20e1f31..f080a6555359 100644 --- a/arch/i386/kernel/irq.h +++ b/arch/i386/kernel/irq.h @@ -56,17 +56,11 @@ extern int handle_IRQ_event(unsigned int, struct pt_regs *); void mask_irq(unsigned int irq); void unmask_irq(unsigned int irq); -void enable_IO_APIC_irq (unsigned int irq); -void disable_IO_APIC_irq (unsigned int irq); -void unmask_IO_APIC_irq (unsigned int irq); -void mask_IO_APIC_irq (unsigned int irq); void set_8259A_irq_mask (unsigned int irq); int i8259A_irq_pending (unsigned int irq); void ack_APIC_irq (void); void setup_IO_APIC (void); -void init_IO_APIC_traps(void); int IO_APIC_get_PCI_irq_vector (int bus, int slot, int fn); -int IO_APIC_irq_trigger (int irq); void make_8259A_irq (unsigned int irq); void send_IPI (int dest, int vector); void init_pic_mode (void); diff --git a/arch/i386/kernel/process.c b/arch/i386/kernel/process.c index e15e490660cc..a04e014ec737 100644 --- a/arch/i386/kernel/process.c +++ b/arch/i386/kernel/process.c @@ -441,13 +441,26 @@ void show_regs(struct pt_regs * regs) * * This extra buffer essentially acts to make for less * "jitter" in the allocations.. + * + * On SMP we don't do this right now because: + * - we aren't holding any locks when called, and we might + * as well just depend on the generic memory management + * to do proper locking for us instead of complicating it + * here. + * - if you use SMP you have a beefy enough machine that + * this shouldn't matter.. */ +#ifndef __SMP__ #define EXTRA_TASK_STRUCT 16 static struct task_struct * task_struct_stack[EXTRA_TASK_STRUCT]; static int task_struct_stack_ptr = -1; +#endif struct task_struct * alloc_task_struct(void) { +#ifndef EXTRA_TASK_STRUCT + return (struct task_struct *) __get_free_pages(GFP_KERNEL,1); +#else int index; struct task_struct *ret; @@ -464,16 +477,19 @@ use_cache: } } return ret; +#endif } void free_task_struct(struct task_struct *p) { +#ifdef EXTRA_TASK_STRUCT int index = task_struct_stack_ptr+1; if (index < EXTRA_TASK_STRUCT) { task_struct_stack[index] = p; task_struct_stack_ptr = index; } else +#endif free_pages((unsigned long) p, 1); } diff --git a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c index 959a65b8df4d..50ff9ba32ae1 100644 --- a/arch/i386/kernel/traps.c +++ b/arch/i386/kernel/traps.c @@ -108,7 +108,7 @@ static void show_registers(struct pt_regs *regs) unsigned long *stack, addr, module_start, module_end; extern char _stext, _etext; - esp = (unsigned long) ®s->esp; + esp = (unsigned long) (1+regs); ss = __KERNEL_DS; if (regs->xcs & 3) { in_kernel = 0; @@ -169,8 +169,8 @@ static void show_registers(struct pt_regs *regs) printk("\nCode: "); for(i=0;i<20;i++) printk("%02x ", ((unsigned char *)regs->eip)[i]); - printk("\n"); } + printk("\n"); } spinlock_t die_lock; diff --git a/arch/i386/mm/fault.c b/arch/i386/mm/fault.c index 0d66961f94c2..c4955d724b97 100644 --- a/arch/i386/mm/fault.c +++ b/arch/i386/mm/fault.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include diff --git a/arch/m68k/amiga/amiga_ksyms.c b/arch/m68k/amiga/amiga_ksyms.c index 8038bc9cb179..4de6e4167dad 100644 --- a/arch/m68k/amiga/amiga_ksyms.c +++ b/arch/m68k/amiga/amiga_ksyms.c @@ -1,3 +1,4 @@ +#include #include #include #include diff --git a/arch/m68k/amiga/pcmcia.c b/arch/m68k/amiga/pcmcia.c index 484c420ef6a4..3faac7eda041 100644 --- a/arch/m68k/amiga/pcmcia.c +++ b/arch/m68k/amiga/pcmcia.c @@ -12,7 +12,6 @@ ** Created: 12/10/97 by Alain Malek */ -#include #include #include #include diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c index 9ceed9fe2584..111c6685e337 100644 --- a/drivers/block/nbd.c +++ b/drivers/block/nbd.c @@ -110,8 +110,8 @@ int nbd_xmit(int send, struct socket *sock, char *buf, int size) if (result <= 0) { #ifdef PARANOIA - printk(KERN_ERR "NBD: %s - sock=%d at buf=%d, size=%d returned %d.\n", - send ? "send" : "receive", (int) sock, (int) buf, size, result); + printk(KERN_ERR "NBD: %s - sock=%ld at buf=%ld, size=%d returned %d.\n", + send ? "send" : "receive", (long) sock, (long) buf, size, result); #endif break; } @@ -371,8 +371,8 @@ static int nbd_ioctl(struct inode *inode, struct file *file, return 0; #ifdef PARANOIA case NBD_PRINT_DEBUG: - printk(KERN_INFO "NBD device %d: head = %x, tail = %x. Global: in %d, out %d\n", - dev, (int) lo->head, (int) lo->tail, requests_in, requests_out); + printk(KERN_INFO "NBD device %d: head = %lx, tail = %lx. Global: in %d, out %d\n", + dev, (long) lo->head, (long) lo->tail, requests_in, requests_out); return 0; #endif } diff --git a/drivers/net/apne.c b/drivers/net/apne.c index 21d2cf89143e..005cc3195d76 100644 --- a/drivers/net/apne.c +++ b/drivers/net/apne.c @@ -29,7 +29,6 @@ #include -#include #include #include #include diff --git a/drivers/scsi/bvme6000.c b/drivers/scsi/bvme6000.c index 3556cbcc6f4d..c8712e92bde5 100644 --- a/drivers/scsi/bvme6000.c +++ b/drivers/scsi/bvme6000.c @@ -8,7 +8,6 @@ #include #include #include -#include #include #include diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c index bf17a6955365..4f94d88456fe 100644 --- a/fs/lockd/svc.c +++ b/fs/lockd/svc.c @@ -186,7 +186,8 @@ lockd(struct svc_rqst *rqstp) nlm_shutdown_hosts(); nlmsvc_pid = 0; } else - printk("lockd: new process, skipping host shutdown\n"); + printk(KERN_DEBUG + "lockd: new process, skipping host shutdown\n"); wake_up(&lockd_exit); /* Exit the RPC thread */ @@ -205,6 +206,7 @@ lockd(struct svc_rqst *rqstp) int lockd_up(void) { + static int warned = 0; struct svc_serv * serv; int error = 0; @@ -225,27 +227,32 @@ lockd_up(void) * we should be the first user ... */ if (nlmsvc_users > 1) - printk("lockd_up: no pid, %d users??\n", nlmsvc_users); + printk(KERN_WARNING + "lockd_up: no pid, %d users??\n", nlmsvc_users); error = -ENOMEM; serv = svc_create(&nlmsvc_program, 0, NLMSVC_XDRSIZE); if (!serv) { - printk("lockd_up: create service failed\n"); + printk(KERN_WARNING "lockd_up: create service failed\n"); goto out; } if ((error = svc_makesock(serv, IPPROTO_UDP, 0)) < 0 || (error = svc_makesock(serv, IPPROTO_TCP, 0)) < 0) { - printk("lockd_up: makesock failed, error=%d\n", error); + if (warned++ == 0) + printk(KERN_WARNING + "lockd_up: makesock failed, error=%d\n", error); goto destroy_and_out; - } + } + warned = 0; /* * Create the kernel thread and wait for it to start. */ error = svc_create_thread(lockd, serv); if (error) { - printk("lockd_up: create thread failed, error=%d\n", error); + printk(KERN_WARNING + "lockd_up: create thread failed, error=%d\n", error); goto destroy_and_out; } sleep_on(&lockd_start); @@ -267,17 +274,21 @@ out: void lockd_down(void) { + static int warned = 0; + down(&nlmsvc_sema); if (nlmsvc_users) { if (--nlmsvc_users) goto out; } else - printk("lockd_down: no users! pid=%d\n", nlmsvc_pid); + printk(KERN_WARNING "lockd_down: no users! pid=%d\n", nlmsvc_pid); if (!nlmsvc_pid) { - printk("lockd_down: nothing to do!\n"); + if (warned++ == 0) + printk(KERN_WARNING "lockd_down: no lockd running.\n"); goto out; } + warned = 0; kill_proc(nlmsvc_pid, SIGKILL, 1); /* @@ -289,7 +300,8 @@ lockd_down(void) interruptible_sleep_on(&lockd_exit); current->timeout = 0; if (nlmsvc_pid) { - printk("lockd_down: lockd failed to exit, clearing pid\n"); + printk(KERN_WARNING + "lockd_down: lockd failed to exit, clearing pid\n"); nlmsvc_pid = 0; } spin_lock_irq(¤t->sigmask_lock); diff --git a/include/asm-alpha/smplock.h b/include/asm-alpha/smplock.h new file mode 100644 index 000000000000..e62326a10791 --- /dev/null +++ b/include/asm-alpha/smplock.h @@ -0,0 +1,49 @@ +/* + * + * + * Default SMP lock implementation + */ +#include +#include + +extern spinlock_t kernel_flag; + +/* + * Release global kernel lock and global interrupt lock + */ +#define release_kernel_lock(task, cpu) \ +do { \ + if (task->lock_depth >= 0) \ + spin_unlock(&kernel_flag); \ + release_irqlock(cpu); \ + __sti(); \ +} while (0) + +/* + * Re-acquire the kernel lock + */ +#define reacquire_kernel_lock(task) \ +do { \ + if (task->lock_depth >= 0) \ + spin_lock(&kernel_flag); \ +} while (0) + + +/* + * Getting the big kernel lock. + * + * This cannot happen asynchronously, + * so we only need to worry about other + * CPU's. + */ +extern __inline__ void lock_kernel(void) +{ + if (!++current->lock_depth) + spin_lock(&kernel_flag); +} + +extern __inline__ void unlock_kernel(void) +{ + if (--current->lock_depth < 0) + spin_unlock(&kernel_flag); +} diff --git a/include/asm-arm/smplock.h b/include/asm-arm/smplock.h new file mode 100644 index 000000000000..e62326a10791 --- /dev/null +++ b/include/asm-arm/smplock.h @@ -0,0 +1,49 @@ +/* + * + * + * Default SMP lock implementation + */ +#include +#include + +extern spinlock_t kernel_flag; + +/* + * Release global kernel lock and global interrupt lock + */ +#define release_kernel_lock(task, cpu) \ +do { \ + if (task->lock_depth >= 0) \ + spin_unlock(&kernel_flag); \ + release_irqlock(cpu); \ + __sti(); \ +} while (0) + +/* + * Re-acquire the kernel lock + */ +#define reacquire_kernel_lock(task) \ +do { \ + if (task->lock_depth >= 0) \ + spin_lock(&kernel_flag); \ +} while (0) + + +/* + * Getting the big kernel lock. + * + * This cannot happen asynchronously, + * so we only need to worry about other + * CPU's. + */ +extern __inline__ void lock_kernel(void) +{ + if (!++current->lock_depth) + spin_lock(&kernel_flag); +} + +extern __inline__ void unlock_kernel(void) +{ + if (--current->lock_depth < 0) + spin_unlock(&kernel_flag); +} diff --git a/include/asm-generic/smplock.h b/include/asm-generic/smplock.h new file mode 100644 index 000000000000..e62326a10791 --- /dev/null +++ b/include/asm-generic/smplock.h @@ -0,0 +1,49 @@ +/* + * + * + * Default SMP lock implementation + */ +#include +#include + +extern spinlock_t kernel_flag; + +/* + * Release global kernel lock and global interrupt lock + */ +#define release_kernel_lock(task, cpu) \ +do { \ + if (task->lock_depth >= 0) \ + spin_unlock(&kernel_flag); \ + release_irqlock(cpu); \ + __sti(); \ +} while (0) + +/* + * Re-acquire the kernel lock + */ +#define reacquire_kernel_lock(task) \ +do { \ + if (task->lock_depth >= 0) \ + spin_lock(&kernel_flag); \ +} while (0) + + +/* + * Getting the big kernel lock. + * + * This cannot happen asynchronously, + * so we only need to worry about other + * CPU's. + */ +extern __inline__ void lock_kernel(void) +{ + if (!++current->lock_depth) + spin_lock(&kernel_flag); +} + +extern __inline__ void unlock_kernel(void) +{ + if (--current->lock_depth < 0) + spin_unlock(&kernel_flag); +} diff --git a/include/asm-i386/smplock.h b/include/asm-i386/smplock.h new file mode 100644 index 000000000000..3bb933e4277a --- /dev/null +++ b/include/asm-i386/smplock.h @@ -0,0 +1,59 @@ +/* + * + * + * i386 SMP lock implementation + */ +#include +#include + +extern spinlock_t kernel_flag; + +/* + * Release global kernel lock and global interrupt lock + */ +#define release_kernel_lock(task, cpu) \ +do { \ + if (task->lock_depth >= 0) \ + spin_unlock(&kernel_flag); \ + release_irqlock(cpu); \ + __sti(); \ +} while (0) + +/* + * Re-acquire the kernel lock + */ +#define reacquire_kernel_lock(task) \ +do { \ + if (task->lock_depth >= 0) \ + spin_lock(&kernel_flag); \ +} while (0) + + +/* + * Getting the big kernel lock. + * + * This cannot happen asynchronously, + * so we only need to worry about other + * CPU's. + */ +extern __inline__ void lock_kernel(void) +{ + __asm__ __volatile__( + "incl %1\n\t" + "jne 9f" + spin_lock_string + "\n9:" + :"=m" (__dummy_lock(&kernel_flag)), + "=m" (current->lock_depth)); +} + +extern __inline__ void unlock_kernel(void) +{ + __asm__ __volatile__( + "decl %1\n\t" + "jns 9f\n" + spin_unlock_string + "\n9:" + :"=m" (__dummy_lock(&kernel_flag)), + "=m" (current->lock_depth)); +} diff --git a/include/asm-i386/spinlock.h b/include/asm-i386/spinlock.h index cd5bdd8e642d..23568dd668ae 100644 --- a/include/asm-i386/spinlock.h +++ b/include/asm-i386/spinlock.h @@ -128,8 +128,7 @@ typedef struct { typedef struct { unsigned long a[100]; } __dummy_lock_t; #define __dummy_lock(lock) (*(__dummy_lock_t *)(lock)) -#define spin_lock(lock) \ -__asm__ __volatile__( \ +#define spin_lock_string \ "\n1:\t" \ "lock ; btsl $0,%0\n\t" \ "jc 2f\n" \ @@ -138,12 +137,19 @@ __asm__ __volatile__( \ "testb $1,%0\n\t" \ "jne 2b\n\t" \ "jmp 1b\n" \ - ".previous" \ + ".previous" + +#define spin_unlock_string \ + "lock ; btrl $0,%0" + +#define spin_lock(lock) \ +__asm__ __volatile__( \ + spin_lock_string \ :"=m" (__dummy_lock(lock))) #define spin_unlock(lock) \ __asm__ __volatile__( \ - "lock ; btrl $0,%0" \ + spin_unlock_string \ :"=m" (__dummy_lock(lock))) #define spin_trylock(lock) (!test_and_set_bit(0,(lock))) diff --git a/include/asm-m68k/smplock.h b/include/asm-m68k/smplock.h new file mode 100644 index 000000000000..e62326a10791 --- /dev/null +++ b/include/asm-m68k/smplock.h @@ -0,0 +1,49 @@ +/* + * + * + * Default SMP lock implementation + */ +#include +#include + +extern spinlock_t kernel_flag; + +/* + * Release global kernel lock and global interrupt lock + */ +#define release_kernel_lock(task, cpu) \ +do { \ + if (task->lock_depth >= 0) \ + spin_unlock(&kernel_flag); \ + release_irqlock(cpu); \ + __sti(); \ +} while (0) + +/* + * Re-acquire the kernel lock + */ +#define reacquire_kernel_lock(task) \ +do { \ + if (task->lock_depth >= 0) \ + spin_lock(&kernel_flag); \ +} while (0) + + +/* + * Getting the big kernel lock. + * + * This cannot happen asynchronously, + * so we only need to worry about other + * CPU's. + */ +extern __inline__ void lock_kernel(void) +{ + if (!++current->lock_depth) + spin_lock(&kernel_flag); +} + +extern __inline__ void unlock_kernel(void) +{ + if (--current->lock_depth < 0) + spin_unlock(&kernel_flag); +} diff --git a/include/asm-mips/smplock.h b/include/asm-mips/smplock.h new file mode 100644 index 000000000000..e62326a10791 --- /dev/null +++ b/include/asm-mips/smplock.h @@ -0,0 +1,49 @@ +/* + * + * + * Default SMP lock implementation + */ +#include +#include + +extern spinlock_t kernel_flag; + +/* + * Release global kernel lock and global interrupt lock + */ +#define release_kernel_lock(task, cpu) \ +do { \ + if (task->lock_depth >= 0) \ + spin_unlock(&kernel_flag); \ + release_irqlock(cpu); \ + __sti(); \ +} while (0) + +/* + * Re-acquire the kernel lock + */ +#define reacquire_kernel_lock(task) \ +do { \ + if (task->lock_depth >= 0) \ + spin_lock(&kernel_flag); \ +} while (0) + + +/* + * Getting the big kernel lock. + * + * This cannot happen asynchronously, + * so we only need to worry about other + * CPU's. + */ +extern __inline__ void lock_kernel(void) +{ + if (!++current->lock_depth) + spin_lock(&kernel_flag); +} + +extern __inline__ void unlock_kernel(void) +{ + if (--current->lock_depth < 0) + spin_unlock(&kernel_flag); +} diff --git a/include/asm-ppc/smplock.h b/include/asm-ppc/smplock.h new file mode 100644 index 000000000000..e62326a10791 --- /dev/null +++ b/include/asm-ppc/smplock.h @@ -0,0 +1,49 @@ +/* + * + * + * Default SMP lock implementation + */ +#include +#include + +extern spinlock_t kernel_flag; + +/* + * Release global kernel lock and global interrupt lock + */ +#define release_kernel_lock(task, cpu) \ +do { \ + if (task->lock_depth >= 0) \ + spin_unlock(&kernel_flag); \ + release_irqlock(cpu); \ + __sti(); \ +} while (0) + +/* + * Re-acquire the kernel lock + */ +#define reacquire_kernel_lock(task) \ +do { \ + if (task->lock_depth >= 0) \ + spin_lock(&kernel_flag); \ +} while (0) + + +/* + * Getting the big kernel lock. + * + * This cannot happen asynchronously, + * so we only need to worry about other + * CPU's. + */ +extern __inline__ void lock_kernel(void) +{ + if (!++current->lock_depth) + spin_lock(&kernel_flag); +} + +extern __inline__ void unlock_kernel(void) +{ + if (--current->lock_depth < 0) + spin_unlock(&kernel_flag); +} diff --git a/include/asm-sparc/smplock.h b/include/asm-sparc/smplock.h new file mode 100644 index 000000000000..e62326a10791 --- /dev/null +++ b/include/asm-sparc/smplock.h @@ -0,0 +1,49 @@ +/* + * + * + * Default SMP lock implementation + */ +#include +#include + +extern spinlock_t kernel_flag; + +/* + * Release global kernel lock and global interrupt lock + */ +#define release_kernel_lock(task, cpu) \ +do { \ + if (task->lock_depth >= 0) \ + spin_unlock(&kernel_flag); \ + release_irqlock(cpu); \ + __sti(); \ +} while (0) + +/* + * Re-acquire the kernel lock + */ +#define reacquire_kernel_lock(task) \ +do { \ + if (task->lock_depth >= 0) \ + spin_lock(&kernel_flag); \ +} while (0) + + +/* + * Getting the big kernel lock. + * + * This cannot happen asynchronously, + * so we only need to worry about other + * CPU's. + */ +extern __inline__ void lock_kernel(void) +{ + if (!++current->lock_depth) + spin_lock(&kernel_flag); +} + +extern __inline__ void unlock_kernel(void) +{ + if (--current->lock_depth < 0) + spin_unlock(&kernel_flag); +} diff --git a/include/asm-sparc64/smplock.h b/include/asm-sparc64/smplock.h new file mode 100644 index 000000000000..e62326a10791 --- /dev/null +++ b/include/asm-sparc64/smplock.h @@ -0,0 +1,49 @@ +/* + * + * + * Default SMP lock implementation + */ +#include +#include + +extern spinlock_t kernel_flag; + +/* + * Release global kernel lock and global interrupt lock + */ +#define release_kernel_lock(task, cpu) \ +do { \ + if (task->lock_depth >= 0) \ + spin_unlock(&kernel_flag); \ + release_irqlock(cpu); \ + __sti(); \ +} while (0) + +/* + * Re-acquire the kernel lock + */ +#define reacquire_kernel_lock(task) \ +do { \ + if (task->lock_depth >= 0) \ + spin_lock(&kernel_flag); \ +} while (0) + + +/* + * Getting the big kernel lock. + * + * This cannot happen asynchronously, + * so we only need to worry about other + * CPU's. + */ +extern __inline__ void lock_kernel(void) +{ + if (!++current->lock_depth) + spin_lock(&kernel_flag); +} + +extern __inline__ void unlock_kernel(void) +{ + if (--current->lock_depth < 0) + spin_unlock(&kernel_flag); +} diff --git a/include/linux/sched.h b/include/linux/sched.h index 8995543264dd..f4ca927104f2 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -213,9 +213,16 @@ struct task_struct { /* various fields */ long counter; long priority; - struct linux_binfmt *binfmt; +/* SMP and runqueue state */ + int has_cpu; + int processor; + int last_processor; + int lock_depth; /* Lock depth. We can context switch in and out of holding a syscall kernel lock... */ struct task_struct *next_task, *prev_task; struct task_struct *next_run, *prev_run; + +/* task state */ + struct linux_binfmt *binfmt; int exit_code, exit_signal; int pdeath_signal; /* The signal sent when the parent dies */ /* ??? */ @@ -282,18 +289,12 @@ struct task_struct { /* memory management info */ struct mm_struct *mm; /* signal handlers */ + spinlock_t sigmask_lock; /* Protects signal and blocked */ struct signal_struct *sig; sigset_t signal, blocked; struct signal_queue *sigqueue, **sigqueue_tail; unsigned long sas_ss_sp; size_t sas_ss_size; -/* SMP state */ - int has_cpu; - int processor; - int last_processor; - int lock_depth; /* Lock depth. We can context switch in and out of holding a syscall kernel lock... */ - /* Spinlocks for various pieces or per-task state. */ - spinlock_t sigmask_lock; /* Protects signal and blocked */ }; /* @@ -338,8 +339,9 @@ struct task_struct { #define INIT_TASK \ /* state etc */ { 0,0,0,KERNEL_DS,&default_exec_domain,0, \ /* counter */ DEF_PRIORITY,DEF_PRIORITY, \ -/* binfmt */ NULL, \ +/* SMP */ 0,0,0,-1, \ /* schedlink */ &init_task,&init_task, &init_task, &init_task, \ +/* binfmt */ NULL, \ /* ec,brk... */ 0,0,0,0,0,0, \ /* pid etc.. */ 0,0,0,0,0, \ /* proc links*/ &init_task,&init_task,NULL,NULL,NULL, \ @@ -365,10 +367,7 @@ struct task_struct { /* fs */ &init_fs, \ /* files */ &init_files, \ /* mm */ &init_mm, \ -/* signals */ &init_signals, {{0}}, {{0}}, NULL, &init_task.sigqueue, \ - 0, 0, \ -/* SMP */ 0,0,0,0, \ -/* locks */ INIT_LOCKS \ +/* signals */ INIT_LOCKS, &init_signals, {{0}}, {{0}}, NULL, &init_task.sigqueue, 0, 0, \ } union task_union { diff --git a/include/linux/smp_lock.h b/include/linux/smp_lock.h index fdb2c1973e74..4583e2f5af63 100644 --- a/include/linux/smp_lock.h +++ b/include/linux/smp_lock.h @@ -10,60 +10,7 @@ #else -#include -#include - -extern spinlock_t kernel_flag; - -/* - * Release global kernel lock and global interrupt lock - */ -#define release_kernel_lock(task, cpu) \ -do { \ - if (task->lock_depth) \ - spin_unlock(&kernel_flag); \ - release_irqlock(cpu); \ - __sti(); \ -} while (0) - -/* - * Re-acquire the kernel lock - */ -#define reacquire_kernel_lock(task) \ -do { \ - if (task->lock_depth) \ - spin_lock(&kernel_flag); \ -} while (0) - - -/* - * Getting the big kernel lock. - * - * This cannot happen asynchronously, - * so we only need to worry about other - * CPU's. - */ -extern __inline__ void lock_kernel(void) -{ - struct task_struct *tsk = current; - int lock_depth; - - lock_depth = tsk->lock_depth; - tsk->lock_depth = lock_depth+1; - if (!lock_depth) - spin_lock(&kernel_flag); -} - -extern __inline__ void unlock_kernel(void) -{ - struct task_struct *tsk = current; - int lock_depth; - - lock_depth = tsk->lock_depth-1; - tsk->lock_depth = lock_depth; - if (!lock_depth) - spin_unlock(&kernel_flag); -} +#include #endif /* __SMP__ */ diff --git a/kernel/exit.c b/kernel/exit.c index b19c2d77b4e5..3de5781c8916 100644 --- a/kernel/exit.c +++ b/kernel/exit.c @@ -36,21 +36,31 @@ static void release(struct task_struct * p) { if (p != current) { #ifdef __SMP__ - /* FIXME! Cheesy, but kills the window... -DaveM */ - do { - barrier(); - } while (p->has_cpu); - spin_unlock_wait(&scheduler_lock); + /* + * Wait to make sure the process isn't active on any + * other CPU + */ + for (;;) { + int has_cpu; + spin_lock(&scheduler_lock); + has_cpu = p->has_cpu; + spin_unlock(&scheduler_lock); + if (!has_cpu) + break; + do { + barrier(); + } while (p->has_cpu); + } #endif charge_uid(p, -1); nr_tasks--; add_free_taskslot(p->tarray_ptr); - { - write_lock_irq(&tasklist_lock); - unhash_pid(p); - REMOVE_LINKS(p); - write_unlock_irq(&tasklist_lock); - } + + write_lock_irq(&tasklist_lock); + unhash_pid(p); + REMOVE_LINKS(p); + write_unlock_irq(&tasklist_lock); + release_thread(p); current->cmin_flt += p->min_flt + p->cmin_flt; current->cmaj_flt += p->maj_flt + p->cmaj_flt; @@ -340,35 +350,39 @@ static void exit_notify(void) NORET_TYPE void do_exit(long code) { + struct task_struct *tsk = current; + if (in_interrupt()) printk("Aiee, killing interrupt handler\n"); - if (current == task[0]) + if (!tsk->pid) panic("Attempted to kill the idle task!"); + tsk->flags |= PF_EXITING; + del_timer(&tsk->real_timer); + + lock_kernel(); fake_volatile: - current->flags |= PF_EXITING; #ifdef CONFIG_BSD_PROCESS_ACCT acct_process(code); #endif - del_timer(¤t->real_timer); sem_exit(); - __exit_mm(current); + __exit_mm(tsk); #if CONFIG_AP1000 - exit_msc(current); + exit_msc(tsk); #endif - __exit_files(current); - __exit_fs(current); - __exit_sighand(current); + __exit_files(tsk); + __exit_fs(tsk); + __exit_sighand(tsk); exit_thread(); - current->state = TASK_ZOMBIE; - current->exit_code = code; + tsk->state = TASK_ZOMBIE; + tsk->exit_code = code; exit_notify(); #ifdef DEBUG_PROC_TREE audit_ptree(); #endif - if (current->exec_domain && current->exec_domain->module) - __MOD_DEC_USE_COUNT(current->exec_domain->module); - if (current->binfmt && current->binfmt->module) - __MOD_DEC_USE_COUNT(current->binfmt->module); + if (tsk->exec_domain && tsk->exec_domain->module) + __MOD_DEC_USE_COUNT(tsk->exec_domain->module); + if (tsk->binfmt && tsk->binfmt->module) + __MOD_DEC_USE_COUNT(tsk->binfmt->module); schedule(); /* * In order to get rid of the "volatile function does return" message @@ -388,9 +402,7 @@ fake_volatile: asmlinkage int sys_exit(int error_code) { - lock_kernel(); do_exit((error_code&0xff)<<8); - unlock_kernel(); } asmlinkage int sys_wait4(pid_t pid,unsigned int * stat_addr, int options, struct rusage * ru) diff --git a/kernel/fork.c b/kernel/fork.c index 0c66e1d35519..d956d502e235 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -476,7 +476,7 @@ static inline void copy_flags(unsigned long clone_flags, struct task_struct *p) int do_fork(unsigned long clone_flags, unsigned long usp, struct pt_regs *regs) { int nr; - int error = -ENOMEM; + int retval = -ENOMEM; struct task_struct *p; down(¤t->mm->mmap_sem); @@ -485,7 +485,7 @@ int do_fork(unsigned long clone_flags, unsigned long usp, struct pt_regs *regs) if (!p) goto bad_fork; - error = -EAGAIN; + retval = -EAGAIN; nr = find_empty_process(); if (nr < 0) goto bad_fork_free; @@ -504,8 +504,16 @@ int do_fork(unsigned long clone_flags, unsigned long usp, struct pt_regs *regs) copy_flags(clone_flags, p); p->pid = get_pid(clone_flags); - p->next_run = NULL; - p->prev_run = NULL; + /* + * This is a "shadow run" state. The process + * is marked runnable, but isn't actually on + * any run queue yet.. (that happens at the + * very end). + */ + p->state = TASK_RUNNING; + p->next_run = p; + p->prev_run = p; + p->p_pptr = p->p_opptr = current; p->p_cptr = NULL; init_waitqueue(&p->wait_chldexit); @@ -535,12 +543,13 @@ int do_fork(unsigned long clone_flags, unsigned long usp, struct pt_regs *regs) spin_lock_init(&p->sigmask_lock); } #endif - p->lock_depth = 0; + p->lock_depth = -1; /* -1 = no lock */ p->start_time = jiffies; p->tarray_ptr = &task[nr]; *p->tarray_ptr = p; { + /* This makes it visible to the rest of the system */ unsigned long flags; write_lock_irqsave(&tasklist_lock, flags); SET_LINKS(p); @@ -550,7 +559,7 @@ int do_fork(unsigned long clone_flags, unsigned long usp, struct pt_regs *regs) nr_tasks++; - error = -ENOMEM; + retval = -ENOMEM; /* copy all the process information */ if (copy_files(clone_flags, p)) goto bad_fork_cleanup; @@ -560,8 +569,8 @@ int do_fork(unsigned long clone_flags, unsigned long usp, struct pt_regs *regs) goto bad_fork_cleanup_fs; if (copy_mm(nr, clone_flags, p)) goto bad_fork_cleanup_sighand; - error = copy_thread(nr, clone_flags, usp, p, regs); - if (error) + retval = copy_thread(nr, clone_flags, usp, p, regs); + if (retval) goto bad_fork_cleanup_sighand; p->semundo = NULL; @@ -579,18 +588,18 @@ int do_fork(unsigned long clone_flags, unsigned long usp, struct pt_regs *regs) current->counter >>= 1; p->counter = current->counter; - if(p->pid) { - wake_up_process(p); /* do this last, just in case */ - } else { - p->state = TASK_RUNNING; - p->next_run = p->prev_run = p; + /* Ok, add it to the run-queues, let it rip! */ + retval = p->pid; + if (retval) { + p->next_run = NULL; + p->prev_run = NULL; + wake_up_process(p); /* do this last */ } ++total_forks; - error = p->pid; bad_fork: up(¤t->mm->mmap_sem); unlock_kernel(); - return error; + return retval; bad_fork_cleanup_sighand: exit_sighand(p); diff --git a/kernel/sched.c b/kernel/sched.c index 25a298d79567..2336a678671a 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -146,14 +146,21 @@ static inline void reschedule_idle(struct task_struct * p) current->need_resched = 1; } - +/* + * Careful! + * + * This has to add the process to the _beginning_ of the + * run-queue, not the end. See the comment about "This is + * subtle" in the scheduler proper.. + */ static inline void add_to_runqueue(struct task_struct * p) { - nr_running++; - reschedule_idle(p); - (p->prev_run = init_task.prev_run)->next_run = p; - p->next_run = &init_task; - init_task.prev_run = p; + struct task_struct *next = init_task.next_run; + + p->prev_run = &init_task; + init_task.next_run = p; + p->next_run = next; + next->prev_run = p; } static inline void del_from_runqueue(struct task_struct * p) @@ -229,8 +236,11 @@ inline void wake_up_process(struct task_struct * p) spin_lock_irqsave(&runqueue_lock, flags); p->state = TASK_RUNNING; - if (!p->next_run) + if (!p->next_run) { add_to_runqueue(p); + reschedule_idle(p); + nr_running++; + } spin_unlock_irqrestore(&runqueue_lock, flags); } @@ -420,6 +430,9 @@ int del_timer(struct timer_list * timer) ret = detach_timer(timer); timer->next = timer->prev = 0; spin_unlock_irqrestore(&timerlist_lock, flags); + + /* Make sure the timer isn't running in parallell.. */ + synchronize_bh(); return ret; } @@ -1351,8 +1364,8 @@ static int setscheduler(pid_t pid, int policy, /* * We play safe to avoid deadlocks. */ - spin_lock_irq(&scheduler_lock); - spin_lock(&runqueue_lock); + spin_lock(&scheduler_lock); + spin_lock_irq(&runqueue_lock); read_lock(&tasklist_lock); p = find_process_by_pid(pid); @@ -1398,8 +1411,8 @@ static int setscheduler(pid_t pid, int policy, out_unlock: read_unlock(&tasklist_lock); - spin_unlock(&runqueue_lock); - spin_unlock_irq(&scheduler_lock); + spin_unlock_irq(&runqueue_lock); + spin_unlock(&scheduler_lock); out_nounlock: return retval; @@ -1590,13 +1603,13 @@ static void show_task(int nr,struct task_struct * p) else printk(" %016lx ", thread_saved_pc(&p->tss)); #endif -#if 0 - for (free = 1; free < PAGE_SIZE/sizeof(long) ; free++) { - if (((unsigned long *)p->kernel_stack_page)[free]) - break; + { + unsigned long * n = (unsigned long *) (p+1); + while (!*n) + n++; + free = (unsigned long) n - (unsigned long)(p+1); } -#endif - printk("%5lu %5d %6d ", free*sizeof(long), p->pid, p->p_pptr->pid); + printk("%5lu %5d %6d ", free, p->pid, p->p_pptr->pid); if (p->p_cptr) printk("%5d ", p->p_cptr->pid); else -- 2.39.5