WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-devel

[Xen-devel] [PATCH 8 of 9] libxl: generate destructors for each libxl de

To: xen-devel@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-devel] [PATCH 8 of 9] libxl: generate destructors for each libxl defined type
From: Ian Campbell <ian.campbell@xxxxxxxxxx>
Date: Fri, 13 Aug 2010 14:50:11 +0100
Cc: Ian Campbell <ian.campbell@xxxxxxxxxx>
Delivery-date: Fri, 13 Aug 2010 07:05:24 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
In-reply-to: <patchbomb.1281707403@xxxxxxxxxxxxxxxxxxxxx>
List-help: <mailto:xen-devel-request@lists.xensource.com?subject=help>
List-id: Xen developer discussion <xen-devel.lists.xensource.com>
List-post: <mailto:xen-devel@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=unsubscribe>
Sender: xen-devel-bounces@xxxxxxxxxxxxxxxxxxx
# HG changeset patch
# User Ian Campbell <ian.campbell@xxxxxxxxxx>
# Date 1281707272 -3600
# Node ID 9b62c9e42f2472aaf4a3d9ce492c5c14cdfa8249
# Parent  eb6b31dba5994e748d1aaf3f3eb60ba46e3ae7c3
libxl: generate destructors for each libxl defined type

I chose the name "_destroy" rather than "_free" because the destructor
functions will free only the members of a type recursively but will
not free the actual type structure itself. The allocation of the type
is typically done by the caller and may not be a single allocation,
e.g. lists/arrays of types or embedded in other strucutures etc.

The exceptions to this rule are libxl_string_list_destroy and
libxl_key_value_list_destroy but I'm not 100% convinced they are
exceptions (since they are kind-of opaque) and I couldn't see a
cleanerway to express this concept. I have made a best effort attempt
to implement these functions sanely but since as far as I can tell
nothing in the current code base ever sets
libxl_domain_create_info.{xsdata,platformdata} I'm flying somewhat
blind.

Signed-off-by: Ian Campbell <ian.campbell@xxxxxxxxxx>

diff -r eb6b31dba599 -r 9b62c9e42f24 .hgignore
--- a/.hgignore Fri Aug 13 14:46:36 2010 +0100
+++ b/.hgignore Fri Aug 13 14:47:52 2010 +0100
@@ -182,6 +182,7 @@
 ^tools/libxen/test/test_bindings$
 ^tools/libxen/test/test_event_handling$
 ^tools/libxl/_.*\.h$
+^tools/libxl/_.*\.c$
 ^tools/libxl/libxlu_cfg_y\.output$
 ^tools/libxl/xl$
 ^tools/libaio/src/.*\.ol$
