Blame view
arch/um/kernel/smp.c
4.79 KB
63ae2a94d [PATCH] uml: move... |
1 |
/* |
4c9e13851 uml: style fixes ... |
2 |
* Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) |
1da177e4c Linux-2.6.12-rc2 |
3 4 |
* Licensed under the GPL */ |
1da177e4c Linux-2.6.12-rc2 |
5 6 7 |
#include "linux/percpu.h" #include "asm/pgalloc.h" #include "asm/tlb.h" |
1da177e4c Linux-2.6.12-rc2 |
8 9 10 11 12 13 14 15 16 17 18 |
#ifdef CONFIG_SMP #include "linux/sched.h" #include "linux/module.h" #include "linux/threads.h" #include "linux/interrupt.h" #include "linux/err.h" #include "linux/hardirq.h" #include "asm/smp.h" #include "asm/processor.h" #include "asm/spinlock.h" |
1da177e4c Linux-2.6.12-rc2 |
19 20 21 |
#include "kern.h" #include "irq_user.h" #include "os.h" |
1da177e4c Linux-2.6.12-rc2 |
22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
/* 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]; /* A statistic, can be a little off */ int num_reschedules_sent = 0; /* Not changed after boot */ struct task_struct *idle_threads[NR_CPUS]; void smp_send_reschedule(int cpu) { |
a6ea4ccee uml: rename os_{r... |
36 |
os_write_file(cpu_data[cpu].ipi_pipe[1], "R", 1); |
1da177e4c Linux-2.6.12-rc2 |
37 38 39 40 41 42 43 44 |
num_reschedules_sent++; } void smp_send_stop(void) { int i; printk(KERN_INFO "Stopping all CPUs..."); |
4c9e13851 uml: style fixes ... |
45 46 |
for (i = 0; i < num_online_cpus(); i++) { if (i == current_thread->cpu) |
1da177e4c Linux-2.6.12-rc2 |
47 |
continue; |
a6ea4ccee uml: rename os_{r... |
48 |
os_write_file(cpu_data[i].ipi_pipe[1], "S", 1); |
1da177e4c Linux-2.6.12-rc2 |
49 |
} |
c5d4bb171 uml: style fixes ... |
50 51 |
printk(KERN_CONT "done "); |
1da177e4c Linux-2.6.12-rc2 |
52 53 54 55 56 57 58 59 60 61 |
} static cpumask_t smp_commenced_mask = CPU_MASK_NONE; static cpumask_t cpu_callin_map = CPU_MASK_NONE; static int idle_proc(void *cpup) { int cpu = (int) cpup, err; err = os_pipe(cpu_data[cpu].ipi_pipe, 1, 1); |
4c9e13851 uml: style fixes ... |
62 |
if (err < 0) |
1da177e4c Linux-2.6.12-rc2 |
63 |
panic("CPU#%d failed to create IPI pipe, err = %d", cpu, -err); |
bf8fde785 uml: miscellaneou... |
64 |
os_set_fd_async(cpu_data[cpu].ipi_pipe[0]); |
63ae2a94d [PATCH] uml: move... |
65 |
|
1da177e4c Linux-2.6.12-rc2 |
66 67 |
wmb(); if (cpu_test_and_set(cpu, cpu_callin_map)) { |
4c9e13851 uml: style fixes ... |
68 69 |
printk(KERN_ERR "huh, CPU#%d already present?? ", cpu); |
1da177e4c Linux-2.6.12-rc2 |
70 71 72 73 74 |
BUG(); } while (!cpu_isset(cpu, smp_commenced_mask)) cpu_relax(); |
e545a6140 kernel/cpu.c: cre... |
75 |
notify_cpu_starting(cpu); |
1da177e4c Linux-2.6.12-rc2 |
76 77 |
cpu_set(cpu, cpu_online_map); default_idle(); |
dc764e508 uml: formatting f... |
78 |
return 0; |
1da177e4c Linux-2.6.12-rc2 |
79 80 81 82 83 |
} static struct task_struct *idle_thread(int cpu) { struct task_struct *new_task; |
1da177e4c Linux-2.6.12-rc2 |
84 |
|
dc764e508 uml: formatting f... |
85 86 |
current->thread.request.u.thread.proc = idle_proc; current->thread.request.u.thread.arg = (void *) cpu; |
1da177e4c Linux-2.6.12-rc2 |
87 |
new_task = fork_idle(cpu); |
4c9e13851 uml: style fixes ... |
88 |
if (IS_ERR(new_task)) |
1da177e4c Linux-2.6.12-rc2 |
89 90 |
panic("copy_process failed in idle_thread, error = %ld", PTR_ERR(new_task)); |
63ae2a94d [PATCH] uml: move... |
91 |
cpu_tasks[cpu] = ((struct cpu_task) |
1da177e4c Linux-2.6.12-rc2 |
92 93 94 |
{ .pid = new_task->thread.mode.tt.extern_pid, .task = new_task } ); idle_threads[cpu] = new_task; |
42fda6638 uml: throw out CO... |
95 |
panic("skas mode doesn't support SMP"); |
dc764e508 uml: formatting f... |
96 |
return new_task; |
1da177e4c Linux-2.6.12-rc2 |
97 98 99 100 101 102 103 104 105 106 |
} void smp_prepare_cpus(unsigned int maxcpus) { struct task_struct *idle; unsigned long waittime; int err, cpu, me = smp_processor_id(); int i; for (i = 0; i < ncpus; ++i) |
a6a01063d cpumask: Use acce... |
107 |
set_cpu_possible(i, true); |
1da177e4c Linux-2.6.12-rc2 |
108 109 110 111 112 113 |
cpu_clear(me, cpu_online_map); cpu_set(me, cpu_online_map); cpu_set(me, cpu_callin_map); err = os_pipe(cpu_data[me].ipi_pipe, 1, 1); |
4c9e13851 uml: style fixes ... |
114 |
if (err < 0) |
1da177e4c Linux-2.6.12-rc2 |
115 |
panic("CPU#0 failed to create IPI pipe, errno = %d", -err); |
bf8fde785 uml: miscellaneou... |
116 |
os_set_fd_async(cpu_data[me].ipi_pipe[0]); |
1da177e4c Linux-2.6.12-rc2 |
117 |
|
4c9e13851 uml: style fixes ... |
118 119 120 |
for (cpu = 1; cpu < ncpus; cpu++) { printk(KERN_INFO "Booting processor %d... ", cpu); |
63ae2a94d [PATCH] uml: move... |
121 |
|
1da177e4c Linux-2.6.12-rc2 |
122 123 124 |
idle = idle_thread(cpu); init_idle(idle, cpu); |
1da177e4c Linux-2.6.12-rc2 |
125 126 127 128 |
waittime = 200000000; while (waittime-- && !cpu_isset(cpu, cpu_callin_map)) cpu_relax(); |
c5d4bb171 uml: style fixes ... |
129 130 131 |
printk(KERN_INFO "%s ", cpu_isset(cpu, cpu_calling_map) ? "done" : "failed"); |
1da177e4c Linux-2.6.12-rc2 |
132 133 134 135 136 137 138 139 140 141 142 143 144 |
} } void smp_prepare_boot_cpu(void) { cpu_set(smp_processor_id(), cpu_online_map); } int __cpu_up(unsigned int cpu) { cpu_set(cpu, smp_commenced_mask); while (!cpu_isset(cpu, cpu_online_map)) mb(); |
dc764e508 uml: formatting f... |
145 |
return 0; |
1da177e4c Linux-2.6.12-rc2 |
146 147 148 149 150 151 |
} int setup_profiling_timer(unsigned int multiplier) { printk(KERN_INFO "setup_profiling_timer "); |
dc764e508 uml: formatting f... |
152 |
return 0; |
1da177e4c Linux-2.6.12-rc2 |
153 154 155 156 157 158 159 160 161 162 |
} void smp_call_function_slave(int cpu); void IPI_handler(int cpu) { unsigned char c; int fd; fd = cpu_data[cpu].ipi_pipe[0]; |
a6ea4ccee uml: rename os_{r... |
163 |
while (os_read_file(fd, &c, 1) == 1) { |
1da177e4c Linux-2.6.12-rc2 |
164 165 166 167 168 169 |
switch (c) { case 'C': smp_call_function_slave(cpu); break; case 'R': |
184748cc5 sched: Provide sc... |
170 |
scheduler_ipi(); |
1da177e4c Linux-2.6.12-rc2 |
171 172 173 |
break; case 'S': |
4c9e13851 uml: style fixes ... |
174 175 176 |
printk(KERN_INFO "CPU#%d stopping ", cpu); while (1) |
1da177e4c Linux-2.6.12-rc2 |
177 178 179 180 |
pause(); break; default: |
4c9e13851 uml: style fixes ... |
181 182 183 |
printk(KERN_ERR "CPU#%d received unknown IPI [%c]! ", cpu, c); |
1da177e4c Linux-2.6.12-rc2 |
184 185 186 187 188 189 190 |
break; } } } int hard_smp_processor_id(void) { |
dc764e508 uml: formatting f... |
191 |
return pid_to_processor_id(os_getpid()); |
1da177e4c Linux-2.6.12-rc2 |
192 193 194 195 196 197 198 199 200 201 202 203 204 205 |
} static DEFINE_SPINLOCK(call_lock); static atomic_t scf_started; static atomic_t scf_finished; static void (*func)(void *info); static void *info; void smp_call_function_slave(int cpu) { atomic_inc(&scf_started); (*func)(info); atomic_inc(&scf_finished); } |
8691e5a8f smp_call_function... |
206 |
int smp_call_function(void (*_func)(void *info), void *_info, int wait) |
1da177e4c Linux-2.6.12-rc2 |
207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 |
{ int cpus = num_online_cpus() - 1; int i; if (!cpus) return 0; /* Can deadlock when called with interrupts disabled */ WARN_ON(irqs_disabled()); spin_lock_bh(&call_lock); atomic_set(&scf_started, 0); atomic_set(&scf_finished, 0); func = _func; info = _info; for_each_online_cpu(i) |
a6ea4ccee uml: rename os_{r... |
224 |
os_write_file(cpu_data[i].ipi_pipe[1], "C", 1); |
1da177e4c Linux-2.6.12-rc2 |
225 226 227 228 229 230 231 232 233 234 235 236 237 |
while (atomic_read(&scf_started) != cpus) barrier(); if (wait) while (atomic_read(&scf_finished) != cpus) barrier(); spin_unlock_bh(&call_lock); return 0; } #endif |