Tasking code cleanup
This commit is contained in:
parent
345df6fbdf
commit
06fde84fc8
@ -11,4 +11,4 @@ HTML_DYNAMIC_SECTIONS = YES
|
||||
GENERATE_TREEVIEW = YES
|
||||
MACRO_EXPANSION = YES
|
||||
EXPAND_ONLY_PREDEF = YES
|
||||
PREDEFINED = __attribute__(x)=
|
||||
PREDEFINED = __attribute__(x)= DOXYGEN_SHOULD_SKIP_THIS=
|
||||
|
@ -2204,7 +2204,7 @@ INCLUDE_FILE_PATTERNS =
|
||||
# recursively expanded use the := operator instead of the = operator.
|
||||
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
|
||||
|
||||
PREDEFINED = __attribute__(x)=
|
||||
PREDEFINED = __attribute__(x)= DOXYGEN_SHOULD_SKIP_THIS=
|
||||
|
||||
# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this
|
||||
# tag can be used to specify a list of macro names that should be expanded. The
|
||||
|
166
kernel/tasking.c
166
kernel/tasking.c
@ -9,6 +9,7 @@
|
||||
#include "kmalloc.h"
|
||||
#include "tasking.h"
|
||||
#include <sys/types.h>
|
||||
#include <string.h>
|
||||
|
||||
#define MAX_PROCS 32768 //!< Maximum number of processes that can be running at a time
|
||||
#define HAS_UNBLOCKED_THREADS(proc) (proc->num_threads!=proc->num_threads_blocked) //!< Macro to check whethe a process has unblocked threads
|
||||
@ -88,53 +89,37 @@ void tasking_create_task(void* eip,void* address_space,char kmode,void* param1,v
|
||||
serial_printf("Failed to create a process, as 32k processes have been created already.\n");
|
||||
halt(); //Cannot ever create more than 32k processes, as I don't currently reuse PIDs.
|
||||
}
|
||||
pid_t pid=isThread ? (pid_t)param2 : next_pid;
|
||||
pid_t pid=isThread ? (pid_t)param2 : next_pid++;
|
||||
Process* proc=&processes[pid];
|
||||
Thread* thread=kmalloc(sizeof(Thread));
|
||||
if (isThread) {
|
||||
proc->num_threads++;
|
||||
thread->address_space=proc->first_thread->address_space;
|
||||
} else {
|
||||
if (current_thread) {
|
||||
proc->priv=current_thread->process->priv;
|
||||
} else {
|
||||
proc->priv=1;
|
||||
}
|
||||
proc->pid=pid;
|
||||
next_pid++;
|
||||
proc->next_tid=0;
|
||||
proc->num_threads=1;
|
||||
proc->num_threads_blocked=0;
|
||||
proc->first_thread=thread;
|
||||
thread->address_space=address_space;
|
||||
}
|
||||
proc->num_threads++;
|
||||
thread->process=proc;
|
||||
thread->errno=0;
|
||||
thread->tid=proc->next_tid;
|
||||
proc->next_tid++;
|
||||
setup_kstack(thread,param1,param2,kmode,eip);
|
||||
thread->tid=proc->next_tid++;
|
||||
thread->prev_ready_to_run=NULL;
|
||||
thread->next_ready_to_run=NULL;
|
||||
thread->prev_thread_in_process=NULL;
|
||||
|
||||
if (isThread) {
|
||||
thread->address_space=proc->first_thread->address_space;
|
||||
thread->next_thread_in_process=proc->first_thread;
|
||||
thread->prev_thread_in_process=NULL;
|
||||
thread->state=THREAD_READY;
|
||||
proc->first_thread->prev_thread_in_process=thread;
|
||||
proc->first_thread=thread;
|
||||
} else {
|
||||
thread->address_space=address_space;
|
||||
thread->next_thread_in_process=NULL;
|
||||
thread->prev_thread_in_process=NULL;
|
||||
schedule_thread(thread);
|
||||
}
|
||||
if (!isThread) {
|
||||
proc->priv=current_thread ? current_thread->process->priv : 1;
|
||||
proc->pid=pid;
|
||||
num_procs++;
|
||||
}
|
||||
proc->first_thread=thread;
|
||||
setup_kstack(thread,param1,param2,kmode,eip);
|
||||
schedule_thread(thread);
|
||||
serial_printf("Created thread with PID %d and TID %d.\n",proc->pid,thread->tid);
|
||||
}
|
||||
|
||||
void tasking_init() {
|
||||
for (size_t i = 0; i < MAX_PROCS; i++) {
|
||||
processes[i].num_threads=0;
|
||||
memset(&processes[i],0,sizeof(Process));
|
||||
}
|
||||
|
||||
tasking_create_task(NULL,get_address_space(),1,NULL,NULL,0);
|
||||
@ -157,6 +142,31 @@ pid_t tasking_new_thread(void* start,pid_t pid,void* param) {
|
||||
return processes[pid].first_thread->tid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the next ready thread in a list of threads, starting at the specified thread's next thread
|
||||
* \param thread The start thread
|
||||
* \param thread_to_skip A thread to skip even if it's ready
|
||||
* \return the next ready thread
|
||||
*/
|
||||
static Thread* get_next_ready_thread(Thread* thread,Thread* thread_to_skip) {
|
||||
#ifndef DOXYGEN_SHOULD_SKIP_THIS
|
||||
#define HELPER \
|
||||
while (thread&&(thread->state!=THREAD_READY||SAME_THREAD(thread,thread_to_skip))) { \
|
||||
thread=thread->next_thread_in_process; \
|
||||
}
|
||||
//end define
|
||||
#endif
|
||||
Thread* start_of_list=thread->process->first_thread;
|
||||
thread=thread->next_thread_in_process;
|
||||
HELPER;
|
||||
if (!thread) {
|
||||
thread=start_of_list;
|
||||
HELPER;
|
||||
}
|
||||
return thread;
|
||||
#undef HELPER
|
||||
}
|
||||
|
||||
/**
|
||||
* Switch to a thread and schedule the next ready thread in the current process, if there is one.
|
||||
* \param thread The thread to switch to
|
||||
@ -180,32 +190,15 @@ void switch_to_thread(Thread* thread) {
|
||||
if (current_thread->state==THREAD_RUNNING) {
|
||||
current_thread->state=THREAD_READY;
|
||||
}
|
||||
Thread* current_thread_next_ready=current_thread->next_thread_in_process;
|
||||
while ((current_thread_next_ready&¤t_thread_next_ready->state!=THREAD_READY)||(current_thread_next_ready&&SAME_THREAD(thread,current_thread_next_ready))) {
|
||||
current_thread_next_ready=current_thread_next_ready->next_thread_in_process;
|
||||
}
|
||||
if (!current_thread_next_ready) {
|
||||
current_thread_next_ready=current_thread->process->first_thread;
|
||||
while ((current_thread_next_ready&¤t_thread_next_ready->state!=THREAD_READY)||(current_thread_next_ready&&SAME_THREAD(thread,current_thread_next_ready))) {
|
||||
current_thread_next_ready=current_thread_next_ready->next_thread_in_process;
|
||||
}
|
||||
}
|
||||
//Get the next ready thread in the current process
|
||||
Thread* current_thread_next_ready=get_next_ready_thread(current_thread,thread);
|
||||
if (!current_thread_next_ready) {
|
||||
//This process is fully blocked, try the process of the thread we're yielding to
|
||||
current_thread_next_ready=thread->next_thread_in_process;
|
||||
while ((current_thread_next_ready&¤t_thread_next_ready->state!=THREAD_READY)||(current_thread_next_ready&&SAME_THREAD(thread,current_thread_next_ready))) {
|
||||
current_thread_next_ready=current_thread_next_ready->next_thread_in_process;
|
||||
}
|
||||
if (!current_thread_next_ready) {
|
||||
current_thread_next_ready=thread->process->first_thread;
|
||||
while ((current_thread_next_ready&¤t_thread_next_ready->state!=THREAD_READY)||(current_thread_next_ready&&SAME_THREAD(thread,current_thread_next_ready))) {
|
||||
current_thread_next_ready=current_thread_next_ready->next_thread_in_process;
|
||||
}
|
||||
}
|
||||
Thread* current_thread_next_ready=get_next_ready_thread(thread,thread);
|
||||
}
|
||||
if (current_thread_next_ready) {
|
||||
schedule_thread(current_thread_next_ready);
|
||||
}
|
||||
}
|
||||
serial_printf("Switching to PID %d TID %d.\n",thread->process->pid,thread->tid);
|
||||
switch_to_thread_asm(thread);
|
||||
}
|
||||
@ -267,23 +260,40 @@ void tasking_block(thread_state newstate) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a thread
|
||||
* \param pid The PID of the thread
|
||||
* \param tid The TID of the thread
|
||||
* \return the thread wih the specified PID and TID
|
||||
*/
|
||||
static Thread* get_thread(pid_t pid,pid_t tid) {
|
||||
if (processes[pid].num_threads==0) {
|
||||
serial_printf("PID %d does not exist!\n",pid);
|
||||
return NULL;
|
||||
}
|
||||
Thread* thread=processes[pid].first_thread;
|
||||
for (;thread!=NULL;thread=thread->next_thread_in_process) {
|
||||
if (thread->tid==tid) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!thread) {
|
||||
serial_printf("PID %d TID %d does not exist!\n",pid,thread);
|
||||
return NULL;
|
||||
}
|
||||
if (thread->tid!=tid) {
|
||||
serial_printf("Error! Got wrong thread! (Wanted TID %d, got TID %d)\n",tid,thread->tid);
|
||||
return NULL;
|
||||
}
|
||||
return thread;
|
||||
}
|
||||
|
||||
void tasking_unblock(pid_t pid,pid_t tid) {
|
||||
serial_printf("Unblocking PID %d TID %d\n",pid,tid);
|
||||
if (processes[pid].num_threads==0) {
|
||||
serial_printf("PID %d does not exist!\n",pid);
|
||||
}
|
||||
Thread* thread=processes[pid].first_thread;
|
||||
for (;thread!=NULL;thread=thread->next_thread_in_process) {
|
||||
if (thread->tid==tid) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!thread) {
|
||||
serial_printf("PID %d TID %d does not exist!\n",pid,thread);
|
||||
}
|
||||
if (thread->tid!=tid) {
|
||||
serial_printf("Error! Got wrong thread! (Wanted TID %d, got TID %d)\n",tid,thread->tid);
|
||||
halt();
|
||||
Thread* thread=get_thread(pid,tid);
|
||||
if (thread==NULL) {
|
||||
return;
|
||||
}
|
||||
if (thread->state==THREAD_EXITED||thread->state==THREAD_READY||thread->state==THREAD_RUNNING) {
|
||||
serial_printf("Tried to unblock an exited/ready/running thread!\n");
|
||||
@ -327,3 +337,29 @@ void tasking_exit(int code) {
|
||||
num_procs--;
|
||||
tasking_yield();
|
||||
}
|
||||
|
||||
void* tasking_get_address_space(pid_t pid) {
|
||||
return processes[pid].first_thread->address_space;
|
||||
}
|
||||
|
||||
void tasking_set_rpc_calling_thread(pid_t pid,pid_t tid) {
|
||||
Thread* thread=get_thread(pid,tid);
|
||||
thread->rpc_calling_pid=current_thread->process->pid;
|
||||
thread->rpc_calling_tid=current_thread->tid;
|
||||
}
|
||||
|
||||
pid_t tasking_get_rpc_calling_thread(pid_t* tid) {
|
||||
*tid=current_thread->rpc_calling_tid;
|
||||
return current_thread->rpc_calling_pid;
|
||||
}
|
||||
|
||||
void tasking_set_rpc_ret_buf(void* buf) {
|
||||
pid_t tid;
|
||||
pid_t pid=tasking_get_rpc_calling_thread(&tid);
|
||||
Thread* thread=get_thread(pid,tid);
|
||||
thread->rpc_ret_buf=buf;
|
||||
}
|
||||
|
||||
void* tasking_get_rpc_ret_buf() {
|
||||
return current_thread->rpc_ret_buf;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user