diff --git a/headers/private/kernel/smp.h b/headers/private/kernel/smp.h index dc45086792..d88e4206bc 100644 --- a/headers/private/kernel/smp.h +++ b/headers/private/kernel/smp.h @@ -91,6 +91,11 @@ int32 smp_get_current_cpu(void); int smp_intercpu_int_handler(int32 cpu); +void call_single_cpu(uint32 targetCPU, void (*func)(void*, int), void* cookie); +void call_single_cpu_sync(uint32 targetCPU, void (*func)(void*, int), + void* cookie); + + #ifdef __cplusplus } #endif diff --git a/src/system/kernel/smp.cpp b/src/system/kernel/smp.cpp index e949a50c1f..ed259d38ae 100644 --- a/src/system/kernel/smp.cpp +++ b/src/system/kernel/smp.cpp @@ -1489,6 +1489,45 @@ smp_get_current_cpu(void) } +static void +_call_single_cpu(uint32 targetCPU, void (*func)(void*, int), void* cookie, bool sync) +{ + cpu_status state = disable_interrupts(); + + if (targetCPU == (uint32)smp_get_current_cpu()) { + func(cookie, smp_get_current_cpu()); + restore_interrupts(state); + return; + } + + if (!sICIEnabled) { + // Early mechanism not available + panic("call_single_cpu is not yet available"); + restore_interrupts(state); + return; + } + + smp_send_ici(targetCPU, SMP_MSG_CALL_FUNCTION, (addr_t)cookie, + 0, 0, (void*)func, sync ? SMP_MSG_FLAG_SYNC : SMP_MSG_FLAG_ASYNC); + + restore_interrupts(state); +} + + +void +call_single_cpu(uint32 targetCPU, void (*func)(void*, int), void* cookie) +{ + return _call_single_cpu(targetCPU, func, cookie, false); +} + + +void +call_single_cpu_sync(uint32 targetCPU, void (*func)(void*, int), void* cookie) +{ + return _call_single_cpu(targetCPU, func, cookie, true); +} + + // #pragma mark - public exported functions