diff -r eb6b31dba599 -r 9b62c9e42f24 tools/libxl/Makefile
--- a/tools/libxl/Makefile      Fri Aug 13 14:46:36 2010 +0100
+++ b/tools/libxl/Makefile      Fri Aug 13 14:47:52 2010 +0100
@@ -19,6 +19,7 @@ LIBS = $(LDLIBS_libxenctrl) $(LDLIBS_lib
 
 LIBXL_OBJS-y = osdeps.o libxl_paths.o libxl_bootloader.o
 LIBXL_OBJS = flexarray.o libxl.o libxl_pci.o libxl_dom.o libxl_exec.o 
libxl_xshelp.o libxl_device.o libxl_internal.o xenguest.o libxl_utils.o 
$(LIBXL_OBJS-y)
+LIBXL_OBJS += _libxl_types.o
 
 AUTOINCS= libxlu_cfg_y.h libxlu_cfg_l.h
 AUTOSRCS= libxlu_cfg_y.c libxlu_cfg_l.c
@@ -58,9 +59,10 @@ libxl.h: _libxl_types.h
 
 $(LIBXL_OBJS:%.o=%.c) $(LIBXLU_OBJS:%.o=%.c) $(XL_OBJS:%.o=%.c): libxl.h
 
-_libxl_types.h: libxltypes.idl gentypes.py libxltypes.py
-       python gentypes.py libxltypes.idl  __libxl_types.h
+_libxl_types.h _libxl_types.c: gentypes.py libxltypes.py
+       python gentypes.py libxltypes.idl __libxl_types.h __libxl_types.c
        mv __libxl_types.h _libxl_types.h
+       mv __libxl_types.c _libxl_types.c
 
 libxenlight.so: libxenlight.so.$(MAJOR)
        ln -sf $< $@
@@ -110,6 +112,7 @@ install: all
 .PHONY: clean
 clean:
        $(RM) -f _*.h *.o *.so* *.a $(CLIENTS) $(DEPS)
+       $(RM) -f _*.c
 #      $(RM) -f $(AUTOSRCS) $(AUTOINCS)
 
 distclean: clean
diff -r eb6b31dba599 -r 9b62c9e42f24 tools/libxl/gentypes.py
--- a/tools/libxl/gentypes.py   Fri Aug 13 14:46:36 2010 +0100
+++ b/tools/libxl/gentypes.py   Fri Aug 13 14:47:52 2010 +0100
@@ -59,16 +59,53 @@ def libxl_C_type_define(ty, indent = "")
         raise NotImplementedError("%s" % type(ty))
     return s.replace("\n", "\n%s" % indent)
 
+def libxl_C_type_destroy(ty, v, reference, indent = "    ", parent = None):
+    if reference:
+        deref = v + "->"
+    else:
+        deref = v + "."
+
+    s = ""
+    if isinstance(ty, libxltypes.KeyedUnion):
+        if parent is None:
+            raise Exception("KeyedUnion type must have a parent")
+        for f in ty.fields:
+            keyvar_expr = f.keyvar_expr % (parent + ty.keyvar_name)
+            s += "if (" + keyvar_expr + ") {\n"
+            s += libxl_C_type_destroy(f.type, deref + f.name, False, indent + 
"    ", deref)
+            s += "}\n"
+    elif isinstance(ty, libxltypes.Reference):
+        s += libxl_C_type_destroy(ty.ref_type, v, True, indent, v)
+    elif isinstance(ty, libxltypes.Struct) and (parent is None or 
ty.destructor_fn is None):
+        for f in [f for f in ty.fields if not f.const]:
+
+            if f.name is None: # Anonynous struct
+                s += libxl_C_type_destroy(f.type, deref, False, "", deref)
+            else:
+                s += libxl_C_type_destroy(f.type, deref + f.name, False, "", 
deref)
+    else:
+        if ty.passby == libxltypes.PASS_BY_REFERENCE and not reference:
+            makeref = "&"
+        else:
+            makeref = ""
+
+        if ty.destructor_fn is not None:
+            s += "%s(%s);\n" % (ty.destructor_fn, makeref + v)
+            
+    if s != "":
+        s = indent + s
+    return s.replace("\n", "\n%s" % indent).rstrip(indent)
+
 if __name__ == '__main__':
-    if len(sys.argv) < 3:
-        print >>sys.stderr, "Usage: gentypes.py <idl> <header>"
+    if len(sys.argv) < 4:
+        print >>sys.stderr, "Usage: gentypes.py <idl> <header> 
<implementation>"
         sys.exit(1)
 
     idl = sys.argv[1]
     (_,types) = libxltypes.parse(idl)
                     
     header = sys.argv[2]
-    print "outputting libxl types to %s" % header
+    print "outputting libxl type definitions to %s" % header
 
     f = open(header, "w")
     
@@ -84,8 +121,39 @@ if __name__ == '__main__':
  
 """ % " ".join(sys.argv))
         
-    for t in types:
-        f.write(libxl_C_type_define(t) + ";\n")
+    for ty in types:
+        f.write(libxl_C_type_define(ty) + ";\n")
+        if ty.destructor_fn is not None:
+            f.write("void %s(%s *p);\n" % (ty.destructor_fn, ty.typename))
         f.write("\n")
 
     f.write("""#endif /* __LIBXL_TYPES_H */\n""")
+    f.close()
+    
+    impl = sys.argv[3]
+    print "outputting libxl type implementations to %s" % impl
+
+    f = open(impl, "w")
+    f.write("""
+/* DO NOT EDIT.
+ *
+ * This file is autogenerated by
+ * "%s"
+ */
+
+#include "libxl_osdeps.h"
+
+#include <stdint.h>
+#include <stdlib.h>
+ 
+#include "libxl.h"
+
+""" % " ".join(sys.argv))
+
+    for ty in [t for t in types if t.autogenerate_destructor]:
+        f.write("void %s(%s *p)\n" % (ty.destructor_fn, ty.typename))
+        f.write("{\n")
+        f.write(libxl_C_type_destroy(ty, "p", True))
+        f.write("}\n")
+        f.write("\n")
+    f.close()
diff -r eb6b31dba599 -r 9b62c9e42f24 tools/libxl/libxl.c
--- a/tools/libxl/libxl.c       Fri Aug 13 14:46:36 2010 +0100
+++ b/tools/libxl/libxl.c       Fri Aug 13 14:47:52 2010 +0100
@@ -72,6 +72,33 @@ int libxl_ctx_free(libxl_ctx *ctx)
     do_free_version_info(&ctx->version_info);
     if (ctx->xsh) xs_daemon_close(ctx->xsh); 
     return 0;
+}
+
+void libxl_string_list_destroy(libxl_string_list sl)
+{
+    int i;
+
+    if (!sl)
+        return;
+
+    for (i = 0; sl[i] != NULL; i++)
+        free(sl[i]);
+    free(sl);
+}
+
+void libxl_key_value_list_destroy(libxl_key_value_list kvl)
+{
+    int i;
+
+    if (!kvl)
+        return;
+
+    for (i = 0; kvl[i] != NULL; i += 2) {
+        free(kvl[i]);
+        if (kvl[i + 1])
+            free(kvl[i + 1]);
+    }
+    free(kvl);
 }
 
 
/******************************************************************************/
diff -r eb6b31dba599 -r 9b62c9e42f24 tools/libxl/libxl.h
--- a/tools/libxl/libxl.h       Fri Aug 13 14:46:36 2010 +0100
+++ b/tools/libxl/libxl.h       Fri Aug 13 14:47:52 2010 +0100
@@ -27,8 +27,10 @@ typedef uint8_t libxl_mac[6];
 typedef uint8_t libxl_mac[6];
 
 typedef char **libxl_string_list;
