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:
Axel Dörfler 2006-01-31 02:29:02 +00:00
parent d14af9fde6
commit 204131dc97
6 changed files with 75 additions and 15 deletions

View File

@ -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);

View File

@ -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);

View File

@ -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)
{

View File

@ -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

View File

@ -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 ;

View File

@ -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;
}