haiku/headers/private/kernel/smp.h

108 lines
2.6 KiB
C
Raw Normal View History

/*
* Copyright 2002-2005, Axel Dörfler, axeld@pinc-software.de.
* Distributed under the terms of the MIT License.
*
* Copyright 2001-2002, Travis Geiselbrecht. All rights reserved.
* Distributed under the terms of the NewOS License.
*/
#ifndef KERNEL_SMP_H
#define KERNEL_SMP_H
#include <KernelExport.h>
struct kernel_args;
// intercpu messages
enum {
SMP_MSG_INVALIDATE_PAGE_RANGE = 0,
SMP_MSG_INVALIDATE_PAGE_LIST,
SMP_MSG_USER_INVALIDATE_PAGES,
SMP_MSG_GLOBAL_INVALIDATE_PAGES,
SMP_MSG_CPU_HALT,
SMP_MSG_CALL_FUNCTION,
SMP_MSG_RESCHEDULE,
SMP_MSG_RESCHEDULE_IF_IDLE
};
enum {
SMP_MSG_FLAG_ASYNC = 0x0,
SMP_MSG_FLAG_SYNC = 0x1,
SMP_MSG_FLAG_FREE_ARG = 0x2,
};
typedef uint32 cpu_mask_t;
typedef void (*smp_call_func)(uint32 data1, int32 currentCPU, uint32 data2, uint32 data3);
#ifdef __cplusplus
extern "C" {
#endif
bool try_acquire_spinlock(spinlock* lock);
status_t smp_init(struct kernel_args *args);
status_t smp_per_cpu_init(struct kernel_args *args, int32 cpu);
status_t smp_init_post_generic_syscalls(void);
bool smp_trap_non_boot_cpus(int32 cpu, uint32* rendezVous);
void smp_wake_up_non_boot_cpus(void);
void smp_cpu_rendezvous(volatile uint32 *var, int current_cpu);
void smp_send_ici(int32 targetCPU, int32 message, uint32 data, uint32 data2, uint32 data3,
void *data_ptr, uint32 flags);
void smp_send_multicast_ici(cpu_mask_t cpuMask, int32 message, uint32 data,
uint32 data2, uint32 data3, void *data_ptr, uint32 flags);
void smp_send_broadcast_ici(int32 message, uint32 data, uint32 data2, uint32 data3,
void *data_ptr, uint32 flags);
More work towards making our double fault handler less triple fault prone: * SMP: - Added smp_send_broadcast_ici_interrupts_disabled(), which is basically equivalent to smp_send_broadcast_ici(), but is only called with interrupts disabled and gets the CPU index, so it doesn't have to use smp_get_current_cpu() (which dereferences the current thread). - Added cpu index parameter to smp_intercpu_int_handler(). * x86: - arch_int.c -> arch_int.cpp - Set up an IDT per CPU. We were using a single IDT for all CPUs, but that can't work, since we need different tasks for the double fault interrupt vector. - Set the per CPU double fault task gates correctly. - Renamed set_intr_gate() to set_interrupt_gate and set_system_gate() to set_trap_gate() and documented them a bit. - Renamed double_fault_exception() x86_double_fault_exception() and fixed it not to use smp_get_current_cpu(). Instead we have the new x86_double_fault_get_cpu() that deducts the CPU index from the used stack. - Fixed the double_fault interrupt handler: It no longer calls int_bottom to avoid accessing the current thread. * debug.cpp: - Introduced explicit debug_double_fault() to enter the kernel debugger from a double fault handler. - Avoid using smp_get_current_cpu(). - Don't use kprintf() before sDebuggerOnCPU is set. Otherwise acquire_spinlock() is invoked by arch_debug_serial_puts(). Things look a bit better when the current thread pointer is broken -- we run into kernel_debugger_loop() and successfully print the "Welcome to KDL" message -- but we still dereference the thread pointer afterwards, so that we don't get a usable kernel debugger yet. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@32050 a95241bf-73f2-0310-859d-f6bbb57e9c96
2009-08-01 05:53:54 +04:00
void smp_send_broadcast_ici_interrupts_disabled(int32 currentCPU, int32 message,
uint32 data, uint32 data2, uint32 data3, void *data_ptr, uint32 flags);
int32 smp_get_num_cpus(void);
void smp_set_num_cpus(int32 numCPUs);
int32 smp_get_current_cpu(void);
More work towards making our double fault handler less triple fault prone: * SMP: - Added smp_send_broadcast_ici_interrupts_disabled(), which is basically equivalent to smp_send_broadcast_ici(), but is only called with interrupts disabled and gets the CPU index, so it doesn't have to use smp_get_current_cpu() (which dereferences the current thread). - Added cpu index parameter to smp_intercpu_int_handler(). * x86: - arch_int.c -> arch_int.cpp - Set up an IDT per CPU. We were using a single IDT for all CPUs, but that can't work, since we need different tasks for the double fault interrupt vector. - Set the per CPU double fault task gates correctly. - Renamed set_intr_gate() to set_interrupt_gate and set_system_gate() to set_trap_gate() and documented them a bit. - Renamed double_fault_exception() x86_double_fault_exception() and fixed it not to use smp_get_current_cpu(). Instead we have the new x86_double_fault_get_cpu() that deducts the CPU index from the used stack. - Fixed the double_fault interrupt handler: It no longer calls int_bottom to avoid accessing the current thread. * debug.cpp: - Introduced explicit debug_double_fault() to enter the kernel debugger from a double fault handler. - Avoid using smp_get_current_cpu(). - Don't use kprintf() before sDebuggerOnCPU is set. Otherwise acquire_spinlock() is invoked by arch_debug_serial_puts(). Things look a bit better when the current thread pointer is broken -- we run into kernel_debugger_loop() and successfully print the "Welcome to KDL" message -- but we still dereference the thread pointer afterwards, so that we don't get a usable kernel debugger yet. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@32050 a95241bf-73f2-0310-859d-f6bbb57e9c96
2009-08-01 05:53:54 +04:00
int smp_intercpu_int_handler(int32 cpu);
#ifdef __cplusplus
}
#endif
// Unless spinlock debug features are enabled, try to inline
// {acquire,release}_spinlock().
#if !DEBUG_SPINLOCKS && !B_DEBUG_SPINLOCK_CONTENTION
static inline bool
try_acquire_spinlock_inline(spinlock* lock)
{
return atomic_or((int32*)lock, 1) == 0;
}
static inline void
acquire_spinlock_inline(spinlock* lock)
{
if (try_acquire_spinlock_inline(lock))
return;
acquire_spinlock(lock);
}
static inline void
release_spinlock_inline(spinlock* lock)
{
atomic_and((int32*)lock, 0);
}
#define try_acquire_spinlock(lock) try_acquire_spinlock_inline(lock)
#define acquire_spinlock(lock) acquire_spinlock_inline(lock)
#define release_spinlock(lock) release_spinlock_inline(lock)
#endif // !DEBUG_SPINLOCKS && !B_DEBUG_SPINLOCK_CONTENTION
#endif /* KERNEL_SMP_H */