+void libxl_string_list_destroy(libxl_string_list sl);
 
 typedef char **libxl_key_value_list;
+void libxl_key_value_list_destroy(libxl_key_value_list kvl);
 
 typedef enum {
     XENFV = 1,
diff -r eb6b31dba599 -r 9b62c9e42f24 tools/libxl/libxltypes.idl
--- a/tools/libxl/libxltypes.idl        Fri Aug 13 14:46:36 2010 +0100
+++ b/tools/libxl/libxltypes.idl        Fri Aug 13 14:47:52 2010 +0100
@@ -11,8 +11,8 @@ libxl_disk_phystype = Builtin("disk_phys
 libxl_disk_phystype = Builtin("disk_phystype")
 libxl_nic_type = Builtin("nic_type")
 
-libxl_string_list = Builtin("string_list")
-libxl_key_value_list = Builtin("key_value_list")
+libxl_string_list = Builtin("string_list", 
destructor_fn="libxl_string_list_destroy")
+libxl_key_value_list = Builtin("key_value_list", 
destructor_fn="libxl_key_value_list_destroy")
 
 #
 # Complex libxl types
diff -r eb6b31dba599 -r 9b62c9e42f24 tools/libxl/libxltypes.py
--- a/tools/libxl/libxltypes.py Fri Aug 13 14:46:36 2010 +0100
+++ b/tools/libxl/libxltypes.py Fri Aug 13 14:47:52 2010 +0100
@@ -1,9 +1,16 @@ import sys
 import sys
+
+PASS_BY_VALUE = 1
+PASS_BY_REFERENCE = 2
 
 class Type(object):
     def __init__(self, typename, **kwargs):
         self.comment = kwargs.setdefault('comment', None)
         self.namespace = kwargs.setdefault('namespace', "libxl_")
+
+        self.passby = kwargs.setdefault('passby', PASS_BY_VALUE)
+        if self.passby not in [PASS_BY_VALUE, PASS_BY_REFERENCE]:
+            raise ValueError
 
         if typename is None: # Anonymous type
             self.typename = None
@@ -12,14 +19,23 @@ class Type(object):
         else:
             self.typename = self.namespace + typename
 
+        if self.typename is not None:
+            self.destructor_fn = kwargs.setdefault('destructor_fn', 
self.typename + "_destroy")
+        else:
+            self.destructor_fn = kwargs.setdefault('destructor_fn', None)
+
+        self.autogenerate_destructor = 
kwargs.setdefault('autogenerate_destructor', True)
+
 class Builtin(Type):
     """Builtin type"""
     def __init__(self, typename, **kwargs):
+        kwargs.setdefault('destructor_fn', None)
         Type.__init__(self, typename, **kwargs)
 
 class UInt(Type):
     def __init__(self, w, **kwargs):
         kwargs.setdefault('namespace', None)
+        kwargs.setdefault('destructor_fn', None)
         Type.__init__(self, "uint%d_t" % w, **kwargs)
 
         self.width = w
@@ -27,6 +43,7 @@ class BitField(Type):
 class BitField(Type):
     def __init__(self, ty, w, **kwargs):
         kwargs.setdefault('namespace', None)
+        kwargs.setdefault('destructor_fn', None)
         Type.__init__(self, ty.typename, **kwargs)
 
         self.width = w
@@ -63,10 +80,16 @@ class Aggregate(Type):
 
 class Struct(Aggregate):
     def __init__(self, name, fields, **kwargs):
+        kwargs.setdefault('passby', PASS_BY_REFERENCE)
         Aggregate.__init__(self, "struct", name, fields, **kwargs)
 
 class Union(Aggregate):
     def __init__(self, name, fields, **kwargs):
+        # Generally speaking some intelligence is required to free a
+        # union therefore any specific instance of this class will
+        # need to provide an explicit destructor function.
+        kwargs.setdefault('passby', PASS_BY_REFERENCE)
+        kwargs.setdefault('destructor_fn', None)
         Aggregate.__init__(self, "union", name, fields, **kwargs)
 
 class KeyedUnion(Aggregate):
@@ -87,7 +110,14 @@ class Reference(Type):
 class Reference(Type):
     """A reference to another type"""
     def __init__(self, ty, **kwargs):
+        self.ref_type = ty
+        
         # Ugh
+        
+        kwargs.setdefault('destructor_fn', "free")
+        kwargs.setdefault('autogenerate_destructor', False)
+        kwargs.setdefault('passby', PASS_BY_VALUE)
+        
         kwargs.setdefault('namespace', ty.namespace)
         typename = ty.typename[len(kwargs['namespace']):]
         Type.__init__(self, typename + " *", **kwargs)
@@ -112,7 +142,7 @@ uint64 = UInt(64)
 
 domid = UInt(32)
 
-string = Builtin("char *", namespace = None)
+string = Builtin("char *", namespace = None, destructor_fn = "free")
 
 inaddr_ip = Builtin("struct in_addr", namespace = None)
 

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel