1 /* 2 * Copyright (c) 2014 Travis Geiselbrecht 3 * 4 * Use of this source code is governed by a MIT-style 5 * license that can be found in the LICENSE file or at 6 * https://opensource.org/licenses/MIT 7 */ 8 #pragma once 9 10 #include <kernel/thread.h> 11 #include <limits.h> 12 #include <lk/compiler.h> 13 #include <stdbool.h> 14 #include <stdint.h> 15 16 __BEGIN_CDECLS 17 18 typedef uint32_t mp_cpu_mask_t; 19 20 #define MP_CPU_ALL_BUT_LOCAL (UINT32_MAX) 21 22 /* by default, mp_mbx_reschedule does not signal to cpus that are running realtime 23 * threads. Override this behavior. 24 */ 25 #define MP_RESCHEDULE_FLAG_REALTIME (0x1) 26 27 typedef enum { 28 MP_IPI_GENERIC, 29 MP_IPI_RESCHEDULE, 30 } mp_ipi_t; 31 32 #ifdef WITH_SMP 33 void mp_init(void); 34 35 void mp_reschedule(mp_cpu_mask_t target, uint flags); 36 void mp_set_curr_cpu_active(bool active); 37 38 /* called from arch code during reschedule irq */ 39 enum handler_return mp_mbx_reschedule_irq(void); 40 41 /* global mp state to track what the cpus are up to */ 42 struct mp_state { 43 volatile mp_cpu_mask_t active_cpus; 44 45 /* only safely accessible with thread lock held */ 46 mp_cpu_mask_t idle_cpus; 47 mp_cpu_mask_t realtime_cpus; 48 }; 49 50 extern struct mp_state mp; 51 mp_is_cpu_active(uint cpu)52static inline int mp_is_cpu_active(uint cpu) { 53 return mp.active_cpus & (1 << cpu); 54 } 55 mp_is_cpu_idle(uint cpu)56static inline int mp_is_cpu_idle(uint cpu) { 57 return mp.idle_cpus & (1 << cpu); 58 } 59 60 /* must be called with the thread lock held */ mp_set_cpu_idle(uint cpu)61static inline void mp_set_cpu_idle(uint cpu) { 62 mp.idle_cpus |= 1UL << cpu; 63 } 64 mp_set_cpu_busy(uint cpu)65static inline void mp_set_cpu_busy(uint cpu) { 66 mp.idle_cpus &= ~(1UL << cpu); 67 } 68 mp_get_idle_mask(void)69static inline mp_cpu_mask_t mp_get_idle_mask(void) { 70 return mp.idle_cpus; 71 } 72 mp_set_cpu_realtime(uint cpu)73static inline void mp_set_cpu_realtime(uint cpu) { 74 mp.realtime_cpus |= 1UL << cpu; 75 } 76 mp_set_cpu_non_realtime(uint cpu)77static inline void mp_set_cpu_non_realtime(uint cpu) { 78 mp.realtime_cpus &= ~(1UL << cpu); 79 } 80 mp_get_realtime_mask(void)81static inline mp_cpu_mask_t mp_get_realtime_mask(void) { 82 return mp.realtime_cpus; 83 } 84 #else mp_init(void)85static inline void mp_init(void) {} mp_reschedule(mp_cpu_mask_t target,uint flags)86static inline void mp_reschedule(mp_cpu_mask_t target, uint flags) {} mp_set_curr_cpu_active(bool active)87static inline void mp_set_curr_cpu_active(bool active) {} 88 mp_mbx_reschedule_irq(void)89static inline enum handler_return mp_mbx_reschedule_irq(void) { return INT_NO_RESCHEDULE; } 90 91 // only one cpu exists in UP and if you're calling these functions, it's active... mp_is_cpu_active(uint cpu)92static inline int mp_is_cpu_active(uint cpu) { return 1; } mp_is_cpu_idle(uint cpu)93static inline int mp_is_cpu_idle(uint cpu) { return (get_current_thread()->flags & THREAD_FLAG_IDLE) != 0; } 94 mp_set_cpu_idle(uint cpu)95static inline void mp_set_cpu_idle(uint cpu) {} mp_set_cpu_busy(uint cpu)96static inline void mp_set_cpu_busy(uint cpu) {} 97 mp_get_idle_mask(void)98static inline mp_cpu_mask_t mp_get_idle_mask(void) { return 0; } 99 mp_set_cpu_realtime(uint cpu)100static inline void mp_set_cpu_realtime(uint cpu) {} mp_set_cpu_non_realtime(uint cpu)101static inline void mp_set_cpu_non_realtime(uint cpu) {} 102 mp_get_realtime_mask(void)103static inline mp_cpu_mask_t mp_get_realtime_mask(void) { return 0; } 104 #endif 105 106 __END_CDECLS 107