From: Lennert B. <bu...@gn...> - 2002-01-03 01:29:31
|
I know it's somewhat ugly right now. I promise to clean it up in the morning, honest :) --- linux-2.4.17-3um-jeff/arch/um/kernel/irq_user.c Thu Jan 3 02:24:46 2002 +++ linux-2.4.17-3um/arch/um/kernel/irq_user.c Thu Jan 3 02:26:39 2002 @@ -41,6 +41,8 @@ struct irq_fd *irq_fd, *next; int i, n; + IPI_handler(hard_smp_processor_id()); + while(1){ if((n = poll(pollfds, pollfds_num, 0)) < 0){ if(errno == EINTR) continue; @@ -65,6 +67,26 @@ } } +int activate_ipi(int fd, int pid) +{ + int retval; + + if((retval = fcntl(fd, F_SETFL, O_ASYNC | O_NONBLOCK)) < 0){ + printk("Failed to set O_ASYNC and O_NONBLOCK on fd # %d, " + errno = %d\n", fd, errno); + return(-retval); + } + + if(((retval = fcntl(fd, F_SETSIG, 0)) < 0) || + ((retval = fcntl(fd, F_SETOWN, pid)) < 0)){ + printk("Failed to fcntl F_SETOWN (or F_SETSIG) " + fd %d to pid %d, errno = %d\n", fd, pid, errno); + return(-retval); + } + + return(0); +} + int activate_fd(int irq, int fd, void *dev_id) { struct irq_fd *new_fd; @@ -204,6 +226,11 @@ irq = find_irq_by_fd(fd, &i); if(irq == NULL) return; pollfds[i].events = irq->events; +} + +void forward_ipi(int fd, int pid) +{ + fcntl(fd, F_SETOWN, pid); } void forward_interrupts(int pid) --- linux-2.4.17-3um-jeff/arch/um/kernel/process_kern.c Thu Jan 3 01:55:25 2002 +++ linux-2.4.17-3um/arch/um/kernel/process_kern.c Thu Jan 3 00:49:48 2002 @@ -238,6 +238,7 @@ to->thread.prev_sched = from; + forward_ipi(cpu_data[from->processor].ipi_pipe[0], to->thread.extern_pid); forward_interrupts(to->thread.extern_pid); block_signals(); --- linux-2.4.17-3um-jeff/arch/um/kernel/smp.c Thu Jan 3 02:03:35 2002 +++ linux-2.4.17-3um/arch/um/kernel/smp.c Thu Jan 3 02:08:21 2002 @@ -44,6 +44,7 @@ void smp_send_reschedule(int cpu) { + write(cpu_data[cpu].ipi_pipe[1], "R", 1); num_reschedules_sent++; } @@ -101,15 +102,24 @@ static int idle_proc(void *unused) { + int cpu; + set_current(current); del_from_runqueue(current); + unhash_process(current); + + cpu = current->processor; + if (socketpair(AF_UNIX, SOCK_STREAM, 0, cpu_data[cpu].ipi_pipe) < 0) + panic("CPU#%d failed to create IPI pipe", cpu); + + 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); BUG(); } - printk("CPU#%d booting..\n", current->processor); while (!atomic_read(&smp_commenced)) cpu_relax(); @@ -127,6 +137,10 @@ current->mm = &init_mm; current->active_mm = &init_mm; + if (socketpair(AF_UNIX, SOCK_STREAM, 0, cpu_data[0].ipi_pipe) < 0) + panic("CPU#0 failed to create IPI pipe"); + 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; @@ -174,12 +188,83 @@ return(0); } -int inited_cpus = 1; +#include <sys/poll.h> + +void smp_call_function_slave(int cpu); + +void IPI_handler(int cpu) +{ + struct pollfd fd; + + fd.fd = cpu_data[cpu].ipi_pipe[0]; + fd.events = POLLIN; + while (poll(&fd, 1, 0)) { + unsigned char c; + + if (read(fd.fd, &c, 1) != 1) { + printk("Failed to read from IPI pipe on CPU#%d\n", cpu); + return; + } + + switch (c) { + case 'C': + smp_call_function_slave(cpu); + break; + + case 'R': + current->need_resched = 1; + break; + + default: + printk("CPU#%d received unknown IPI [%c]!\n", cpu, c); + break; + } + } +} + + +int inited_cpus = 1; + int hard_smp_processor_id(void) { return(pid_to_processor_id(getpid())); +} + + +/*****/ +static void (*func)(void *info); +static void *info; +static unsigned long smp_call_function_callin_map; + +void smp_call_function_slave(int cpu) +{ + (*func)(info); + clear_bit(cpu, &smp_call_function_callin_map); +} + +int smp_call_function(void (*_func)(void *info), void *_info, int nonatomic, in +t wait) +{ + int me = current->processor; + int i; + + /* @@@@ need locking here */ + func = _func; + info = _info; + + smp_call_function_callin_map = cpu_online_map; + clear_bit(me, &smp_call_function_callin_map); + + for (i=0;i<NR_CPUS;i++) + if (test_bit(i, &smp_call_function_callin_map)) + write(cpu_data[i].ipi_pipe[1], "C", 1); + + while (smp_call_function_callin_map) + cpu_relax(); + + return 0; } #endif --- linux-2.4.17-3um-jeff/include/asm-um/processor-generic.h Thu Jan 3 02:18:00 2002 +++ linux-2.4.17-3um/include/asm-um/processor-generic.h Wed Jan 2 23:21:36 2002 @@ -162,6 +162,7 @@ unsigned long *pmd_quick; unsigned long *pte_quick; unsigned long pgtable_cache_sz; + int ipi_pipe[2]; }; extern struct cpuinfo_um boot_cpu_data; |