[MINIOS] Support xenbus watches.
authorkfraser@localhost.localdomain <kfraser@localhost.localdomain>
Fri, 12 Jan 2007 15:15:25 +0000 (15:15 +0000)
committerkfraser@localhost.localdomain <kfraser@localhost.localdomain>
Fri, 12 Jan 2007 15:15:25 +0000 (15:15 +0000)
Signed-off-by: Jacob Gorm Hansen <jacobg@diku.dk>
extras/mini-os/include/xenbus.h
extras/mini-os/xenbus/xenbus.c

index 4bf35ce8fb4e87975a1cfdcaad56f5df4fd16d37..3866a8bbce1dbf3ce101a0d0b5119f9c24a36490 100644 (file)
@@ -12,6 +12,9 @@ void init_xenbus(void);
    set to a malloc'd copy of the value. */
 char *xenbus_read(xenbus_transaction_t xbt, const char *path, char **value);
 
+char *xenbus_watch_path(xenbus_transaction_t xbt, const char *path);
+char* xenbus_wait_for_value(const char*,const char*);
+
 /* Associates a value with a path.  Returns a malloc'd error string on
    failure. */
 char *xenbus_write(xenbus_transaction_t xbt, const char *path, const char *value);
index cb62eb3ef61bbc10976fe37403f0cc20d8e979e1..09ededbab1d20dd78919c3f24fd6fffc7f413b7b 100644 (file)
@@ -45,9 +45,9 @@
 #define DEBUG(_f, _a...)    ((void)0)
 #endif
 
-
 static struct xenstore_domain_interface *xenstore_buf;
 static DECLARE_WAIT_QUEUE_HEAD(xb_waitq);
+static DECLARE_WAIT_QUEUE_HEAD(watch_queue);
 struct xenbus_req_info 
 {
     int in_use:1;
@@ -72,6 +72,34 @@ static void memcpy_from_ring(const void *Ring,
     memcpy(dest + c1, ring, c2);
 }
 
+static inline void wait_for_watch(void)
+{
+    DEFINE_WAIT(w);
+    add_waiter(w,watch_queue);
+    schedule();
+    wake(current);
+}
+
+char* xenbus_wait_for_value(const char* path,const char* value)
+{
+    for(;;)
+    {
+        char *res, *msg;
+        int r;
+
+        msg = xenbus_read(XBT_NIL, path, &res);
+        if(msg) return msg;
+
+        r = strcmp(value,res);
+        free(res);
+
+        if(r==0) break;
+        else wait_for_watch();
+    }
+    return NULL;
+}
+
+
 static void xenbus_thread_func(void *ign)
 {
     struct xsd_sockmsg msg;
@@ -101,13 +129,35 @@ static void xenbus_thread_func(void *ign)
                 break;
 
             DEBUG("Message is good.\n");
-            req_info[msg.req_id].reply = malloc(sizeof(msg) + msg.len);
-            memcpy_from_ring(xenstore_buf->rsp,
+
+            if(msg.type == XS_WATCH_EVENT)
+            {
+                char* payload = (char*)malloc(sizeof(msg) + msg.len);
+                char *path,*token;
+
+                memcpy_from_ring(xenstore_buf->rsp,
+                    payload,
+                    MASK_XENSTORE_IDX(xenstore_buf->rsp_cons),
+                    msg.len + sizeof(msg));
+
+                path = payload + sizeof(msg);
+                token = path + strlen(path) + 1;
+
+                xenstore_buf->rsp_cons += msg.len + sizeof(msg);
+                free(payload);
+                wake_up(&watch_queue);
+            }
+
+            else
+            {
+                req_info[msg.req_id].reply = malloc(sizeof(msg) + msg.len);
+                memcpy_from_ring(xenstore_buf->rsp,
                     req_info[msg.req_id].reply,
                     MASK_XENSTORE_IDX(xenstore_buf->rsp_cons),
                     msg.len + sizeof(msg));
-            wake_up(&req_info[msg.req_id].waitq);
-            xenstore_buf->rsp_cons += msg.len + sizeof(msg);
+                xenstore_buf->rsp_cons += msg.len + sizeof(msg);
+                wake_up(&req_info[msg.req_id].waitq);
+            }
         }
     }
 }
@@ -381,12 +431,32 @@ char *xenbus_write(xenbus_transaction_t xbt, const char *path, const char *value
     struct xsd_sockmsg *rep;
     rep = xenbus_msg_reply(XS_WRITE, xbt, req, ARRAY_SIZE(req));
     char *msg = errmsg(rep);
-    if (msg)
-       return msg;
+    if (msg) return msg;
     free(rep);
     return NULL;
 }
 
+char* xenbus_watch_path( xenbus_transaction_t xbt, const char *path)
+{
+       /* in the future one could have multiple watch queues, and use
+        * the token for demuxing. For now the token is 0. */
+
+    struct xsd_sockmsg *rep;
+
+    struct write_req req[] = { 
+        {path, strlen(path) + 1},
+        {"0",2 },
+    };
+
+    rep = xenbus_msg_reply(XS_WATCH, xbt, req, ARRAY_SIZE(req));
+
+    char *msg = errmsg(rep);
+    if (msg) return msg;
+    free(rep);
+
+    return NULL;
+}
+
 char *xenbus_rm(xenbus_transaction_t xbt, const char *path)
 {
     struct write_req req[] = { {path, strlen(path) + 1} };