]> git.neil.brown.name Git - history.git/commitdiff
This is the merge of the initial 2.4 SMP support.
authorJeff Dike <jdike@uml.karaya.com>
Mon, 14 Oct 2002 05:53:55 +0000 (01:53 -0400)
committerJeff Dike <jdike@uml.karaya.com>
Mon, 14 Oct 2002 05:53:55 +0000 (01:53 -0400)
Locking was added where necessary.
All processors take timer interrupts, but only CPU 0 calls the timer
IRQ.  The others just call update_process_times to keep the
accounting straight.
The timer interrupt is blocked along with the other signals.

54 files changed:
arch/um/drivers/chan_user.c
arch/um/drivers/harddog_kern.c
arch/um/drivers/hostaudio_kern.c
arch/um/drivers/line.c
arch/um/drivers/mconsole_kern.c
arch/um/drivers/mconsole_user.c
arch/um/drivers/mmapper_kern.c
arch/um/drivers/net_kern.c
arch/um/drivers/port_kern.c
arch/um/drivers/ssl.c
arch/um/drivers/stdio_console.c
arch/um/drivers/ubd_kern.c
arch/um/drivers/ubd_user.c
arch/um/drivers/xterm.c
arch/um/include/2_5compat.h
arch/um/include/irq_user.h
arch/um/include/kern_util.h
arch/um/include/mconsole.h
arch/um/include/sigio.h
arch/um/include/time_user.h
arch/um/kernel/exec_kern.c
arch/um/kernel/exitcode.c
arch/um/kernel/frame.c
arch/um/kernel/helper.c
arch/um/kernel/initrd_kern.c
arch/um/kernel/irq.c
arch/um/kernel/irq_user.c
arch/um/kernel/mem.c
arch/um/kernel/mem_user.c
arch/um/kernel/process.c
arch/um/kernel/process_kern.c
arch/um/kernel/sigio_kern.c
arch/um/kernel/sigio_user.c
arch/um/kernel/signal_user.c
arch/um/kernel/smp.c
arch/um/kernel/syscall_kern.c
arch/um/kernel/syscall_user.c
arch/um/kernel/time.c
arch/um/kernel/time_kern.c
arch/um/kernel/trap_kern.c
arch/um/kernel/trap_user.c
arch/um/kernel/tty_log.c
arch/um/kernel/um_arch.c
arch/um/kernel/umid.c
arch/um/kernel/user_util.c
arch/um/main.c
arch/um/ptproxy/proxy.c
arch/um/sys-i386/bugs.c
arch/um/sys-i386/ptrace_user.c
arch/um/sys-ppc/miscthings.c
arch/um/uml.lds.S
include/asm-um/cache.h
include/asm-um/smp.h
include/asm-um/thread_info.h

index c1ac4d8fbb26c9655144d572885540f7adcc5388..79879f30aef50503b96293b6422f32575e1b03eb 100644 (file)
@@ -155,6 +155,8 @@ static void tracer_winch_handler(int sig)
                       errno);
 }
 
+/* Called only by the tracing thread during initialization */
+
 void setup_tracer_winch(void)
 {
        int err;
index dd1214f116abbcdc585158d134be0321bbc9c3e8..efe03723db54e826535eb29f28a17e7e9f1bdad7 100644 (file)
@@ -51,8 +51,8 @@
 
 MODULE_LICENSE("GPL");
 
+/* Locked by the BKL in harddog_open and harddog_release */
 static int timer_alive;
-
 static int harddog_in_fd = -1;
 static int harddog_out_fd = -1;
 
@@ -67,6 +67,7 @@ static int harddog_open(struct inode *inode, struct file *file)
        int err;
        char *sock = NULL;
 
+       lock_kernel();
        if(timer_alive)
                return -EBUSY;
 #ifdef CONFIG_HARDDOG_NOWAYOUT  
@@ -80,6 +81,7 @@ static int harddog_open(struct inode *inode, struct file *file)
        if(err) return(err);
 
        timer_alive = 1;
+       unlock_kernel();
        return 0;
 }
 
index 5ae1c44294f63c85ec6d643f735bf84fb80a2c05..d5c950b4bb836eab79f191ace1e7cc532e2e860b 100644 (file)
@@ -15,6 +15,7 @@
 #include "init.h"
 #include "hostaudio.h"
 
+/* Only changed from linux_main at boot time */
 char *dsp = HOSTAUDIO_DEV_DSP;
 char *mixer = HOSTAUDIO_DEV_MIXER;
 
index 50e9adfa5e758382f22c47145070ada0e6a84e3a..a7ff39d3862fe79c3b389ba810ecbbf0c41a9168 100644 (file)
@@ -99,19 +99,27 @@ int line_write(struct line *lines, struct tty_struct *tty, const char *buf,
        i = minor(tty->device) - tty->driver.minor_start;
        line = &lines[i];
 
+       down(&line->sem);
        if(line->head != line->tail){
                local_irq_save(flags);
                buffer_data(line, buf, len);
                err = flush_buffer(line);
                local_irq_restore(flags);
-               if(err <= 0) return(len);
+               if(err <= 0)
+                       goto out;
        }
        else {
                n = write_chan(&line->chan_list, buf, len, 
                               line->driver->write_irq);
-               if(n < 0) return(n);
-               if(n < len) buffer_data(line, buf + n, len - n);
+               if(n < 0){
+                       len = n;
+                       goto out;
+               }
+               if(n < len)
+                       buffer_data(line, buf + n, len - n);
        }
+ out:
+       up(&line->sem);
        return(len);
 }
 
@@ -249,6 +257,7 @@ void line_close(struct line *lines, struct tty_struct *tty)
        else n = minor(tty->device) - tty->driver.minor_start;
        line = &lines[n];
 
+       down(&line->sem);
        line->count--;
 
        /* I don't like this, but I can't think of anything better.  What's
@@ -261,6 +270,7 @@ void line_close(struct line *lines, struct tty_struct *tty)
                line->tty = NULL;
        if(line->count == 0)
                line_disable(line, -1);
+       up(&line->sem);
 }
 
 void close_lines(struct line *lines, int nlines)
@@ -408,16 +418,18 @@ void winch_interrupt(int irq, void *data, struct pt_regs *unused)
        reactivate_fd(winch->fd, WINCH_IRQ);
 }
 
+DECLARE_MUTEX(winch_handler_sem);
 LIST_HEAD(winch_handlers);
 
 void register_winch_irq(int fd, int tty_fd, int pid, void *line)
 {
        struct winch *winch;
 
+       down(&winch_handler_sem);
        winch = kmalloc(sizeof(*winch), GFP_KERNEL);
        if(winch == NULL){
                printk("register_winch_irq - kmalloc failed\n");
-               return;
+               goto out;
        }
        *winch = ((struct winch) { list :       LIST_HEAD_INIT(winch->list),
                                   fd :         fd,
@@ -429,6 +441,8 @@ void register_winch_irq(int fd, int tty_fd, int pid, void *line)
                          SA_INTERRUPT | SA_SHIRQ | SA_SAMPLE_RANDOM, 
                          "winch", winch) < 0)
                printk("register_winch_irq - failed to register IRQ\n");
+ out:
+       up(&winch_handler_sem);
 }
 
 static void winch_cleanup(void)
index a90786aff133529503762469b43128dddf203102..c2822cb872c28322561b49266d538f26ec487d30 100644 (file)
@@ -40,6 +40,11 @@ static struct notifier_block reboot_notifier = {
        priority:               0,
 };
 
+/* Safe without explicit locking for now.  Tasklets provide their own 
+ * locking, and the interrupt handler is safe because it can't interrupt
+ * itself and it can only happen on CPU 0.
+ */
+
 LIST_HEAD(mc_requests);
 
 void mc_work_proc(void *unused)
@@ -49,12 +54,12 @@ void mc_work_proc(void *unused)
        int done;
 
        do {
-               save_flags(flags);
+               local_save_flags(flags);
                req = list_entry(mc_requests.next, struct mconsole_entry, 
                                 list);
                list_del(&req->list);
                done = list_empty(&mc_requests);
-               restore_flags(flags);
+               local_irq_restore(flags);
                req->request.cmd->handler(&req->request);
                kfree(req);
        } while(!done);
@@ -152,6 +157,8 @@ void mconsole_stop(struct mc_request *req)
        mconsole_reply(req, "", 0, 0);
 }
 
+/* This list is populated by __initcall routines. */
+
 LIST_HEAD(mconsole_devices);
 
 void mconsole_register_dev(struct mc_device *new)
@@ -224,7 +231,10 @@ void mconsole_sysrq(struct mc_request *req)
 }
 #endif
 
-static char *notify_socket = NULL;
+/* Changed by mconsole_setup, which is __setup, and called before SMP is
+ * active.
+ */
+static char *notify_socket = NULL; 
 
 int mconsole_init(void)
 {
@@ -301,6 +311,18 @@ static int create_proc_mconsole(void)
        return(0);
 }
 
+static spinlock_t notify_spinlock = SPIN_LOCK_UNLOCKED;
+
+void lock_notify(void)
+{
+       spin_lock(&notify_spinlock);
+}
+
+void unlock_notify(void)
+{
+       spin_unlock(&notify_spinlock);
+}
+
 __initcall(create_proc_mconsole);
 
 #define NOTIFY "=notify:"
index d60be6eead37897cee00d3538a0354a0fc345162..11b09a96f45458ff94104873ab54960411753049 100644 (file)
@@ -30,6 +30,7 @@ static struct mconsole_command commands[] = {
        { "go", mconsole_go, 1 },
 };
 
+/* Initialized in mconsole_init, which is an initcall */
 char mconsole_socket_name[256];
 
 int mconsole_reply_v0(struct mc_request *req, char *reply)
@@ -162,16 +163,21 @@ int mconsole_notify(char *sock_name, int type, const void *data, int len)
 {
        struct sockaddr_un target;
        struct mconsole_notify packet;
-       int n, err;
+       int n, err = 0;
 
+       lock_notify();
        if(notify_sock < 0){
                notify_sock = socket(PF_UNIX, SOCK_DGRAM, 0);
                if(notify_sock < 0){
                        printk("mconsole_notify - socket failed, errno = %d\n",
                               errno);
-                       return(-errno);
+                       err = -errno;
                }
        }
+       unlock_notify();
+       
+       if(err)
+               return(err);
 
        target.sun_family = AF_UNIX;
        strcpy(target.sun_path, sock_name);
index d03082be380d4e60d32d0736b3807e473d3d04c0..dc2937a0ed2eea8f3fafca22965ec8ff4c19dd1f 100644 (file)
 #include <linux/mm.h> 
 #include <linux/slab.h>
 #include <linux/init.h> 
+#include <linux/smp_lock.h>
 #include <asm/uaccess.h>
 #include <asm/irq.h>
-#include <asm/smplock.h>
 #include <asm/pgtable.h>
 #include "mem_user.h"
 #include "user_util.h"
  
+/* These are set in mmapper_init, which is called at boot time */
 static unsigned long mmapper_size;
 static unsigned long p_buf = 0;
 static char *v_buf = NULL;
index a83f84c367d48ea95d570dbd809341a715f66b00..5b35b8e5e74e9726c504ded9c2f3af5a476216df 100644 (file)
@@ -27,6 +27,7 @@
 #include "init.h"
 #include "irq_user.h"
 
+static spinlock_t opened_lock = SPIN_LOCK_UNLOCKED;
 LIST_HEAD(opened);
 
 static int uml_net_rx(struct net_device *dev)
@@ -118,7 +119,9 @@ static int uml_net_open(struct net_device *dev)
        lp->tl.data = (unsigned long) &lp->user;
        netif_start_queue(dev);
 
+       spin_lock(&opened_lock);
        list_add(&lp->list, &opened);
+       spin_unlock(&opened_lock);
        MOD_INC_USE_COUNT;
  out:
        spin_unlock(&lp->lock);
@@ -135,8 +138,10 @@ static int uml_net_close(struct net_device *dev)
        free_irq(dev->irq, dev);
        if(lp->close != NULL) (*lp->close)(lp->fd, &lp->user);
        lp->fd = -1;
+       spin_lock(&opened_lock);
        list_del(&lp->list);
-       
+       spin_unlock(&opened_lock);
+
        MOD_DEC_USE_COUNT;
        spin_unlock(&lp->lock);
        return 0;
@@ -245,6 +250,7 @@ void uml_net_user_timer_expire(unsigned long _conn)
 #endif
 }
 
+static spinlock_t devices_lock = SPIN_LOCK_UNLOCKED;
 static struct list_head devices = LIST_HEAD_INIT(devices);
 
 static int eth_configure(int n, void *init, char *mac,
@@ -261,7 +267,10 @@ static int eth_configure(int n, void *init, char *mac,
                return(1);
        }
 
+       spin_lock(&devices_lock);
        list_add(&device->list, &devices);
+       spin_unlock(&devices_lock);
+
        device->index = n;
 
        size = transport->private_size + sizeof(struct uml_net_private) + 
@@ -373,12 +382,16 @@ static struct uml_net *find_device(int n)
        struct uml_net *device;
        struct list_head *ele;
 
+       spin_lock(&devices_lock);
        list_for_each(ele, &devices){
                device = list_entry(ele, struct uml_net, list);
                if(device->index == n)
-                       return(device);
+                       goto out;
        }
-       return(NULL);
+       device = NULL;
+ out:
+       spin_unlock(&devices_lock);
+       return(device);
 }
 
 static int eth_parse(char *str, int *index_out, char **str_out)
@@ -418,8 +431,12 @@ struct eth_init {
        int index;
 };
 
+/* Filled in at boot time.  Will need locking if the transports become
+ * modular.
+ */
 struct list_head transports = LIST_HEAD_INIT(transports);
 
+/* Filled in during early boot */
 struct list_head eth_cmd_line = LIST_HEAD_INIT(eth_cmd_line);
 
 static int check_transport(struct transport *transport, char *eth, int n,
index 0acb925a70f60a540bf7c83f69c87ddde76a28e9..b85f8f23bd49a271dfed6859b4d14646d8f9ee99 100644 (file)
@@ -62,8 +62,6 @@ static void pipe_interrupt(int irq, void *data, struct pt_regs *regs)
        up(&conn->port->sem);
 }
 
-struct list_head ports = LIST_HEAD_INIT(ports);
-
 static void port_interrupt(int irq, void *data, struct pt_regs *regs)
 {
        struct port_list *port = data;
@@ -107,6 +105,9 @@ static void port_interrupt(int irq, void *data, struct pt_regs *regs)
        reactivate_fd(port->fd, ACCEPT_IRQ);
 } 
 
+DECLARE_MUTEX(ports_sem);
+struct list_head ports = LIST_HEAD_INIT(ports);
+
 void *port_data(int port_num)
 {
        struct list_head *ele;
@@ -114,6 +115,7 @@ void *port_data(int port_num)
        struct port_dev *dev;
        int fd;
 
+       down(&ports_sem);
        list_for_each(ele, &ports){
                port = list_entry(ele, struct port_list, list);
                if(port->port == port_num) goto found;
@@ -121,7 +123,7 @@ void *port_data(int port_num)
        port = kmalloc(sizeof(struct port_list), GFP_KERNEL);
        if(port == NULL){
                printk(KERN_ERR "Allocation of port list failed\n");
-               return(NULL);
+               goto out;
        }
 
        fd = port_listen_fd(port_num);
@@ -151,18 +153,21 @@ void *port_data(int port_num)
        dev = kmalloc(sizeof(struct port_dev), GFP_KERNEL);
        if(dev == NULL){
                printk(KERN_ERR "Allocation of port device entry failed\n");
-               return(NULL);
+               goto out;
        }
 
        *dev = ((struct port_dev) { port :              port,
                                    fd :                -1,
                                    helper_pid :        -1 });
+       up(&ports_sem);
        return(dev);
 
  out_free:
        kfree(port);
  out_close:
        os_close_file(fd);
+ out:
+       up(&ports_sem);
        return(NULL);
 }
 
index 5d52974e3726516f911ac0ab7a9ad9db2f9b4dcb..fce548deafea56ef587224812dbca4c5390e72b7 100644 (file)
@@ -58,7 +58,10 @@ static struct line_driver driver = {
        symlink_to :            "tts",
 };
 
-static struct line serial_lines[NR_PORTS] = 
+/* The array is initialized by line_init, which is an initcall.  The 
+ * individual elements are protected by individual semaphores.
+ */
+static struct line serial_lines[NR_PORTS] =
        { [0 ... NR_PORTS - 1] = LINE_INIT(CONFIG_SSL_CHAN, &driver) };
 
 static struct lines lines = LINES_INIT(NR_PORTS);
index 3ef550107a93dbda63ebd2b47a28c326beaf301d..979793f47d96d6b1aaa8930ae7ec1a2cf8b794c3 100644 (file)
 
 #define MAX_TTYS (8)
 
+/* Referenced only by tty_driver below - presumably it's locked correctly
+ * by the tty driver.
+ */
+
 static struct tty_driver console_driver;
 
+static int console_refcount = 0;
+
 static struct chan_ops init_console_ops = {
        init :          NULL,
        open :          NULL,
@@ -88,6 +94,9 @@ static struct line_driver driver = {
 
 static struct lines console_lines = LINES_INIT(MAX_TTYS);
 
+/* The array is initialized by line_init, which is an initcall.  The 
+ * individual elements are protected by individual semaphores.
+ */
 struct line vts[MAX_TTYS] = { LINE_INIT(CONFIG_CON_ZERO_CHAN, &driver),
                              [ 1 ... MAX_TTYS - 1 ] = 
                              LINE_INIT(CONFIG_CON_CHAN, &driver) };
index 36995c3f84f6b5535632d5a82689fd3497e1b2ad..6777b7e970030802d9ada25b3a5bb72c0879aefa 100644 (file)
@@ -25,6 +25,7 @@
 #include "linux/vmalloc.h"
 #include "linux/blkpg.h"
 #include "linux/genhd.h"
+#include "linux/spinlock.h"
 #include "asm/segment.h"
 #include "asm/uaccess.h"
 #include "asm/irq.h"
@@ -41,7 +42,9 @@
 #include "2_5compat.h"
 #include "os.h"
 
-static spinlock_t ubd_lock;
+static spinlock_t ubd_io_lock = SPIN_LOCK_UNLOCKED;
+static spinlock_t ubd_lock = SPIN_LOCK_UNLOCKED;
+
 static void (*do_ubd)(void);
 
 static int ubd_open(struct inode * inode, struct file * filp);
@@ -62,9 +65,12 @@ static struct block_device_operations ubd_blops = {
         .revalidate =  ubd_revalidate,
 };
 
+/* Protected by the queue_lock */
 static request_queue_t *ubd_queue;
 
+/* Protected by ubd_lock */
 static int fake_major = 0;
+
 static struct gendisk *ubd_gendisk[MAX_DEV];
 static struct gendisk *fake_gendisk[MAX_DEV];
  
@@ -74,6 +80,9 @@ static struct gendisk *fake_gendisk[MAX_DEV];
 #define OPEN_FLAGS ((struct openflags) { .r = 1, .w = 1, .s = 0, .c = 0 })
 #endif
 
+/* Not protected - changed only in ubd_setup_common and then only to
+ * to enable O_SYNC.
+ */
 static struct openflags global_openflags = OPEN_FLAGS;
 
 struct cow {
@@ -170,7 +179,9 @@ static void make_ide_entries(char *dev_name)
        char name[64];
 
        if(!fake_ide) return;
+
        if(proc_ide_root == NULL) make_proc_ide();
+
        dir = proc_mkdir(dev_name, proc_ide);
        ent = create_proc_entry("media", S_IFREG|S_IRUGO, dir);
        if(!ent) return;
@@ -199,7 +210,7 @@ static int ubd_setup_common(char *str, int *index_out)
 {
        struct openflags flags = global_openflags;
        char *backing_file;
-       int n;
+       int n, err;
 
        if(index_out) *index_out = -1;
        n = *str++;
@@ -224,12 +235,22 @@ static int ubd_setup_common(char *str, int *index_out)
                        return(1);
                }
 
-               fake_major = major;
+               err = 1;
+               spin_lock(&ubd_lock);
+               if(!fake_major_allowed){
+                       printk(KERN_ERR "Can't assign a fake major twice\n");
+                       goto out1;
+               }
+               fake_major = major;
                fake_major_allowed = 0;
 
                printk(KERN_INFO "Setting extra ubd major number to %d\n",
                       major);
-               return(0);
+               err = 0;
+       out1:
+               spin_unlock(&ubd_lock);
+               return(err);
        }
 
        if(n < '0'){
@@ -247,9 +268,12 @@ static int ubd_setup_common(char *str, int *index_out)
                return(1);
        }
 
+       err = 1;
+       spin_lock(&ubd_lock);
+
        if(ubd_dev[n].file != NULL){
                printk(KERN_ERR "ubd_setup : device already configured\n");
-               return(1);
+               goto out2;
        }
 
        if(index_out) *index_out = n;
@@ -264,8 +288,10 @@ static int ubd_setup_common(char *str, int *index_out)
        }
        if(*str++ != '='){
                printk(KERN_ERR "ubd_setup : Expected '='\n");
-               return(1);
+               goto out2;
        }
+
+       err = 0;
        backing_file = strchr(str, ',');
        if(backing_file){
                *backing_file = '\0';
@@ -276,7 +302,9 @@ static int ubd_setup_common(char *str, int *index_out)
                ubd_dev[n].is_dir = 1;
        ubd_dev[n].cow.file = backing_file;
        ubd_dev[n].boot_openflags = flags;
-       return(0);
+ out2:
+       spin_unlock(&ubd_lock);
+       return(err);
 }
 
 static int ubd_setup(char *str)
@@ -317,8 +345,12 @@ __uml_help(fakehd,
 
 static void do_ubd_request(request_queue_t * q);
 
+/* Only changed by ubd_init, which is an initcall. */
 int thread_fd = -1;
 
+/* Changed by ubd_handler, which is serialized because interrupts only
+ * happen on CPU 0.
+ */
 int intr_count = 0;
 
 static void ubd_finish(int error)
@@ -326,7 +358,9 @@ static void ubd_finish(int error)
        int nsect;
 
        if(error){
+               spin_lock(&ubd_io_lock);
                end_request(CURRENT, 0);
+               spin_unlock(&ubd_io_lock);
                return;
        }
        nsect = CURRENT->current_nr_sectors;
@@ -335,7 +369,9 @@ static void ubd_finish(int error)
        CURRENT->errors = 0;
        CURRENT->nr_sectors -= nsect;
        CURRENT->current_nr_sectors = 0;
+       spin_lock(&ubd_io_lock);
        end_request(CURRENT, 1);
+       spin_unlock(&ubd_io_lock);
 }
 
 static void ubd_handler(void)
@@ -349,9 +385,9 @@ static void ubd_handler(void)
        if(n != sizeof(req)){
                printk(KERN_ERR "Pid %d - spurious interrupt in ubd_handler, "
                       "errno = %d\n", os_getpid(), -n);
-               spin_lock(&ubd_lock);
+               spin_lock(&ubd_io_lock);
                end_request(CURRENT, 0);
-               spin_unlock(&ubd_lock);
+               spin_unlock(&ubd_io_lock);
                return;
        }
         
@@ -359,11 +395,9 @@ static void ubd_handler(void)
           (req.length != (CURRENT->current_nr_sectors) << 9))
                panic("I/O op mismatch");
        
-       spin_lock(&ubd_lock);
        ubd_finish(req.error);
        reactivate_fd(thread_fd, UBD_IRQ);      
        do_ubd_request(ubd_queue);
-       spin_unlock(&ubd_lock);
 }
 
 static void ubd_intr(int irq, void *dev, struct pt_regs *unused)
@@ -371,6 +405,7 @@ static void ubd_intr(int irq, void *dev, struct pt_regs *unused)
        ubd_handler();
 }
 
+/* Only changed by ubd_init, which is an initcall. */
 static int io_pid = -1;
 
 void kill_io_thread(void)
@@ -390,6 +425,7 @@ static int ubd_file_size(struct ubd *dev, __u64 *size_out)
        return(os_file_size(file, size_out));
 }
 
+/* Initialized in an initcall, and unchanged thereafter */
 devfs_handle_t ubd_dir_handle;
 devfs_handle_t ubd_fake_dir_handle;
 
@@ -402,7 +438,7 @@ static int ubd_add(int n)
        u64 size;
 
        if (!dev->file)
-               return -1;
+               goto out;
 
        disk = alloc_disk();
        if (!disk)
@@ -443,23 +479,32 @@ static int ubd_add(int n)
                              MAJOR_NR, n << UBD_SHIFT,
                              S_IFBLK | S_IRUSR | S_IWUSR | S_IRGRP |S_IWGRP,
                              &ubd_blops, NULL);
-       add_disk(disk);
+       if(real == NULL) 
+               goto out;
+       ubd_dev[n].real = real;
+
        if (fake_major) {
                fake = devfs_register(ubd_fake_dir_handle, name, 
                                      DEVFS_FL_REMOVABLE, fake_major,
                                      n << UBD_SHIFT, 
                                      S_IFBLK | S_IRUSR | S_IWUSR | S_IRGRP |
                                      S_IWGRP, &ubd_blops, NULL);
-               add_disk(fake_disk);
-               if(fake == NULL) return(-1);
+               if(fake == NULL)
+                       goto out_unregister;
+
                ubd_dev[n].fake = fake;
+               add_disk(fake_disk);
        }
  
-       if(real == NULL) return(-1);
-       ubd_dev[n].real = real;
+       add_disk(disk);
        make_ide_entries(disk->disk_name);
        return(0);
+
+ out_unregister:
+       devfs_unregister(real);
+       ubd_dev[n].real = NULL;
+ out:
+       return(-1);
 }
 
 static int ubd_config(char *str)
@@ -478,24 +523,29 @@ static int ubd_config(char *str)
        }
        if(n == -1) return(0);
 
+       spin_lock(&ubd_lock);
        err = ubd_add(n);
-       if(err){
+       if(err)
                ubd_dev[n].file = NULL;
-               return(err);
-       }
+       spin_unlock(&ubd_lock);
 
-       return(0);
+       return(err);
 }
 
 static int ubd_remove(char *str)
 {
        struct ubd *dev;
-       int n;
+       int n, err;
 
-       if(!isdigit(*str)) return(-1);
+       if(!isdigit(*str)) 
+               return(-1);
        n = *str - '0';
-       if(n > MAX_DEV) return(-1);
+       if(n > MAX_DEV) 
+               return(-1);
        dev = &ubd_dev[n];
+
+       err = 0;
+       spin_lock(&ubd_lock);
        del_gendisk(ubd_gendisk[n]);
        put_disk(ubd_gendisk[n]);
        ubd_gendisk[n] = NULL;
@@ -504,12 +554,20 @@ static int ubd_remove(char *str)
                put_disk(fake_gendisk[n]);
                fake_gendisk[n] = NULL;
        }
