Added a real yield function to the kernel (using the next_priority approach).
The test application lets run a thread at the highest priority that calls yield all the time - the system stays responsible when it runs, so it seems to work fine :) Changed the malloc implementation to use _kern_thread_yield() instead of snoozing. We should think about making this call public, too. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@16166 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -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_set_thread_priority(thread_id thread, int32 newPriority);
|
||||||
extern status_t _kern_kill_thread(thread_id thread);
|
extern status_t _kern_kill_thread(thread_id thread);
|
||||||
extern void _kern_exit_thread(status_t returnValue);
|
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 status_t _kern_wait_for_thread(thread_id thread, status_t *_returnCode);
|
||||||
extern bool _kern_has_data(thread_id thread);
|
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);
|
extern status_t _kern_send_data(thread_id thread, int32 code, const void *buffer, size_t bufferSize);
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2002-2005, Axel Dörfler, [email protected].
|
* Copyright 2002-2006, Axel Dörfler, [email protected].
|
||||||
* Distributed under the terms of the MIT License.
|
* Distributed under the terms of the MIT License.
|
||||||
*
|
*
|
||||||
* Copyright 2001-2002, Travis Geiselbrecht. All rights reserved.
|
* 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_init(struct kernel_args *args);
|
||||||
status_t thread_per_cpu_init(int32 cpuNum);
|
status_t thread_per_cpu_init(int32 cpuNum);
|
||||||
|
void thread_yield(void);
|
||||||
void thread_exit(void);
|
void thread_exit(void);
|
||||||
|
|
||||||
bigtime_t thread_get_active_cpu_time(int32 cpuNum);
|
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_wait_for_thread(thread_id id, status_t *_returnCode);
|
||||||
status_t _user_snooze_etc(bigtime_t timeout, int timebase, uint32 flags);
|
status_t _user_snooze_etc(bigtime_t timeout, int timebase, uint32 flags);
|
||||||
status_t _user_kill_thread(thread_id thread);
|
status_t _user_kill_thread(thread_id thread);
|
||||||
|
void _user_thread_yield(void);
|
||||||
void _user_exit_thread(status_t return_value);
|
void _user_exit_thread(status_t return_value);
|
||||||
bool _user_has_data(thread_id thread);
|
bool _user_has_data(thread_id thread);
|
||||||
status_t _user_send_data(thread_id thread, int32 code, const void *buffer, size_t buffer_size);
|
status_t _user_send_data(thread_id thread, int32 code, const void *buffer, size_t buffer_size);
|
||||||
|
|||||||
@@ -1232,19 +1232,40 @@ thread_dequeue_id(struct thread_queue *q, thread_id id)
|
|||||||
|
|
||||||
|
|
||||||
thread_id
|
thread_id
|
||||||
allocate_thread_id()
|
allocate_thread_id(void)
|
||||||
{
|
{
|
||||||
return atomic_add(&sNextThreadID, 1);
|
return atomic_add(&sNextThreadID, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
thread_id
|
thread_id
|
||||||
peek_next_thread_id()
|
peek_next_thread_id(void)
|
||||||
{
|
{
|
||||||
return atomic_get(&sNextThreadID);
|
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.
|
/** Kernel private thread creation function.
|
||||||
*
|
*
|
||||||
* \param threadID The ID to be assigned to the new thread. If
|
* \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
|
status_t
|
||||||
_user_get_thread_info(thread_id id, thread_info *userInfo)
|
_user_get_thread_info(thread_id id, thread_info *userInfo)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -317,10 +317,7 @@ hoardUnlock(hoardLockType &lock)
|
|||||||
void
|
void
|
||||||
hoardYield(void)
|
hoardYield(void)
|
||||||
{
|
{
|
||||||
// We need to snooze longer than a thread quantum (3ms) to ensure
|
_kern_thread_yield();
|
||||||
// real-time threads won't hog the CPU completely
|
|
||||||
// ToDo: we should have a real one in the kernel
|
|
||||||
snooze(4000);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace BPrivate
|
} // namespace BPrivate
|
||||||
|
|||||||
@@ -1,20 +1,19 @@
|
|||||||
SubDir HAIKU_TOP src tests system kernel ;
|
SubDir HAIKU_TOP src tests system kernel ;
|
||||||
|
|
||||||
UsePrivateHeaders kernel ;
|
UsePrivateHeaders kernel ;
|
||||||
|
UseHeaders $(TARGET_PRIVATE_KERNEL_HEADERS) : true ;
|
||||||
if $(TARGET_PLATFORM) = r5 {
|
|
||||||
LIBROOT = root ;
|
|
||||||
} else {
|
|
||||||
LIBROOT = libroot.so ;
|
|
||||||
}
|
|
||||||
|
|
||||||
SimpleTest transfer_area_test :
|
SimpleTest transfer_area_test :
|
||||||
transfer_area_test.cpp
|
transfer_area_test.cpp
|
||||||
: libroot.so ;
|
;
|
||||||
|
|
||||||
SimpleTest syscall_time :
|
SimpleTest syscall_time :
|
||||||
syscall_time.cpp
|
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 cache ;
|
||||||
#SubInclude HAIKU_TOP src tests system kernel disk_device_manager ;
|
#SubInclude HAIKU_TOP src tests system kernel disk_device_manager ;
|
||||||
|
|||||||
@@ -0,0 +1,33 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2006, Axel Dörfler, axeld@pinc-software.de.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <OS.h>
|
||||||
|
#include <syscalls.h>
|
||||||
|
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user