* Changed _kern_spawn_thread() and create_thread(): Instead of individual

arguments they get a single thread_creation_attributes structure now.
* Added stack_address and stack_size to thread_creation_attributes,
  which allow to specify the stack size or the stack to be used for the
  new user thread.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@25389 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Ingo Weinhold
2008-05-09 01:32:36 +00:00
parent 6eea7aabb8
commit 4c49f2056b
5 changed files with 124 additions and 44 deletions
+90 -40
View File
@@ -364,8 +364,7 @@ _create_kernel_thread_kentry(void)
\code < 0 \endcode a fresh one is allocated.
*/
static thread_id
create_thread(const char *name, team_id teamID, thread_entry_func entry,
void *args1, void *args2, int32 priority, bool kernel, thread_id threadID)
create_thread(thread_creation_attributes& attributes, bool kernel)
{
struct thread *thread, *currentThread;
struct team *team;
@@ -375,14 +374,16 @@ create_thread(const char *name, team_id teamID, thread_entry_func entry,
bool abort = false;
bool debugNewThread = false;
TRACE(("create_thread(%s, id = %ld, %s)\n", name, threadID,
kernel ? "kernel" : "user"));
TRACE(("create_thread(%s, id = %ld, %s)\n", attributes.name,
attributes.thread, kernel ? "kernel" : "user"));
thread = create_thread_struct(NULL, name, threadID, NULL);
thread = create_thread_struct(NULL, attributes.name, attributes.thread,
NULL);
if (thread == NULL)
return B_NO_MEMORY;
thread->priority = priority == -1 ? B_NORMAL_PRIORITY : priority;
thread->priority = attributes.priority == -1
? B_NORMAL_PRIORITY : attributes.priority;
thread->next_priority = thread->priority;
// ToDo: this could be dangerous in case someone calls resume_thread() on us
thread->state = B_THREAD_SUSPENDED;
@@ -391,7 +392,8 @@ create_thread(const char *name, team_id teamID, thread_entry_func entry,
// init debug structure
clear_thread_debug_info(&thread->debug_info, false);
snprintf(stack_name, B_OS_NAME_LENGTH, "%s_%ld_kstack", name, thread->id);
snprintf(stack_name, B_OS_NAME_LENGTH, "%s_%ld_kstack", attributes.name,
thread->id);
thread->kernel_stack_area = create_area(stack_name,
(void **)&thread->kernel_stack_base, B_ANY_KERNEL_ADDRESS,
KERNEL_STACK_SIZE, B_FULL_LOCK,
@@ -416,7 +418,7 @@ create_thread(const char *name, team_id teamID, thread_entry_func entry,
// If the new thread belongs to the same team as the current thread,
// it may inherit some of the thread debug flags.
currentThread = thread_get_current_thread();
if (currentThread && currentThread->team->id == teamID) {
if (currentThread && currentThread->team->id == attributes.team) {
// inherit all user flags...
int32 debugFlags = currentThread->debug_info.flags
& B_THREAD_DEBUG_USER_FLAG_MASK;
@@ -440,7 +442,7 @@ create_thread(const char *name, team_id teamID, thread_entry_func entry,
GRAB_TEAM_LOCK();
// look at the team, make sure it's not being deleted
team = team_get_team_struct_locked(teamID);
team = team_get_team_struct_locked(attributes.team);
if (team != NULL && team->state != TEAM_STATE_DEATH) {
// Debug the new thread, if the parent thread required that (see above),
// or the respective global team debug flag is set. But only, if a
@@ -470,9 +472,9 @@ create_thread(const char *name, team_id teamID, thread_entry_func entry,
return B_BAD_TEAM_ID;
}
thread->args1 = args1;
thread->args2 = args2;
thread->entry = entry;
thread->args1 = attributes.args1;
thread->args2 = attributes.args2;
thread->entry = attributes.entry;
status = thread->id;
if (kernel) {
@@ -485,22 +487,33 @@ create_thread(const char *name, team_id teamID, thread_entry_func entry,
} else {
// create user stack
// the stack will be between USER_STACK_REGION and the main thread stack area
// (the user stack of the main thread is created in team_create_team())
thread->user_stack_base = USER_STACK_REGION;
thread->user_stack_size = USER_STACK_SIZE;
// the stack will be between USER_STACK_REGION and the main thread stack
// area (the user stack of the main thread is created in
// team_create_team())
if (attributes.stack_address == NULL) {
thread->user_stack_base = USER_STACK_REGION;
if (attributes.stack_size <= 0)
thread->user_stack_size = USER_STACK_SIZE;
else
thread->user_stack_size = PAGE_ALIGN(attributes.stack_size);
snprintf(stack_name, B_OS_NAME_LENGTH, "%s_%ld_stack", name, thread->id);
thread->user_stack_area = create_area_etc(team, stack_name,
(void **)&thread->user_stack_base, B_BASE_ADDRESS,
thread->user_stack_size + TLS_SIZE, B_NO_LOCK,
B_READ_AREA | B_WRITE_AREA | B_STACK_AREA);
if (thread->user_stack_area < B_OK
|| arch_thread_init_tls(thread) < B_OK) {
// great, we have a fully running thread without a (usable) stack
dprintf("create_thread: unable to create proper user stack!\n");
status = thread->user_stack_area;
kill_thread(thread->id);
snprintf(stack_name, B_OS_NAME_LENGTH, "%s_%ld_stack",
attributes.name, thread->id);
thread->user_stack_area = create_area_etc(team, stack_name,
(void **)&thread->user_stack_base, B_BASE_ADDRESS,
thread->user_stack_size + TLS_SIZE, B_NO_LOCK,
B_READ_AREA | B_WRITE_AREA | B_STACK_AREA);
if (thread->user_stack_area < B_OK
|| arch_thread_init_tls(thread) < B_OK) {
// great, we have a fully running thread without a (usable)
// stack
dprintf("create_thread: unable to create proper user stack!\n");
status = thread->user_stack_area;
kill_thread(thread->id);
}
} else {
thread->user_stack_base = (addr_t)attributes.stack_address;
thread->user_stack_size = attributes.stack_size;
}
user_debug_update_new_thread_flags(thread->id);
@@ -1829,8 +1842,18 @@ thread_id
spawn_kernel_thread_etc(thread_func function, const char *name, int32 priority,
void *arg, team_id team, thread_id threadID)
{
return create_thread(name, team, (thread_entry_func)function, arg, NULL,
priority, true, threadID);
thread_creation_attributes attributes;
attributes.entry = (thread_entry_func)function;
attributes.name = name;
attributes.priority = priority;
attributes.args1 = arg;
attributes.args2 = NULL;
attributes.stack_address = NULL;
attributes.stack_size = 0;
attributes.team = team;
attributes.thread = threadID;
return create_thread(attributes, true);
}
@@ -2593,8 +2616,18 @@ thread_id
spawn_kernel_thread(thread_func function, const char *name, int32 priority,
void *arg)
{
return create_thread(name, team_get_kernel_team()->id,
(thread_entry_func)function, arg, NULL, priority, true, -1);
thread_creation_attributes attributes;
attributes.entry = (thread_entry_func)function;
attributes.name = name;
attributes.priority = priority;
attributes.args1 = arg;
attributes.args2 = NULL;
attributes.stack_address = NULL;
attributes.stack_size = 0;
attributes.team = team_get_kernel_team()->id;
attributes.thread = -1;
return create_thread(attributes, true);
}
@@ -2677,22 +2710,39 @@ _user_set_thread_priority(thread_id thread, int32 newPriority)
thread_id
_user_spawn_thread(int32 (*entry)(thread_func, void *), const char *userName,
int32 priority, void *data1, void *data2)
_user_spawn_thread(thread_creation_attributes* userAttributes)
{
thread_creation_attributes attributes;
if (userAttributes == NULL || !IS_USER_ADDRESS(userAttributes)
|| user_memcpy(&attributes, userAttributes,
sizeof(attributes)) != B_OK) {
return B_BAD_ADDRESS;
}
if (attributes.stack_size != 0
&& (attributes.stack_size < MIN_USER_STACK_SIZE
|| attributes.stack_size > MAX_USER_STACK_SIZE)) {
return B_BAD_VALUE;
}
char name[B_OS_NAME_LENGTH];
thread_id threadID;
if (!IS_USER_ADDRESS(entry) || entry == NULL
|| (userName != NULL && (!IS_USER_ADDRESS(userName)
|| user_strlcpy(name, userName, B_OS_NAME_LENGTH) < B_OK)))
if (!IS_USER_ADDRESS(attributes.entry) || attributes.entry == NULL
|| attributes.stack_address != NULL
&& !IS_USER_ADDRESS(attributes.stack_address)
|| (attributes.name != NULL && (!IS_USER_ADDRESS(attributes.name)
|| user_strlcpy(name, attributes.name, B_OS_NAME_LENGTH) < 0)))
return B_BAD_ADDRESS;
threadID = create_thread(userName != NULL ? name : "user thread",
thread_get_current_thread()->team->id, entry,
data1, data2, priority, false, -1);
attributes.name = attributes.name != NULL ? name : "user thread";
attributes.team = thread_get_current_thread()->team->id;
attributes.thread = -1;
user_debug_thread_created(threadID);
threadID = create_thread(attributes, false);
if (threadID >= 0)
user_debug_thread_created(threadID);
return threadID;
}