⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 kthread.c.bak

📁 The main purpose of this project is to add a new scheduling algorithm to GeekOS and to implement a s
💻 BAK
📖 第 1 页 / 共 2 页
字号:
    }}/* ---------------------------------------------------------------------- * Public functions * ---------------------------------------------------------------------- */void Init_Scheduler(void){    struct Kernel_Thread* mainThread = (struct Kernel_Thread *) KERN_THREAD_OBJ;    /*     * Create initial kernel thread context object and stack,     * and make them current.     */    Init_Thread(mainThread, (void *) KERN_STACK, PRIORITY_NORMAL, true);    g_currentThread = mainThread;    Add_To_Back_Of_All_Thread_List(&s_allThreadList, mainThread);    /*     * Create the idle thread.     */    /*Print("starting idle thread\n");*/    Start_Kernel_Thread(Idle, 0, PRIORITY_IDLE, true);    /*     * Create the reaper thread.     */    /*Print("starting reaper thread\n");*/    Start_Kernel_Thread(Reaper, 0, PRIORITY_NORMAL, true);}/* * Start a kernel-mode-only thread, using given function as its body * and passing given argument as its parameter.  Returns pointer * to the new thread if successful, null otherwise. * * startFunc - is the function to be called by the new thread * arg - is a paramter to pass to the new function * priority - the priority of this thread (use PRIORITY_NORMAL) for *    most things * detached - use false for kernel threads */struct Kernel_Thread* Start_Kernel_Thread(    Thread_Start_Func startFunc,    ulong_t arg,    int priority,    bool detached){    struct Kernel_Thread* kthread = Create_Thread(priority, detached);    if (kthread != 0) {	/*	 * Create the initial context for the thread to make	 * it schedulable.	 */	Setup_Kernel_Thread(kthread, startFunc, arg);	/* Atomically put the thread on the run queue. */	Make_Runnable_Atomic(kthread);    }    return kthread;}/* * Start a user-mode thread (i.e., a process), using given user context. * Returns pointer to the new thread if successful, null otherwise. */struct Kernel_Thread*Start_User_Thread(struct User_Context* userContext, bool detached){    /*     * Hints:     * - Use Create_Thread() to create a new "raw" thread object     * - Call Setup_User_Thread() to get the thread ready to     *   execute in user mode     * - Call Make_Runnable_Atomic() to schedule the process     *   for execution     *///    TODO("Start user thread");	struct Kernel_Thread * kthread = Create_Thread(PRIORITY_USER, detached);	if (kthread != 0)	{		Setup_User_Thread(kthread, userContext);		Make_Runnable_Atomic(kthread);	}	return kthread;}/* * Add given thread to the run queue, so that it * may be scheduled.  Must be called with interrupts disabled! */void Make_Runnable(struct Kernel_Thread* kthread){    KASSERT(!Interrupts_Enabled());    { int currentQ = kthread->currentReadyQueue;      KASSERT(currentQ >= 0 && currentQ < MAX_QUEUE_LEVEL);      kthread->blocked = false;      Enqueue_Thread(&s_runQueue[currentQ], kthread);    }}/* * Atomically make a thread runnable. * Assumes interrupts are currently enabled. */void Make_Runnable_Atomic(struct Kernel_Thread* kthread){    Disable_Interrupts();    Make_Runnable(kthread);    Enable_Interrupts();}/* * Get the thread that currently has the CPU. */struct Kernel_Thread* Get_Current(void){    return g_currentThread;}/* * Get the next runnable thread from the run queue. * This is the scheduler. *///struct Kernel_Thread* Get_Next_Runnable(void)//{//    struct Kernel_Thread* best = 0;////    best = Find_Best(&s_runQueue);//    KASSERT(best != 0);//    Remove_Thread(&s_runQueue, best);/////*// *    Print("Scheduling %x\n", best);// *///    return best;//}/* * Get the next runnable thread from the run queue. * This is the scheduler. */struct Kernel_Thread* Get_Next_Runnable(void){    struct Kernel_Thread* best = 0;    /* Find the best thread from the highest-priority run queue *///    TODO("Find a runnable thread from run queues");	if(g_SchedPolicy==1)	{		best=Find_Best(&s_runQueue[0]);		if(best!=0)		{			KASSERT(best!=0);			Remove_Thread(&s_runQueue[0],best);			return best;			}				best=Find_Best(&s_runQueue[1]);		if(best!=0)		{			KASSERT(best!=0);			Remove_Thread(&s_runQueue[1],best);			return best;			}					best=Find_Best(&s_runQueue[2]);		if(best!=0)		{			KASSERT(best!=0);			Remove_Thread(&s_runQueue[2],best);			return best;			}					best=Find_Best(&s_runQueue[3]);		if(best!=0)		{			KASSERT(best!=0);			Remove_Thread(&s_runQueue[3],best);			return best;			}		}	else		{			best = Find_Best(&s_runQueue);		  KASSERT(best != 0);	    Remove_Thread(&s_runQueue, best);		   return best;		}}/* * Schedule a thread that is waiting to run. * Must be called with interrupts off! * The current thread should already have been placed * on whatever queue is appropriate (i.e., either the * run queue if it is still runnable, or a wait queue * if it is waiting for an event to occur). */void Schedule(void){    struct Kernel_Thread* runnable;    /* Make sure interrupts really are disabled */    KASSERT(!Interrupts_Enabled());    /* Preemption should not be disabled. */    KASSERT(!g_preemptionDisabled);    /* Get next thread to run from the run queue */    runnable = Get_Next_Runnable();    /*     * Activate the new thread, saving the context of the current thread.     * Eventually, this thread will get re-activated and Switch_To_Thread()     * will "return", and then Schedule() will return to wherever     * it was called from.     */    Switch_To_Thread(runnable);}/* * Voluntarily give up the CPU to another thread. * Does nothing if no other threads are ready to run. */void Yield(void){    Disable_Interrupts();    Make_Runnable(g_currentThread);    Schedule();    Enable_Interrupts();}/* * Exit the current thread. * Calling this function initiates a context switch. */void Exit(int exitCode){    struct Kernel_Thread* current = g_currentThread;    if (Interrupts_Enabled())	Disable_Interrupts();    /* Thread is dead */    current->exitCode = exitCode;    current->alive = false;    /* Clean up any thread-local memory */    Tlocal_Exit(g_currentThread);    /* Notify the thread's owner, if any */    Wake_Up(&current->joinQueue);    /* Remove the thread's implicit reference to itself. */    Detach_Thread(g_currentThread);    /*     * Schedule a new thread.     * Since the old thread wasn't placed on any     * thread queue, it won't get scheduled again.     */    Schedule();    /* Shouldn't get here */    KASSERT(false);}/* * Wait for given thread to die. * Interrupts must be enabled. * Returns the thread exit code. */int Join(struct Kernel_Thread* kthread){    int exitCode;    KASSERT(Interrupts_Enabled());    /* It is only legal for the owner to join */    KASSERT(kthread->owner == g_currentThread);    Disable_Interrupts();    /* Wait for it to die */    while (kthread->alive) {	Wait(&kthread->joinQueue);    }    /* Get thread exit code. */    exitCode = kthread->exitCode;    /* Release our reference to the thread */    Detach_Thread(kthread);    Enable_Interrupts();    return exitCode;}/* * Look up a thread by its process id. * The caller must be the thread's owner. */struct Kernel_Thread* Lookup_Thread(int pid){    struct Kernel_Thread *result = 0;    bool iflag = Begin_Int_Atomic();    /*     * TODO: we could remove the requirement that the caller     * needs to be the thread's owner by specifying that another     * reference is added to the thread before it is returned.     */    result = Get_Front_Of_All_Thread_List(&s_allThreadList);    while (result != 0) {	if (result->pid == pid) {	    if (g_currentThread != result->owner)		result = 0;	    break;	}	result = Get_Next_In_All_Thread_List(result);    }    End_Int_Atomic(iflag);    return result;}/* * Wait on given wait queue. * Must be called with interrupts disabled! * Note that the function will return with interrupts * disabled.  This is desirable, because it allows us to * atomically test a condition that can be affected by an interrupt * and wait for it to be satisfied (if necessary). * See the Wait_For_Key() function in keyboard.c * for an example. */void Wait(struct Thread_Queue* waitQueue){    struct Kernel_Thread* current = g_currentThread;    KASSERT(!Interrupts_Enabled());    /* Add the thread to the wait queue. */    current->blocked = true;    Enqueue_Thread(waitQueue, current);    /* Find another thread to run. */    Schedule();}/* * Wake up all threads waiting on given wait queue. * Must be called with interrupts disabled! * See Keyboard_Interrupt_Handler() function in keyboard.c * for an example. */void Wake_Up(struct Thread_Queue* waitQueue){    struct Kernel_Thread *kthread = waitQueue->head, *next;    KASSERT(!Interrupts_Enabled());    /*     * Walk throught the list of threads in the wait queue,     * transferring each one to the run queue.     */    while (kthread != 0) {	next = Get_Next_In_Thread_Queue(kthread);	Make_Runnable(kthread);	kthread = next;    }    /* The wait queue is now empty. */    Clear_Thread_Queue(waitQueue);}/* * Wake up a single thread waiting on given wait queue * (if there are any threads waiting).  Chooses the highest priority thread. * Interrupts must be disabled! */void Wake_Up_One(struct Thread_Queue* waitQueue){    struct Kernel_Thread* best;    KASSERT(!Interrupts_Enabled());    best = Find_Best(waitQueue);    if (best != 0) {	Remove_Thread(waitQueue, best);	Make_Runnable(best);	/*Print("Wake_Up_One: waking up %x from %x\n", best, g_currentThread); */    }}/* * Allocate a key for accessing thread-local data. */int Tlocal_Create(tlocal_key_t *key, tlocal_destructor_t destructor) {    KASSERT(key);    bool iflag = Begin_Int_Atomic();    if (s_tlocalKeyCounter == MAX_TLOCAL_KEYS) return -1;    s_tlocalDestructors[s_tlocalKeyCounter] = destructor;    *key = s_tlocalKeyCounter++;    End_Int_Atomic(iflag);      return 0;}/* * Store a value for a thread-local item */void Tlocal_Put(tlocal_key_t k, const void *v) {    const void **pv;    KASSERT(k < s_tlocalKeyCounter);    pv = Get_Tlocal_Pointer(k);    *pv = v;}/* * Acquire a thread-local value */void *Tlocal_Get(tlocal_key_t k) {    const void **pv;    KASSERT(k < s_tlocalKeyCounter);    pv = Get_Tlocal_Pointer(k);    return (void *)*pv;}/* * Print list of all threads in system. * For debugging. */void Dump_All_Thread_List(void){    struct Kernel_Thread *kthread;    int count = 0;    bool iflag = Begin_Int_Atomic();    kthread = Get_Front_Of_All_Thread_List(&s_allThreadList);    Print("[");    while (kthread != 0) {	++count;	Print("<%lx,%lx,%lx>",	    (ulong_t) Get_Prev_In_All_Thread_List(kthread),	    (ulong_t) kthread,	    (ulong_t) Get_Next_In_All_Thread_List(kthread));	KASSERT(kthread != Get_Next_In_All_Thread_List(kthread));	kthread = Get_Next_In_All_Thread_List(kthread);    }    Print("]\n");    Print("%d threads are running\n", count);    End_Int_Atomic(iflag);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -