* 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:
parent
6eea7aabb8
commit
4c49f2056b
@ -37,6 +37,8 @@
|
||||
/** Size of the stack given to teams in user space */
|
||||
#define USER_MAIN_THREAD_STACK_SIZE (16 * 1024 * 1024) // 16 MB
|
||||
#define USER_STACK_SIZE (256 * 1024) // 256 kB
|
||||
#define MIN_USER_STACK_SIZE (4 * 1024) // 4 KB
|
||||
#define MAX_USER_STACK_SIZE (16 * 1024 * 1024) // 16 MB
|
||||
#define USER_STACK_GUARD_PAGES 4 // 16 kB
|
||||
|
||||
/** Size of the environmental variables space for a process */
|
||||
|
@ -33,6 +33,7 @@ struct stat;
|
||||
|
||||
struct disk_device_job_progress_info;
|
||||
struct partitionable_space_data;
|
||||
struct thread_creation_attributes;
|
||||
struct user_disk_device_data;
|
||||
struct user_disk_device_job_info;
|
||||
struct user_disk_system_info;
|
||||
@ -107,8 +108,8 @@ extern pid_t _kern_setpgid(pid_t process, pid_t group);
|
||||
extern pid_t _kern_setsid(void);
|
||||
extern status_t _kern_change_root(const char *path);
|
||||
|
||||
extern thread_id _kern_spawn_thread(int32 (*func)(thread_func, void *),
|
||||
const char *name, int32 priority, void *data1, void *data2);
|
||||
extern thread_id _kern_spawn_thread(
|
||||
struct thread_creation_attributes* attributes);
|
||||
extern thread_id _kern_find_thread(const char *name);
|
||||
extern status_t _kern_suspend_thread(thread_id thread);
|
||||
extern status_t _kern_resume_thread(thread_id thread);
|
||||
|
@ -20,6 +20,21 @@
|
||||
|
||||
struct kernel_args;
|
||||
struct select_info;
|
||||
struct thread_creation_attributes;
|
||||
|
||||
struct thread_creation_attributes {
|
||||
int32 (*entry)(thread_func, void *);
|
||||
const char* name;
|
||||
int32 priority;
|
||||
void* args1;
|
||||
void* args2;
|
||||
void* stack_address;
|
||||
size_t stack_size;
|
||||
|
||||
// when calling kernel only
|
||||
team_id team;
|
||||
thread_id thread;
|
||||
};
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
@ -89,7 +104,7 @@ status_t _user_rename_thread(thread_id thread, const char *name);
|
||||
status_t _user_suspend_thread(thread_id thread);
|
||||
status_t _user_resume_thread(thread_id thread);
|
||||
status_t _user_rename_thread(thread_id thread, const char *name);
|
||||
thread_id _user_spawn_thread(thread_entry_func entry, const char *name, int32 priority, void *arg1, void *arg2);
|
||||
thread_id _user_spawn_thread(struct thread_creation_attributes* attributes);
|
||||
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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -9,6 +9,8 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <thread.h>
|
||||
|
||||
#include "libroot_private.h"
|
||||
#include "tls.h"
|
||||
#include "syscalls.h"
|
||||
@ -42,10 +44,20 @@ thread_entry(thread_func entry, void *data)
|
||||
thread_id
|
||||
spawn_thread(thread_func entry, const char *name, int32 priority, void *data)
|
||||
{
|
||||
struct thread_creation_attributes attributes;
|
||||
|
||||
_single_threaded = false;
|
||||
// used for I/O locking - BeOS compatibility issue
|
||||
|
||||
return _kern_spawn_thread(thread_entry, name, priority, entry, data);
|
||||
attributes.entry = &thread_entry;
|
||||
attributes.name = name;
|
||||
attributes.priority = priority;
|
||||
attributes.args1 = entry;
|
||||
attributes.args2 = data;
|
||||
attributes.stack_address = NULL;
|
||||
attributes.stack_size = 0;
|
||||
|
||||
return _kern_spawn_thread(&attributes);
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user