-       if(dev->file == NULL) return(0);
-       if(dev->count > 0) return(-1);
-       if(dev->real != NULL) devfs_unregister(dev->real);
-       if(dev->fake != NULL) devfs_unregister(dev->fake);
+       if(dev->file == NULL)
+               goto out;
+       err = -1;
+       if(dev->count > 0)
+               goto out;
+       if(dev->real != NULL) 
+               devfs_unregister(dev->real);
+       if(dev->fake != NULL) 
+               devfs_unregister(dev->fake);
        *dev = ((struct ubd) DEFAULT_UBD);
-       return(0);
+       err = 0;
+ out:
+       spin_unlock(&ubd_lock);
+       return(err);
 }
 
 static struct mc_device ubd_mc = {
@@ -541,7 +599,7 @@ int ubd_init(void)
                return -1;
        }
        ubd_queue = BLK_DEFAULT_QUEUE(MAJOR_NR);
-       INIT_QUEUE(ubd_queue, do_ubd_request, &ubd_lock);
+       blk_init_queue(ubd_queue, do_ubd_request, &ubd_io_lock);
        elevator_init(ubd_queue, &elevator_noop);
        if(fake_major != 0){
                char name[sizeof("ubd_nnn\0")];
@@ -644,22 +702,23 @@ static int ubd_open_dev(struct ubd *dev)
        }
        return(0);
  error:
-       close_fd(dev->fd);
+       os_close_file(dev->fd);
        return(err);
 }
 
 static int ubd_open(struct inode *inode, struct file *filp)
 {
        struct ubd *dev;
-       int n, offset, err;
+       int n, offset, err = 0;
 
        n = DEVICE_NR(inode->i_rdev);
        dev = &ubd_dev[n];
        if(n > MAX_DEV)
                return -ENODEV;
+
        offset = n << UBD_SHIFT;
        if(dev->is_dir == 1)
-               return(0);
+               goto out;
 
        if(dev->count == 0){
                dev->openflags = dev->boot_openflags;
@@ -668,16 +727,16 @@ static int ubd_open(struct inode *inode, struct file *filp)
                if(err){
                        printk(KERN_ERR "ubd%d: Can't open \"%s\": "
                               "errno = %d\n", n, dev->file, -err);
-                       return(err);
+                       goto out;
                }
-               if(err) return(err);
        }
        dev->count++;
        if((filp->f_mode & FMODE_WRITE) && !dev->openflags.w){
                if(--dev->count == 0) ubd_close(dev);
-               return -EROFS;
+               err = -EROFS;
        }
-       return(0);
+ out:
+       return(err);
 }
 
 static int ubd_release(struct inode * inode, struct file * file)
@@ -752,13 +811,17 @@ static int prepare_request(struct request *req, struct io_thread_req *io_req)
        if(dev->is_dir){
                strcpy(req->buffer, "HOSTFS:");
                strcat(req->buffer, dev->file);
+               spin_lock(&ubd_io_lock);
                end_request(req, 1);
+               spin_unlock(&ubd_io_lock);
                return(1);
        }
 
        if((rq_data_dir(req) == WRITE) && !dev->openflags.w){
                printk("Write attempted on readonly ubd device %d\n", n);
+               spin_lock(&ubd_io_lock);
                end_request(req, 0);
+               spin_unlock(&ubd_io_lock);
                return(1);
        }
 
@@ -892,8 +955,11 @@ static int ubd_revalidate(kdev_t rdev)
 
        n = minor(rdev) >> UBD_SHIFT;
        dev = &ubd_dev[n];
+
+       err = 0;
+       spin_lock(&ubd_lock);
        if(dev->is_dir) 
-               return(0);
+               goto out;
        
        err = ubd_file_size(dev, &size);
        if (!err) {
@@ -902,7 +968,8 @@ static int ubd_revalidate(kdev_t rdev)
                        set_capacity(fake_gendisk[n], size / 512);
                dev->size = size;
        }
-
+       spin_unlock(&ubd_lock);
+ out:
        return err;
 }
 
index 59eb46ff73a280aaf9ec6fa3c48df407598f902c..8a4b6f52888c962e48cae0b8b044129d458066a5 100644 (file)
@@ -533,8 +533,12 @@ void do_io(struct io_thread_req *req)
        return;
 }
 
+/* Changed in start_io_thread, which is serialized by being called only
+ * from ubd_init, which is an initcall.
+ */
 int kernel_fd = -1;
 
+/* Only changed by the io thread */
 int io_count = 0;
 
 int io_thread(void *arg)
index 9f4a6296fe66b307b017acee844f44054c125aeb..d3f69887f3c20714a5f8f5bcfd6802cbf5c08cb2 100644 (file)
@@ -44,6 +44,7 @@ void *xterm_init(char *str, int device, struct chan_opts *opts)
        return(data);
 }
 
+/* Only changed by xterm_setup, which is a setup */
 static char *terminal_emulator = "xterm";
 static char *title_switch = "-T";
 static char *exec_switch = "-e";
index 3802d4fafb480023e1e1b1be9285a8219e9cbad5..6d36d9c30b911a81ae49866b34c3c28e303cb861 100644 (file)
@@ -20,8 +20,6 @@
        next :          NULL \
 }
 
-#define INIT_QUEUE(queue, request, lock) blk_init_queue(queue, request, lock)
-
 #define INIT_HARDSECT(arr, maj, sizes)
 
 #define SET_PRI(task) do ; while(0)
index 4852f2c3613e8c4a3a16d6cfad7cd6f60beaa4f0..52bed51752292a933ed5744f33742f5293b56c15 100644 (file)
@@ -18,7 +18,9 @@ extern void forward_interrupts(int pid);
 extern void init_irq_signals(int on_sigstack);
 extern void forward_ipi(int fd, int pid);
 extern void free_irq_later(int irq, void *dev_id);
-
+extern int activate_ipi(int fd, int pid);
+extern unsigned long irq_lock(void);
+extern void irq_unlock(unsigned long flags);
 #endif
 
 /*
index 07511e1e7e6e17360286e33f911b37530247188b..34e107d545da589f9d6a8354fbe2bf57fbd7daef 100644 (file)
@@ -50,12 +50,8 @@ extern int pid_to_processor_id(int pid);
 extern void block_signals(void);
 extern void unblock_signals(void);
 extern void deliver_signals(void *t);
-extern void lock_syscall(void);
-extern void unlock_syscall(void);
-extern void lock_trap(void);
-extern void unlock_trap(void);
-extern void lock_pid(void);
-extern void unlock_pid(void);
+extern int next_syscall_index(int max);
+extern int next_trap_index(int max);
 extern void default_idle(void);
 extern void finish_fork(void);
 extern void paging_init(void);
@@ -121,7 +117,7 @@ extern void arch_switch(void);
 extern int is_valid_pid(int pid);
 extern void free_irq(unsigned int, void *);
 extern int um_in_interrupt(void);
-
+extern int cpu(void);
 #endif
 
 /*
index 192aab5b8e79f373661648533683e87b479e1a89..8f82ef7201ea34f6898316de42164e2f5273c49c 100644 (file)
@@ -77,6 +77,8 @@ extern int mconsole_get_request(int fd, struct mc_request *req);
 extern int mconsole_notify(char *sock_name, int type, const void *data, 
                           int len);
 extern char *mconsole_notify_socket(void);
+extern void lock_notify(void);
+extern void unlock_notify(void);
 
 #endif
 
index 23aef0140b7b32742b13356523f6a67713394f4b..37d76e29a147f30bff4ecd56d197997d218b7ce8 100644 (file)
@@ -11,6 +11,8 @@ extern int register_sigio_fd(int fd);
 extern int read_sigio_fd(int fd);
 extern int add_sigio_fd(int fd, int read);
 extern int ignore_sigio_fd(int fd);
+extern void sigio_lock(void);
+extern void sigio_unlock(void);
 
 #endif
 
index d68caf278f05328ab20f961f48f10c11b0cbb9f4..d49a34f0bee81e2f071078cd287e16c2bfe4506a 100644 (file)
@@ -7,11 +7,11 @@
 #define __TIME_USER_H__
 
 extern void timer(void);
-extern void get_profile_timer(void);
-extern void disable_profile_timer(void);
 extern void switch_timers(int to_real);
 extern void user_time_init(void);
-extern void set_timers(int set_signal);
 extern void idle_sleep(int secs);
+extern void enable_timer(void);
+extern void time_lock(void);
+extern void time_unlock(void);
 
 #endif
index 34a2e527a3f8f58a9af8b8760c11d6a2be71b395..353bfa4da610aaf9817441dcae78372cc71e8df1 100644 (file)
@@ -17,6 +17,7 @@
 #include "tlb.h"
 #include "2_5compat.h"
 #include "os.h"
+#include "time_user.h"
 
 /* See comment above fork_tramp for why sigstop is defined and used like
  * this
@@ -28,7 +29,6 @@ static int exec_tramp(void *sig_stack)
 {
        int sig = sigstop;
 
-       block_signals();
        init_new_thread(sig_stack, NULL);
        kill(os_getpid(), sig);
        return(0);
@@ -62,6 +62,7 @@ void flush_thread(void)
        unprotect_stack((unsigned long) current->thread_info);
        os_usr1_process(os_getpid());
 
+       enable_timer();
        free_page(stack);
        protect(uml_reserved, high_physmem - uml_reserved, 1, 1, 0, 1);
        task_protections((unsigned long) current->thread_info);
index 6c5c30e9c380242d7e5fc269ba16b4b136e9414b..788f914d85101010ee525add4da93d65d7b5071d 100644 (file)
@@ -8,6 +8,9 @@
 #include "linux/proc_fs.h"
 #include "asm/uaccess.h"
 
+/* If read and write race, the read will still atomically read a valid
+ * value.
+ */
 int uml_exitcode = 0;
 
 static int read_proc_exitcode(char *page, char **start, off_t off,
index a5d77c0ee15d21f90948e23751de9b4dc7093e91..28793041426a710e966a3f256fbfbe5ff048d2e3 100644 (file)
@@ -130,6 +130,7 @@ static void child_common(void *sp, int size, sighandler_t handler, int flags)
        os_stop_process(os_getpid());
 }
 
+/* Changed only during early boot */
 struct sc_frame signal_frame_sc;
 
 struct sc_frame_raw {
@@ -142,6 +143,7 @@ struct sc_frame_raw {
        struct arch_frame_data_raw arch;
 };
 
+/* Changed only during early boot */
 static struct sc_frame_raw *raw_sc = NULL;
 
 static void sc_handler(int sig, struct sigcontext sc)
@@ -163,6 +165,7 @@ static int sc_child(void *arg)
        return(-1);
 }
 
+/* Changed only during early boot */
 struct si_frame signal_frame_si;
 
 struct si_frame_raw {
@@ -175,6 +178,7 @@ struct si_frame_raw {
        unsigned long sp;
 };
 
+/* Changed only during early boot */
 static struct si_frame_raw *raw_si = NULL;
 
 static void si_handler(int sig, siginfo_t *si)
index 324e08974d33597795253aa83cb2be37cbd803a7..5d8fb7bba2b1eff019749f6d2065db3e0ad714b7 100644 (file)
@@ -22,6 +22,7 @@ struct helper_data {
        int fd;
 };
 
+/* Debugging aid, changed only from gdb */
 int helper_pause = 0;
 
 static void helper_hup(int sig)
index dc6cff88b7a621f78262751419d511825943eb2b..a8f7e70f1a179de14a023a0eda04c8f82c92048c 100644 (file)
@@ -13,6 +13,7 @@
 #include "init.h"
 #include "os.h"
 
+/* Changed by uml_initrd_setup, which is a setup */
 static char *initrd __initdata = NULL;
 
 static int __init read_initrd(void)
index 865ecec8d9050e9129588625a22bae35c419663d..56454f28f03b2fd7673d83095c8f5d4ff18508eb 100644 (file)
@@ -78,6 +78,7 @@ struct hw_interrupt_type no_irq_type = {
        end_none
 };
 
+/* Not changed */
 volatile unsigned long irq_err_count;
 
 /*
@@ -87,6 +88,7 @@ volatile unsigned long irq_err_count;
 int get_irq_list(char *buf)
 {
        int i, j;
+       unsigned long flags;
        struct irqaction * action;
        char *p = buf;
 
@@ -96,9 +98,10 @@ int get_irq_list(char *buf)
        *p++ = '\n';
 
        for (i = 0 ; i < NR_IRQS ; i++) {
+               spin_lock_irqsave(&irq_desc[i].lock, flags);
                action = irq_desc[i].action;
                if (!action) 
-                       continue;
+                       goto end;
                p += sprintf(p, "%3d: ",i);
 #ifndef CONFIG_SMP
                p += sprintf(p, "%10u ", kstat_irqs(i));
@@ -113,6 +116,8 @@ int get_irq_list(char *buf)
                for (action=action->next; action; action = action->next)
                        p += sprintf(p, ", %s", action->name);
                *p++ = '\n';
+       end:
+               spin_unlock_irqrestore(&irq_desc[i].lock, flags);
        }
        p += sprintf(p, "\n");
 #ifdef notdef
@@ -548,11 +553,15 @@ void free_irq(unsigned int irq, void *dev_id)
        }
 }
 
+/* These are initialized by sysctl_init, which is called from init/main.c */
 static struct proc_dir_entry * root_irq_dir;
 static struct proc_dir_entry * irq_dir [NR_IRQS];
 static struct proc_dir_entry * smp_affinity_entry [NR_IRQS];
 
-unsigned long irq_affinity [NR_IRQS] = { [0 ... NR_IRQS-1] = ~0UL };
+/* These are read and written as longs, so a read won't see a partial write
+ * even during a race.
+ */
+static unsigned long irq_affinity [NR_IRQS] = { [0 ... NR_IRQS-1] = ~0UL };
 
 #define HEX_DIGITS 8
 
@@ -679,6 +688,7 @@ static void register_irq_proc (unsigned int irq)
        smp_affinity_entry[irq] = entry;
 }
 
