From 026c8b9c040966d5ccfbae23bac19eddc040c8d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Duval?= Date: Thu, 10 Sep 2020 22:16:56 +0200 Subject: [PATCH] kernel/smp: add call_single_cpu() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit to call a function on the target cpu. Early mechanism not available. Change-Id: I9d049e618c319c59729d1ab53fb313b748f82315 Reviewed-on: https://review.haiku-os.org/c/haiku/+/3212 Reviewed-by: Axel Dörfler --- headers/private/kernel/smp.h | 5 +++++ src/system/kernel/smp.cpp | 39 ++++++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+) 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