team_create_team2() now also allocates a region for TLS in the primary stack
area. It now also calls arch_thread_init_tls(). Cleaned it up to make it more readable, added some comments. Some other cleanups. git-svn-id: file:///srv/svn/repos/haiku/trunk/current@2381 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
+52
-43
@@ -21,6 +21,7 @@
|
|||||||
#include <elf.h>
|
#include <elf.h>
|
||||||
#include <atomic.h>
|
#include <atomic.h>
|
||||||
#include <syscalls.h>
|
#include <syscalls.h>
|
||||||
|
#include <tls.h>
|
||||||
|
|
||||||
|
|
||||||
struct team_key {
|
struct team_key {
|
||||||
@@ -393,12 +394,12 @@ team_create_team2(void *args)
|
|||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
struct thread *t;
|
struct thread *t;
|
||||||
struct team *p;
|
struct team *team;
|
||||||
struct team_arg *pargs = args;
|
struct team_arg *pargs = args;
|
||||||
char *path;
|
char *path;
|
||||||
addr entry;
|
addr entry;
|
||||||
char ustack_name[128];
|
char ustack_name[128];
|
||||||
int tot_top_size;
|
uint32 totalSize;
|
||||||
char **uargs;
|
char **uargs;
|
||||||
char **uenv;
|
char **uenv;
|
||||||
char *udest;
|
char *udest;
|
||||||
@@ -407,25 +408,33 @@ team_create_team2(void *args)
|
|||||||
unsigned int env_cnt;
|
unsigned int env_cnt;
|
||||||
|
|
||||||
t = thread_get_current_thread();
|
t = thread_get_current_thread();
|
||||||
p = t->team;
|
team = t->team;
|
||||||
|
|
||||||
dprintf("team_create_team2: entry thread %ld\n", t->id);
|
dprintf("team_create_team2: entry thread %ld\n", t->id);
|
||||||
|
|
||||||
// create an initial primary stack region
|
// create an initial primary stack region
|
||||||
|
|
||||||
// ToDo: give the main thread a larger user stack (for gcc and friends, as in BeOS)
|
// ToDo: make ENV_SIZE variable?
|
||||||
// ToDo: clean up the ENV_SIZE/STACK_SIZE/whatever mess (and maybe add TLS to it)
|
// ToDo: when B_BASE_ADDRESS is implemented, we could just allocate the stack from
|
||||||
tot_top_size = STACK_SIZE + ENV_SIZE + PAGE_ALIGN(get_arguments_data_size(pargs->args, pargs->argc));
|
// the bottom of the USER_STACK_REGION.
|
||||||
t->user_stack_base = ((USER_STACK_REGION - tot_top_size) + USER_STACK_REGION_SIZE);
|
|
||||||
sprintf(ustack_name, "%s_primary_stack", p->name);
|
totalSize = PAGE_ALIGN(MAIN_THREAD_STACK_SIZE + TLS_SIZE + ENV_SIZE +
|
||||||
t->user_stack_region_id = vm_create_anonymous_region(p->_aspace_id, ustack_name, (void **)&t->user_stack_base,
|
get_arguments_data_size(pargs->args, pargs->argc));
|
||||||
REGION_ADDR_EXACT_ADDRESS, tot_top_size, REGION_WIRING_LAZY, LOCK_RW);
|
t->user_stack_base = USER_STACK_REGION + USER_STACK_REGION_SIZE - totalSize;
|
||||||
|
// the exact location at the end of the user stack region
|
||||||
|
|
||||||
|
sprintf(ustack_name, "%s_primary_stack", team->name);
|
||||||
|
t->user_stack_region_id = vm_create_anonymous_region(team->_aspace_id, ustack_name, (void **)&t->user_stack_base,
|
||||||
|
REGION_ADDR_EXACT_ADDRESS, totalSize, REGION_WIRING_LAZY, LOCK_RW);
|
||||||
if (t->user_stack_region_id < 0) {
|
if (t->user_stack_region_id < 0) {
|
||||||
panic("team_create_team2: could not create default user stack region\n");
|
panic("team_create_team2: could not create default user stack region\n");
|
||||||
return t->user_stack_region_id;
|
return t->user_stack_region_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
uspa = (struct uspace_prog_args_t *)(t->user_stack_base + STACK_SIZE + ENV_SIZE);
|
// now that the TLS area is allocated, initialize TLS
|
||||||
|
arch_thread_init_tls(t);
|
||||||
|
|
||||||
|
uspa = (struct uspace_prog_args_t *)(t->user_stack_base + STACK_SIZE + TLS_SIZE + ENV_SIZE);
|
||||||
uargs = (char **)(uspa + 1);
|
uargs = (char **)(uspa + 1);
|
||||||
udest = (char *)(uargs + pargs->argc + 1);
|
udest = (char *)(uargs + pargs->argc + 1);
|
||||||
// dprintf("addr: stack base=0x%x uargs = 0x%x udest=0x%x tot_top_size=%d \n\n",t->user_stack_base,uargs,udest,tot_top_size);
|
// dprintf("addr: stack base=0x%x uargs = 0x%x udest=0x%x tot_top_size=%d \n\n",t->user_stack_base,uargs,udest,tot_top_size);
|
||||||
@@ -437,9 +446,9 @@ team_create_team2(void *args)
|
|||||||
}
|
}
|
||||||
uargs[arg_cnt] = NULL;
|
uargs[arg_cnt] = NULL;
|
||||||
|
|
||||||
p->user_env_base = t->user_stack_base + STACK_SIZE;
|
team->user_env_base = t->user_stack_base + STACK_SIZE + TLS_SIZE;
|
||||||
uenv = (char **)p->user_env_base;
|
uenv = (char **)team->user_env_base;
|
||||||
udest = (char *)p->user_env_base + ENV_SIZE - 1;
|
udest = (char *)team->user_env_base + ENV_SIZE - 1;
|
||||||
// dprintf("team_create_team2: envc: %d, envp: 0x%p\n", pargs->envc, (void *)pargs->envp);
|
// dprintf("team_create_team2: envc: %d, envp: 0x%p\n", pargs->envc, (void *)pargs->envp);
|
||||||
for (env_cnt=0; env_cnt<pargs->envc; env_cnt++) {
|
for (env_cnt=0; env_cnt<pargs->envc; env_cnt++) {
|
||||||
udest -= (strlen(pargs->envp[env_cnt]) + 1);
|
udest -= (strlen(pargs->envp[env_cnt]) + 1);
|
||||||
@@ -448,7 +457,7 @@ team_create_team2(void *args)
|
|||||||
}
|
}
|
||||||
uenv[env_cnt] = NULL;
|
uenv[env_cnt] = NULL;
|
||||||
|
|
||||||
user_memcpy(uspa->prog_name, p->name, sizeof(uspa->prog_name));
|
user_memcpy(uspa->prog_name, team->name, sizeof(uspa->prog_name));
|
||||||
user_memcpy(uspa->prog_path, pargs->path, sizeof(uspa->prog_path));
|
user_memcpy(uspa->prog_path, pargs->path, sizeof(uspa->prog_path));
|
||||||
uspa->argc = arg_cnt;
|
uspa->argc = arg_cnt;
|
||||||
uspa->argv = uargs;
|
uspa->argv = uargs;
|
||||||
@@ -463,8 +472,8 @@ team_create_team2(void *args)
|
|||||||
path = pargs->path;
|
path = pargs->path;
|
||||||
dprintf("team_create_team2: loading elf binary '%s'\n", path);
|
dprintf("team_create_team2: loading elf binary '%s'\n", path);
|
||||||
|
|
||||||
err = elf_load_uspace("/boot/libexec/rld.so", p, 0, &entry);
|
err = elf_load_uspace("/boot/libexec/rld.so", team, 0, &entry);
|
||||||
if(err < 0){
|
if (err < 0){
|
||||||
// XXX clean up team
|
// XXX clean up team
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
@@ -475,10 +484,10 @@ team_create_team2(void *args)
|
|||||||
|
|
||||||
dprintf("team_create_team2: loaded elf. entry = 0x%lx\n", entry);
|
dprintf("team_create_team2: loaded elf. entry = 0x%lx\n", entry);
|
||||||
|
|
||||||
p->state = TEAM_STATE_NORMAL;
|
team->state = TEAM_STATE_NORMAL;
|
||||||
|
|
||||||
// jump to the entry point in user space
|
// jump to the entry point in user space
|
||||||
arch_thread_enter_uspace(entry, uspa, t->user_stack_base + STACK_SIZE);
|
arch_thread_enter_uspace(t, entry, uspa);
|
||||||
|
|
||||||
// never gets here
|
// never gets here
|
||||||
return 0;
|
return 0;
|
||||||
@@ -488,7 +497,7 @@ team_create_team2(void *args)
|
|||||||
team_id
|
team_id
|
||||||
team_create_team(const char *path, const char *name, char **args, int argc, char **envp, int envc, int priority)
|
team_create_team(const char *path, const char *name, char **args, int argc, char **envp, int envc, int priority)
|
||||||
{
|
{
|
||||||
struct team *p;
|
struct team *team;
|
||||||
thread_id tid;
|
thread_id tid;
|
||||||
team_id pid;
|
team_id pid;
|
||||||
int err;
|
int err;
|
||||||
@@ -498,15 +507,15 @@ team_create_team(const char *path, const char *name, char **args, int argc, char
|
|||||||
|
|
||||||
dprintf("team_create_team: entry '%s', name '%s' args = %p argc = %d\n", path, name, args, argc);
|
dprintf("team_create_team: entry '%s', name '%s' args = %p argc = %d\n", path, name, args, argc);
|
||||||
|
|
||||||
p = create_team_struct(name, false);
|
team = create_team_struct(name, false);
|
||||||
if (p == NULL)
|
if (team == NULL)
|
||||||
return ENOMEM;
|
return ENOMEM;
|
||||||
|
|
||||||
pid = p->id;
|
pid = team->id;
|
||||||
|
|
||||||
state = disable_interrupts();
|
state = disable_interrupts();
|
||||||
GRAB_TEAM_LOCK();
|
GRAB_TEAM_LOCK();
|
||||||
hash_insert(team_hash, p);
|
hash_insert(team_hash, team);
|
||||||
RELEASE_TEAM_LOCK();
|
RELEASE_TEAM_LOCK();
|
||||||
restore_interrupts(state);
|
restore_interrupts(state);
|
||||||
|
|
||||||
@@ -527,22 +536,22 @@ team_create_team(const char *path, const char *name, char **args, int argc, char
|
|||||||
pargs->envc = envc;
|
pargs->envc = envc;
|
||||||
|
|
||||||
// create a new io_context for this team
|
// create a new io_context for this team
|
||||||
p->io_context = vfs_new_io_context(thread_get_current_thread()->team->io_context);
|
team->io_context = vfs_new_io_context(thread_get_current_thread()->team->io_context);
|
||||||
if (!p->io_context) {
|
if (!team->io_context) {
|
||||||
err = ENOMEM;
|
err = ENOMEM;
|
||||||
goto err3;
|
goto err3;
|
||||||
}
|
}
|
||||||
|
|
||||||
// create an address space for this team
|
// create an address space for this team
|
||||||
p->_aspace_id = vm_create_aspace(p->name, USER_BASE, USER_SIZE, false);
|
team->_aspace_id = vm_create_aspace(team->name, USER_BASE, USER_SIZE, false);
|
||||||
if (p->_aspace_id < 0) {
|
if (team->_aspace_id < 0) {
|
||||||
err = p->_aspace_id;
|
err = team->_aspace_id;
|
||||||
goto err4;
|
goto err4;
|
||||||
}
|
}
|
||||||
p->aspace = vm_get_aspace_by_id(p->_aspace_id);
|
team->aspace = vm_get_aspace_by_id(team->_aspace_id);
|
||||||
|
|
||||||
// create a kernel thread, but under the context of the new team
|
// create a kernel thread, but under the context of the new team
|
||||||
tid = thread_create_kernel_thread_etc(name, team_create_team2, pargs, p);
|
tid = thread_create_kernel_thread_etc(name, team_create_team2, pargs, team);
|
||||||
if (tid < 0) {
|
if (tid < 0) {
|
||||||
err = tid;
|
err = tid;
|
||||||
goto err5;
|
goto err5;
|
||||||
@@ -553,10 +562,10 @@ team_create_team(const char *path, const char *name, char **args, int argc, char
|
|||||||
return pid;
|
return pid;
|
||||||
|
|
||||||
err5:
|
err5:
|
||||||
vm_put_aspace(p->aspace);
|
vm_put_aspace(team->aspace);
|
||||||
vm_delete_aspace(p->_aspace_id);
|
vm_delete_aspace(team->_aspace_id);
|
||||||
err4:
|
err4:
|
||||||
vfs_free_io_context(p->io_context);
|
vfs_free_io_context(team->io_context);
|
||||||
err3:
|
err3:
|
||||||
free(pargs->path);
|
free(pargs->path);
|
||||||
err2:
|
err2:
|
||||||
@@ -565,10 +574,10 @@ err1:
|
|||||||
// remove the team structure from the team hash table and delete the team structure
|
// remove the team structure from the team hash table and delete the team structure
|
||||||
state = disable_interrupts();
|
state = disable_interrupts();
|
||||||
GRAB_TEAM_LOCK();
|
GRAB_TEAM_LOCK();
|
||||||
hash_remove(team_hash, p);
|
hash_remove(team_hash, team);
|
||||||
RELEASE_TEAM_LOCK();
|
RELEASE_TEAM_LOCK();
|
||||||
restore_interrupts(state);
|
restore_interrupts(state);
|
||||||
delete_team_struct(p);
|
delete_team_struct(team);
|
||||||
//err:
|
//err:
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
@@ -578,7 +587,7 @@ int
|
|||||||
team_kill_team(team_id id)
|
team_kill_team(team_id id)
|
||||||
{
|
{
|
||||||
int state;
|
int state;
|
||||||
struct team *p;
|
struct team *team;
|
||||||
// struct thread *t;
|
// struct thread *t;
|
||||||
thread_id tid = -1;
|
thread_id tid = -1;
|
||||||
int retval = 0;
|
int retval = 0;
|
||||||
@@ -586,16 +595,16 @@ team_kill_team(team_id id)
|
|||||||
state = disable_interrupts();
|
state = disable_interrupts();
|
||||||
GRAB_TEAM_LOCK();
|
GRAB_TEAM_LOCK();
|
||||||
|
|
||||||
p = team_get_team_struct_locked(id);
|
team = team_get_team_struct_locked(id);
|
||||||
if(p != NULL) {
|
if (team != NULL)
|
||||||
tid = p->main_thread->id;
|
tid = team->main_thread->id;
|
||||||
} else {
|
else
|
||||||
retval = ERR_INVALID_HANDLE;
|
retval = ERR_INVALID_HANDLE;
|
||||||
}
|
|
||||||
|
|
||||||
RELEASE_TEAM_LOCK();
|
RELEASE_TEAM_LOCK();
|
||||||
restore_interrupts(state);
|
restore_interrupts(state);
|
||||||
if(retval < 0)
|
|
||||||
|
if (retval < 0)
|
||||||
return retval;
|
return retval;
|
||||||
|
|
||||||
// just kill the main thread in the team. The cleanup code there will
|
// just kill the main thread in the team. The cleanup code there will
|
||||||
|
|||||||
Reference in New Issue
Block a user