+/* Read and written as a long */
 unsigned long prof_cpu_mask = -1;
 
 void __init init_irq_proc (void)
@@ -704,6 +714,21 @@ void __init init_irq_proc (void)
                register_irq_proc(i);
 }
 
+static spinlock_t irq_spinlock = SPIN_LOCK_UNLOCKED;
+
+unsigned long irq_lock(void)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&irq_spinlock, flags);
+       return(flags);
+}
+
+void irq_unlock(unsigned long flags)
+{
+       spin_unlock_irqrestore(&irq_spinlock, flags);
+}
+
 unsigned long probe_irq_on(void)
 {
        return(0);
index 32099fc7603bf5ccbaa96d5e0c737ecf51f6812a..d1b66a0eb66f6630fc6da56f250cb065013892c3 100644 (file)
@@ -111,40 +111,20 @@ static void maybe_sigio_broken(int fd, int type)
 
 int activate_fd(int irq, int fd, int type, void *dev_id)
 {
-       struct irq_fd *new_fd;
-       int pid, retval, events, err;
+       struct pollfd *tmp_pfd;
+       struct irq_fd *new_fd, *irq_fd;
+       unsigned long flags;
+       int pid, events, err, n, size;
+
+       pid = os_getpid();
+       err = os_set_fd_async(fd, pid);
+       if(err < 0)
+               goto out;
 
-       for(new_fd = active_fds;new_fd;new_fd = new_fd->next){
-               if((new_fd->fd == fd) && (new_fd->type == type)){
-                       printk("Registering fd %d twice\n", fd);
-                       printk("Irqs : %d, %d\n", new_fd->irq, irq);
-                       printk("Ids : 0x%x, 0x%x\n", new_fd->id, dev_id);
-                       return(-EIO);
-               }
-       }
-       pid = cpu_tasks[0].pid;
-       if((retval = os_set_fd_async(fd, pid)) != 0)
-               return(retval);
        new_fd = um_kmalloc(sizeof(*new_fd));
        err = -ENOMEM;
-       if(new_fd == NULL) return(err);
-       pollfds_num++;
-       if(pollfds_num > pollfds_size){
-               struct pollfd *tmp_pfd;
-
-               tmp_pfd = um_kmalloc(pollfds_num * sizeof(pollfds[0]));
-               if(tmp_pfd == NULL){
-                       pollfds_num--;
-                       goto out_irq;
-               }
-               if(pollfds != NULL){
-                       memcpy(tmp_pfd, pollfds,
-                              sizeof(pollfds[0]) * pollfds_size);
-                       kfree(pollfds);
-               }
-               pollfds = tmp_pfd;
-               pollfds_size = pollfds_num;
-       }
+       if(new_fd == NULL)
+               goto out;
 
        if(type == IRQ_READ) events = POLLIN | POLLPRI;
        else events = POLLOUT;
@@ -158,29 +138,90 @@ int activate_fd(int irq, int fd, int type, void *dev_id)
                                     current_events:    0,
                                     freed :            0  } );
 
-       *last_irq_ptr = new_fd;
-       last_irq_ptr = &new_fd->next;
+       /* Critical section - locked by a spinlock because this stuff can
+        * be changed from interrupt handlers.  The stuff above is done 
+        * outside the lock because it allocates memory.
+        */
+
+       /* Actually, it only looks like it can be called from interrupt
+        * context.  The culprit is reactivate_fd, which calls 
+        * maybe_sigio_broken, which calls write_sigio_workaround,
+        * which calls activate_fd.  However, write_sigio_workaround should
+        * only be called once, at boot time.  That would make it clear that
+        * this is called only from process context, and can be locked with
+        * a semaphore.
+        */
+       flags = irq_lock();
+       for(irq_fd = active_fds; irq_fd != NULL; irq_fd = irq_fd->next){
+               if((irq_fd->fd == fd) && (irq_fd->type == type)){
+                       printk("Registering fd %d twice\n", fd);
+                       printk("Irqs : %d, %d\n", irq_fd->irq, irq);
+                       printk("Ids : 0x%x, 0x%x\n", irq_fd->id, dev_id);
+                       goto out_free;
+               }
+       }
+
+       n = pollfds_num;
+       if(n == pollfds_size){
+               while(1){
+                       /* Here we have to drop the lock in order to call 
+                        * kmalloc, which might sleep.  If something else
+                        * came in and changed the pollfds array, we free
+                        * the buffer and try again.
+                        */
+                       irq_unlock(flags);
+                       size = (pollfds_num + 1) * sizeof(pollfds[0]);
+                       tmp_pfd = um_kmalloc(size);
+                       flags = irq_lock();
+                       if(tmp_pfd == NULL)
+                               goto out_unlock;
+                       if(n == pollfds_size)
+                               break;
+                       kfree(tmp_pfd);
+               }
+               if(pollfds != NULL){
+                       memcpy(tmp_pfd, pollfds,
+                              sizeof(pollfds[0]) * pollfds_size);
+                       kfree(pollfds);
+               }
+               pollfds = tmp_pfd;
+               pollfds_size++;
+       }
 
        if(type == IRQ_WRITE) events = 0;
 
-       pollfds[pollfds_num - 1] = ((struct pollfd) { fd :      fd,
-                                                     events :  events,
-                                                     revents : 0 });
+       pollfds[pollfds_num] = ((struct pollfd) { fd :  fd,
+                                                 events :      events,
+                                                 revents :     0 });
+       pollfds_num++;
+
+       *last_irq_ptr = new_fd;
+       last_irq_ptr = &new_fd->next;
 
+       irq_unlock(flags);
+
+       /* This calls activate_fd, so it has to be outside the critical
+        * section.
+        */
        maybe_sigio_broken(fd, type);
 
        return(0);
 
- out_irq:
+ out_unlock:
+       irq_unlock(flags);
+ out_free:
        kfree(new_fd);
+ out:
        return(err);
 }
 
 static void free_irq_by_cb(int (*test)(struct irq_fd *, void *), void *arg)
 {
        struct irq_fd **prev;
+       unsigned long flags;
        int i = 0;
 
+       flags = irq_lock();
        prev = &active_fds;
        while(*prev != NULL){
                if((*test)(*prev, arg)){
@@ -190,7 +231,7 @@ static void free_irq_by_cb(int (*test)(struct irq_fd *, void *), void *arg)
                                printk("free_irq_by_cb - mismatch between "
                                       "active_fds and pollfds, fd %d vs %d\n",
                                       (*prev)->fd, pollfds[i].fd);
-                               return;
+                               goto out;
                        }
                        memcpy(&pollfds[i], &pollfds[i + 1],
                               (pollfds_num - i - 1) * sizeof(pollfds[0]));
@@ -206,6 +247,8 @@ static void free_irq_by_cb(int (*test)(struct irq_fd *, void *), void *arg)
                prev = &(*prev)->next;
                i++;
        }
+ out:
+       irq_unlock(flags);
 }
 
 struct irq_and_dev {
@@ -242,29 +285,33 @@ static struct irq_fd *find_irq_by_fd(int fd, int irqnum, int *index_out)
 {
        struct irq_fd *irq;
        int i = 0;
-       
+
        for(irq=active_fds; irq != NULL; irq = irq->next){
                if((irq->fd == fd) && (irq->irq == irqnum)) break;
                i++;
        }
        if(irq == NULL){
                printk("find_irq_by_fd doesn't have descriptor %d\n", fd);
-               return(NULL);
+               goto out;
        }
        if((pollfds[i].fd != -1) && (pollfds[i].fd != fd)){
                printk("find_irq_by_fd - mismatch between active_fds and "
                       "pollfds, fd %d vs %d, need %d\n", irq->fd, 
                       pollfds[i].fd, fd);
-               return(NULL);
+               irq = NULL;
+               goto out;
        }
        *index_out = i;
+ out:
        return(irq);
 }
 
 void free_irq_later(int irq, void *dev_id)
 {
        struct irq_fd *irq_fd;
+       unsigned long flags;
 
+       flags = irq_lock();
        for(irq_fd = active_fds; irq_fd != NULL; irq_fd = irq_fd->next){
                if((irq_fd->irq == irq) && (irq_fd->id == dev_id))
                        break;
@@ -272,30 +319,48 @@ void free_irq_later(int irq, void *dev_id)
        if(irq_fd == NULL){
                printk("free_irq_later found no irq, irq = %d, "
                       "dev_id = 0x%p\n", irq, dev_id);
-               return;
+               goto out;
        }
        irq_fd->freed = 1;
+ out:
+       irq_unlock(flags);
 }
 
 void reactivate_fd(int fd, int irqnum)
 {
        struct irq_fd *irq;
+       unsigned long flags;
        int i;
 
+       flags = irq_lock();
        irq = find_irq_by_fd(fd, irqnum, &i);
-       if(irq == NULL) return;
+       if(irq == NULL) 
+               goto out;
        pollfds[i].fd = irq->fd;
+
+       irq_unlock(flags);
+
+       /* This calls activate_fd, so it has to be outside the critical
+        * section.
+        */
        maybe_sigio_broken(fd, irq->type);
+ out:
+       irq_unlock(flags);
 }
 
 void deactivate_fd(int fd, int irqnum)
 {
        struct irq_fd *irq;
+       unsigned long flags;
        int i;
 
+       flags = irq_lock();
        irq = find_irq_by_fd(fd, irqnum, &i);
-       if(irq == NULL) return;
+       if(irq == NULL)
+               goto out;
        pollfds[i].fd = -1;
+ out:
+       irq_unlock(flags);
 }
 
 void forward_ipi(int fd, int pid)
@@ -313,7 +378,9 @@ void forward_ipi(int fd, int pid)
 void forward_interrupts(int pid)
 {
        struct irq_fd *irq;
+       unsigned long flags;
 
+       flags = irq_lock();
        for(irq=active_fds;irq != NULL;irq = irq->next){
                if(fcntl(irq->fd, F_SETOWN, pid) < 0){
                        int save_errno = errno;
@@ -328,6 +395,7 @@ void forward_interrupts(int pid)
                }
                irq->pid = pid;
        }
+       irq_unlock(flags);
 }
 
 void init_irq_signals(int on_sigstack)
@@ -339,10 +407,10 @@ void init_irq_signals(int on_sigstack)
        if(timer_irq_inited) h = (__sighandler_t) alarm_handler;
        else h = boot_timer_handler;
 
-       set_handler(SIGVTALRM, h, flags | SA_NODEFER | SA_RESTART, 
-                   SIGUSR1, SIGIO, SIGWINCH, -1);
+       set_handler(SIGVTALRM, h, flags | SA_RESTART, 
+                   SIGUSR1, SIGIO, SIGWINCH, SIGALRM, -1);
        set_handler(SIGIO, (__sighandler_t) sig_handler, flags | SA_RESTART,
-                   SIGUSR1, SIGIO, SIGWINCH, -1);
+                   SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1);
        signal(SIGWINCH, SIG_IGN);
 }
 
index da7f4b318255f7b55631ce300d3f192485e1d270..5a582a8de7d1b2e1ff36912bfdbac9f29c4c47f9 100644 (file)
 #include "kern.h"
 #include "init.h"
 
+/* Changed during early boot */
+pgd_t swapper_pg_dir[1024];
 unsigned long high_physmem;
-unsigned long low_physmem;
-
 unsigned long vm_start;
 unsigned long vm_end;
-
 unsigned long highmem;
-
-pgd_t swapper_pg_dir[1024];
-
 unsigned long *empty_zero_page = NULL;
-
 unsigned long *empty_bad_page = NULL;
 
+/* Not modified */
 const char bad_pmd_string[] = "Bad pmd in pte_alloc: %08lx\n";
 
 extern char __init_begin, __init_end;
 extern long physmem_size;
 
+/* Not changed by UML */
 mmu_gather_t mmu_gathers[NR_CPUS];
 
+/* Changed during early boot */
 int kmalloc_ok = 0;
 
 #define NREGIONS (phys_region_index(0xffffffff) - phys_region_index(0x0) + 1)
 struct mem_region *regions[NREGIONS] = { [ 0 ... NREGIONS - 1 ] = NULL };
 #define REGION_SIZE ((0xffffffff & ~REGION_MASK) + 1)
 
+/* Changed during early boot */
 static unsigned long brk_end;
 
 static void map_cb(void *unused)
@@ -108,6 +107,7 @@ void mem_init(void)
 }
 
 #if CONFIG_HIGHMEM
+/* Changed during early boot */
 pte_t *kmap_pte;
 pgprot_t kmap_prot;
 
@@ -187,18 +187,22 @@ int init_maps(struct mem_region *region)
        return(0);
 }
 
+DECLARE_MUTEX(regions_sem);
+
 static int setup_one_range(int fd, char *driver, unsigned long start, 
                           unsigned long pfn, int len, 
                           struct mem_region *region)
 {
        int i;
 
+       down(&regions_sem);
        for(i = 0; i < NREGIONS; i++){
                if(regions[i] == NULL) break;           
        }
        if(i == NREGIONS){
                printk("setup_range : no free regions\n");
-               return(-1);
+               i = -1;
+               goto out;
        }
 
        if(fd == -1)
@@ -216,6 +220,8 @@ static int setup_one_range(int fd, char *driver, unsigned long start,
                                         len :          len, 
                                         fd :           fd } );
        regions[i] = region;
+ out:
+       up(&regions_sem);
        return(i);
 }
 
@@ -373,7 +379,8 @@ void show_mem(void)
         printk("%d pages swap cached\n", cached);
 }
 
-unsigned long kmem_top = 0;
+/* Changed during early boot */
+static unsigned long kmem_top = 0;
 
 unsigned long get_kmem_end(void)
 {
@@ -428,8 +435,10 @@ struct page *arch_validate(struct page *page, int mask, int order)
        goto again;
 }
 
+DECLARE_MUTEX(vm_reserved_sem);
 static struct list_head vm_reserved = LIST_HEAD_INIT(vm_reserved);
 
+/* Static structures, linked in to the list in early boot */
 static struct vm_reserved head = {
        list :          LIST_HEAD_INIT(head.list),
        start :         0,
@@ -455,7 +464,9 @@ int reserve_vm(unsigned long start, unsigned long end, void *e)
 {
        struct vm_reserved *entry = e, *reserved, *prev;
        struct list_head *ele;
+       int err;
 
+       down(&vm_reserved_sem);
        list_for_each(ele, &vm_reserved){
                reserved = list_entry(ele, struct vm_reserved, list);
                if(reserved->start >= end) goto found;
@@ -469,13 +480,17 @@ int reserve_vm(unsigned long start, unsigned long end, void *e)
                entry = kmalloc(sizeof(*entry), GFP_KERNEL);
        if(entry == NULL){
                printk("reserve_vm : Failed to allocate entry\n");
-               return(-ENOMEM);
+               err = -ENOMEM;
+               goto out;
        }
        *entry = ((struct vm_reserved) 
                { list :        LIST_HEAD_INIT(entry->list),
                  start :       start,
                  end :         end });
        list_add(&entry->list, &prev->list);
+       err = 0;
+ out:
+       up(&vm_reserved_sem);
        return(0);
 }
 
@@ -486,6 +501,7 @@ unsigned long get_vm(unsigned long len)
        unsigned long start;
        int err;
        
+       down(&vm_reserved_sem);
        list_for_each(ele, &vm_reserved){
                this = list_entry(ele, struct vm_reserved, list);
                next = list_entry(ele->next, struct vm_reserved, list);
@@ -493,8 +509,10 @@ unsigned long get_vm(unsigned long len)
                   (this->end + len + PAGE_SIZE <= next->start))
                        goto found;
        }
+       up(&vm_reserved_sem);
        return(0);
  found:
+       up(&vm_reserved_sem);
        start = (unsigned long) ROUND_UP(this->end) + PAGE_SIZE;
        err = reserve_vm(start, start + len, NULL);
        if(err) return(0);
@@ -533,7 +551,11 @@ struct iomem {
        unsigned long size;
 };
 
-struct iomem iomem_regions[NREGIONS] = { [ 0 ... NREGIONS - 1 ] = 
+/* iomem regions can only be added on the command line at the moment.  
+ * Locking will be needed when they can be added via mconsole.
+ */
+
+struct iomem iomem_regions[NREGIONS] = { [ 0 ... NREGIONS - 1 ] =
                                         { name :       NULL,
                                           fd :         -1,
                                           size :       0 } };
@@ -569,6 +591,7 @@ __initcall(setup_iomem);
 #define PFN_UP(x)      (((x) + PAGE_SIZE-1) >> PAGE_SHIFT)
 #define PFN_DOWN(x)    ((x) >> PAGE_SHIFT)
 
+/* Changed during early boot */
 static struct mem_region physmem_region;
 static struct vm_reserved physmem_reserved;
 
index 8e036687f717423cfd1dfda5ed962bd888715482..af857510d17a54f1d68143cb7daca26a42ec74a8 100644 (file)
 #include "mem_user.h"
 #include "init.h"
 #include "os.h"
+#include "tempfile.h"
 
-struct mem_region physmem_region;
-
-struct mem_region *mem_list = &physmem_region;
+extern struct mem_region physmem_region;
 
 #define TEMPNAME_TEMPLATE "vm_file-XXXXXX"
 
index c3731bfd454784c238e874fb05aea8d6ddb6b287..d410aaa7332b9e3be20196101fb6008aff7cad71 100644 (file)
@@ -48,23 +48,23 @@ void init_new_thread(void *sig_stack, void (*usr1_handler)(int))
                flags = SA_ONSTACK;
        }
        set_handler(SIGSEGV, (__sighandler_t) sig_handler, flags,
-                   SIGUSR1, SIGIO, SIGWINCH, -1);
+                   SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1);
        set_handler(SIGTRAP, (__sighandler_t) sig_handler, flags, 
-                   SIGUSR1, SIGIO, SIGWINCH, -1);
+                   SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1);
        set_handler(SIGFPE, (__sighandler_t) sig_handler, flags, 
-                   SIGUSR1, SIGIO, SIGWINCH, -1);
+                   SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1);
        set_handler(SIGILL, (__sighandler_t) sig_handler, flags, 
-                   SIGUSR1, SIGIO, SIGWINCH, -1);
+                   SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1);
        set_handler(SIGBUS, (__sighandler_t) sig_handler, flags, 
-                   SIGUSR1, SIGIO, SIGWINCH, -1);
+                   SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1);
        set_handler(SIGWINCH, (__sighandler_t) sig_handler, flags, 
-                   SIGUSR1, SIGIO, SIGWINCH, -1);
+                   SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1);
        set_handler(SIGUSR2, (__sighandler_t) sig_handler, 
                    SA_NOMASK | flags, -1);
        if(usr1_handler) set_handler(SIGUSR1, usr1_handler, flags, -1);
        signal(SIGCHLD, SIG_IGN);
        signal(SIGHUP, SIG_IGN);
-       set_timers(1);  /* XXX A bit of a race here */
+
        init_irq_signals(sig_stack != NULL);
 }
 
index 8bd714887a3f04f81e03ec8ca0bd8910cc639a24..4e48f8ab3f8ab30ab604a8771d4a617eacc6a94c 100644 (file)
 #include "2_5compat.h"
 #include "os.h"
 
+/* This is a per-cpu array.  A processor only modifies its entry and it only
+ * cares about its entry, so it's OK if another processor is modifying its
+ * entry.
+ */
 struct cpu_task cpu_tasks[NR_CPUS] = { [0 ... NR_CPUS - 1] = { -1, NULL } };
 
 struct task_struct *get_task(int pid, int require)
@@ -86,7 +90,7 @@ int pid_to_processor_id(int pid)
 {
        int i;
 
-       for(i = 0; i < num_online_cpus(); i++){
+       for(i = 0; i < ncpus; i++){
                if(cpu_tasks[i].pid == pid) return(i);
        }
        return(-1);
@@ -152,12 +156,19 @@ static void new_thread_handler(int sig)
        current->thread.regs.regs.sc = (void *) (&sig + 1);
        suspend_new_thread(current->thread.switch_pipe[0]);
 
+       block_signals();
+#ifdef CONFIG_SMP
+       schedule_tail(NULL);
+#endif
+       enable_timer();
        free_page(current->thread.temp_stack);
        set_cmdline("(kernel thread)");
        force_flush_all();
 
        current->thread.prev_sched = NULL;
        change_sig(SIGUSR1, 1);
+       change_sig(SIGVTALRM, 1);
+       change_sig(SIGPROF, 1);
        unblock_signals();
        if(!run_kernel_thread(fn, arg, &current->thread.jmp))
                do_exit(0);
@@ -165,7 +176,9 @@ static void new_thread_handler(int sig)
 
 static int new_thread_proc(void *stack)
 {
-       block_signals();
+       change_sig(SIGIO, 0);
+       change_sig(SIGVTALRM, 0);
+       change_sig(SIGPROF, 0);
        init_new_thread(stack, new_thread_handler);
        os_usr1_process(os_getpid());
        return(0);
@@ -204,6 +217,9 @@ void *switch_to(void *prev, void *next, void *last)
        unsigned long flags;
        int vtalrm, alrm, prof, err, cpu;
        char c;
+       /* jailing and SMP are incompatible, so this doesn't need to be 
+        * made per-cpu 
+        */
        static int reading;
 
        from = prev;
@@ -298,13 +314,14 @@ void exit_thread(void)
  * onto the signal frame.
  */
 
-extern int hit_me;
-
 void finish_fork_handler(int sig)
 {
        current->thread.regs.regs.sc = (void *) (&sig + 1);
        suspend_new_thread(current->thread.switch_pipe[0]);
        
+       schedule_tail(NULL);
+       enable_timer();
+       change_sig(SIGVTALRM, 1);
        force_flush_all();
        if(current->mm != current->parent->mm)
                protect(uml_reserved, high_physmem - uml_reserved, 1, 1, 0, 1);
@@ -313,7 +330,6 @@ void finish_fork_handler(int sig)
        current->thread.prev_sched = NULL;
 
        free_page(current->thread.temp_stack);
-       block_signals();
        change_sig(SIGUSR1, 0);
        set_user_mode(current);
 }
@@ -339,7 +355,9 @@ int fork_tramp(void *stack)
 {
        int sig = sigusr1;
 
-       block_signals();
+       change_sig(SIGIO, 0);
+       change_sig(SIGVTALRM, 0);
+       change_sig(SIGPROF, 0);
        init_new_thread(stack, finish_fork_handler);
 
        kill(os_getpid(), sig);
@@ -474,7 +492,7 @@ int current_pid(void)
 
 void default_idle(void)
 {
-       if(current->thread_info->cpu == 0) idle_timer();
+       idle_timer();
 
        atomic_inc(&init_mm.mm_count);
        current->mm = &init_mm;
@@ -644,6 +662,7 @@ char *uml_strdup(char *string)
        return(new);
 }
 
+/* Changed by jail_setup, which is a setup */
 int jail = 0;
 
 int __init jail_setup(char *line, int *add)
@@ -708,17 +727,14 @@ static void mprotect_kernel_mem(int w)
        mprotect_kernel_vm(w);
 }
 
-int jail_timer_off = 0;
-
+/* No SMP problems since jailing and SMP are incompatible */
 void unprotect_kernel_mem(void)
 {
        mprotect_kernel_mem(1);
-       jail_timer_off = 0;
 }
 
 void protect_kernel_mem(void)
 {
-       jail_timer_off = 1;
        mprotect_kernel_mem(0);
 }
 
@@ -749,9 +765,11 @@ void set_thread_sc(void *sc)
 
 int smp_sigio_handler(void)
 {
+       int cpu = current->thread_info->cpu;
 #ifdef CONFIG_SMP
-       IPI_handler(hard_smp_processor_id());
-       if (hard_smp_processor_id() != 0) return(1);
+       IPI_handler(cpu);
+       if(cpu != 0)
+               return(1);
 #endif
        return(0);
 }
@@ -761,6 +779,11 @@ int um_in_interrupt(void)
        return(in_interrupt());
 }
 
+int cpu(void)
+{
+       return(current->thread_info->cpu);
+}
+
 /*
  * Overrides for Emacs so that we follow Linus's tabbing style.
  * Emacs will notice this stuff at the end of the file and automatically
index fc37b78b4009b991ab3d695b496f47130d6666cf..02272e6236147bc26dccc0c70f0ed173b37bbc20 100644 (file)
@@ -11,6 +11,7 @@
 #include "sigio.h"
 #include "irq_user.h"
 
+/* Protected by sigio_lock() called from write_sigio_workaround */
 static int sigio_irq_fd = -1;
 
 void sigio_interrupt(int irq, void *data, struct pt_regs *unused)
@@ -31,6 +32,18 @@ int write_sigio_irq(int fd)
        return(0);
 }
 
+static spinlock_t sigio_spinlock = SPIN_LOCK_UNLOCKED;
+
+void sigio_lock(void)
+{
+       spin_lock(&sigio_spinlock);
+}
+
+void sigio_unlock(void)
+{
+       spin_unlock(&sigio_spinlock);
+}
+
 /*
  * Overrides for Emacs so that we follow Linus's tabbing style.
  * Emacs will notice this stuff at the end of the file and automatically
index fd3b70704621588026151cd6ab3927704a86342e..740608075b7c01190478fadb7769c696782943e4 100644 (file)
 #include "helper.h"
 #include "os.h"
 
+/* Changed during early boot */
 int pty_output_sigio = 0;
 int pty_close_sigio = 0;
 
+/* Used as a flag during SIGIO testing early in boot */
 static int got_sigio = 0;
 
 void __init handler(int sig)
@@ -151,7 +153,15 @@ void __init check_sigio(void)
        check_one_sigio(tty_close);
 }
 
+/* Protected by sigio_lock(), also used by sigio_cleanup, which is an 
+ * exitcall.
+ */
 static int write_sigio_pid = -1;
+
+/* These arrays are initialized before the sigio thread is started, and
+ * the descriptors closed after it is killed.  So, it can't see them change.
+ * On the UML side, they are changed under the sigio_lock.
+ */
 static int write_sigio_fds[2] = { -1, -1 };
 static int sigio_private[2] = { -1, -1 };
 
@@ -161,6 +171,9 @@ struct pollfds {
        int used;
 };
 
