diff --git a/headers/private/kernel/syscalls.h b/headers/private/kernel/syscalls.h index 62afb6d17c..670f4b92ea 100644 --- a/headers/private/kernel/syscalls.h +++ b/headers/private/kernel/syscalls.h @@ -96,6 +96,7 @@ extern status_t _kern_rename_thread(thread_id thread, const char *newName); extern status_t _kern_set_thread_priority(thread_id thread, int32 newPriority); extern status_t _kern_kill_thread(thread_id thread); extern void _kern_exit_thread(status_t returnValue); +extern void _kern_thread_yield(void); extern status_t _kern_wait_for_thread(thread_id thread, status_t *_returnCode); extern bool _kern_has_data(thread_id thread); extern status_t _kern_send_data(thread_id thread, int32 code, const void *buffer, size_t bufferSize); diff --git a/headers/private/kernel/thread.h b/headers/private/kernel/thread.h index 6b32ab8d66..bc5c037110 100644 --- a/headers/private/kernel/thread.h +++ b/headers/private/kernel/thread.h @@ -1,5 +1,5 @@ /* - * Copyright 2002-2005, Axel Dörfler, axeld@pinc-software.de. + * Copyright 2002-2006, Axel Dörfler, axeld@pinc-software.de. * Distributed under the terms of the MIT License. * * Copyright 2001-2002, Travis Geiselbrecht. All rights reserved. @@ -31,6 +31,7 @@ void thread_at_kernel_exit(void); status_t thread_init(struct kernel_args *args); status_t thread_per_cpu_init(int32 cpuNum); +void thread_yield(void); void thread_exit(void); bigtime_t thread_get_active_cpu_time(int32 cpuNum); @@ -66,6 +67,7 @@ thread_id _user_spawn_thread(thread_entry_func entry, const char *name, int32 pr status_t _user_wait_for_thread(thread_id id, status_t *_returnCode); status_t _user_snooze_etc(bigtime_t timeout, int timebase, uint32 flags); status_t _user_kill_thread(thread_id thread); +void _user_thread_yield(void); void _user_exit_thread(status_t return_value); bool _user_has_data(thread_id thread); status_t _user_send_data(thread_id thread, int32 code, const void *buffer, size_t buffer_size); diff --git a/src/system/kernel/thread.c b/src/system/kernel/thread.c index 47fd19a2da..d2aa2ef12d 100644 --- a/src/system/kernel/thread.c +++ b/src/system/kernel/thread.c @@ -1232,19 +1232,40 @@ thread_dequeue_id(struct thread_queue *q, thread_id id) thread_id -allocate_thread_id() +allocate_thread_id(void) { return atomic_add(&sNextThreadID, 1); } thread_id -peek_next_thread_id() +peek_next_thread_id(void) { return atomic_get(&sNextThreadID); } +void +thread_yield(void) +{ + cpu_status state; + + struct thread *thread = thread_get_current_thread(); + if (thread == NULL) + return; + + state = disable_interrupts(); + GRAB_THREAD_LOCK(); + + // just add the thread at the end of the run queue + thread->next_priority = B_LOWEST_ACTIVE_PRIORITY; + scheduler_reschedule(); + + RELEASE_THREAD_LOCK(); + restore_interrupts(state); +} + + /** Kernel private thread creation function. * * \param threadID The ID to be assigned to the new thread. If @@ -2044,6 +2065,13 @@ _user_snooze_etc(bigtime_t timeout, int timebase, uint32 flags) } +void +_user_thread_yield(void) +{ + thread_yield(); +} + + status_t _user_get_thread_info(thread_id id, thread_info *userInfo) { diff --git a/src/system/libroot/posix/malloc/arch-specific.cpp b/src/system/libroot/posix/malloc/arch-specific.cpp index ef780e594f..0afb82d71f 100644 --- a/src/system/libroot/posix/malloc/arch-specific.cpp +++ b/src/system/libroot/posix/malloc/arch-specific.cpp @@ -317,10 +317,7 @@ hoardUnlock(hoardLockType &lock) void hoardYield(void) { - // We need to snooze longer than a thread quantum (3ms) to ensure - // real-time threads won't hog the CPU completely - // ToDo: we should have a real one in the kernel - snooze(4000); + _kern_thread_yield(); } } // namespace BPrivate diff --git a/src/tests/system/kernel/Jamfile b/src/tests/system/kernel/Jamfile index 298deca031..85a3f41e8a 100644 --- a/src/tests/system/kernel/Jamfile +++ b/src/tests/system/kernel/Jamfile @@ -1,20 +1,19 @@ SubDir HAIKU_TOP src tests system kernel ; UsePrivateHeaders kernel ; - -if $(TARGET_PLATFORM) = r5 { - LIBROOT = root ; -} else { - LIBROOT = libroot.so ; -} +UseHeaders $(TARGET_PRIVATE_KERNEL_HEADERS) : true ; SimpleTest transfer_area_test : transfer_area_test.cpp - : libroot.so ; + ; SimpleTest syscall_time : syscall_time.cpp - : $(LIBROOT) ; + ; + +SimpleTest yield_test : + yield_test.cpp + ; SubInclude HAIKU_TOP src tests system kernel cache ; #SubInclude HAIKU_TOP src tests system kernel disk_device_manager ; diff --git a/src/tests/system/kernel/yield_test.cpp b/src/tests/system/kernel/yield_test.cpp new file mode 100644 index 0000000000..28b3e235bb --- /dev/null +++ b/src/tests/system/kernel/yield_test.cpp @@ -0,0 +1,33 @@ +/* + * Copyright 2006, Axel Dörfler, axeld@pinc-software.de. + * Distributed under the terms of the MIT License. + */ + + +#include +#include + + +status_t +looper(void *) +{ + while (true) { + _kern_thread_yield(); + } + + return B_OK; +} + + +int +main() +{ + thread_id thread = spawn_thread(looper, "Real-Time Looper", B_REAL_TIME_PRIORITY, NULL); + if (thread < B_OK) + return -1; + + resume_thread(thread); + wait_for_thread(thread, NULL); + + return 0; +}