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

📄 synch.c

📁 The main purpose of this project is to add a new scheduling algorithm to GeekOS and to implement a s
💻 C
字号:
/* * Synchronization primitives * Copyright (c) 2001,2004 David H. Hovemeyer <daveho@cs.umd.edu> * $Revision: 1.13 $ *  * This is free software.  You are permitted to use, * redistribute, and modify it as specified in the file "COPYING". */#include <geekos/kthread.h>#include <geekos/int.h>#include <geekos/kassert.h>#include <geekos/screen.h>#include <geekos/synch.h>/* * NOTES: * - The GeekOS mutex and condition variable APIs are based on those *   in pthreads. * - Unlike disabling interrupts, mutexes offer NO protection against *   concurrent execution of interrupt handlers.  Mutexes and *   condition variables should only be used from kernel threads, *   with interrupts enabled. *//* ---------------------------------------------------------------------- * Private functions * ---------------------------------------------------------------------- *//* * The mutex is currently locked. * Atomically reenable preemption and wait in the * mutex's wait queue. */static void Mutex_Wait(struct Mutex *mutex){    KASSERT(mutex->state == MUTEX_LOCKED);    KASSERT(g_preemptionDisabled);    Disable_Interrupts();    g_preemptionDisabled = false;    Wait(&mutex->waitQueue);    g_preemptionDisabled = true;    Enable_Interrupts();}/* * Lock given mutex. * Preemption must be disabled. */static __inline__ void Mutex_Lock_Imp(struct Mutex* mutex){    KASSERT(g_preemptionDisabled);    /* Make sure we're not already holding the mutex */    KASSERT(!IS_HELD(mutex));    /* Wait until the mutex is in an unlocked state */    while (mutex->state == MUTEX_LOCKED) {	Mutex_Wait(mutex);    }    /* Now it's ours! */    mutex->state = MUTEX_LOCKED;    mutex->owner = g_currentThread;}/* * Unlock given mutex. * Preemption must be disabled. */static __inline__ void Mutex_Unlock_Imp(struct Mutex* mutex){    KASSERT(g_preemptionDisabled);    /* Make sure mutex was actually acquired by this thread. */    KASSERT(IS_HELD(mutex));    /* Unlock the mutex. */    mutex->state = MUTEX_UNLOCKED;    mutex->owner = 0;    /*     * If there are threads waiting to acquire the mutex,     * wake one of them up.  Note that it is legal to inspect     * the queue with interrupts enabled because preemption     * is disabled, and therefore we know that no thread can     * concurrently add itself to the queue.     */    if (!Is_Thread_Queue_Empty(&mutex->waitQueue)) {	Disable_Interrupts();	Wake_Up_One(&mutex->waitQueue);	Enable_Interrupts();    }}/* ---------------------------------------------------------------------- * Public functions * ---------------------------------------------------------------------- *//* * Initialize given mutex. */void Mutex_Init(struct Mutex* mutex){    mutex->state = MUTEX_UNLOCKED;    mutex->owner = 0;    Clear_Thread_Queue(&mutex->waitQueue);}/* * Lock given mutex. */void Mutex_Lock(struct Mutex* mutex){    KASSERT(Interrupts_Enabled());    g_preemptionDisabled = true;    Mutex_Lock_Imp(mutex);    g_preemptionDisabled = false;}/* * Unlock given mutex. */void Mutex_Unlock(struct Mutex* mutex){    KASSERT(Interrupts_Enabled());    g_preemptionDisabled = true;    Mutex_Unlock_Imp(mutex);    g_preemptionDisabled = false;}/* * Initialize given condition. */void Cond_Init(struct Condition* cond){    Clear_Thread_Queue(&cond->waitQueue);}/* * Wait on given condition (protected by given mutex). */void Cond_Wait(struct Condition* cond, struct Mutex* mutex){    KASSERT(Interrupts_Enabled());    /* Ensure mutex is held. */    KASSERT(IS_HELD(mutex));    /* Turn off scheduling. */    g_preemptionDisabled = true;    /*     * Release the mutex, but leave preemption disabled.     * No other threads will be able to run before this thread     * is able to wait.  Therefore, this thread will not     * miss the eventual notification on the condition.     */    Mutex_Unlock_Imp(mutex);    /*     * Atomically reenable preemption and wait in the condition wait queue.     * Other threads can run while this thread is waiting,     * and eventually one of them will call Cond_Signal() or Cond_Broadcast()     * to wake up this thread.     * On wakeup, disable preemption again.     */    Disable_Interrupts();    g_preemptionDisabled = false;    Wait(&cond->waitQueue);    g_preemptionDisabled = true;    Enable_Interrupts();    /* Reacquire the mutex. */    Mutex_Lock_Imp(mutex);    /* Turn scheduling back on. */    g_preemptionDisabled = false;}/* * Wake up one thread waiting on the given condition. * The mutex guarding the condition should be held! */void Cond_Signal(struct Condition* cond){    KASSERT(Interrupts_Enabled());    Disable_Interrupts();  /* prevent scheduling */    Wake_Up_One(&cond->waitQueue);    Enable_Interrupts();  /* resume scheduling */}/* * Wake up all threads waiting on the given condition. * The mutex guarding the condition should be held! */void Cond_Broadcast(struct Condition* cond){    KASSERT(Interrupts_Enabled());    Disable_Interrupts();  /* prevent scheduling */    Wake_Up(&cond->waitQueue);    Enable_Interrupts();  /* resume scheduling */}

⌨️ 快捷键说明

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