+/* Protected by sigio_lock().  Used by the sigio thread, but the UML thread
+ * synchronizes with it.
+ */
 struct pollfds current_poll = {
        poll :          NULL,
        size :          0,
@@ -217,8 +230,6 @@ static int write_sigio_thread(void *unused)
        }
 }
 
-/* XXX SMP locking needed here too */
-
 static int need_poll(int n)
 {
        if(n <= next_poll.size){
@@ -260,25 +271,31 @@ static void update_thread(void)
        set_signals(flags);
        return;
  fail:
+       sigio_lock();
        if(write_sigio_pid != -1) kill(write_sigio_pid, SIGKILL);
        write_sigio_pid = -1;
        close(sigio_private[0]);
        close(sigio_private[1]);        
        close(write_sigio_fds[0]);
        close(write_sigio_fds[1]);
+       sigio_unlock();
        set_signals(flags);
 }
 
 int add_sigio_fd(int fd, int read)
 {
-       int err, i, n, events;
+       int err = 0, i, n, events;
 
-       for(i = 0; i < current_poll.used; i++)
-               if(current_poll.poll[i].fd == fd) return(0);
+       sigio_lock();
+       for(i = 0; i < current_poll.used; i++){
+               if(current_poll.poll[i].fd == fd) 
+                       goto out;
+       }
 
        n = current_poll.used + 1;
        err = need_poll(n);
-       if(err) return(err);
+       if(err) 
+               goto out;
 
        for(i = 0; i < current_poll.used; i++)
                next_poll.poll[i] = current_poll.poll[i];
@@ -290,21 +307,26 @@ int add_sigio_fd(int fd, int read)
                                                   events :     events,
                                                   revents :    0 });
        update_thread();
-       return(0);
+ out:
+       sigio_unlock();
+       return(err);
 }
 
 int ignore_sigio_fd(int fd)
 {
        struct pollfd *p;
-       int err, i, n = 0;
+       int err = 0, i, n = 0;
 
+       sigio_lock();
        for(i = 0; i < current_poll.used; i++){
                if(current_poll.poll[i].fd == fd) break;
        }
-       if(i == current_poll.used) return(0);
+       if(i == current_poll.used)
+               goto out;
        
        err = need_poll(current_poll.used - 1);
-       if(err) return(err);
+       if(err)
+               goto out;
 
        for(i = 0; i < current_poll.used; i++){
                p = &current_poll.poll[i];
@@ -312,11 +334,14 @@ int ignore_sigio_fd(int fd)
        }
        if(n == i){
                printk("ignore_sigio_fd : fd %d not found\n", fd);
-               return(-1);
+               err = -1;
+               goto out;
        }
 
        update_thread();
-       return(0);
+ out:
+       sigio_unlock();
+       return(err);
 }
 
 static int setup_initial_poll(int fd)
@@ -342,14 +367,15 @@ void write_sigio_workaround(void)
        unsigned long stack;
        int err;
 
-       if(write_sigio_pid != -1) return;
+       sigio_lock();
+       if(write_sigio_pid != -1)
+               goto out;
 
-       /* XXX This needs SMP locking */
        err = os_pipe(write_sigio_fds, 1, 1);
        if(err){
                printk("write_sigio_workaround - os_pipe 1 failed, "
                       "errno = %d\n", -err);
-               return;
+               goto out;
        }
        err = os_pipe(sigio_private, 1, 1);
        if(err){
@@ -368,6 +394,8 @@ void write_sigio_workaround(void)
        if(write_sigio_irq(write_sigio_fds[0])) 
                goto out_kill;
 
+ out:
+       sigio_unlock();
        return;
 
  out_kill:
@@ -379,6 +407,7 @@ void write_sigio_workaround(void)
  out_close1:
        close(write_sigio_fds[0]);
        close(write_sigio_fds[1]);
+       sigio_unlock();
 }
 
 int read_sigio_fd(int fd)
index b5b3296144938ee16c3895d35ce70a04147fe083..3d1231765bb71e6c12be00b706f23460c2cc35db 100644 (file)
@@ -19,8 +19,6 @@
 #include "sysdep/sigcontext.h"
 #include "sigcontext.h"
 
-extern int kern_timer_on;
-
 void set_sigstack(void *sig_stack, int size)
 {
        stack_t stack;
@@ -65,12 +63,8 @@ static void change_signals(int type)
        sigset_t mask;
 
        sigemptyset(&mask);
-       if(type == SIG_BLOCK) kern_timer_on = 0;
-       else {
-               kern_timer_on = 1;
-               sigaddset(&mask, SIGVTALRM);
-               sigaddset(&mask, SIGALRM);
-       }
+       sigaddset(&mask, SIGVTALRM);
+       sigaddset(&mask, SIGALRM);
        sigaddset(&mask, SIGIO);
        sigaddset(&mask, SIGPROF);
        if(sigprocmask(type, &mask, NULL) < 0)
@@ -97,7 +91,6 @@ static int disable_mask(sigset_t *mask)
        sigs = sigismember(mask, SIGIO) ? 1 << SIGIO_BIT : 0;
        sigs |= sigismember(mask, SIGVTALRM) ? 1 << SIGVTALRM_BIT : 0;
        sigs |= sigismember(mask, SIGALRM) ? 1 << SIGVTALRM_BIT : 0;
-       if(!kern_timer_on) sigs |= 1 << SIGVTALRM_BIT;
        return(sigs);
 }
 
@@ -116,21 +109,27 @@ int set_signals(int disable)
        int ret;
 
        sigemptyset(&mask);
-       if(!(disable & (1 << SIGIO_BIT))) sigaddset(&mask, SIGIO);
+       if(!(disable & (1 << SIGIO_BIT)))
+               sigaddset(&mask, SIGIO);
        if(!(disable & (1 << SIGVTALRM_BIT))){
-               kern_timer_on = 1;
                sigaddset(&mask, SIGVTALRM);
                sigaddset(&mask, SIGALRM);
        }
        if(sigprocmask(SIG_UNBLOCK, &mask, &mask) < 0)
                panic("Failed to enable signals");
+
        ret = disable_mask(&mask);
+
        sigemptyset(&mask);
-       if(disable & (1 << SIGIO_BIT)) sigaddset(&mask, SIGIO);
-       if(disable & (1 << SIGVTALRM_BIT))
-               kern_timer_on = 0;
+       if(disable & (1 << SIGIO_BIT))
+               sigaddset(&mask, SIGIO);
+       if(disable & (1 << SIGVTALRM_BIT)){
+               sigaddset(&mask, SIGVTALRM);
+               sigaddset(&mask, SIGALRM);
+       }
        if(sigprocmask(SIG_BLOCK, &mask, NULL) < 0)
                panic("Failed to block signals");
+
        return(ret);
 }
 
index d53644005d4fa7b5c88129033baa1e7bd660dade..689db0e805d29374f05c94a59daf12f751eb10f4 100644 (file)
@@ -5,7 +5,7 @@
 
 #include "linux/config.h"
 
-/* CPU online map */
+/* CPU online map, set by smp_boot_cpus */
 unsigned long cpu_online_map = 1;
 
 #ifdef CONFIG_SMP
@@ -21,25 +21,32 @@ unsigned long cpu_online_map = 1;
 #include "user_util.h"
 #include "kern_util.h"
 #include "kern.h"
+#include "irq_user.h"
 #include "os.h"
 
-/* The 'big kernel lock' */
-spinlock_t kernel_flag __cacheline_aligned_in_smp = SPIN_LOCK_UNLOCKED;
-
-/* Per CPU bogomips and other parameters */
+/* Per CPU bogomips and other parameters
+ * The only piece used here is the ipi pipe, which is set before SMP is
+ * started and never changed.
+ */
 struct cpuinfo_um cpu_data[NR_CPUS];
 
 spinlock_t um_bh_lock = SPIN_LOCK_UNLOCKED;
 
 atomic_t global_bh_count;
 
+/* Not used by UML */
 unsigned char global_irq_holder = NO_PROC_ID;
 unsigned volatile long global_irq_lock;
 
 /* Set when the idlers are all forked */
 int smp_threads_ready = 0;
+
+/* A statistic, can be a little off */
 int num_reschedules_sent = 0;
 
+/* Small, random number, never changed */
+unsigned long cache_decay_ticks = 5;
+
 void smp_send_reschedule(int cpu)
 {
        write(cpu_data[cpu].ipi_pipe[1], "R", 1);
@@ -83,30 +90,24 @@ void synchronize_bh(void)
 
 void smp_send_stop(void)
 {
-       printk(KERN_INFO "Stopping all CPUs\n");
-}
+       int i;
 
+       printk(KERN_INFO "Stopping all CPUs...");
+       for(i = 0; i < num_online_cpus(); i++){
+               if(i == current->thread_info->cpu)
+                       continue;
+               write(cpu_data[i].ipi_pipe[1], "S", 1);
+       }
+       printk("done\n");
+}
 
-static atomic_t smp_commenced = ATOMIC_INIT(0);
+static unsigned long smp_commenced_mask;
 static volatile unsigned long smp_callin_map = 0;
 
