Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


added support for timing out Cond_Wait's
Jack Lange [Mon, 29 Sep 2008 16:07:55 +0000 (11:07 -0500)]
also added support for waking up specific threads by pid

palacios/include/geekos/kthread.h
palacios/include/geekos/synch.h
palacios/src/geekos/kthread.c
palacios/src/geekos/synch.c

index f0ef23c..48ade1c 100644 (file)
@@ -123,6 +123,7 @@ void Switch_To_Thread(struct Kernel_Thread*);
 void Wait(struct Thread_Queue* waitQueue);
 void Wake_Up(struct Thread_Queue* waitQueue);
 void Wake_Up_One(struct Thread_Queue* waitQueue);
+void Wake_Up_Thread(struct Thread_Queue* waitQueue, int pid);
 
 /*
  * Pointer to currently executing thread.
index 5cb95ef..b1ad875 100644 (file)
@@ -18,9 +18,9 @@
 enum { MUTEX_UNLOCKED, MUTEX_LOCKED };
 
 struct Mutex {
-    int state;
-    struct Kernel_Thread* owner;
-    struct Thread_Queue waitQueue;
+  int state;
+  struct Kernel_Thread* owner;
+  struct Thread_Queue waitQueue;
 };
 
 #define MUTEX_INITIALIZER { MUTEX_UNLOCKED, 0, THREAD_QUEUE_INITIALIZER }
@@ -35,6 +35,7 @@ void Mutex_Unlock(struct Mutex* mutex);
 
 void Cond_Init(struct Condition* cond);
 void Cond_Wait(struct Condition* cond, struct Mutex* mutex);
+int Cond_Wait_Timeout(struct Condition * cond, struct Mutex * mutex, uint_t ms);
 void Cond_Signal(struct Condition* cond);
 void Cond_Broadcast(struct Condition* cond);
 
index 0cba546..6ecb30f 100644 (file)
@@ -748,6 +748,30 @@ void Wake_Up_One(struct 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_Thread(struct Thread_Queue* waitQueue, int pid)
+{
+  struct Kernel_Thread* thread = Lookup_Thread(pid);;
+
+  KASSERT(!Interrupts_Enabled());
+  
+  
+  if (thread != 0) {
+    Remove_Thread(waitQueue, thread);
+    Make_Runnable(thread);
+       /*Print("Wake_Up_One: waking up %x from %x\n", best, g_currentThread); */
+  }
+}
+
+
+
+
 /*
  * Allocate a key for accessing thread-local data.
  */
index 86e7191..fdc1f34 100644 (file)
@@ -12,6 +12,7 @@
 #include <geekos/kassert.h>
 #include <geekos/screen.h>
 #include <geekos/synch.h>
+#include <geekos/timer.h>
 
 /*
  * NOTES:
@@ -181,6 +182,82 @@ void Cond_Wait(struct Condition* cond, struct Mutex* mutex)
     g_preemptionDisabled = false;
 }
 
+
+
+struct timeout_data {
+  int pid;
+  int timed_out;
+  struct Thread_Queue * waitQueue;
+};
+
+
+static void timeout_cb(int id, void * arg) {
+  struct timeout_data * to_state = (struct timeout_data *)arg;
+  
+  to_state->timed_out = 1;
+  Wake_Up_Thread(to_state->waitQueue, to_state->pid);
+
+}
+
+
+/*
+ * Wait on given condition (protected by given mutex).
+ */
+int Cond_Wait_Timeout(struct Condition* cond, struct Mutex* mutex, uint_t ms)
+{
+  struct timeout_data to_state;
+  struct Kernel_Thread * self = Get_Current();
+
+  to_state.pid = self->pid;
+  to_state.timed_out = 0;
+  to_state.waitQueue = &cond->waitQueue;
+
+    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);
+
+
+    Start_Timer_MSecs(ms, timeout_cb, &to_state);
+
+    /*
+     * 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();
+
+    if (to_state.timed_out == 0) {  
+      /* Reacquire the mutex. */
+      Mutex_Lock_Imp(mutex);
+    }
+
+    /* Turn scheduling back on. */
+    g_preemptionDisabled = false;
+
+
+    return to_state.timed_out;
+}
+
 /*
  * Wake up one thread waiting on the given condition.
  * The mutex guarding the condition should be held!