* Resolved TODO: Use an object cache for the thread structure alloction.
* Align the allocated objects to 16 byte. This is required by the x86 arch_thread structure. Haiku only didn't crash and burn since the until recently used heap allocator apparently aligned the structures to 16 byte anyway and the now used slab allocator has a bug preventing slab coloring for that object size. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@37532 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -14,6 +14,7 @@
|
|||||||
#include <thread.h>
|
#include <thread.h>
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <malloc.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@@ -34,6 +35,7 @@
|
|||||||
#include <ksignal.h>
|
#include <ksignal.h>
|
||||||
#include <Notifications.h>
|
#include <Notifications.h>
|
||||||
#include <real_time_clock.h>
|
#include <real_time_clock.h>
|
||||||
|
#include <slab/Slab.h>
|
||||||
#include <smp.h>
|
#include <smp.h>
|
||||||
#include <syscalls.h>
|
#include <syscalls.h>
|
||||||
#include <syscall_restart.h>
|
#include <syscall_restart.h>
|
||||||
@@ -114,10 +116,8 @@ static ConditionVariable sUndertakerCondition;
|
|||||||
static ThreadNotificationService sNotificationService;
|
static ThreadNotificationService sNotificationService;
|
||||||
|
|
||||||
|
|
||||||
// The dead queue is used as a pool from which to retrieve and reuse previously
|
// object cache to allocate thread structures from
|
||||||
// allocated thread structs when creating a new thread. It should be gone once
|
static object_cache* sThreadCache;
|
||||||
// the slab allocator is in.
|
|
||||||
static struct thread_queue dead_q;
|
|
||||||
|
|
||||||
static void thread_kthread_entry(void);
|
static void thread_kthread_entry(void);
|
||||||
static void thread_kthread_exit(void);
|
static void thread_kthread_exit(void);
|
||||||
@@ -203,45 +203,29 @@ reset_signals(struct thread *thread)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*! Allocates and fills in thread structure (or reuses one from the
|
/*! Allocates and fills in thread structure.
|
||||||
dead queue).
|
|
||||||
|
|
||||||
\param threadID The ID to be assigned to the new thread. If
|
\param threadID The ID to be assigned to the new thread. If
|
||||||
\code < 0 \endcode a fresh one is allocated.
|
\code < 0 \endcode a fresh one is allocated.
|
||||||
\param thread initialize this thread struct if nonnull
|
\param thread initialize this thread struct if nonnull
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static struct thread *
|
static struct thread *
|
||||||
create_thread_struct(struct thread *inthread, const char *name,
|
create_thread_struct(struct thread *inthread, const char *name,
|
||||||
thread_id threadID, struct cpu_ent *cpu)
|
thread_id threadID, struct cpu_ent *cpu)
|
||||||
{
|
{
|
||||||
struct thread *thread;
|
struct thread *thread;
|
||||||
cpu_status state;
|
|
||||||
char temp[64];
|
char temp[64];
|
||||||
bool recycled = false;
|
|
||||||
|
|
||||||
if (inthread == NULL) {
|
if (inthread == NULL) {
|
||||||
// try to recycle one from the dead queue first
|
thread = (struct thread*)object_cache_alloc(sThreadCache, 0);
|
||||||
state = disable_interrupts();
|
if (thread == NULL)
|
||||||
GRAB_THREAD_LOCK();
|
return NULL;
|
||||||
thread = thread_dequeue(&dead_q);
|
|
||||||
RELEASE_THREAD_LOCK();
|
|
||||||
restore_interrupts(state);
|
|
||||||
|
|
||||||
// if not, create a new one
|
|
||||||
if (thread == NULL) {
|
|
||||||
thread = (struct thread *)malloc(sizeof(struct thread));
|
|
||||||
if (thread == NULL)
|
|
||||||
return NULL;
|
|
||||||
} else {
|
|
||||||
recycled = true;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
thread = inthread;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!recycled)
|
|
||||||
scheduler_on_thread_create(thread);
|
scheduler_on_thread_create(thread);
|
||||||
|
// TODO: We could use the object cache object
|
||||||
|
// constructor/destructor!
|
||||||
|
} else
|
||||||
|
thread = inthread;
|
||||||
|
|
||||||
if (name != NULL)
|
if (name != NULL)
|
||||||
strlcpy(thread->name, name, B_OS_NAME_LENGTH);
|
strlcpy(thread->name, name, B_OS_NAME_LENGTH);
|
||||||
@@ -313,7 +297,7 @@ err1:
|
|||||||
// ToDo: put them in the dead queue instead?
|
// ToDo: put them in the dead queue instead?
|
||||||
if (inthread == NULL) {
|
if (inthread == NULL) {
|
||||||
scheduler_on_thread_destroy(thread);
|
scheduler_on_thread_destroy(thread);
|
||||||
free(thread);
|
object_cache_free(sThreadCache, thread, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -328,9 +312,7 @@ delete_thread_struct(struct thread *thread)
|
|||||||
delete_sem(thread->msg.read_sem);
|
delete_sem(thread->msg.read_sem);
|
||||||
|
|
||||||
scheduler_on_thread_destroy(thread);
|
scheduler_on_thread_destroy(thread);
|
||||||
|
object_cache_free(sThreadCache, thread, 0);
|
||||||
// ToDo: put them in the dead queue instead?
|
|
||||||
free(thread);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -629,9 +611,7 @@ undertaker(void* /*args*/)
|
|||||||
// needed for the debugger notification below
|
// needed for the debugger notification below
|
||||||
|
|
||||||
// free the thread structure
|
// free the thread structure
|
||||||
locker.Lock();
|
delete_thread_struct(thread);
|
||||||
thread_enqueue(thread, &dead_q);
|
|
||||||
// TODO: Use the slab allocator!
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// never can get here
|
// never can get here
|
||||||
@@ -2125,8 +2105,12 @@ thread_init(kernel_args *args)
|
|||||||
sThreadHash = hash_init(15, offsetof(struct thread, all_next),
|
sThreadHash = hash_init(15, offsetof(struct thread, all_next),
|
||||||
&thread_struct_compare, &thread_struct_hash);
|
&thread_struct_compare, &thread_struct_hash);
|
||||||
|
|
||||||
// zero out the dead thread structure q
|
// create the thread structure object cache
|
||||||
memset(&dead_q, 0, sizeof(dead_q));
|
sThreadCache = create_object_cache("threads", sizeof(thread), 16, NULL,
|
||||||
|
NULL, NULL);
|
||||||
|
// Note: The x86 port requires 16 byte alignment of thread structures.
|
||||||
|
if (sThreadCache == NULL)
|
||||||
|
panic("thread_init(): failed to allocate thread object cache!");
|
||||||
|
|
||||||
if (arch_thread_init(args) < B_OK)
|
if (arch_thread_init(args) < B_OK)
|
||||||
panic("arch_thread_init() failed!\n");
|
panic("arch_thread_init() failed!\n");
|
||||||
|
|||||||
Reference in New Issue
Block a user