-void smp_commence(void)
+static int idle_proc(void *cpup)
 {
-       printk("All CPUs are go!\n");
-
-       wmb();
-       atomic_set(&smp_commenced, 1);
-}
-
-static int idle_proc(void *unused)
-{
-       int cpu, err;
-
-       set_current(current);
-       del_from_runqueue(current);
-       unhash_process(current);
+       int cpu = (int) cpup, err;
 
-       cpu = current->processor;
        err = os_pipe(cpu_data[cpu].ipi_pipe, 1, 1);
        if(err)
                panic("CPU#%d failed to create IPI pipe, errno = %d", cpu, 
@@ -115,46 +116,41 @@ static int idle_proc(void *unused)
        activate_ipi(cpu_data[cpu].ipi_pipe[0], current->thread.extern_pid);
  
        wmb();
-       if (test_and_set_bit(current->processor, &smp_callin_map)) {
-               printk("huh, CPU#%d already present??\n", current->processor);
+       if (test_and_set_bit(cpu, &smp_callin_map)) {
+               printk("huh, CPU#%d already present??\n", cpu);
                BUG();
        }
 
-       while (!atomic_read(&smp_commenced))
+       while (!test_bit(cpu, &smp_commenced_mask))
                cpu_relax();
 
-       init_idle();
+       set_bit(cpu, &cpu_online_map);
        default_idle();
        return(0);
 }
 
-int inited_cpus = 1;
-
-static int idle_thread(int (*fn)(void *), int cpu)
+static struct task_struct *idle_thread(int cpu)
 {
-       struct task_struct *p;
-       int pid;
+       struct task_struct *new_task;
        unsigned char c;
 
-        current->thread.request.u.thread.proc = fn;
-        current->thread.request.u.thread.arg = NULL;
-       p = do_fork(CLONE_VM | CLONE_PID, 0, NULL, 0);
-       if(IS_ERR(p)) panic("do_fork failed in idle_thread");
-
-       cpu_tasks[cpu].pid = p->thread.extern_pid;
-       cpu_tasks[cpu].task = p;
-       inited_cpus++;
-       init_tasks[cpu] = p;
-       p->processor = cpu;
-       p->cpus_allowed = 1 << cpu;
-       p->cpus_runnable = p->cpus_allowed;
-       write(p->thread.switch_pipe[1], &c, sizeof(c));
-       return(p->thread.extern_pid);
+        current->thread.request.u.thread.proc = idle_proc;
+        current->thread.request.u.thread.arg = (void *) cpu;
+       new_task = do_fork(CLONE_VM | CLONE_IDLETASK, 0, NULL, 0, NULL);
+       if(IS_ERR(new_task)) panic("do_fork failed in idle_thread");
+
+       cpu_tasks[cpu] = ((struct cpu_task) 
+                         { .pid =      new_task->thread.extern_pid,
+                           .task =     new_task } );
+       write(new_task->thread.switch_pipe[1], &c, sizeof(c));
+       return(new_task);
 }
 
-void smp_boot_cpus(void)
+void smp_prepare_cpus(unsigned int maxcpus)
 {
-       int err;
+       struct task_struct *idle;
+       unsigned long waittime;
+       int err, cpu;
 
        set_bit(0, &cpu_online_map);
        set_bit(0, &smp_callin_map);
@@ -164,46 +160,32 @@ void smp_boot_cpus(void)
 
        activate_ipi(cpu_data[0].ipi_pipe[0], current->thread.extern_pid);
 
-       if(ncpus < 1){
-               printk(KERN_INFO "ncpus set to 1\n");
-               ncpus = 1;
-       }
-       else if(ncpus > NR_CPUS){
-               printk(KERN_INFO 
-                      "ncpus can't be greater than NR_CPUS, set to %d\n",
-                      NR_CPUS);
-               ncpus = NR_CPUS;
-       }
-
-       if(ncpus > 1){
-               int i, pid;
-
-               printk(KERN_INFO "Starting up other processors:\n");
-               for(i=1;i<ncpus;i++){
-                       int waittime;
-
-                       /* Do this early, for hard_smp_processor_id()  */
-                       cpu_tasks[i].pid = -1;
-                       set_bit(i, &cpu_online_map);
+       for(cpu = 1; cpu < ncpus; cpu++){
+               printk("Booting processor %d...\n", cpu);
+               
+               idle = idle_thread(cpu);
 
-                       pid = idle_thread(idle_proc, i);
-                       printk(KERN_INFO "\t#%d - idle thread pid = %d.. ",
-                              i, pid);
+               init_idle(idle, cpu);
+               unhash_process(idle);
 
-                       waittime = 200000000;
-                       while (waittime-- && !test_bit(i, &smp_callin_map))
-                               cpu_relax();
+               waittime = 200000000;
+               while (waittime-- && !test_bit(cpu, &smp_callin_map))
+                       cpu_relax();
 
-                       if (test_bit(i, &smp_callin_map))
-                               printk("online\n");
-                       else {
-                               printk("failed\n");
-                               clear_bit(i, &cpu_online_map);
-                       }
-               }
+               if (test_bit(cpu, &smp_callin_map))
+                       printk("done\n");
+               else printk("failed\n");
        }
 }
 
+int __cpu_up(unsigned int cpu)
+{
+       set_bit(cpu, &smp_commenced_mask);
+       while (!test_bit(cpu, &cpu_online_map))
+               mb();
+       return(0);
+}
+
 int setup_profiling_timer(unsigned int multiplier)
 {
        printk(KERN_INFO "setup_profiling_timer\n");
@@ -225,7 +207,13 @@ void IPI_handler(int cpu)
                        break;
 
                case 'R':
-                       current->need_resched = 1;
+                       set_tsk_need_resched(current);
+                       break;
+
+               case 'S':
+                       printk("CPU#%d stopping\n", cpu);
+                       while(1)
+                               pause();
                        break;
 
                default:
@@ -269,7 +257,8 @@ int smp_call_function(void (*_func)(void *info), void *_info, int nonatomic,
        info = _info;
 
        for (i=0;i<NR_CPUS;i++)
-               if (i != current->processor && test_bit(i, &cpu_online_map))
+               if((i != current->thread_info->cpu) && 
+                  test_bit(i, &cpu_online_map))
                        write(cpu_data[i].ipi_pipe[1], "C", 1);
 
        while (atomic_read(&scf_started) != cpus)
index 1aea2a00678890e200a2543c30acac86203c5461..b15340a6b837c7e8b383157d52031f598ff8868b 100644 (file)
@@ -384,6 +384,7 @@ static int check_bogosity(struct pt_regs *regs)
        return(0);
 }
 
+/*  Unlocked, I don't care if this is a bit off */
 int nsyscalls = 0;
 
 extern syscall_handler_t *sys_call_table[];
@@ -417,14 +418,18 @@ long execute_syscall(void *r)
 
 spinlock_t syscall_lock = SPIN_LOCK_UNLOCKED;
 
-void lock_syscall(void)
-{
-       spin_lock(&syscall_lock);
-}
+static int syscall_index = 0;
 
-void unlock_syscall(void)
+int next_syscall_index(int limit)
 {
+       int ret;
+
+       spin_lock(&syscall_lock);
+       ret = syscall_index;
+       if(++syscall_index == limit)
+               syscall_index = 0;
        spin_unlock(&syscall_lock);
+       return(ret);
 }
 
 /*
index 921045f804b7a62e73fbf913e0d1c1c1cac329cf..5da5aefce6d8df92947e21690897e300f3e965ac 100644 (file)
@@ -34,21 +34,14 @@ struct {
        struct timeval end;
 } syscall_record[1024];
 
-int syscall_index = 0;
-
-extern int kern_timer_on;
-
 void syscall_handler(int sig, struct uml_pt_regs *regs)
 {
        void *sc;
        long result;
-       int index, syscall;
+       int index, max, syscall;
 
-       lock_syscall();
-       if(syscall_index == 1024) syscall_index = 0;
-       index = syscall_index;
-       syscall_index++;
-       unlock_syscall();
+       max = sizeof(syscall_record)/sizeof(syscall_record[0]);
+       index = next_syscall_index(max);
 
        syscall = regs->syscall;
        sc = regs->sc;
index a9d4669132decd10ed1cea03240e84845371561f..2ab57626b43f582e7676bcf63c530d2b9c16072c 100644 (file)
 #include "user.h"
 #include "process.h"
 #include "signal_user.h"
+#include "time_user.h"
 
 extern struct timeval xtime;
 
-void timer_handler(int sig, struct uml_pt_regs *regs)
-{
-       timer_irq(regs);
-}
-
 void timer(void)
 {
        gettimeofday(&xtime, NULL);
 }
 
-static struct itimerval profile_interval;
-
-void get_profile_timer(void)
-{
-       getitimer(ITIMER_PROF, &profile_interval);
-       profile_interval.it_value = profile_interval.it_interval;
-}
-
-void disable_profile_timer(void)
-{
-       struct itimerval interval = ((struct itimerval) { { 0, 0 }, { 0, 0 }});
-       setitimer(ITIMER_PROF, &interval, NULL);
-}
-
 static void set_interval(int timer_type)
 {
        struct itimerval interval;
@@ -53,6 +35,15 @@ static void set_interval(int timer_type)
                panic("setitimer failed - errno = %d\n", errno);
 }
 
+void enable_timer(void)
+{
+       struct itimerval enable = ((struct itimerval) { { 0, 1000000/hz() },
+                                                       { 0, 1000000/hz() }});
+       if(setitimer(ITIMER_VIRTUAL, &enable, NULL))
+               printk("enable_timer - setitimer failed, errno = %d\n",
+                      errno);
+}
+
 void switch_timers(int to_real)
 {
        struct itimerval disable = ((struct itimerval) { { 0, 0 }, { 0, 0 }});
@@ -79,8 +70,9 @@ void idle_timer(void)
 {
        if(signal(SIGVTALRM, SIG_IGN) == SIG_ERR)
                panic("Couldn't unset SIGVTALRM handler");
+       
        set_handler(SIGALRM, (__sighandler_t) alarm_handler, 
-                   SA_NODEFER | SA_RESTART, SIGUSR1, SIGIO, SIGWINCH, -1);
+                   SA_RESTART, SIGUSR1, SIGIO, SIGWINCH, SIGVTALRM, -1);
        set_interval(ITIMER_REAL);
 }
 
@@ -98,28 +90,24 @@ void time_init(void)
        set_interval(ITIMER_VIRTUAL);
 }
 
-void set_timers(int set_signal)
-{
-       if(set_signal)
-               set_interval(ITIMER_VIRTUAL);
-       if(setitimer(ITIMER_PROF, &profile_interval, NULL) == -1)
-               panic("setitimer ITIMER_PROF failed - errno = %d\n", errno);
-}
-
 struct timeval local_offset = { 0, 0 };
 
 void do_gettimeofday(struct timeval *tv)
 {
+       time_lock();
        gettimeofday(tv, NULL);
        timeradd(tv, &local_offset, tv);
+       time_unlock();
 }
 
 void do_settimeofday(struct timeval *tv)
 {
        struct timeval now;
 
+       time_lock();
        gettimeofday(&now, NULL);
        timersub(tv, &now, &local_offset);
+       time_unlock();
 }
 
 void idle_sleep(int secs)
index 4c96bd9637e7f427906f0931d25f673cfb946687..14305874878bf1a4df19a35082fb0554b41d39a4 100644 (file)
@@ -27,21 +27,21 @@ int hz(void)
        return(HZ);
 }
 
+/* Changed at early boot */
 int timer_irq_inited = 0;
 
-/* kern_timer_on and missed_ticks are modified after kernel memory has been 
+/* missed_ticks will be modified after kernel memory has been 
  * write-protected, so this puts it in a section which will be left 
  * write-enabled.
  */
-int __attribute__ ((__section__ (".unprotected"))) kern_timer_on = 0;
-int __attribute__ ((__section__ (".unprotected"))) missed_ticks = 0;
+int __attribute__ ((__section__ (".unprotected"))) missed_ticks[NR_CPUS];
 
 void timer_irq(struct uml_pt_regs *regs)
 {
-       int ticks = missed_ticks;
+       int cpu = current->thread_info->cpu, ticks = missed_ticks[cpu];
 
         if(!timer_irq_inited) return;
-       missed_ticks = 0;
+       missed_ticks[cpu] = 0;
        while(ticks--) do_IRQ(TIMER_IRQ, regs);
 }
 
@@ -116,6 +116,27 @@ void __const_udelay(um_udelay_t usecs)
        for(i=0;i<n;i++) ;
 }
 
+void timer_handler(int sig, struct uml_pt_regs *regs)
+{
+#ifdef CONFIG_SMP
+       update_process_times(user_context(UPT_SP(regs)));
+#endif
+       if(current->thread_info->cpu == 0)
+               timer_irq(regs);
+}
+
+static spinlock_t timer_spinlock = SPIN_LOCK_UNLOCKED;
+
+void time_lock(void)
+{
+       spin_lock(&timer_spinlock);
+}
+
+void time_unlock(void)
+{
+       spin_unlock(&timer_spinlock);
+}
+
 int __init timer_init(void)
 {
        int err;
index 8f104d7a18537ff7c9933155d8dc5efc50fbd7dc..158ea30937b3917bd9af2cfe5a98b11c3016518e 100644 (file)
@@ -171,14 +171,18 @@ void trap_init(void)
 
 spinlock_t trap_lock = SPIN_LOCK_UNLOCKED;
 
-void lock_trap(void)
-{
-       spin_lock(&trap_lock);
-}
+static int trap_index = 0;
 
-void unlock_trap(void)
+int next_trap_index(int limit)
 {
+       int ret;
+
+       spin_lock(&trap_lock);
+       ret = trap_index;
+       if(++trap_index == limit)
+               trap_index = 0;
        spin_unlock(&trap_lock);
+       return(ret);
 }
 
 extern int debugger_pid;
@@ -209,6 +213,7 @@ static struct chan_opts opts = {
        tramp_stack :   0,
 };
 
+/* Accessed by the tracing thread, which automatically serializes access */
 static void *xterm_data;
 static int xterm_fd;
 
index 90a6df7a43ecfc96513117b5d8ce59e37175e0af..a87c94b9a367713632cc240c695ac73c20a2f79f 100644 (file)
@@ -70,10 +70,10 @@ void kill_child_dead(int pid)
        while(waitpid(pid, NULL, 0) > 0) kill(pid, SIGCONT);
 }
 
+/* Changed early in boot, and then only read */
 int debug = 0;
 int debug_stop = 1;
 int debug_parent = 0;
-
 int honeypot = 0;
 
 static int signal_tramp(void *arg)
@@ -90,7 +90,6 @@ static int signal_tramp(void *arg)
        signal(SIGUSR1, SIG_IGN);
        change_sig(SIGCHLD, 0);
        signal(SIGSEGV, (__sighandler_t) sig_handler);
-       set_timers(0);
        set_cmdline("(idle thread)");
        set_init_pid(os_getpid());
        proc = arg;
@@ -142,33 +141,20 @@ static void sleeping_process_signal(int pid, int sig)
        }
 }
 
-#ifdef CONFIG_SMP
-#error need to make these arrays
-#endif
-
+/* Accessed only by the tracing thread */
 int debugger_pid = -1;
 int debugger_parent = -1;
 int debugger_fd = -1;
 int gdb_pid = -1;
 
-struct {
-       unsigned long address;
-       int is_write;
-       int pid;
-       unsigned long sp;
-       int is_user;
-} segfault_record[1024];
-
-int segfault_index = 0;
-
 struct {
        int pid;
        int signal;
        unsigned long addr;
        struct timeval time;
-} signal_record[1024];
+} signal_record[1024][32];
 
-int signal_index = 0;
+int signal_index[32];
 int nsignals = 0;
 int debug_trace = 0;
 extern int io_nsignals, io_count, intr_count;
