[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [PATCH 3/3] libxl: ocaml: use 'for_app_registration' in osevent callbacks



This allows the application to pass a token to libxl in the fd/timeout
registration callbacks, which it receives back in modification or
deregistration callbacks.

It turns out that this is essential for timeout handling, in order to
identify which timeout to change on a modify event.

Signed-off-by: Rob Hoes <rob.hoes@xxxxxxxxxx>
---
 tools/ocaml/libs/xl/xenlight.mli.in  |   10 ++--
 tools/ocaml/libs/xl/xenlight_stubs.c |   97 ++++++++++++++++++++++++++--------
 2 files changed, 81 insertions(+), 26 deletions(-)

diff --git a/tools/ocaml/libs/xl/xenlight.mli.in 
b/tools/ocaml/libs/xl/xenlight.mli.in
index b9819e1..277e81d 100644
--- a/tools/ocaml/libs/xl/xenlight.mli.in
+++ b/tools/ocaml/libs/xl/xenlight.mli.in
@@ -68,11 +68,11 @@ module Async : sig
 
        val osevent_register_hooks : ctx ->
                user:'a ->
-               fd_register:('a -> Unix.file_descr -> event list -> for_libxl 
-> unit) ->
-               fd_modify:('a -> Unix.file_descr -> event list -> unit) ->
-               fd_deregister:('a -> Unix.file_descr -> unit) ->
-               timeout_register:('a -> int64 -> int64 -> for_libxl -> unit) ->
-               timeout_modify:('a -> unit) ->
+               fd_register:('a -> Unix.file_descr -> event list -> for_libxl 
-> 'b) ->
+               fd_modify:('a -> Unix.file_descr -> 'b -> event list -> 'b) ->
+               fd_deregister:('a -> Unix.file_descr -> 'b -> unit) ->
+               timeout_register:('a -> int64 -> int64 -> for_libxl -> 'c) ->
+               timeout_modify:('a -> 'c -> 'c) ->
                osevent_hooks
 
        external osevent_occurred_fd : ctx -> for_libxl -> Unix.file_descr -> 
event list -> event list -> unit = "stub_libxl_osevent_occurred_fd"
diff --git a/tools/ocaml/libs/xl/xenlight_stubs.c 
b/tools/ocaml/libs/xl/xenlight_stubs.c
index 2e2606a..3c72eeb 100644
--- a/tools/ocaml/libs/xl/xenlight_stubs.c
+++ b/tools/ocaml/libs/xl/xenlight_stubs.c
@@ -1211,14 +1211,20 @@ value Val_poll_events(short events)
        CAMLreturn(event_list);
 }
 
+/* The process for dealing with the for_app_registration_  values in the
+ * callbacks below (GC registrations etc) is similar to the way for_callback is
+ * handled in the asynchronous operations above. */
+
 int fd_register(void *user, int fd, void **for_app_registration_out,
                      short events, void *for_libxl)
 {
        caml_leave_blocking_section();
        CAMLparam0();
        CAMLlocalN(args, 4);
+       int ret = 0;
        static value *func = NULL;
        value *p = (value *) user;
+       value *for_app;
 
        if (func == NULL) {
                /* First time around, lookup by name */
@@ -1230,10 +1236,18 @@ int fd_register(void *user, int fd, void 
**for_app_registration_out,
        args[2] = Val_poll_events(events);
        args[3] = (value) for_libxl;
 
-       caml_callbackN(*func, 4, args);
+       for_app = malloc(sizeof(value));
+       if (for_app) {
+               *for_app = caml_callbackN(*func, 4, args);
+               caml_register_global_root(for_app);
+               *for_app_registration_out = for_app;
+       }
+       else
+               ret = ERROR_OSEVENT_REG_FAIL;
+
        CAMLdone;
        caml_enter_blocking_section();
-       return 0;
+       return ret;
 }
 
 int fd_modify(void *user, int fd, void **for_app_registration_update,
@@ -1241,32 +1255,43 @@ int fd_modify(void *user, int fd, void 
**for_app_registration_update,
 {
        caml_leave_blocking_section();
        CAMLparam0();
-       CAMLlocalN(args, 3);
+       CAMLlocalN(args, 4);
+       int ret = 0;
        static value *func = NULL;
        value *p = (value *) user;
+       value *for_app = *for_app_registration_update;
 
-       if (func == NULL) {
-               /* First time around, lookup by name */
-               func = caml_named_value("libxl_fd_modify");
-       }
+       /* if for_app == NULL, assume that something is wrong and don't 
callback */
+       if (for_app) {
+               if (func == NULL) {
+                       /* First time around, lookup by name */
+                       func = caml_named_value("libxl_fd_modify");
+               }
 
-       args[0] = *p;
-       args[1] = Val_int(fd);
-       args[2] = Val_poll_events(events);
+               args[0] = *p;
+               args[1] = Val_int(fd);
+               args[2] = *for_app;
+               args[3] = Val_poll_events(events);
+
+               *for_app = caml_callbackN(*func, 4, args);
+               *for_app_registration_update = for_app;
+       }
+       else
+               ret = ERROR_OSEVENT_REG_FAIL;
 
-       caml_callbackN(*func, 3, args);
        CAMLdone;
        caml_enter_blocking_section();
-       return 0;
+       return ret;
 }
 
 void fd_deregister(void *user, int fd, void *for_app_registration)
 {
        caml_leave_blocking_section();
        CAMLparam0();
-       CAMLlocalN(args, 2);
+       CAMLlocalN(args, 3);
        static value *func = NULL;
        value *p = (value *) user;
+       value *for_app = for_app_registration;
 
        if (func == NULL) {
                /* First time around, lookup by name */
@@ -1275,8 +1300,12 @@ void fd_deregister(void *user, int fd, void 
*for_app_registration)
 
        args[0] = *p;
        args[1] = Val_int(fd);
+       args[2] = *for_app;
 
-       caml_callbackN(*func, 2, args);
+       caml_remove_global_root(for_app);
+       free(for_app);
+
+       caml_callbackN(*func, 3, args);
        CAMLdone;
        caml_enter_blocking_section();
 }
@@ -1288,8 +1317,10 @@ int timeout_register(void *user, void 
**for_app_registration_out,
        CAMLparam0();
        CAMLlocal2(sec, usec);
        CAMLlocalN(args, 4);
+       int ret = 0;
        static value *func = NULL;
        value *p = (value *) user;
+       value *for_app;
 
        if (func == NULL) {
                /* First time around, lookup by name */
@@ -1304,10 +1335,18 @@ int timeout_register(void *user, void 
**for_app_registration_out,
        args[2] = usec;
        args[3] = (value) for_libxl;
 
-       caml_callbackN(*func, 4, args);
+       for_app = malloc(sizeof(value));
+       if (for_app) {
+               *for_app = caml_callbackN(*func, 4, args);
+               caml_register_global_root(for_app);
+               *for_app_registration_out = for_app;
+       }
+       else
+               ret = ERROR_OSEVENT_REG_FAIL;
+
        CAMLdone;
        caml_enter_blocking_section();
-       return 0;
+       return ret;
 }
 
 int timeout_modify(void *user, void **for_app_registration_update,
@@ -1315,18 +1354,34 @@ int timeout_modify(void *user, void 
**for_app_registration_update,
 {
        caml_leave_blocking_section();
        CAMLparam0();
+       CAMLlocalN(args, 2);
+       int ret = 0;
        static value *func = NULL;
        value *p = (value *) user;
+       value *for_app = *for_app_registration_update;
 
-       if (func == NULL) {
-               /* First time around, lookup by name */
-               func = caml_named_value("libxl_timeout_modify");
+       /* if for_app == NULL, assume that something is wrong and don't 
callback */
+       if (for_app) {
+               if (func == NULL) {
+                       /* First time around, lookup by name */
+                       func = caml_named_value("libxl_timeout_modify");
+               }
+
+               args[0] = *p;
+               args[1] = *for_app;
+
+               caml_callbackN(*func, 2, args);
+
+               caml_remove_global_root(for_app);
+               free(for_app);
+               *for_app_registration_update = NULL;
        }
+       else
+               ret = ERROR_OSEVENT_REG_FAIL;
 
-       caml_callback(*func, *p);
        CAMLdone;
        caml_enter_blocking_section();
-       return 0;
+       return ret;
 }
 
 void timeout_deregister(void *user, void *for_app_registration)
-- 
1.7.10.4


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.