* 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:
Ingo Weinhold
2010-07-16 01:13:22 +00:00
parent 7ad694e346
commit 44db70a313
+21 -37
View File
@@ -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");