@@ -259,36 +245,36 @@ int signals(int (*init_proc)(void *), void *sp)
                if(WIFEXITED(status)) ;
 #ifdef notdef
                {
-                       printk("Child %d exited with status %d\n", pid, 
+                       printf("Child %d exited with status %d\n", pid, 
                               WEXITSTATUS(status));
                }
 #endif
                else if(WIFSIGNALED(status)){
                        sig = WTERMSIG(status);
                        if(sig != 9){
-                               printk("Child %d exited with signal %d\n", pid,
+                               printf("Child %d exited with signal %d\n", pid,
                                       sig);
                        }
                }
                else if(WIFSTOPPED(status)){
+                       proc_id = pid_to_processor_id(pid);
                        sig = WSTOPSIG(status);
-                       if(signal_index == 1024){
-                               signal_index = 0;
+                       if(signal_index[proc_id] == 1024){
+                               signal_index[proc_id] = 0;
                                last_index = 1023;
                        }
-                       else last_index = signal_index - 1;
+                       else last_index = signal_index[proc_id] - 1;
                        if(((sig == SIGPROF) || (sig == SIGVTALRM) || 
                            (sig == SIGALRM)) &&
-                          (signal_record[last_index].signal == sig) &&
-                          (signal_record[last_index].pid == pid))
-                               signal_index = last_index;
-                       signal_record[signal_index].pid = pid;
-                       gettimeofday(&signal_record[signal_index].time, NULL);
+                          (signal_record[proc_id][last_index].signal == sig)&&
+                          (signal_record[proc_id][last_index].pid == pid))
+                               signal_index[proc_id] = last_index;
+                       signal_record[proc_id][signal_index[proc_id]].pid = pid;
+                       gettimeofday(&signal_record[proc_id][signal_index[proc_id]].time, NULL);
                        eip = ptrace(PTRACE_PEEKUSER, pid, PT_IP_OFFSET, 0);
-                       signal_record[signal_index].addr = eip;
-                       signal_record[signal_index++].signal = sig;
+                       signal_record[proc_id][signal_index[proc_id]].addr = eip;
+                       signal_record[proc_id][signal_index[proc_id]++].signal = sig;
                        
-                       proc_id = pid_to_processor_id(pid);
                        if(proc_id == -1){
                                sleeping_process_signal(pid, sig);
                                continue;
@@ -413,22 +399,30 @@ __uml_setup("honeypot", uml_honeypot_setup,
 "    UML.  This implies 'jail'.\n\n"
 );
 
+/* Unlocked - don't care if this is a bit off */
 int nsegfaults = 0;
 
+struct {
+       unsigned long address;
+       int is_write;
+       int pid;
+       unsigned long sp;
+       int is_user;
+} segfault_record[1024];
+
 void segv_handler(int sig, struct uml_pt_regs *regs)
 {
        struct sigcontext *context = regs->sc;
-       int index;
+       int index, max;
 
        if(regs->is_user && !SEGV_IS_FIXABLE(context)){
                bad_segv(SC_FAULT_ADDR(context), SC_IP(context), 
                         SC_FAULT_WRITE(context));
                return;
        }
-       lock_trap();
-       index = segfault_index++;
-       if(segfault_index == 1024) segfault_index = 0;
-       unlock_trap();
+       max = sizeof(segfault_record)/sizeof(segfault_record[0]);
+       index = next_trap_index(max);
+
        nsegfaults++;
        segfault_record[index].address = SC_FAULT_ADDR(context);
        segfault_record[index].pid = os_getpid();
@@ -439,8 +433,6 @@ void segv_handler(int sig, struct uml_pt_regs *regs)
             regs->is_user, context);
 }
 
-extern int kern_timer_on;
-
 struct signal_info {
        void (*handler)(int, struct uml_pt_regs *);
        int is_irq;
@@ -471,7 +463,7 @@ void sig_handler_common(int sig, struct sigcontext *sc)
 {
        struct uml_pt_regs save_regs, *r;
        struct signal_info *info;
-       int save_errno = errno, save_timer = kern_timer_on, is_user;
+       int save_errno = errno, is_user;
 
        unprotect_kernel_mem();
 
@@ -488,7 +480,6 @@ void sig_handler_common(int sig, struct sigcontext *sc)
 
        (*info->handler)(sig, r);
 
-       kern_timer_on = save_timer;
        if(is_user){
                interrupt_end();
                block_signals();
@@ -505,19 +496,15 @@ void sig_handler(int sig, struct sigcontext sc)
        sig_handler_common(sig, &sc);
 }
 
-extern int timer_irq_inited, missed_ticks;
-
-extern int jail_timer_off;
+extern int timer_irq_inited, missed_ticks[];
 
 void alarm_handler(int sig, struct sigcontext sc)
 {
        int user;
 
        if(!timer_irq_inited) return;
-       missed_ticks++;
+       missed_ticks[cpu()]++;
        user = user_context(SC_SP(&sc));
-       if(!user && !kern_timer_on) return;
-       if(!user && jail_timer_off) return;
 
        if(sig == SIGALRM)
                switch_timers(0);
index 1472a99a76862345c7c197e94cff439bbe4fe211..09aa5639007c76439d9852825e057ea4582cc724 100644 (file)
@@ -17,8 +17,8 @@
 
 #define TTY_LOG_DIR "./"
 
-char *tty_log_dir = TTY_LOG_DIR;
-
+/* Set early in boot and then unchanged */
+static char *tty_log_dir = TTY_LOG_DIR;
 static int tty_log_fd = -1;
 
 #define TTY_LOG_OPEN 1
index 5452d3f2563cfe23a71a2caa89712ad98f1b338d..4bc2377adba608aa5345478d606b08d31c2834ea 100644 (file)
 
 #define DEFAULT_COMMAND_LINE "root=6200"
 
+struct cpuinfo_um boot_cpu_data = { 
+       .loops_per_jiffy =      0,
+       .ipi_pipe =             { -1, -1 }
+};
+
 unsigned long thread_saved_pc(struct task_struct *task)
 {
        return(os_process_pc(task->thread.extern_pid));
@@ -119,6 +124,7 @@ static int start_kernel_proc(void *unused)
 #define SIZE ((CONFIG_NEST_LEVEL + CONFIG_KERNEL_HALF_GIGS) * 0x20000000)
 #define START (TOP - SIZE)
 
+/* Set in main */
 unsigned long host_task_size;
 unsigned long task_size;
 
@@ -129,17 +135,21 @@ void set_task_sizes(int arg)
        task_size = START;
 }
 
+/* Set in early boot */
 unsigned long uml_physmem;
 unsigned long uml_reserved;
-
 unsigned long start_vm;
 unsigned long end_vm;
-
 int ncpus = 1;
 
+/* Pointer set in linux_main, the array itself is private to each thread,
+ * and changed at address space creation time so this poses no concurrency
+ * problems.
+ */
 static char *argv1_begin = NULL;
 static char *argv1_end = NULL;
 
+/* Set in early boot */
 static int have_root __initdata = 0;
 long physmem_size = 32 * 1024 * 1024;
 
@@ -258,8 +268,9 @@ static void __init uml_postsetup(void)
 }
 
 extern int debug_trace;
-unsigned long brk_start;
 
+/* Set during early boot */
+unsigned long brk_start;
 static struct vm_reserved kernel_vm_reserved;
 
 #define MIN_VMALLOC (32 * 1024 * 1024)
@@ -365,18 +376,6 @@ void __init check_bugs(void)
        check_sigio();
 }
 
-spinlock_t pid_lock = SPIN_LOCK_UNLOCKED;
-
-void lock_pid(void)
-{
-       spin_lock(&pid_lock);
-}
-
-void unlock_pid(void)
-{
-       spin_unlock(&pid_lock);
-}
-
 /*
  * Overrides for Emacs so that we follow Linus's tabbing style.
  * Emacs will notice this stuff at the end of the file and automatically
index ca6735f415ba3c3893c3893c6e240dcacbc9cadf..2ba2049510b3834769e37d288401d1bf6b22bc65 100644 (file)
 #define UMID_LEN 64
 #define UML_DIR "~/.uml/"
 
+/* Changed by set_umid and make_umid, which are run early in boot */
 static char umid[UMID_LEN] = { 0 };
+
+/* Changed by set_uml_dir and make_uml_dir, which are run early in boot */
 static char *uml_dir = UML_DIR;
 
+/* Changed by set_umid */
 static int umid_is_random = 1;
 static int umid_inited = 0;
 
index 0445cde3cb5230022d4a7d6a7d4331d757887e9a..d0d1891c1a202959a1067e43e6eb5d9791277076 100644 (file)
@@ -32,6 +32,7 @@
 
 #define COMMAND_LINE_SIZE _POSIX_ARG_MAX
 
+/* Changed in linux_main and setup_arch, which run before SMP is started */
 char saved_command_line[COMMAND_LINE_SIZE] = { 0 };
 char command_line[COMMAND_LINE_SIZE] = { 0 };
 
index 7005f4d7bc3bb7805fcc09ad1b78e4b66f1b6e47..204c7a189fdd4b59e1b1d38f087eafe9094258a3 100644 (file)
 #include "user.h"
 #include "init.h"
 
+/* Set in set_stklim, which is called from main and __wrap_malloc.  
+ * __wrap_malloc only calls it if main hasn't started.
+ */
 unsigned long stacksizelim;
 
+/* Set in main */
 char *linux_prog;
 
 #define PGD_BOUND (4 * 1024 * 1024)
 #define STACKSIZE (8 * 1024 * 1024)
 #define THREAD_NAME_LEN (256)
 
-char padding[THREAD_NAME_LEN] = { [ 0 ...  THREAD_NAME_LEN - 2] = ' ', '\0' };
+/* Never changed */
+static char padding[THREAD_NAME_LEN] = { 
+       [ 0 ...  THREAD_NAME_LEN - 2] = ' ', '\0' 
+};
 
 static void set_stklim(void)
 {
@@ -129,7 +136,8 @@ int main(int argc, char **argv, char **envp)
        return(uml_exitcode);
 }
 
-int allocating_monbuf = 0;
+/* Changed in  __wrap___monstartup and __wrap_malloc very early */
+static int allocating_monbuf = 0;
 
 #ifdef PROFILING
 extern void __real___monstartup (unsigned long, unsigned long);
@@ -146,6 +154,7 @@ void __wrap___monstartup (unsigned long lowpc, unsigned long highpc)
 extern void *__real_malloc(int);
 extern unsigned long host_task_size;
 
+/* Set in __wrap_malloc early */
 static void *gmon_buf = NULL;
 
 void *__wrap_malloc(int size)
index 78789b9403e80491044324ff2939c05cd5145271..2c6189ab9922b5e6a13382d5a6dddbececee532b 100644 (file)
@@ -122,6 +122,7 @@ int debugger_syscall(debugger_state *debugger, pid_t child)
        return(0);
 }
 
+/* Used by the tracing thread */
 static debugger_state parent;
 static int parent_syscall(debugger_state *debugger, int pid);
 
@@ -174,10 +175,7 @@ void debugger_cancelled_return(debugger_state *debugger, int result)
        syscall_continue(debugger->pid);
 }
 
-#ifdef CONFIG_SMP
-#error need to make these arrays
-#endif
-
+/* Used by the tracing thread */
 static debugger_state debugger;
 static debugee_state debugee;
 
index 678b04a127c9e2a45c304d56081b36871d7c0b08..5b01a07368cc0afdcf94b00880b6876bed868fc0 100644 (file)
@@ -15,6 +15,7 @@
 
 #define MAXTOKEN 64
 
+/* Set during early boot */
 int cpu_has_cmov = 1;
 int cpu_has_xmm = 0;
 
index 45a45edd28dc686af9c5ec36029aeaa140acdf75..659db8a6e2d80edd638d19ecf1faecb1920ed40c 100644 (file)
@@ -59,6 +59,7 @@ static void read_debugregs(int pid, unsigned long *regs)
        }
 }
 
+/* Accessed only by the tracing thread */
 static unsigned long kernel_debugregs[8] = { [ 0 ... 7 ] = 0 };
 static int debugregs_seq = 0;
 
index 2377b5930ea851459edaa753bccbd6819fe493ae..373061c50129b8796e8deb05221e1528eb79e431 100644 (file)
@@ -2,9 +2,6 @@
 #include "linux/stddef.h"  // for NULL
 #include "linux/elf.h"  // for AT_NULL
 
-/* unsigned int local_bh_count[NR_CPUS]; */
-unsigned long isa_io_base = 0;
-
 /* The following function nicked from arch/ppc/kernel/process.c and
  * adapted slightly */
 /*
index f6c40ec0d1432a76ed0b8ed0bc5674db39fd9c5a..212f614b76212f49a11df29faa3e6a8b6f05fec1 100644 (file)
@@ -67,6 +67,9 @@ SECTIONS
   __setup_start = .;
   .setup.init : { *(.setup.init) }
   __setup_end = .;
+  __per_cpu_start = . ; 
+  .data.percpu : { *(.data.percpu) }
+  __per_cpu_end = . ; 
   __initcall_start = .;
   .initcall.init : {
        *(.initcall1.init) 
index a4962992cf86cd67b2f3539e14fc6f89493acaa4..4b134fe8504e9eeeb7998fe2410a38286f79b719 100644 (file)
@@ -1,7 +1,10 @@
 #ifndef __UM_CACHE_H
 #define __UM_CACHE_H
 
+/* These are x86 numbers */
 #define L1_CACHE_SHIFT 5
 #define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT)
 
+#define L1_CACHE_SHIFT_MAX 7   /* largest L1 which this arch supports */
+
 #endif
index 931b1f956f1770e2f3dedd38cd79140311da55ed..a991b9feea3fa721657e541d66071ceff16579dc 100644 (file)
@@ -6,15 +6,30 @@ extern unsigned long cpu_online_map;
 #ifdef CONFIG_SMP
 
 #include "linux/config.h"
+#include "linux/bitops.h"
 #include "asm/current.h"
 
-#define smp_processor_id() (current->processor)
+#define smp_processor_id() (current->thread_info->cpu)
 #define cpu_logical_map(n) (n)
 #define cpu_number_map(n) (n)
 #define PROC_CHANGE_PENALTY    15 /* Pick a number, any number */
 extern int hard_smp_processor_id(void);
 #define NO_PROC_ID -1
 
+#define cpu_online(cpu) (cpu_online_map & (1<<(cpu)))
+
+extern int ncpus;
+#define cpu_possible(cpu) (cpu < ncpus)
+
+extern inline unsigned int num_online_cpus(void)
+{
+       return(hweight32(cpu_online_map));
+}
+
+extern inline void smp_cpus_done(unsigned int maxcpus)
+{
+}
+
 #endif
 
 #endif
index 494e367f4ff917051888698c8210782b90714d5c..1cb0f45359f5db87fbec93620d2d06894b8ea85c 100644 (file)
@@ -64,10 +64,14 @@ static inline struct thread_info *current_thread_info(void)
 #define TIF_SYSCALL_TRACE      0       /* syscall trace active */
 #define TIF_SIGPENDING         1       /* signal pending */
 #define TIF_NEED_RESCHED       2       /* rescheduling necessary */
+#define TIF_POLLING_NRFLAG      3       /* true if poll_idle() is polling 
+                                        * TIF_NEED_RESCHED 
+                                        */
 
 #define _TIF_SYSCALL_TRACE     (1 << TIF_SYSCALL_TRACE)
 #define _TIF_SIGPENDING                (1 << TIF_SIGPENDING)
 #define _TIF_NEED_RESCHED      (1 << TIF_NEED_RESCHED)
+#define _TIF_POLLING_NRFLAG     (1 << TIF_POLLING_NRFLAG)
 
 #endif