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.


Merge branch 'lwip_dev' of ssh://palacios@newskysaw.cs.northwestern.edu/home/palacios...
Lei Xia [Mon, 29 Sep 2008 16:18:21 +0000 (11:18 -0500)]
palacios/include/geekos/kthread.h
palacios/include/geekos/synch.h
palacios/include/geekos/timer.h
palacios/src/geekos/kthread.c
palacios/src/geekos/socket.c
palacios/src/geekos/synch.c
palacios/src/geekos/timer.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 f5d7ebb..c452e31 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 }
@@ -36,6 +36,7 @@ void Mutex_Destroy(struct Mutex *mutex);   //added by Lei, do some cleaning work
 
 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);
 void Cond_Destroy(struct Condition *cond); //added by Lei
index 6b123aa..b9f4eb4 100644 (file)
@@ -16,7 +16,7 @@
 
 extern volatile ulong_t g_numTicks;
 
-typedef void (*timerCallback)(int);
+typedef void (*timerCallback)(int, void*);
 
 void Init_Timer(void);
 
@@ -24,15 +24,17 @@ void Micro_Delay(int us);
 
 
 typedef struct {
-    int ticks;                           /* timer code decrements this */
-    int id;                              /* unqiue id for this timer even */
-    timerCallback callBack;              /* Queue to wakeup on timer expire */
-    int origTicks;
+  int ticks;                           /* timer code decrements this */
+  int id;                              /* unqiue id for this timer even */
+  timerCallback callBack;              /* Queue to wakeup on timer expire */
+  void * cb_arg;                       /* Argument to add to callback */
+  int origTicks;
+
 } timerEvent;
 
-int Start_Timer_Secs(int seconds, timerCallback cb);
-int Start_Timer_MSecs(int msecs, timerCallback cb);
-int Start_Timer(int ticks, timerCallback);
+int Start_Timer_Secs(int seconds, timerCallback cb, void * arg);
+int Start_Timer_MSecs(int msecs, timerCallback cb, void * arg);
+int Start_Timer(int ticks, timerCallback, void * arg);
 
 double Get_Remaining_Timer_Secs(int id);
 int Get_Remaining_Timer_MSecs(int id);
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 63b3ce1..661970e 100644 (file)
@@ -28,7 +28,7 @@ void socket_appcall(void);
 
 
 static int Packet_Received(struct NE2K_Packet_Info* info, uchar_t *pkt);
-static void periodic_caller(int timer_id);
+static void periodic_caller(int timer_id, void * arg);
 
 void init_socket_layer() {
    int i = 0;
@@ -52,7 +52,7 @@ void init_socket_layer() {
     Init_Ne2k(&Packet_Received);
 
     iflag = Begin_Int_Atomic();
-    Start_Timer(2, periodic_caller);
+    Start_Timer(2, periodic_caller, NULL);
     End_Int_Atomic(iflag);
 
 }
@@ -108,7 +108,7 @@ struct socket * get_socket_from_fd(int fd) {
 
 
 
-static void periodic_caller(int timer_id) {
+static void periodic_caller(int timer_id, void * arg) {
   int i;
   //handle the periodic calls of uIP
   
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!
index fb5c9d2..9a54ff2 100644 (file)
@@ -192,7 +192,7 @@ static void Timer_Interrupt_Handler(struct Interrupt_State* state)
     if (pendingTimerEvents[i].ticks == 0) {
       if (timerDebug) Print("timer: event %d expired (%d ticks)\n", 
                            pendingTimerEvents[i].id, pendingTimerEvents[i].origTicks);
-      (pendingTimerEvents[i].callBack)(pendingTimerEvents[i].id);
+      (pendingTimerEvents[i].callBack)(pendingTimerEvents[i].id, pendingTimerEvents[i].cb_arg);
       pendingTimerEvents[i].ticks = pendingTimerEvents[i].origTicks;
     } else {
       pendingTimerEvents[i].ticks--;
@@ -338,20 +338,20 @@ void Init_Timer(void)
 }
 
 
-int Start_Timer_Secs(int seconds, timerCallback cb) {
-  return Start_Timer(seconds * HZ, cb);
+int Start_Timer_Secs(int seconds, timerCallback cb, void * arg) {
+  return Start_Timer(seconds * HZ, cb, arg);
 }
 
 
-int Start_Timer_MSecs(int msecs, timerCallback cb) {
+int Start_Timer_MSecs(int msecs, timerCallback cb, void * arg) {
   msecs += 10 - (msecs % 10);
 
-  return Start_Timer(msecs * (HZ / 1000), cb);
+  return Start_Timer(msecs * (HZ / 1000), cb, arg);
 }
 
 
 
-int Start_Timer(int ticks, timerCallback cb)
+int Start_Timer(int ticks, timerCallback cb, void * arg)
 {
     int ret;
 
@@ -363,6 +363,7 @@ int Start_Timer(int ticks, timerCallback cb)
        ret = nextEventID++;
        pendingTimerEvents[timeEventCount].id = ret;
        pendingTimerEvents[timeEventCount].callBack = cb;
+       pendingTimerEvents[timeEventCount].cb_arg = arg;
        pendingTimerEvents[timeEventCount].ticks = ticks;
        pendingTimerEvents[timeEventCount].origTicks = ticks;
        timeEventCount++;