X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?a=blobdiff_plain;f=kitten%2Fkernel%2Fxcall.c;fp=kitten%2Fkernel%2Fxcall.c;h=cd5ace8ff6cf01fa20fbc944f5ef91320ea1cf07;hb=66a1a4c7a9edcd7d8bc207aca093d694a6e6b5b2;hp=0000000000000000000000000000000000000000;hpb=f7cf9c19ecb0a589dd45ae0d2c91814bd3c2acc2;p=palacios.git diff --git a/kitten/kernel/xcall.c b/kitten/kernel/xcall.c new file mode 100644 index 0000000..cd5ace8 --- /dev/null +++ b/kitten/kernel/xcall.c @@ -0,0 +1,71 @@ +#include +#include +#include + +/** + * Carries out an inter-CPU function call. The specified function is executed + * on all of the target CPUs that are currently online and executes in + * interrupt context with interrupts disabled... it must not block and should + * be short. + * + * Arguments: + * [IN] cpu_mask: The target CPUs of the cross-call. + * [IN] func: The function to execute on each target CPU. + * [IN] info: Argument to pass to func(). + * [IN] wait: true = wait for cross-call to fully complete. + * + * Returns: + * Success: 0 + * Failure: Error code + * + * NOTE: If wait=0, care must be taken to ensure that the data pointed to by + * the info argument remains valid until the cross-call function func() + * completes on all target CPUs. + */ +int +xcall_function( + cpumask_t cpu_mask, + void (*func)(void *info), + void * info, + bool wait +) +{ + bool contains_me; + int status; + + BUG_ON(irqs_disabled()); + BUG_ON(!func); + + /* Only target online CPUs */ + cpus_and(cpu_mask, cpu_mask, cpu_online_map); + + /* No need to xcall ourself... we'll just call func() directly */ + if ((contains_me = cpu_isset(this_cpu, cpu_mask))) + cpu_clear(this_cpu, cpu_mask); + + /* Perform xcall to remote CPUs */ + if ((status = arch_xcall_function(cpu_mask, func, info, wait))) + return status; + + /* Call func() on the local CPU, if it was in cpu_mask */ + if (contains_me) + (*func)(info); + + return 0; +} + +/** + * Sends a reschedule inter-processor interrupt to the target CPU. + * This causes the target CPU to call schedule(). + * + * NOTE: It is safe to call this with locks held and interrupts + * disabled so long as the caller will drop the locks and + * re-enable interrupts "soon", independent of whether the + * target actually receives the reschedule interrupt. + * Deadlock may occur if these conditions aren't met. + */ +void +xcall_reschedule(id_t cpu) +{ + arch_xcall_reschedule(cpu); +}