Broke kernelland_emu.cpp into several source files.
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@29447 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
aa4ba93e25
commit
52c8e07fde
@ -1,32 +1,9 @@
|
|||||||
SubDir HAIKU_TOP src tests add-ons kernel ;
|
SubDir HAIKU_TOP src tests add-ons kernel ;
|
||||||
|
|
||||||
UsePrivateHeaders [ FDirName kernel ] ;
|
|
||||||
UsePrivateHeaders shared ;
|
|
||||||
UseHeaders $(TARGET_PRIVATE_KERNEL_HEADERS) : true ;
|
|
||||||
|
|
||||||
SharedLibrary libkernelland_emu.so :
|
|
||||||
kernelland_emu.cpp
|
|
||||||
strlcpy.c
|
|
||||||
khash.c
|
|
||||||
list.c
|
|
||||||
|
|
||||||
: be $(TARGET_LIBSTDC++) ;
|
|
||||||
|
|
||||||
AbsSymLink <boot!home!config!lib>libkernelland_emu.so : libkernelland_emu.so
|
|
||||||
: /boot/home/config/lib : false ;
|
|
||||||
|
|
||||||
SEARCH on [ FGristFiles
|
|
||||||
strlcpy.c
|
|
||||||
] = [ FDirName $(HAIKU_TOP) src system libroot posix string ] ;
|
|
||||||
|
|
||||||
SEARCH on [ FGristFiles
|
|
||||||
list.c khash.c
|
|
||||||
] = [ FDirName $(HAIKU_TOP) src system kernel util ] ;
|
|
||||||
|
|
||||||
SubInclude HAIKU_TOP src tests add-ons kernel bus_managers ;
|
SubInclude HAIKU_TOP src tests add-ons kernel bus_managers ;
|
||||||
SubInclude HAIKU_TOP src tests add-ons kernel busses ;
|
SubInclude HAIKU_TOP src tests add-ons kernel busses ;
|
||||||
SubInclude HAIKU_TOP src tests add-ons kernel debugger ;
|
SubInclude HAIKU_TOP src tests add-ons kernel debugger ;
|
||||||
# SubInclude HAIKU_TOP src tests add-ons kernel disk_scanner ;
|
|
||||||
SubInclude HAIKU_TOP src tests add-ons kernel drivers ;
|
SubInclude HAIKU_TOP src tests add-ons kernel drivers ;
|
||||||
SubInclude HAIKU_TOP src tests add-ons kernel file_systems ;
|
SubInclude HAIKU_TOP src tests add-ons kernel file_systems ;
|
||||||
|
SubInclude HAIKU_TOP src tests add-ons kernel kernelland_emu ;
|
||||||
SubInclude HAIKU_TOP src tests add-ons kernel network ;
|
SubInclude HAIKU_TOP src tests add-ons kernel network ;
|
||||||
|
@ -21,9 +21,10 @@ SEARCH_SOURCE += $(bfsTop) ;
|
|||||||
SubDirC++Flags $(defines) -Wall -Wno-multichar -fno-rtti ;
|
SubDirC++Flags $(defines) -Wall -Wno-multichar -fno-rtti ;
|
||||||
}
|
}
|
||||||
|
|
||||||
UsePrivateHeaders [ FDirName kernel ] ;
|
UsePrivateKernelHeaders ;
|
||||||
UsePrivateHeaders [ FDirName kernel disk_device_manager ] ;
|
UsePrivateHeaders shared ;
|
||||||
UsePrivateHeaders [ FDirName storage ] ;
|
#UsePrivateHeaders [ FDirName kernel disk_device_manager ] ;
|
||||||
|
#UsePrivateHeaders [ FDirName storage ] ;
|
||||||
|
|
||||||
Addon <userland>bfs
|
Addon <userland>bfs
|
||||||
:
|
:
|
||||||
|
27
src/tests/add-ons/kernel/kernelland_emu/Jamfile
Normal file
27
src/tests/add-ons/kernel/kernelland_emu/Jamfile
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
SubDir HAIKU_TOP src tests add-ons kernel kernelland_emu ;
|
||||||
|
|
||||||
|
UsePrivateKernelHeaders ;
|
||||||
|
UsePrivateHeaders shared ;
|
||||||
|
|
||||||
|
SharedLibrary libkernelland_emu.so :
|
||||||
|
condition_variable.cpp
|
||||||
|
lock.cpp
|
||||||
|
misc.cpp
|
||||||
|
module.cpp
|
||||||
|
|
||||||
|
strlcpy.c
|
||||||
|
khash.c
|
||||||
|
list.c
|
||||||
|
|
||||||
|
: be $(TARGET_LIBSTDC++) ;
|
||||||
|
|
||||||
|
AbsSymLink <boot!home!config!lib>libkernelland_emu.so : libkernelland_emu.so
|
||||||
|
: /boot/home/config/lib : false ;
|
||||||
|
|
||||||
|
SEARCH on [ FGristFiles
|
||||||
|
strlcpy.c
|
||||||
|
] = [ FDirName $(HAIKU_TOP) src system libroot posix string ] ;
|
||||||
|
|
||||||
|
SEARCH on [ FGristFiles
|
||||||
|
list.c khash.c
|
||||||
|
] = [ FDirName $(HAIKU_TOP) src system kernel util ] ;
|
115
src/tests/add-ons/kernel/kernelland_emu/condition_variable.cpp
Normal file
115
src/tests/add-ons/kernel/kernelland_emu/condition_variable.cpp
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2002-2009, Haiku Inc. All Rights Reserved.
|
||||||
|
* Distributed under the terms of the MIT license.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Ingo Weinhold, bonefish@cs.tu-berlin.de.
|
||||||
|
* Axel Dörfler, axeld@pinc-software.de.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <condition_variable.h>
|
||||||
|
|
||||||
|
#include <new>
|
||||||
|
|
||||||
|
#include <lock.h>
|
||||||
|
|
||||||
|
|
||||||
|
#define STATUS_ADDED 1
|
||||||
|
#define STATUS_WAITING 2
|
||||||
|
|
||||||
|
|
||||||
|
struct condition_private {
|
||||||
|
mutex lock;
|
||||||
|
sem_id wait_sem;
|
||||||
|
const void* object;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
ConditionVariableEntry::Wait(uint32 flags, bigtime_t timeout)
|
||||||
|
{
|
||||||
|
if (fVariable == NULL)
|
||||||
|
return fWaitStatus;
|
||||||
|
|
||||||
|
condition_private* condition = (condition_private*)fVariable->fObject;
|
||||||
|
fWaitStatus = STATUS_WAITING;
|
||||||
|
|
||||||
|
status_t status;
|
||||||
|
do {
|
||||||
|
status = acquire_sem_etc(condition->wait_sem, 1, flags, timeout);
|
||||||
|
} while (status == B_INTERRUPTED);
|
||||||
|
|
||||||
|
mutex_lock(&condition->lock);
|
||||||
|
|
||||||
|
// remove entry from variable, if not done yet
|
||||||
|
if (fVariable != NULL) {
|
||||||
|
fVariable->fEntries.Remove(this);
|
||||||
|
fVariable = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
mutex_unlock(&condition->lock);
|
||||||
|
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline void
|
||||||
|
ConditionVariableEntry::AddToVariable(ConditionVariable* variable)
|
||||||
|
{
|
||||||
|
fVariable = variable;
|
||||||
|
fWaitStatus = STATUS_ADDED;
|
||||||
|
fVariable->fEntries.Add(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
ConditionVariable::Init(const void* object, const char* objectType)
|
||||||
|
{
|
||||||
|
fObjectType = objectType;
|
||||||
|
new(&fEntries) EntryList;
|
||||||
|
|
||||||
|
condition_private* condition = new condition_private;
|
||||||
|
mutex_init(&condition->lock, objectType);
|
||||||
|
condition->wait_sem = create_sem(0, "condition variable wait");
|
||||||
|
if (condition->wait_sem < B_OK)
|
||||||
|
panic("cannot create condition variable.");
|
||||||
|
|
||||||
|
condition->object = object;
|
||||||
|
|
||||||
|
fObject = condition;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
ConditionVariable::Add(ConditionVariableEntry* entry)
|
||||||
|
{
|
||||||
|
entry->AddToVariable(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
ConditionVariable::_Notify(bool all, bool threadsLocked)
|
||||||
|
{
|
||||||
|
condition_private* condition = (condition_private*)fObject;
|
||||||
|
mutex_lock(&condition->lock);
|
||||||
|
|
||||||
|
uint32 count = 0;
|
||||||
|
|
||||||
|
while (ConditionVariableEntry* entry = fEntries.RemoveHead()) {
|
||||||
|
entry->fVariable = NULL;
|
||||||
|
if (entry->fWaitStatus <= 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
entry->fWaitStatus = B_OK;
|
||||||
|
count++;
|
||||||
|
|
||||||
|
if (!all)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
release_sem_etc(condition->wait_sem, count, 0);
|
||||||
|
mutex_unlock(&condition->lock);
|
||||||
|
}
|
287
src/tests/add-ons/kernel/kernelland_emu/lock.cpp
Normal file
287
src/tests/add-ons/kernel/kernelland_emu/lock.cpp
Normal file
@ -0,0 +1,287 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2002-2009, Haiku Inc. All Rights Reserved.
|
||||||
|
* Distributed under the terms of the MIT license.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Ingo Weinhold, bonefish@cs.tu-berlin.de.
|
||||||
|
* Axel Dörfler, axeld@pinc-software.de.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <lock.h>
|
||||||
|
|
||||||
|
|
||||||
|
#define RW_MAX_READERS 10000
|
||||||
|
|
||||||
|
|
||||||
|
int32
|
||||||
|
recursive_lock_get_recursion(recursive_lock *lock)
|
||||||
|
{
|
||||||
|
thread_id thread = find_thread(NULL);
|
||||||
|
|
||||||
|
#if !KDEBUG
|
||||||
|
if (lock->holder == thread)
|
||||||
|
return lock->recursion;
|
||||||
|
#else
|
||||||
|
if (lock->lock.holder == thread)
|
||||||
|
return lock->recursion;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
recursive_lock_init_etc(recursive_lock *lock, const char *name, uint32 flags)
|
||||||
|
{
|
||||||
|
if (lock == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (name == NULL)
|
||||||
|
name = "recursive lock";
|
||||||
|
|
||||||
|
#if !KDEBUG
|
||||||
|
lock->holder = -1;
|
||||||
|
#else
|
||||||
|
lock->lock.holder = -1;
|
||||||
|
#endif
|
||||||
|
lock->recursion = 0;
|
||||||
|
lock->lock.waiters = (mutex_waiter*)create_sem(1, name);
|
||||||
|
|
||||||
|
if ((sem_id)lock->lock.waiters < B_OK)
|
||||||
|
panic("recursive lock creation failed: %s\n", name);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
recursive_lock_init(recursive_lock *lock, const char *name)
|
||||||
|
{
|
||||||
|
recursive_lock_init_etc(lock, name, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
recursive_lock_destroy(recursive_lock *lock)
|
||||||
|
{
|
||||||
|
if (lock == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
delete_sem((sem_id)lock->lock.waiters);
|
||||||
|
lock->lock.waiters = (mutex_waiter*)-1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
recursive_lock_lock(recursive_lock *lock)
|
||||||
|
{
|
||||||
|
thread_id thread = find_thread(NULL);
|
||||||
|
|
||||||
|
#if !KDEBUG
|
||||||
|
if (thread != lock->holder) {
|
||||||
|
status_t status;
|
||||||
|
do {
|
||||||
|
status = acquire_sem((sem_id)lock->lock.waiters);
|
||||||
|
} while (status == B_INTERRUPTED);
|
||||||
|
if (status < B_OK)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
lock->holder = thread;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
if (thread != lock->lock.holder) {
|
||||||
|
status_t status;
|
||||||
|
do {
|
||||||
|
status = acquire_sem((sem_id)lock->lock.waiters);
|
||||||
|
} while (status == B_INTERRUPTED);
|
||||||
|
if (status < B_OK)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
lock->lock.holder = thread;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
lock->recursion++;
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
recursive_lock_unlock(recursive_lock *lock)
|
||||||
|
{
|
||||||
|
#if !KDEBUG
|
||||||
|
if (find_thread(NULL) != lock->holder)
|
||||||
|
panic("recursive_lock %p unlocked by non-holder thread!\n", lock);
|
||||||
|
#else
|
||||||
|
if (find_thread(NULL) != lock->lock.holder)
|
||||||
|
panic("recursive_lock %p unlocked by non-holder thread!\n", lock);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (--lock->recursion == 0) {
|
||||||
|
#if !KDEBUG
|
||||||
|
lock->holder = -1;
|
||||||
|
#else
|
||||||
|
lock->lock.holder = -1;
|
||||||
|
#endif
|
||||||
|
release_sem_etc((sem_id)lock->lock.waiters, 1, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
mutex_init(mutex *m, const char *name)
|
||||||
|
{
|
||||||
|
if (m == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (name == NULL)
|
||||||
|
name = "mutex_sem";
|
||||||
|
|
||||||
|
// We need to store the semaphore in "waiters", as it is no sem anymore
|
||||||
|
// Also, kernel mutex creation cannot fail anymore, but we could...
|
||||||
|
m->waiters = (struct mutex_waiter *)create_sem(1, name);
|
||||||
|
if ((sem_id)m->waiters < B_OK)
|
||||||
|
debugger("semaphore creation failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
mutex_init_etc(mutex *m, const char *name, uint32 flags)
|
||||||
|
{
|
||||||
|
if (m == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (name == NULL)
|
||||||
|
name = "mutex_sem";
|
||||||
|
|
||||||
|
m->waiters = (struct mutex_waiter *)create_sem(1, name);
|
||||||
|
if ((sem_id)m->waiters < B_OK)
|
||||||
|
debugger("semaphore creation failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
mutex_destroy(mutex *mutex)
|
||||||
|
{
|
||||||
|
if (mutex == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if ((sem_id)mutex->waiters >= 0) {
|
||||||
|
delete_sem((sem_id)mutex->waiters);
|
||||||
|
mutex->waiters = (struct mutex_waiter *)-1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
_mutex_trylock(mutex *mutex)
|
||||||
|
{
|
||||||
|
status_t status;
|
||||||
|
do {
|
||||||
|
status = acquire_sem_etc((sem_id)mutex->waiters, 1, B_RELATIVE_TIMEOUT,
|
||||||
|
0);
|
||||||
|
} while (status == B_INTERRUPTED);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
_mutex_lock(mutex *mutex, bool threadsLocked)
|
||||||
|
{
|
||||||
|
if (mutex->waiters == NULL) {
|
||||||
|
// MUTEX_INITIALIZER has been used; this is not thread-safe!
|
||||||
|
mutex_init(mutex, mutex->name);
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t status;
|
||||||
|
do {
|
||||||
|
status = acquire_sem((sem_id)mutex->waiters);
|
||||||
|
} while (status == B_INTERRUPTED);
|
||||||
|
|
||||||
|
#if KDEBUG
|
||||||
|
if (status == B_OK)
|
||||||
|
mutex->holder = find_thread(NULL);
|
||||||
|
#endif
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
_mutex_unlock(mutex *mutex, bool threadsLocked)
|
||||||
|
{
|
||||||
|
#if KDEBUG
|
||||||
|
mutex->holder = -1;
|
||||||
|
#endif
|
||||||
|
release_sem((sem_id)mutex->waiters);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
rw_lock_init_etc(rw_lock *lock, const char *name, uint32 flags)
|
||||||
|
{
|
||||||
|
if (lock == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (name == NULL)
|
||||||
|
name = "r/w lock";
|
||||||
|
|
||||||
|
lock->waiters = (rw_lock_waiter*)create_sem(RW_MAX_READERS, name);
|
||||||
|
if ((sem_id)lock->waiters < B_OK)
|
||||||
|
panic("r/w lock \"%s\" creation failed.", name);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
rw_lock_init(rw_lock *lock, const char *name)
|
||||||
|
{
|
||||||
|
rw_lock_init_etc(lock, name, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
rw_lock_destroy(rw_lock *lock)
|
||||||
|
{
|
||||||
|
if (lock == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
delete_sem((sem_id)lock->waiters);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
rw_lock_read_lock(rw_lock *lock)
|
||||||
|
{
|
||||||
|
status_t status;
|
||||||
|
do {
|
||||||
|
status = acquire_sem((sem_id)lock->waiters);
|
||||||
|
} while (status == B_INTERRUPTED);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
rw_lock_read_unlock(rw_lock *lock)
|
||||||
|
{
|
||||||
|
return release_sem((sem_id)lock->waiters);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
rw_lock_write_lock(rw_lock *lock)
|
||||||
|
{
|
||||||
|
status_t status;
|
||||||
|
do {
|
||||||
|
status = acquire_sem_etc((sem_id)lock->waiters, RW_MAX_READERS, 0, 0);
|
||||||
|
} while (status == B_INTERRUPTED);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
rw_lock_write_unlock(rw_lock *lock)
|
||||||
|
{
|
||||||
|
return release_sem_etc((sem_id)lock->waiters, RW_MAX_READERS, 0);
|
||||||
|
}
|
346
src/tests/add-ons/kernel/kernelland_emu/misc.cpp
Normal file
346
src/tests/add-ons/kernel/kernelland_emu/misc.cpp
Normal file
@ -0,0 +1,346 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2002-2008, Haiku Inc. All Rights Reserved.
|
||||||
|
* Distributed under the terms of the MIT license.
|
||||||
|
*
|
||||||
|
* Authors:
|
||||||
|
* Ingo Weinhold, bonefish@cs.tu-berlin.de.
|
||||||
|
* Axel Dörfler, axeld@pinc-software.de.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <signal.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include <KernelExport.h>
|
||||||
|
#include <module.h>
|
||||||
|
|
||||||
|
#include <low_resource_manager.h>
|
||||||
|
#include <fs/devfs.h>
|
||||||
|
#include <kscheduler.h>
|
||||||
|
#include <slab/Slab.h>
|
||||||
|
|
||||||
|
|
||||||
|
bool gDebugOutputEnabled = true;
|
||||||
|
|
||||||
|
|
||||||
|
thread_id
|
||||||
|
spawn_kernel_thread(thread_func func, const char *name, int32 priority,
|
||||||
|
void *data)
|
||||||
|
{
|
||||||
|
return spawn_thread(func, name, priority, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
extern "C" status_t
|
||||||
|
devfs_unpublish_partition(const char *path)
|
||||||
|
{
|
||||||
|
printf("unpublish partition: %s\n", path);
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
extern "C" status_t
|
||||||
|
devfs_publish_partition(const char *path, const partition_info *info)
|
||||||
|
{
|
||||||
|
if (info == NULL)
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
|
printf("publish partition: %s (device \"%s\", size %Ld)\n", path, info->device, info->size);
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
extern "C" int32
|
||||||
|
atomic_test_and_set(vint32 *value, int32 newValue, int32 testAgainst)
|
||||||
|
{
|
||||||
|
#if __INTEL__
|
||||||
|
int32 oldValue;
|
||||||
|
asm volatile("lock; cmpxchg %%ecx, (%%edx)"
|
||||||
|
: "=a" (oldValue) : "a" (testAgainst), "c" (newValue), "d" (value));
|
||||||
|
return oldValue;
|
||||||
|
#else
|
||||||
|
#warn "atomic_test_and_set() won't work correctly!"
|
||||||
|
int32 oldValue = *value;
|
||||||
|
if (oldValue == testAgainst)
|
||||||
|
*value = newValue;
|
||||||
|
|
||||||
|
return oldValue;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
extern "C" int
|
||||||
|
send_signal_etc(pid_t thread, uint signal, uint32 flags)
|
||||||
|
{
|
||||||
|
return send_signal(thread, signal);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
extern "C" int32
|
||||||
|
low_resource_state(uint32 resources)
|
||||||
|
{
|
||||||
|
return B_NO_LOW_RESOURCE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
extern "C" void
|
||||||
|
low_resource(uint32 resource, uint64 requirements, uint32 flags,
|
||||||
|
uint32 timeout)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
extern "C" status_t
|
||||||
|
register_low_resource_handler(low_resource_func function, void *data,
|
||||||
|
uint32 resources, int32 priority)
|
||||||
|
{
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
extern "C" status_t
|
||||||
|
unregister_low_resource_handler(low_resource_func function, void *data)
|
||||||
|
{
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
extern "C" void
|
||||||
|
panic(const char *format, ...)
|
||||||
|
{
|
||||||
|
va_list args;
|
||||||
|
|
||||||
|
puts("*** PANIC ***");
|
||||||
|
va_start(args, format);
|
||||||
|
vprintf(format, args);
|
||||||
|
va_end(args);
|
||||||
|
|
||||||
|
putchar('\n');
|
||||||
|
debugger("Kernel Panic");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
extern "C" void
|
||||||
|
dprintf(const char *format,...)
|
||||||
|
{
|
||||||
|
if (!gDebugOutputEnabled)
|
||||||
|
return;
|
||||||
|
|
||||||
|
va_list args;
|
||||||
|
va_start(args, format);
|
||||||
|
printf("\33[34m");
|
||||||
|
vprintf(format, args);
|
||||||
|
printf("\33[0m");
|
||||||
|
fflush(stdout);
|
||||||
|
va_end(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
extern "C" void
|
||||||
|
kprintf(const char *format,...)
|
||||||
|
{
|
||||||
|
va_list args;
|
||||||
|
va_start(args, format);
|
||||||
|
printf("\33[35m");
|
||||||
|
vprintf(format, args);
|
||||||
|
printf("\33[0m");
|
||||||
|
fflush(stdout);
|
||||||
|
va_end(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
extern "C" void
|
||||||
|
dump_block(const char *buffer, int size, const char *prefix)
|
||||||
|
{
|
||||||
|
const int DUMPED_BLOCK_SIZE = 16;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < size;) {
|
||||||
|
int start = i;
|
||||||
|
|
||||||
|
dprintf(prefix);
|
||||||
|
for (; i < start + DUMPED_BLOCK_SIZE; i++) {
|
||||||
|
if (!(i % 4))
|
||||||
|
dprintf(" ");
|
||||||
|
|
||||||
|
if (i >= size)
|
||||||
|
dprintf(" ");
|
||||||
|
else
|
||||||
|
dprintf("%02x", *(unsigned char *)(buffer + i));
|
||||||
|
}
|
||||||
|
dprintf(" ");
|
||||||
|
|
||||||
|
for (i = start; i < start + DUMPED_BLOCK_SIZE; i++) {
|
||||||
|
if (i < size) {
|
||||||
|
char c = buffer[i];
|
||||||
|
|
||||||
|
if (c < 30)
|
||||||
|
dprintf(".");
|
||||||
|
else
|
||||||
|
dprintf("%c", c);
|
||||||
|
} else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
dprintf("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
extern "C" status_t
|
||||||
|
user_memcpy(void *to, const void *from, size_t size)
|
||||||
|
{
|
||||||
|
char *tmp = (char *)to;
|
||||||
|
char *s = (char *)from;
|
||||||
|
|
||||||
|
while (size--)
|
||||||
|
*tmp++ = *s++;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
extern "C" int
|
||||||
|
user_strcpy(char *to, const char *from)
|
||||||
|
{
|
||||||
|
while ((*to++ = *from++) != '\0')
|
||||||
|
;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! \brief Copies at most (\a size - 1) characters from the string in \a from to
|
||||||
|
the string in \a to, NULL-terminating the result.
|
||||||
|
|
||||||
|
\param to Pointer to the destination C-string.
|
||||||
|
\param from Pointer to the source C-string.
|
||||||
|
\param size Size in bytes of the string buffer pointed to by \a to.
|
||||||
|
|
||||||
|
\return strlen(\a from).
|
||||||
|
*/
|
||||||
|
extern "C" ssize_t
|
||||||
|
user_strlcpy(char *to, const char *from, size_t size)
|
||||||
|
{
|
||||||
|
int from_length = 0;
|
||||||
|
|
||||||
|
if (size > 0) {
|
||||||
|
to[--size] = '\0';
|
||||||
|
// copy
|
||||||
|
for ( ; size; size--, from_length++, to++, from++) {
|
||||||
|
if ((*to = *from) == '\0')
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// count any leftover from chars
|
||||||
|
while (*from++ != '\0')
|
||||||
|
from_length++;
|
||||||
|
|
||||||
|
return from_length;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - Debugger
|
||||||
|
|
||||||
|
|
||||||
|
extern "C" uint64
|
||||||
|
parse_expression(const char* arg)
|
||||||
|
{
|
||||||
|
return strtoull(arg, NULL, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
extern "C" bool
|
||||||
|
set_debug_variable(const char* variableName, uint64 value)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
extern "C" bool
|
||||||
|
print_debugger_command_usage(const char* command)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
extern "C" status_t
|
||||||
|
add_debugger_command_etc(const char* name, debugger_command_hook func,
|
||||||
|
const char* description, const char* usage, uint32 flags)
|
||||||
|
{
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
extern "C" int
|
||||||
|
add_debugger_command(const char *name, int (*func)(int, char **),
|
||||||
|
const char *desc)
|
||||||
|
{
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
extern "C" int
|
||||||
|
remove_debugger_command(const char * name, int (*func)(int, char **))
|
||||||
|
{
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - Slab allocator
|
||||||
|
|
||||||
|
|
||||||
|
extern "C" void *
|
||||||
|
object_cache_alloc(object_cache *cache, uint32 flags)
|
||||||
|
{
|
||||||
|
return malloc((size_t)cache);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
extern "C" void
|
||||||
|
object_cache_free(object_cache *cache, void *object)
|
||||||
|
{
|
||||||
|
free(object);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
extern "C" object_cache *
|
||||||
|
create_object_cache_etc(const char *name, size_t objectSize,
|
||||||
|
size_t alignment, size_t maxByteUsage, uint32 flags, void *cookie,
|
||||||
|
object_cache_constructor constructor, object_cache_destructor destructor,
|
||||||
|
object_cache_reclaimer reclaimer)
|
||||||
|
{
|
||||||
|
return (object_cache*)objectSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
extern "C" object_cache *
|
||||||
|
create_object_cache(const char *name, size_t objectSize,
|
||||||
|
size_t alignment, void *cookie, object_cache_constructor constructor,
|
||||||
|
object_cache_destructor)
|
||||||
|
{
|
||||||
|
return (object_cache*)objectSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
extern "C" void
|
||||||
|
delete_object_cache(object_cache *cache)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
extern "C" void
|
||||||
|
object_cache_get_usage(object_cache *cache, size_t *_allocatedMemory)
|
||||||
|
{
|
||||||
|
*_allocatedMemory = 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - Thread/scheduler functions
|
||||||
|
|
||||||
|
|
||||||
|
struct scheduler_ops kScheduler = {
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
};
|
||||||
|
struct scheduler_ops* gScheduler = &kScheduler;
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2002-2008, Haiku Inc. All Rights Reserved.
|
* Copyright 2002-2009, Haiku Inc. All Rights Reserved.
|
||||||
* Distributed under the terms of the MIT license.
|
* Distributed under the terms of the MIT license.
|
||||||
*
|
*
|
||||||
* Authors:
|
* Authors:
|
||||||
@ -8,7 +8,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <signal.h>
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
@ -23,31 +22,18 @@
|
|||||||
#include <Path.h>
|
#include <Path.h>
|
||||||
#include <String.h>
|
#include <String.h>
|
||||||
|
|
||||||
#ifdef ASSERT
|
|
||||||
# undef ASSERT
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <condition_variable.h>
|
|
||||||
#include <lock.h>
|
|
||||||
#include <low_resource_manager.h>
|
|
||||||
#include <fs/devfs.h>
|
|
||||||
#include <kscheduler.h>
|
|
||||||
#include <slab/Slab.h>
|
|
||||||
|
|
||||||
#ifdef TRACE
|
#ifdef TRACE
|
||||||
# undef TRACE
|
# undef TRACE
|
||||||
#endif
|
#endif
|
||||||
#define TRACE(x)
|
#define TRACE(x)
|
||||||
//#define TRACE(x) printf x
|
//#define TRACE(x) printf x
|
||||||
|
|
||||||
#define RW_MAX_READERS 10000
|
|
||||||
|
|
||||||
static const char *gModuleDirs[] = {
|
static const char *gModuleDirs[] = {
|
||||||
"distro/x86.R1/beos/system/add-ons/userland",
|
"distro/x86.R1/beos/system/add-ons/userland",
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
bool gDebugOutputEnabled = true;
|
|
||||||
|
|
||||||
struct module_name_list {
|
struct module_name_list {
|
||||||
set<string> names;
|
set<string> names;
|
||||||
@ -811,707 +797,3 @@ close_module_list(void *cookie)
|
|||||||
return ModuleManager::Default()->CloseModuleList(
|
return ModuleManager::Default()->CloseModuleList(
|
||||||
(module_name_list*)cookie);
|
(module_name_list*)cookie);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
thread_id
|
|
||||||
spawn_kernel_thread(thread_func func, const char *name, int32 priority,
|
|
||||||
void *data)
|
|
||||||
{
|
|
||||||
return spawn_thread(func, name, priority, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
extern "C" status_t
|
|
||||||
devfs_unpublish_partition(const char *path)
|
|
||||||
{
|
|
||||||
printf("unpublish partition: %s\n", path);
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
extern "C" status_t
|
|
||||||
devfs_publish_partition(const char *path, const partition_info *info)
|
|
||||||
{
|
|
||||||
if (info == NULL)
|
|
||||||
return B_BAD_VALUE;
|
|
||||||
|
|
||||||
printf("publish partition: %s (device \"%s\", size %Ld)\n", path, info->device, info->size);
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
extern "C" int32
|
|
||||||
atomic_test_and_set(vint32 *value, int32 newValue, int32 testAgainst)
|
|
||||||
{
|
|
||||||
#if __INTEL__
|
|
||||||
int32 oldValue;
|
|
||||||
asm volatile("lock; cmpxchg %%ecx, (%%edx)"
|
|
||||||
: "=a" (oldValue) : "a" (testAgainst), "c" (newValue), "d" (value));
|
|
||||||
return oldValue;
|
|
||||||
#else
|
|
||||||
#warn "atomic_test_and_set() won't work correctly!"
|
|
||||||
int32 oldValue = *value;
|
|
||||||
if (oldValue == testAgainst)
|
|
||||||
*value = newValue;
|
|
||||||
|
|
||||||
return oldValue;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
extern "C" int
|
|
||||||
send_signal_etc(pid_t thread, uint signal, uint32 flags)
|
|
||||||
{
|
|
||||||
return send_signal(thread, signal);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
extern "C" int32
|
|
||||||
low_resource_state(uint32 resources)
|
|
||||||
{
|
|
||||||
return B_NO_LOW_RESOURCE;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
extern "C" void
|
|
||||||
low_resource(uint32 resource, uint64 requirements, uint32 flags,
|
|
||||||
uint32 timeout)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
extern "C" status_t
|
|
||||||
register_low_resource_handler(low_resource_func function, void *data,
|
|
||||||
uint32 resources, int32 priority)
|
|
||||||
{
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
extern "C" status_t
|
|
||||||
unregister_low_resource_handler(low_resource_func function, void *data)
|
|
||||||
{
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
extern "C" void
|
|
||||||
panic(const char *format, ...)
|
|
||||||
{
|
|
||||||
va_list args;
|
|
||||||
|
|
||||||
puts("*** PANIC ***");
|
|
||||||
va_start(args, format);
|
|
||||||
vprintf(format, args);
|
|
||||||
va_end(args);
|
|
||||||
|
|
||||||
putchar('\n');
|
|
||||||
debugger("Kernel Panic");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
extern "C" void
|
|
||||||
dprintf(const char *format,...)
|
|
||||||
{
|
|
||||||
if (!gDebugOutputEnabled)
|
|
||||||
return;
|
|
||||||
|
|
||||||
va_list args;
|
|
||||||
va_start(args, format);
|
|
||||||
printf("\33[34m");
|
|
||||||
vprintf(format, args);
|
|
||||||
printf("\33[0m");
|
|
||||||
fflush(stdout);
|
|
||||||
va_end(args);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
extern "C" void
|
|
||||||
kprintf(const char *format,...)
|
|
||||||
{
|
|
||||||
va_list args;
|
|
||||||
va_start(args, format);
|
|
||||||
printf("\33[35m");
|
|
||||||
vprintf(format, args);
|
|
||||||
printf("\33[0m");
|
|
||||||
fflush(stdout);
|
|
||||||
va_end(args);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
extern "C" void
|
|
||||||
dump_block(const char *buffer, int size, const char *prefix)
|
|
||||||
{
|
|
||||||
const int DUMPED_BLOCK_SIZE = 16;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; i < size;) {
|
|
||||||
int start = i;
|
|
||||||
|
|
||||||
dprintf(prefix);
|
|
||||||
for (; i < start + DUMPED_BLOCK_SIZE; i++) {
|
|
||||||
if (!(i % 4))
|
|
||||||
dprintf(" ");
|
|
||||||
|
|
||||||
if (i >= size)
|
|
||||||
dprintf(" ");
|
|
||||||
else
|
|
||||||
dprintf("%02x", *(unsigned char *)(buffer + i));
|
|
||||||
}
|
|
||||||
dprintf(" ");
|
|
||||||
|
|
||||||
for (i = start; i < start + DUMPED_BLOCK_SIZE; i++) {
|
|
||||||
if (i < size) {
|
|
||||||
char c = buffer[i];
|
|
||||||
|
|
||||||
if (c < 30)
|
|
||||||
dprintf(".");
|
|
||||||
else
|
|
||||||
dprintf("%c", c);
|
|
||||||
} else
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
dprintf("\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
extern "C" status_t
|
|
||||||
user_memcpy(void *to, const void *from, size_t size)
|
|
||||||
{
|
|
||||||
char *tmp = (char *)to;
|
|
||||||
char *s = (char *)from;
|
|
||||||
|
|
||||||
while (size--)
|
|
||||||
*tmp++ = *s++;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
extern "C" int
|
|
||||||
user_strcpy(char *to, const char *from)
|
|
||||||
{
|
|
||||||
while ((*to++ = *from++) != '\0')
|
|
||||||
;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*! \brief Copies at most (\a size - 1) characters from the string in \a from to
|
|
||||||
the string in \a to, NULL-terminating the result.
|
|
||||||
|
|
||||||
\param to Pointer to the destination C-string.
|
|
||||||
\param from Pointer to the source C-string.
|
|
||||||
\param size Size in bytes of the string buffer pointed to by \a to.
|
|
||||||
|
|
||||||
\return strlen(\a from).
|
|
||||||
*/
|
|
||||||
extern "C" ssize_t
|
|
||||||
user_strlcpy(char *to, const char *from, size_t size)
|
|
||||||
{
|
|
||||||
int from_length = 0;
|
|
||||||
|
|
||||||
if (size > 0) {
|
|
||||||
to[--size] = '\0';
|
|
||||||
// copy
|
|
||||||
for ( ; size; size--, from_length++, to++, from++) {
|
|
||||||
if ((*to = *from) == '\0')
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// count any leftover from chars
|
|
||||||
while (*from++ != '\0')
|
|
||||||
from_length++;
|
|
||||||
|
|
||||||
return from_length;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark - Debugger
|
|
||||||
|
|
||||||
|
|
||||||
extern "C" uint64
|
|
||||||
parse_expression(const char* arg)
|
|
||||||
{
|
|
||||||
return strtoull(arg, NULL, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
extern "C" bool
|
|
||||||
set_debug_variable(const char* variableName, uint64 value)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
extern "C" bool
|
|
||||||
print_debugger_command_usage(const char* command)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
extern "C" status_t
|
|
||||||
add_debugger_command_etc(const char* name, debugger_command_hook func,
|
|
||||||
const char* description, const char* usage, uint32 flags)
|
|
||||||
{
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
extern "C" int
|
|
||||||
add_debugger_command(char *name, int (*func)(int, char **), char *desc)
|
|
||||||
{
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
extern "C" int
|
|
||||||
remove_debugger_command(char * name, int (*func)(int, char **))
|
|
||||||
{
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark - Slab allocator
|
|
||||||
|
|
||||||
|
|
||||||
extern "C" void *
|
|
||||||
object_cache_alloc(object_cache *cache, uint32 flags)
|
|
||||||
{
|
|
||||||
return malloc((size_t)cache);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
extern "C" void
|
|
||||||
object_cache_free(object_cache *cache, void *object)
|
|
||||||
{
|
|
||||||
free(object);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
extern "C" object_cache *
|
|
||||||
create_object_cache_etc(const char *name, size_t objectSize,
|
|
||||||
size_t alignment, size_t maxByteUsage, uint32 flags, void *cookie,
|
|
||||||
object_cache_constructor constructor, object_cache_destructor destructor,
|
|
||||||
object_cache_reclaimer reclaimer)
|
|
||||||
{
|
|
||||||
return (object_cache*)objectSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
extern "C" object_cache *
|
|
||||||
create_object_cache(const char *name, size_t objectSize,
|
|
||||||
size_t alignment, void *cookie, object_cache_constructor constructor,
|
|
||||||
object_cache_destructor)
|
|
||||||
{
|
|
||||||
return (object_cache*)objectSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
extern "C" void
|
|
||||||
delete_object_cache(object_cache *cache)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
extern "C" void
|
|
||||||
object_cache_get_usage(object_cache *cache, size_t *_allocatedMemory)
|
|
||||||
{
|
|
||||||
*_allocatedMemory = 100;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark - Thread/scheduler functions
|
|
||||||
|
|
||||||
|
|
||||||
struct scheduler_ops kScheduler = {
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
};
|
|
||||||
struct scheduler_ops* gScheduler = &kScheduler;
|
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark - Private locking functions
|
|
||||||
|
|
||||||
|
|
||||||
int32
|
|
||||||
recursive_lock_get_recursion(recursive_lock *lock)
|
|
||||||
{
|
|
||||||
thread_id thread = find_thread(NULL);
|
|
||||||
|
|
||||||
#if !KDEBUG
|
|
||||||
if (lock->holder == thread)
|
|
||||||
return lock->recursion;
|
|
||||||
#else
|
|
||||||
if (lock->lock.holder == thread)
|
|
||||||
return lock->recursion;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
recursive_lock_init_etc(recursive_lock *lock, const char *name, uint32 flags)
|
|
||||||
{
|
|
||||||
if (lock == NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (name == NULL)
|
|
||||||
name = "recursive lock";
|
|
||||||
|
|
||||||
#if !KDEBUG
|
|
||||||
lock->holder = -1;
|
|
||||||
#else
|
|
||||||
lock->lock.holder = -1;
|
|
||||||
#endif
|
|
||||||
lock->recursion = 0;
|
|
||||||
lock->lock.waiters = (mutex_waiter*)create_sem(1, name);
|
|
||||||
|
|
||||||
if ((sem_id)lock->lock.waiters < B_OK)
|
|
||||||
panic("recursive lock creation failed: %s\n", name);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
recursive_lock_init(recursive_lock *lock, const char *name)
|
|
||||||
{
|
|
||||||
recursive_lock_init_etc(lock, name, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
recursive_lock_destroy(recursive_lock *lock)
|
|
||||||
{
|
|
||||||
if (lock == NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
delete_sem((sem_id)lock->lock.waiters);
|
|
||||||
lock->lock.waiters = (mutex_waiter*)-1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
recursive_lock_lock(recursive_lock *lock)
|
|
||||||
{
|
|
||||||
thread_id thread = find_thread(NULL);
|
|
||||||
|
|
||||||
#if !KDEBUG
|
|
||||||
if (thread != lock->holder) {
|
|
||||||
status_t status;
|
|
||||||
do {
|
|
||||||
status = acquire_sem((sem_id)lock->lock.waiters);
|
|
||||||
} while (status == B_INTERRUPTED);
|
|
||||||
if (status < B_OK)
|
|
||||||
return status;
|
|
||||||
|
|
||||||
lock->holder = thread;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
if (thread != lock->lock.holder) {
|
|
||||||
status_t status;
|
|
||||||
do {
|
|
||||||
status = acquire_sem((sem_id)lock->lock.waiters);
|
|
||||||
} while (status == B_INTERRUPTED);
|
|
||||||
if (status < B_OK)
|
|
||||||
return status;
|
|
||||||
|
|
||||||
lock->lock.holder = thread;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
lock->recursion++;
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
recursive_lock_unlock(recursive_lock *lock)
|
|
||||||
{
|
|
||||||
#if !KDEBUG
|
|
||||||
if (find_thread(NULL) != lock->holder)
|
|
||||||
panic("recursive_lock %p unlocked by non-holder thread!\n", lock);
|
|
||||||
#else
|
|
||||||
if (find_thread(NULL) != lock->lock.holder)
|
|
||||||
panic("recursive_lock %p unlocked by non-holder thread!\n", lock);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (--lock->recursion == 0) {
|
|
||||||
#if !KDEBUG
|
|
||||||
lock->holder = -1;
|
|
||||||
#else
|
|
||||||
lock->lock.holder = -1;
|
|
||||||
#endif
|
|
||||||
release_sem_etc((sem_id)lock->lock.waiters, 1, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark -
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
mutex_init(mutex *m, const char *name)
|
|
||||||
{
|
|
||||||
if (m == NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (name == NULL)
|
|
||||||
name = "mutex_sem";
|
|
||||||
|
|
||||||
// We need to store the semaphore in "waiters", as it is no sem anymore
|
|
||||||
// Also, kernel mutex creation cannot fail anymore, but we could...
|
|
||||||
m->waiters = (struct mutex_waiter *)create_sem(1, name);
|
|
||||||
if ((sem_id)m->waiters < B_OK)
|
|
||||||
debugger("semaphore creation failed");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
mutex_init_etc(mutex *m, const char *name, uint32 flags)
|
|
||||||
{
|
|
||||||
if (m == NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (name == NULL)
|
|
||||||
name = "mutex_sem";
|
|
||||||
|
|
||||||
m->waiters = (struct mutex_waiter *)create_sem(1, name);
|
|
||||||
if ((sem_id)m->waiters < B_OK)
|
|
||||||
debugger("semaphore creation failed");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
mutex_destroy(mutex *mutex)
|
|
||||||
{
|
|
||||||
if (mutex == NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if ((sem_id)mutex->waiters >= 0) {
|
|
||||||
delete_sem((sem_id)mutex->waiters);
|
|
||||||
mutex->waiters = (struct mutex_waiter *)-1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
_mutex_trylock(mutex *mutex)
|
|
||||||
{
|
|
||||||
status_t status;
|
|
||||||
do {
|
|
||||||
status = acquire_sem_etc((sem_id)mutex->waiters, 1, B_RELATIVE_TIMEOUT,
|
|
||||||
0);
|
|
||||||
} while (status == B_INTERRUPTED);
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
_mutex_lock(mutex *mutex, bool threadsLocked)
|
|
||||||
{
|
|
||||||
if (mutex->waiters == NULL) {
|
|
||||||
// MUTEX_INITIALIZER has been used; this is not thread-safe!
|
|
||||||
mutex_init(mutex, mutex->name);
|
|
||||||
}
|
|
||||||
|
|
||||||
status_t status;
|
|
||||||
do {
|
|
||||||
status = acquire_sem((sem_id)mutex->waiters);
|
|
||||||
} while (status == B_INTERRUPTED);
|
|
||||||
|
|
||||||
#if KDEBUG
|
|
||||||
if (status == B_OK)
|
|
||||||
mutex->holder = find_thread(NULL);
|
|
||||||
#endif
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
_mutex_unlock(mutex *mutex, bool threadsLocked)
|
|
||||||
{
|
|
||||||
#if KDEBUG
|
|
||||||
mutex->holder = -1;
|
|
||||||
#endif
|
|
||||||
release_sem((sem_id)mutex->waiters);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark -
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
rw_lock_init_etc(rw_lock *lock, const char *name, uint32 flags)
|
|
||||||
{
|
|
||||||
if (lock == NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (name == NULL)
|
|
||||||
name = "r/w lock";
|
|
||||||
|
|
||||||
lock->waiters = (rw_lock_waiter*)create_sem(RW_MAX_READERS, name);
|
|
||||||
if ((sem_id)lock->waiters < B_OK)
|
|
||||||
panic("r/w lock \"%s\" creation failed.", name);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
rw_lock_init(rw_lock *lock, const char *name)
|
|
||||||
{
|
|
||||||
rw_lock_init_etc(lock, name, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
rw_lock_destroy(rw_lock *lock)
|
|
||||||
{
|
|
||||||
if (lock == NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
delete_sem((sem_id)lock->waiters);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
rw_lock_read_lock(rw_lock *lock)
|
|
||||||
{
|
|
||||||
status_t status;
|
|
||||||
do {
|
|
||||||
status = acquire_sem((sem_id)lock->waiters);
|
|
||||||
} while (status == B_INTERRUPTED);
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
rw_lock_read_unlock(rw_lock *lock)
|
|
||||||
{
|
|
||||||
return release_sem((sem_id)lock->waiters);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
rw_lock_write_lock(rw_lock *lock)
|
|
||||||
{
|
|
||||||
status_t status;
|
|
||||||
do {
|
|
||||||
status = acquire_sem_etc((sem_id)lock->waiters, RW_MAX_READERS, 0, 0);
|
|
||||||
} while (status == B_INTERRUPTED);
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
rw_lock_write_unlock(rw_lock *lock)
|
|
||||||
{
|
|
||||||
return release_sem_etc((sem_id)lock->waiters, RW_MAX_READERS, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark - Condition variables (anonymous only)
|
|
||||||
|
|
||||||
|
|
||||||
#define STATUS_ADDED 1
|
|
||||||
#define STATUS_WAITING 2
|
|
||||||
|
|
||||||
|
|
||||||
struct condition_private {
|
|
||||||
mutex lock;
|
|
||||||
sem_id wait_sem;
|
|
||||||
const void* object;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
ConditionVariableEntry::Wait(uint32 flags, bigtime_t timeout)
|
|
||||||
{
|
|
||||||
if (fVariable == NULL)
|
|
||||||
return fWaitStatus;
|
|
||||||
|
|
||||||
condition_private* condition = (condition_private*)fVariable->fObject;
|
|
||||||
fWaitStatus = STATUS_WAITING;
|
|
||||||
|
|
||||||
status_t status;
|
|
||||||
do {
|
|
||||||
status = acquire_sem_etc(condition->wait_sem, 1, flags, timeout);
|
|
||||||
} while (status == B_INTERRUPTED);
|
|
||||||
|
|
||||||
mutex_lock(&condition->lock);
|
|
||||||
|
|
||||||
// remove entry from variable, if not done yet
|
|
||||||
if (fVariable != NULL) {
|
|
||||||
fVariable->fEntries.Remove(this);
|
|
||||||
fVariable = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
mutex_unlock(&condition->lock);
|
|
||||||
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
inline void
|
|
||||||
ConditionVariableEntry::AddToVariable(ConditionVariable* variable)
|
|
||||||
{
|
|
||||||
fVariable = variable;
|
|
||||||
fWaitStatus = STATUS_ADDED;
|
|
||||||
fVariable->fEntries.Add(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark -
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
ConditionVariable::Init(const void* object, const char* objectType)
|
|
||||||
{
|
|
||||||
fObjectType = objectType;
|
|
||||||
new(&fEntries) EntryList;
|
|
||||||
|
|
||||||
condition_private* condition = new condition_private;
|
|
||||||
mutex_init(&condition->lock, objectType);
|
|
||||||
condition->wait_sem = create_sem(0, "condition variable wait");
|
|
||||||
if (condition->wait_sem < B_OK)
|
|
||||||
panic("cannot create condition variable.");
|
|
||||||
|
|
||||||
condition->object = object;
|
|
||||||
|
|
||||||
fObject = condition;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
ConditionVariable::Add(ConditionVariableEntry* entry)
|
|
||||||
{
|
|
||||||
entry->AddToVariable(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
ConditionVariable::_Notify(bool all, bool threadsLocked)
|
|
||||||
{
|
|
||||||
condition_private* condition = (condition_private*)fObject;
|
|
||||||
mutex_lock(&condition->lock);
|
|
||||||
|
|
||||||
uint32 count = 0;
|
|
||||||
|
|
||||||
while (ConditionVariableEntry* entry = fEntries.RemoveHead()) {
|
|
||||||
entry->fVariable = NULL;
|
|
||||||
if (entry->fWaitStatus <= 0)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
entry->fWaitStatus = B_OK;
|
|
||||||
count++;
|
|
||||||
|
|
||||||
if (!all)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
release_sem_etc(condition->wait_sem, count, 0);
|
|
||||||
mutex_unlock(&condition->lock);
|
|
||||||
}
|
|
||||||
|
|
Loading…
x
Reference in New Issue
Block a user