Cleaned up the source a bit, and rearranged the code, (hopefully) no functional
changes, though. git-svn-id: file:///srv/svn/repos/haiku/trunk/current@1393 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
+303
-259
@@ -81,11 +81,10 @@ static struct thread *thread_get_thread_struct_locked(thread_id id);
|
|||||||
static void thread_kthread_exit(void);
|
static void thread_kthread_exit(void);
|
||||||
static void deliver_signal(struct thread *t, int signal);
|
static void deliver_signal(struct thread *t, int signal);
|
||||||
|
|
||||||
#ifdef NEW_SCHEDULER
|
|
||||||
|
|
||||||
#endif /* NEW_SCHEDULER */
|
|
||||||
// insert a thread onto the tail of a queue
|
// insert a thread onto the tail of a queue
|
||||||
void thread_enqueue(struct thread *t, struct thread_queue *q)
|
void
|
||||||
|
thread_enqueue(struct thread *t, struct thread_queue *q)
|
||||||
{
|
{
|
||||||
t->q_next = NULL;
|
t->q_next = NULL;
|
||||||
if(q->head == NULL) {
|
if(q->head == NULL) {
|
||||||
@@ -97,17 +96,21 @@ void thread_enqueue(struct thread *t, struct thread_queue *q)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct thread *thread_lookat_queue(struct thread_queue *q)
|
|
||||||
|
struct thread *
|
||||||
|
thread_lookat_queue(struct thread_queue *q)
|
||||||
{
|
{
|
||||||
return q->head;
|
return q->head;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct thread *thread_dequeue(struct thread_queue *q)
|
|
||||||
|
struct thread *
|
||||||
|
thread_dequeue(struct thread_queue *q)
|
||||||
{
|
{
|
||||||
struct thread *t;
|
struct thread *t;
|
||||||
|
|
||||||
t = q->head;
|
t = q->head;
|
||||||
if(t != NULL) {
|
if (t != NULL) {
|
||||||
q->head = t->q_next;
|
q->head = t->q_next;
|
||||||
if(q->tail == t)
|
if(q->tail == t)
|
||||||
q->tail = NULL;
|
q->tail = NULL;
|
||||||
@@ -115,20 +118,22 @@ struct thread *thread_dequeue(struct thread_queue *q)
|
|||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct thread *thread_dequeue_id(struct thread_queue *q, thread_id thr_id)
|
|
||||||
|
struct thread *
|
||||||
|
thread_dequeue_id(struct thread_queue *q, thread_id thr_id)
|
||||||
{
|
{
|
||||||
struct thread *t;
|
struct thread *t;
|
||||||
struct thread *last = NULL;
|
struct thread *last = NULL;
|
||||||
|
|
||||||
t = q->head;
|
t = q->head;
|
||||||
while(t != NULL) {
|
while (t != NULL) {
|
||||||
if(t->id == thr_id) {
|
if (t->id == thr_id) {
|
||||||
if(last == NULL) {
|
if (last == NULL)
|
||||||
q->head = t->q_next;
|
q->head = t->q_next;
|
||||||
} else {
|
else
|
||||||
last->q_next = t->q_next;
|
last->q_next = t->q_next;
|
||||||
}
|
|
||||||
if(q->tail == t)
|
if (q->tail == t)
|
||||||
q->tail = last;
|
q->tail = last;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -139,51 +144,59 @@ struct thread *thread_dequeue_id(struct thread_queue *q, thread_id thr_id)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifndef NEW_SCHEDULER
|
#ifndef NEW_SCHEDULER
|
||||||
struct thread *thread_lookat_run_q(int priority)
|
struct thread *
|
||||||
|
thread_lookat_run_q(int priority)
|
||||||
{
|
{
|
||||||
return thread_lookat_queue(&run_q[(priority + 1) >> 1]);
|
return thread_lookat_queue(&run_q[(priority + 1) >> 1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void thread_enqueue_run_q(struct thread *t)
|
|
||||||
|
void
|
||||||
|
thread_enqueue_run_q(struct thread *t)
|
||||||
{
|
{
|
||||||
// these shouldn't exist
|
// these shouldn't exist
|
||||||
if(t->priority > B_MAX_PRIORITY)
|
if (t->priority > B_MAX_PRIORITY)
|
||||||
t->priority = B_MAX_PRIORITY;
|
t->priority = B_MAX_PRIORITY;
|
||||||
if(t->priority < B_MIN_PRIORITY)
|
else if (t->priority < B_MIN_PRIORITY)
|
||||||
t->priority = B_MIN_PRIORITY;
|
t->priority = B_MIN_PRIORITY;
|
||||||
|
|
||||||
thread_enqueue(t, &run_q[(t->priority + 1) >> 1]);
|
thread_enqueue(t, &run_q[(t->priority + 1) >> 1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct thread *thread_dequeue_run_q(int priority)
|
|
||||||
|
struct thread *
|
||||||
|
thread_dequeue_run_q(int priority)
|
||||||
{
|
{
|
||||||
return thread_dequeue(&run_q[(priority + 1) >> 1]);
|
return thread_dequeue(&run_q[(priority + 1) >> 1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* not NEW_SCHEDULER */
|
#endif /* not NEW_SCHEDULER */
|
||||||
static void insert_thread_into_team(struct team *p, struct thread *t)
|
|
||||||
|
static void
|
||||||
|
insert_thread_into_team(struct team *p, struct thread *t)
|
||||||
{
|
{
|
||||||
t->team_next = p->thread_list;
|
t->team_next = p->thread_list;
|
||||||
p->thread_list = t;
|
p->thread_list = t;
|
||||||
p->num_threads++;
|
p->num_threads++;
|
||||||
if(p->num_threads == 1) {
|
if (p->num_threads == 1) {
|
||||||
// this was the first thread
|
// this was the first thread
|
||||||
p->main_thread = t;
|
p->main_thread = t;
|
||||||
}
|
}
|
||||||
t->team = p;
|
t->team = p;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void remove_thread_from_team(struct team *p, struct thread *t)
|
|
||||||
|
static void
|
||||||
|
remove_thread_from_team(struct team *p, struct thread *t)
|
||||||
{
|
{
|
||||||
struct thread *temp, *last = NULL;
|
struct thread *temp, *last = NULL;
|
||||||
|
|
||||||
for(temp = p->thread_list; temp != NULL; temp = temp->team_next) {
|
for (temp = p->thread_list; temp != NULL; temp = temp->team_next) {
|
||||||
if(temp == t) {
|
if (temp == t) {
|
||||||
if(last == NULL) {
|
if (last == NULL)
|
||||||
p->thread_list = temp->team_next;
|
p->thread_list = temp->team_next;
|
||||||
} else {
|
else
|
||||||
last->team_next = temp->team_next;
|
last->team_next = temp->team_next;
|
||||||
}
|
|
||||||
p->num_threads--;
|
p->num_threads--;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -191,27 +204,35 @@ static void remove_thread_from_team(struct team *p, struct thread *t)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int thread_struct_compare(void *_t, const void *_key)
|
|
||||||
|
static int
|
||||||
|
thread_struct_compare(void *_t, const void *_key)
|
||||||
{
|
{
|
||||||
struct thread *t = _t;
|
struct thread *t = _t;
|
||||||
const struct thread_key *key = _key;
|
const struct thread_key *key = _key;
|
||||||
|
|
||||||
if(t->id == key->id) return 0;
|
if (t->id == key->id)
|
||||||
else return 1;
|
return 0;
|
||||||
|
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned int thread_struct_hash(void *_t, const void *_key, unsigned int range)
|
|
||||||
|
static unsigned int
|
||||||
|
thread_struct_hash(void *_t, const void *_key, unsigned int range)
|
||||||
{
|
{
|
||||||
struct thread *t = _t;
|
struct thread *t = _t;
|
||||||
const struct thread_key *key = _key;
|
const struct thread_key *key = _key;
|
||||||
|
|
||||||
if(t != NULL)
|
if (t != NULL)
|
||||||
return (t->id % range);
|
return (t->id % range);
|
||||||
else
|
|
||||||
return (key->id % range);
|
return (key->id % range);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct thread *create_thread_struct(const char *name)
|
|
||||||
|
static struct thread *
|
||||||
|
create_thread_struct(const char *name)
|
||||||
{
|
{
|
||||||
struct thread *t;
|
struct thread *t;
|
||||||
int state;
|
int state;
|
||||||
@@ -223,9 +244,9 @@ static struct thread *create_thread_struct(const char *name)
|
|||||||
RELEASE_THREAD_LOCK();
|
RELEASE_THREAD_LOCK();
|
||||||
restore_interrupts(state);
|
restore_interrupts(state);
|
||||||
|
|
||||||
if(t == NULL) {
|
if (t == NULL) {
|
||||||
t = (struct thread *)kmalloc(sizeof(struct thread));
|
t = (struct thread *)kmalloc(sizeof(struct thread));
|
||||||
if(t == NULL)
|
if (t == NULL)
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -253,7 +274,7 @@ static struct thread *create_thread_struct(const char *name)
|
|||||||
|
|
||||||
sprintf(temp, "thread_0x%lx_retcode_sem", t->id);
|
sprintf(temp, "thread_0x%lx_retcode_sem", t->id);
|
||||||
t->return_code_sem = create_sem(0, temp);
|
t->return_code_sem = create_sem(0, temp);
|
||||||
if(t->return_code_sem < 0)
|
if (t->return_code_sem < 0)
|
||||||
goto err1;
|
goto err1;
|
||||||
|
|
||||||
sprintf(temp, "%s data write sem", t->name);
|
sprintf(temp, "%s data write sem", t->name);
|
||||||
@@ -266,7 +287,7 @@ static struct thread *create_thread_struct(const char *name)
|
|||||||
if (t->msg.read_sem < 0)
|
if (t->msg.read_sem < 0)
|
||||||
goto err3;
|
goto err3;
|
||||||
|
|
||||||
if(arch_thread_init_thread_struct(t) < 0)
|
if (arch_thread_init_thread_struct(t) < 0)
|
||||||
goto err4;
|
goto err4;
|
||||||
|
|
||||||
return t;
|
return t;
|
||||||
@@ -283,7 +304,9 @@ err:
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void delete_thread_struct(struct thread *t)
|
|
||||||
|
static void
|
||||||
|
delete_thread_struct(struct thread *t)
|
||||||
{
|
{
|
||||||
if (t->return_code_sem >= 0)
|
if (t->return_code_sem >= 0)
|
||||||
delete_sem_etc(t->return_code_sem, -1);
|
delete_sem_etc(t->return_code_sem, -1);
|
||||||
@@ -294,7 +317,9 @@ static void delete_thread_struct(struct thread *t)
|
|||||||
kfree(t);
|
kfree(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _create_user_thread_kentry(void)
|
|
||||||
|
static int
|
||||||
|
_create_user_thread_kentry(void)
|
||||||
{
|
{
|
||||||
struct thread *t;
|
struct thread *t;
|
||||||
|
|
||||||
@@ -310,7 +335,9 @@ static int _create_user_thread_kentry(void)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _create_kernel_thread_kentry(void)
|
|
||||||
|
static int
|
||||||
|
_create_kernel_thread_kentry(void)
|
||||||
{
|
{
|
||||||
int (*func)(void *args);
|
int (*func)(void *args);
|
||||||
struct thread *t;
|
struct thread *t;
|
||||||
@@ -338,6 +365,7 @@ _create_thread(const char *name, team_id pid, addr entry, void *args, int priori
|
|||||||
return ENOMEM;
|
return ENOMEM;
|
||||||
|
|
||||||
t->priority = priority == -1 ? B_NORMAL_PRIORITY : priority;
|
t->priority = priority == -1 ? B_NORMAL_PRIORITY : priority;
|
||||||
|
// ToDo: revisit this one - the thread might go to early to B_THREAD_SUSPENDED
|
||||||
// t->state = THREAD_STATE_BIRTH;
|
// t->state = THREAD_STATE_BIRTH;
|
||||||
t->state = B_THREAD_SUSPENDED; // Is this right?
|
t->state = B_THREAD_SUSPENDED; // Is this right?
|
||||||
t->next_state = B_THREAD_SUSPENDED;
|
t->next_state = B_THREAD_SUSPENDED;
|
||||||
@@ -352,11 +380,11 @@ _create_thread(const char *name, team_id pid, addr entry, void *args, int priori
|
|||||||
GRAB_TEAM_LOCK();
|
GRAB_TEAM_LOCK();
|
||||||
// look at the team, make sure it's not being deleted
|
// look at the team, make sure it's not being deleted
|
||||||
p = team_get_team_struct_locked(pid);
|
p = team_get_team_struct_locked(pid);
|
||||||
if (p != NULL && p->state != TEAM_STATE_DEATH) {
|
if (p != NULL && p->state != TEAM_STATE_DEATH)
|
||||||
insert_thread_into_team(p, t);
|
insert_thread_into_team(p, t);
|
||||||
} else {
|
else
|
||||||
abort = true;
|
abort = true;
|
||||||
}
|
|
||||||
RELEASE_TEAM_LOCK();
|
RELEASE_TEAM_LOCK();
|
||||||
if (abort) {
|
if (abort) {
|
||||||
GRAB_THREAD_LOCK();
|
GRAB_THREAD_LOCK();
|
||||||
@@ -413,41 +441,30 @@ _create_thread(const char *name, team_id pid, addr entry, void *args, int priori
|
|||||||
return t->id;
|
return t->id;
|
||||||
}
|
}
|
||||||
|
|
||||||
thread_id user_thread_create_user_thread(addr entry, team_id pid, const char *uname, int priority,
|
|
||||||
void *args)
|
|
||||||
{
|
|
||||||
char name[SYS_MAX_OS_NAME_LEN];
|
|
||||||
int rc;
|
|
||||||
|
|
||||||
if((addr)uname >= KERNEL_BASE && (addr)uname <= KERNEL_TOP)
|
thread_id
|
||||||
return ERR_VM_BAD_USER_MEMORY;
|
thread_create_user_thread(char *name, team_id pid, addr entry, void *args)
|
||||||
if(entry >= KERNEL_BASE && entry <= KERNEL_TOP)
|
|
||||||
return ERR_VM_BAD_USER_MEMORY;
|
|
||||||
|
|
||||||
rc = user_strncpy(name, uname, SYS_MAX_OS_NAME_LEN-1);
|
|
||||||
if(rc < 0)
|
|
||||||
return rc;
|
|
||||||
name[SYS_MAX_OS_NAME_LEN-1] = 0;
|
|
||||||
|
|
||||||
return _create_thread(name, pid, entry, args, priority, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
thread_id thread_create_user_thread(char *name, team_id pid, addr entry, void *args)
|
|
||||||
{
|
{
|
||||||
return _create_thread(name, pid, entry, args, -1, false);
|
return _create_thread(name, pid, entry, args, -1, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
thread_id thread_create_kernel_thread(const char *name, int (*func)(void *), void *args)
|
|
||||||
|
thread_id
|
||||||
|
thread_create_kernel_thread(const char *name, int (*func)(void *), void *args)
|
||||||
{
|
{
|
||||||
return _create_thread(name, team_get_kernel_team()->id, (addr)func, args, -1, true);
|
return _create_thread(name, team_get_kernel_team()->id, (addr)func, args, -1, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
thread_id thread_create_kernel_thread_etc(const char *name, int (*func)(void *), void *args, struct team *p)
|
|
||||||
|
thread_id
|
||||||
|
thread_create_kernel_thread_etc(const char *name, int (*func)(void *), void *args, struct team *p)
|
||||||
{
|
{
|
||||||
return _create_thread(name, p->id, (addr)func, args, -1, true);
|
return _create_thread(name, p->id, (addr)func, args, -1, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
int thread_suspend_thread(thread_id id)
|
|
||||||
|
int
|
||||||
|
thread_suspend_thread(thread_id id)
|
||||||
{
|
{
|
||||||
int state;
|
int state;
|
||||||
struct thread *t;
|
struct thread *t;
|
||||||
@@ -458,7 +475,7 @@ int thread_suspend_thread(thread_id id)
|
|||||||
GRAB_THREAD_LOCK();
|
GRAB_THREAD_LOCK();
|
||||||
|
|
||||||
t = thread_get_current_thread();
|
t = thread_get_current_thread();
|
||||||
if(t->id != id) {
|
if (t->id != id) {
|
||||||
t = thread_get_thread_struct_locked(id);
|
t = thread_get_thread_struct_locked(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -474,21 +491,21 @@ int thread_suspend_thread(thread_id id)
|
|||||||
global_resched = true;
|
global_resched = true;
|
||||||
retval = B_NO_ERROR;
|
retval = B_NO_ERROR;
|
||||||
}
|
}
|
||||||
} else {
|
} else
|
||||||
retval = ERR_INVALID_HANDLE;
|
retval = ERR_INVALID_HANDLE;
|
||||||
}
|
|
||||||
|
|
||||||
RELEASE_THREAD_LOCK();
|
RELEASE_THREAD_LOCK();
|
||||||
restore_interrupts(state);
|
restore_interrupts(state);
|
||||||
|
|
||||||
if(global_resched) {
|
if (global_resched)
|
||||||
smp_send_broadcast_ici(SMP_MSG_RESCHEDULE, 0, 0, 0, NULL, SMP_MSG_FLAG_SYNC);
|
smp_send_broadcast_ici(SMP_MSG_RESCHEDULE, 0, 0, 0, NULL, SMP_MSG_FLAG_SYNC);
|
||||||
}
|
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
int thread_resume_thread(thread_id id)
|
|
||||||
|
int
|
||||||
|
thread_resume_thread(thread_id id)
|
||||||
{
|
{
|
||||||
int state;
|
int state;
|
||||||
struct thread *t;
|
struct thread *t;
|
||||||
@@ -498,15 +515,14 @@ int thread_resume_thread(thread_id id)
|
|||||||
GRAB_THREAD_LOCK();
|
GRAB_THREAD_LOCK();
|
||||||
|
|
||||||
t = thread_get_thread_struct_locked(id);
|
t = thread_get_thread_struct_locked(id);
|
||||||
if(t != NULL && t->state == B_THREAD_SUSPENDED) {
|
if (t != NULL && t->state == B_THREAD_SUSPENDED) {
|
||||||
t->state = B_THREAD_READY;
|
t->state = B_THREAD_READY;
|
||||||
t->next_state = B_THREAD_READY;
|
t->next_state = B_THREAD_READY;
|
||||||
|
|
||||||
thread_enqueue_run_q(t);
|
thread_enqueue_run_q(t);
|
||||||
retval = B_NO_ERROR;
|
retval = B_NO_ERROR;
|
||||||
} else {
|
} else
|
||||||
retval = ERR_INVALID_HANDLE;
|
retval = ERR_INVALID_HANDLE;
|
||||||
}
|
|
||||||
|
|
||||||
RELEASE_THREAD_LOCK();
|
RELEASE_THREAD_LOCK();
|
||||||
restore_interrupts(state);
|
restore_interrupts(state);
|
||||||
@@ -515,19 +531,20 @@ int thread_resume_thread(thread_id id)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifndef NEW_SCHEDULER
|
#ifndef NEW_SCHEDULER
|
||||||
int thread_set_priority(thread_id id, int priority)
|
int
|
||||||
|
thread_set_priority(thread_id id, int32 priority)
|
||||||
{
|
{
|
||||||
struct thread *t;
|
struct thread *t;
|
||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
// make sure the passed in priority is within bounds
|
// make sure the passed in priority is within bounds
|
||||||
if(priority > B_MAX_PRIORITY)
|
if (priority > B_MAX_PRIORITY)
|
||||||
priority = B_MAX_PRIORITY;
|
priority = B_MAX_PRIORITY;
|
||||||
if(priority < B_MIN_PRIORITY)
|
if (priority < B_MIN_PRIORITY)
|
||||||
priority = B_MIN_PRIORITY;
|
priority = B_MIN_PRIORITY;
|
||||||
|
|
||||||
t = thread_get_current_thread();
|
t = thread_get_current_thread();
|
||||||
if(t->id == id) {
|
if (t->id == id) {
|
||||||
// it's ourself, so we know we aren't in a run queue, and we can manipulate
|
// it's ourself, so we know we aren't in a run queue, and we can manipulate
|
||||||
// our structure directly
|
// our structure directly
|
||||||
t->priority = priority;
|
t->priority = priority;
|
||||||
@@ -537,19 +554,18 @@ int thread_set_priority(thread_id id, int priority)
|
|||||||
GRAB_THREAD_LOCK();
|
GRAB_THREAD_LOCK();
|
||||||
|
|
||||||
t = thread_get_thread_struct_locked(id);
|
t = thread_get_thread_struct_locked(id);
|
||||||
if(t) {
|
if (t) {
|
||||||
if(t->state == B_THREAD_READY && t->priority != priority) {
|
if (t->state == B_THREAD_READY && t->priority != priority) {
|
||||||
// this thread is in a ready queue right now, so it needs to be reinserted
|
// this thread is in a ready queue right now, so it needs to be reinserted
|
||||||
thread_dequeue_id(&run_q[(t->priority + 1) >> 1], t->id);
|
thread_dequeue_id(&run_q[(t->priority + 1) >> 1], t->id);
|
||||||
t->priority = priority;
|
t->priority = priority;
|
||||||
thread_enqueue_run_q(t);
|
thread_enqueue_run_q(t);
|
||||||
} else {
|
} else
|
||||||
t->priority = priority;
|
t->priority = priority;
|
||||||
}
|
|
||||||
retval = B_NO_ERROR;
|
retval = B_NO_ERROR;
|
||||||
} else {
|
} else
|
||||||
retval = ERR_INVALID_HANDLE;
|
retval = ERR_INVALID_HANDLE;
|
||||||
}
|
|
||||||
|
|
||||||
RELEASE_THREAD_LOCK();
|
RELEASE_THREAD_LOCK();
|
||||||
restore_interrupts(state);
|
restore_interrupts(state);
|
||||||
@@ -643,9 +659,8 @@ dump_thread_info(int argc, char **argv)
|
|||||||
// XXX semi-hack
|
// XXX semi-hack
|
||||||
_dump_thread_info((struct thread *)num);
|
_dump_thread_info((struct thread *)num);
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else
|
||||||
id = num;
|
id = num;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// walk through the thread list, trying to match name or id
|
// walk through the thread list, trying to match name or id
|
||||||
@@ -698,11 +713,11 @@ dump_next_thread_in_q(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
dprintf("next thread in queue after thread @ %p\n", t);
|
dprintf("next thread in queue after thread @ %p\n", t);
|
||||||
if (t->q_next != NULL) {
|
if (t->q_next != NULL)
|
||||||
_dump_thread_info(t->q_next);
|
_dump_thread_info(t->q_next);
|
||||||
} else {
|
else
|
||||||
dprintf("NULL\n");
|
dprintf("NULL\n");
|
||||||
}
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -718,11 +733,11 @@ dump_next_thread_in_all_list(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
dprintf("next thread in global list after thread @ %p\n", t);
|
dprintf("next thread in global list after thread @ %p\n", t);
|
||||||
if (t->all_next != NULL) {
|
if (t->all_next != NULL)
|
||||||
_dump_thread_info(t->all_next);
|
_dump_thread_info(t->all_next);
|
||||||
} else {
|
else
|
||||||
dprintf("NULL\n");
|
dprintf("NULL\n");
|
||||||
}
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -738,11 +753,11 @@ dump_next_thread_in_team(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
dprintf("next thread in team after thread @ %p\n", t);
|
dprintf("next thread in team after thread @ %p\n", t);
|
||||||
if (t->team_next != NULL) {
|
if (t->team_next != NULL)
|
||||||
_dump_thread_info(t->team_next);
|
_dump_thread_info(t->team_next);
|
||||||
} else {
|
else
|
||||||
dprintf("NULL\n");
|
dprintf("NULL\n");
|
||||||
}
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -879,7 +894,7 @@ thread_init(kernel_args *ka)
|
|||||||
{
|
{
|
||||||
char temp[64];
|
char temp[64];
|
||||||
|
|
||||||
for(i = 0; i < num_death_stacks; i++) {
|
for (i = 0; i < num_death_stacks; i++) {
|
||||||
sprintf(temp, "death_stack%d", i);
|
sprintf(temp, "death_stack%d", i);
|
||||||
death_stacks[i].rid = vm_create_anonymous_region(vm_get_kernel_aspace_id(), temp,
|
death_stacks[i].rid = vm_create_anonymous_region(vm_get_kernel_aspace_id(), temp,
|
||||||
(void **)&death_stacks[i].address,
|
(void **)&death_stacks[i].address,
|
||||||
@@ -1015,7 +1030,7 @@ thread_exit(int retcode)
|
|||||||
GRAB_TEAM_LOCK();
|
GRAB_TEAM_LOCK();
|
||||||
remove_thread_from_team(p, t);
|
remove_thread_from_team(p, t);
|
||||||
insert_thread_into_team(team_get_kernel_team(), t);
|
insert_thread_into_team(team_get_kernel_team(), t);
|
||||||
if(p->main_thread == t) {
|
if (p->main_thread == t) {
|
||||||
// this was main thread in this team
|
// this was main thread in this team
|
||||||
delete_team = true;
|
delete_team = true;
|
||||||
team_remove_team_from_hash(p);
|
team_remove_team_from_hash(p);
|
||||||
@@ -1133,9 +1148,8 @@ _thread_kill_thread(thread_id id, bool wait_on)
|
|||||||
if (t->id == thread_get_current_thread()->id)
|
if (t->id == thread_get_current_thread()->id)
|
||||||
wait_on = false; // can't wait on ourself
|
wait_on = false; // can't wait on ourself
|
||||||
}
|
}
|
||||||
} else {
|
} else
|
||||||
rc = ERR_INVALID_HANDLE;
|
rc = ERR_INVALID_HANDLE;
|
||||||
}
|
|
||||||
|
|
||||||
RELEASE_THREAD_LOCK();
|
RELEASE_THREAD_LOCK();
|
||||||
restore_interrupts(state);
|
restore_interrupts(state);
|
||||||
@@ -1170,25 +1184,6 @@ thread_kthread_exit(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
|
||||||
user_thread_wait_on_thread(thread_id id, int *uretcode)
|
|
||||||
{
|
|
||||||
int retcode;
|
|
||||||
int rc, rc2;
|
|
||||||
|
|
||||||
if ((addr)uretcode >= KERNEL_BASE && (addr)uretcode <= KERNEL_TOP)
|
|
||||||
return ERR_VM_BAD_USER_MEMORY;
|
|
||||||
|
|
||||||
rc = thread_wait_on_thread(id, &retcode);
|
|
||||||
|
|
||||||
rc2 = user_memcpy(uretcode, &retcode, sizeof(int));
|
|
||||||
if (rc2 < 0)
|
|
||||||
return rc2;
|
|
||||||
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
thread_wait_on_thread(thread_id id, int *retcode)
|
thread_wait_on_thread(thread_id id, int *retcode)
|
||||||
{
|
{
|
||||||
@@ -1380,15 +1375,6 @@ thread_atkernel_exit(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
user_send_data(thread_id tid, int32 code, const void *buffer, size_t buffer_size)
|
|
||||||
{
|
|
||||||
if (((addr)buffer >= KERNEL_BASE) && ((addr)buffer <= KERNEL_TOP))
|
|
||||||
return B_BAD_ADDRESS;
|
|
||||||
return send_data(tid, code, buffer, buffer_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
send_data(thread_id tid, int32 code, const void *buffer, size_t buffer_size)
|
send_data(thread_id tid, int32 code, const void *buffer, size_t buffer_size)
|
||||||
{
|
{
|
||||||
@@ -1461,28 +1447,6 @@ send_data(thread_id tid, int32 code, const void *buffer, size_t buffer_size)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
user_receive_data(thread_id *sender, void *buffer, size_t buffer_size)
|
|
||||||
{
|
|
||||||
thread_id ksender;
|
|
||||||
status_t code;
|
|
||||||
status_t rv;
|
|
||||||
|
|
||||||
if (((addr)sender >= KERNEL_BASE) && ((addr)sender <= KERNEL_TOP))
|
|
||||||
return B_BAD_ADDRESS;
|
|
||||||
if (((addr)buffer >= KERNEL_BASE) && ((addr)buffer <= KERNEL_TOP))
|
|
||||||
return B_BAD_ADDRESS;
|
|
||||||
|
|
||||||
code = receive_data(&ksender, buffer, buffer_size);
|
|
||||||
|
|
||||||
rv = user_memcpy(sender, &ksender, sizeof(thread_id));
|
|
||||||
if (rv < 0)
|
|
||||||
return rv;
|
|
||||||
|
|
||||||
return code;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
receive_data(thread_id *sender, void *buffer, size_t buffer_size)
|
receive_data(thread_id *sender, void *buffer, size_t buffer_size)
|
||||||
{
|
{
|
||||||
@@ -1522,28 +1486,6 @@ has_data(thread_id thread)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
user_get_thread_info(thread_id id, thread_info *info)
|
|
||||||
{
|
|
||||||
thread_info kinfo;
|
|
||||||
status_t rc = B_OK;
|
|
||||||
status_t rc2;
|
|
||||||
|
|
||||||
if ((addr)info >= KERNEL_BASE && (addr)info <= KERNEL_TOP)
|
|
||||||
return ERR_VM_BAD_USER_MEMORY;
|
|
||||||
|
|
||||||
rc = _get_thread_info(id, &kinfo, sizeof(thread_info));
|
|
||||||
if (rc != B_OK)
|
|
||||||
return rc;
|
|
||||||
|
|
||||||
rc2 = user_memcpy(info, &kinfo, sizeof(thread_info));
|
|
||||||
if (rc2 < 0)
|
|
||||||
return rc2;
|
|
||||||
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
_get_thread_info(thread_id id, thread_info *info, size_t size)
|
_get_thread_info(thread_id id, thread_info *info, size_t size)
|
||||||
{
|
{
|
||||||
@@ -1578,6 +1520,7 @@ _get_thread_info(thread_id id, thread_info *info, size_t size)
|
|||||||
info->kernel_time = t->kernel_time;
|
info->kernel_time = t->kernel_time;
|
||||||
info->stack_base = (void *)t->user_stack_base;
|
info->stack_base = (void *)t->user_stack_base;
|
||||||
info->stack_end = (void *)(t->user_stack_base + STACK_SIZE);
|
info->stack_end = (void *)(t->user_stack_base + STACK_SIZE);
|
||||||
|
|
||||||
err:
|
err:
|
||||||
RELEASE_THREAD_LOCK();
|
RELEASE_THREAD_LOCK();
|
||||||
restore_interrupts(state);
|
restore_interrupts(state);
|
||||||
@@ -1586,39 +1529,6 @@ err:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
|
||||||
user_get_next_thread_info(team_id team, int32 *cookie, thread_info *info)
|
|
||||||
{
|
|
||||||
int32 kcookie;
|
|
||||||
thread_info kinfo;
|
|
||||||
status_t rc = B_OK;
|
|
||||||
status_t rc2;
|
|
||||||
|
|
||||||
if ((addr)cookie >= KERNEL_BASE && (addr)cookie <= KERNEL_TOP)
|
|
||||||
return ERR_VM_BAD_USER_MEMORY;
|
|
||||||
if ((addr)info >= KERNEL_BASE && (addr)info <= KERNEL_TOP)
|
|
||||||
return ERR_VM_BAD_USER_MEMORY;
|
|
||||||
|
|
||||||
rc2 = user_memcpy(&kcookie, cookie, sizeof(int32));
|
|
||||||
if (rc2 < 0)
|
|
||||||
return rc2;
|
|
||||||
|
|
||||||
rc = _get_next_thread_info(team, &kcookie, &kinfo, sizeof(thread_info));
|
|
||||||
if (rc != B_OK)
|
|
||||||
return rc;
|
|
||||||
|
|
||||||
rc2 = user_memcpy(cookie, &kcookie, sizeof(int32));
|
|
||||||
if (rc2 < 0)
|
|
||||||
return rc2;
|
|
||||||
|
|
||||||
rc2 = user_memcpy(info, &kinfo, sizeof(thread_info));
|
|
||||||
if (rc2 < 0)
|
|
||||||
return rc2;
|
|
||||||
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
_get_next_thread_info(team_id tid, int32 *cookie, thread_info *info, size_t size)
|
_get_next_thread_info(team_id tid, int32 *cookie, thread_info *info, size_t size)
|
||||||
{
|
{
|
||||||
@@ -1680,38 +1590,13 @@ err:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int user_getrlimit(int resource, struct rlimit * urlp)
|
int
|
||||||
|
getrlimit(int resource, struct rlimit * rlp)
|
||||||
{
|
{
|
||||||
int ret;
|
if (!rlp)
|
||||||
struct rlimit rl;
|
|
||||||
|
|
||||||
if (urlp == NULL) {
|
|
||||||
return EINVAL;
|
|
||||||
}
|
|
||||||
if((addr)urlp >= KERNEL_BASE && (addr)urlp <= KERNEL_TOP) {
|
|
||||||
return ERR_VM_BAD_USER_MEMORY;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = getrlimit(resource, &rl);
|
|
||||||
|
|
||||||
if (ret == 0) {
|
|
||||||
ret = user_memcpy(urlp, &rl, sizeof(struct rlimit));
|
|
||||||
if (ret < 0) {
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
int getrlimit(int resource, struct rlimit * rlp)
|
|
||||||
{
|
|
||||||
if (!rlp) {
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
|
||||||
|
|
||||||
switch(resource) {
|
switch (resource) {
|
||||||
case RLIMIT_NOFILE:
|
case RLIMIT_NOFILE:
|
||||||
return vfs_getrlimit(resource, rlp);
|
return vfs_getrlimit(resource, rlp);
|
||||||
|
|
||||||
@@ -1722,33 +1607,14 @@ int getrlimit(int resource, struct rlimit * rlp)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int user_setrlimit(int resource, const struct rlimit * urlp)
|
|
||||||
|
int
|
||||||
|
setrlimit(int resource, const struct rlimit * rlp)
|
||||||
{
|
{
|
||||||
int err;
|
if (!rlp)
|
||||||
struct rlimit rl;
|
|
||||||
|
|
||||||
if (urlp == NULL) {
|
|
||||||
return EINVAL;
|
|
||||||
}
|
|
||||||
if((addr)urlp >= KERNEL_BASE && (addr)urlp <= KERNEL_TOP) {
|
|
||||||
return ERR_VM_BAD_USER_MEMORY;
|
|
||||||
}
|
|
||||||
|
|
||||||
err = user_memcpy(&rl, urlp, sizeof(struct rlimit));
|
|
||||||
if (err < 0) {
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
return setrlimit(resource, &rl);
|
|
||||||
}
|
|
||||||
|
|
||||||
int setrlimit(int resource, const struct rlimit * rlp)
|
|
||||||
{
|
|
||||||
if (!rlp) {
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
|
||||||
|
|
||||||
switch(resource) {
|
switch (resource) {
|
||||||
case RLIMIT_NOFILE:
|
case RLIMIT_NOFILE:
|
||||||
return vfs_setrlimit(resource, rlp);
|
return vfs_setrlimit(resource, rlp);
|
||||||
|
|
||||||
@@ -1758,3 +1624,181 @@ int setrlimit(int resource, const struct rlimit * rlp)
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark -
|
||||||
|
/* user calls */
|
||||||
|
|
||||||
|
|
||||||
|
thread_id
|
||||||
|
user_thread_create_user_thread(addr entry, team_id pid, const char *uname, int priority,
|
||||||
|
void *args)
|
||||||
|
{
|
||||||
|
char name[SYS_MAX_OS_NAME_LEN];
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
if ((addr)uname >= KERNEL_BASE && (addr)uname <= KERNEL_TOP)
|
||||||
|
return ERR_VM_BAD_USER_MEMORY;
|
||||||
|
if (entry >= KERNEL_BASE && entry <= KERNEL_TOP)
|
||||||
|
return ERR_VM_BAD_USER_MEMORY;
|
||||||
|
|
||||||
|
rc = user_strncpy(name, uname, SYS_MAX_OS_NAME_LEN-1);
|
||||||
|
if (rc < 0)
|
||||||
|
return rc;
|
||||||
|
name[SYS_MAX_OS_NAME_LEN-1] = 0;
|
||||||
|
|
||||||
|
return _create_thread(name, pid, entry, args, priority, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
user_get_thread_info(thread_id id, thread_info *info)
|
||||||
|
{
|
||||||
|
thread_info kinfo;
|
||||||
|
status_t rc = B_OK;
|
||||||
|
status_t rc2;
|
||||||
|
|
||||||
|
if ((addr)info >= KERNEL_BASE && (addr)info <= KERNEL_TOP)
|
||||||
|
return ERR_VM_BAD_USER_MEMORY;
|
||||||
|
|
||||||
|
rc = _get_thread_info(id, &kinfo, sizeof(thread_info));
|
||||||
|
if (rc != B_OK)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
rc2 = user_memcpy(info, &kinfo, sizeof(thread_info));
|
||||||
|
if (rc2 < 0)
|
||||||
|
return rc2;
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
user_get_next_thread_info(team_id team, int32 *cookie, thread_info *info)
|
||||||
|
{
|
||||||
|
int32 kcookie;
|
||||||
|
thread_info kinfo;
|
||||||
|
status_t rc = B_OK;
|
||||||
|
status_t rc2;
|
||||||
|
|
||||||
|
if ((addr)cookie >= KERNEL_BASE && (addr)cookie <= KERNEL_TOP)
|
||||||
|
return ERR_VM_BAD_USER_MEMORY;
|
||||||
|
if ((addr)info >= KERNEL_BASE && (addr)info <= KERNEL_TOP)
|
||||||
|
return ERR_VM_BAD_USER_MEMORY;
|
||||||
|
|
||||||
|
rc2 = user_memcpy(&kcookie, cookie, sizeof(int32));
|
||||||
|
if (rc2 < 0)
|
||||||
|
return rc2;
|
||||||
|
|
||||||
|
rc = _get_next_thread_info(team, &kcookie, &kinfo, sizeof(thread_info));
|
||||||
|
if (rc != B_OK)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
rc2 = user_memcpy(cookie, &kcookie, sizeof(int32));
|
||||||
|
if (rc2 < 0)
|
||||||
|
return rc2;
|
||||||
|
|
||||||
|
rc2 = user_memcpy(info, &kinfo, sizeof(thread_info));
|
||||||
|
if (rc2 < 0)
|
||||||
|
return rc2;
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
user_thread_wait_on_thread(thread_id id, int *uretcode)
|
||||||
|
{
|
||||||
|
int retcode;
|
||||||
|
int rc, rc2;
|
||||||
|
|
||||||
|
if ((addr)uretcode >= KERNEL_BASE && (addr)uretcode <= KERNEL_TOP)
|
||||||
|
return ERR_VM_BAD_USER_MEMORY;
|
||||||
|
|
||||||
|
rc = thread_wait_on_thread(id, &retcode);
|
||||||
|
|
||||||
|
rc2 = user_memcpy(uretcode, &retcode, sizeof(int));
|
||||||
|
if (rc2 < 0)
|
||||||
|
return rc2;
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
user_send_data(thread_id tid, int32 code, const void *buffer, size_t buffer_size)
|
||||||
|
{
|
||||||
|
if (((addr)buffer >= KERNEL_BASE) && ((addr)buffer <= KERNEL_TOP))
|
||||||
|
return B_BAD_ADDRESS;
|
||||||
|
return send_data(tid, code, buffer, buffer_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
user_receive_data(thread_id *sender, void *buffer, size_t buffer_size)
|
||||||
|
{
|
||||||
|
thread_id ksender;
|
||||||
|
status_t code;
|
||||||
|
status_t rv;
|
||||||
|
|
||||||
|
if (((addr)sender >= KERNEL_BASE) && ((addr)sender <= KERNEL_TOP))
|
||||||
|
return B_BAD_ADDRESS;
|
||||||
|
if (((addr)buffer >= KERNEL_BASE) && ((addr)buffer <= KERNEL_TOP))
|
||||||
|
return B_BAD_ADDRESS;
|
||||||
|
|
||||||
|
code = receive_data(&ksender, buffer, buffer_size);
|
||||||
|
|
||||||
|
rv = user_memcpy(sender, &ksender, sizeof(thread_id));
|
||||||
|
if (rv < 0)
|
||||||
|
return rv;
|
||||||
|
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
user_getrlimit(int resource, struct rlimit * urlp)
|
||||||
|
{
|
||||||
|
struct rlimit rl;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (urlp == NULL)
|
||||||
|
return EINVAL;
|
||||||
|
|
||||||
|
if ((addr)urlp >= KERNEL_BASE && (addr)urlp <= KERNEL_TOP)
|
||||||
|
return ERR_VM_BAD_USER_MEMORY;
|
||||||
|
|
||||||
|
ret = getrlimit(resource, &rl);
|
||||||
|
|
||||||
|
if (ret == 0) {
|
||||||
|
ret = user_memcpy(urlp, &rl, sizeof(struct rlimit));
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
user_setrlimit(int resource, const struct rlimit * urlp)
|
||||||
|
{
|
||||||
|
struct rlimit rl;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
if (urlp == NULL)
|
||||||
|
return EINVAL;
|
||||||
|
|
||||||
|
if ((addr)urlp >= KERNEL_BASE && (addr)urlp <= KERNEL_TOP)
|
||||||
|
return ERR_VM_BAD_USER_MEMORY;
|
||||||
|
|
||||||
|
err = user_memcpy(&rl, urlp, sizeof(struct rlimit));
|
||||||
|
if (err < 0)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
return setrlimit(resource, &rl);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user