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 12 of 26] libxl: generate destructors for each libxl

To: xen-devel@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-devel] [PATCH 12 of 26] libxl: generate destructors for each libxl defined type
From: Ian Campbell <ian.campbell@xxxxxxxxxx>
Date: Mon, 16 Aug 2010 15:33:36 +0100
Cc: Ian Campbell <ian.campbell@xxxxxxxxxx>
Delivery-date: Mon, 16 Aug 2010 07:48:27 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
In-reply-to: <patchbomb.1281969204@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 1281969065 -3600
# Node ID 5567b7c1b303d6f54d76a0efe63353701a12dad3
# Parent  d8761fd067bebad80872da3bb7b5c3d373ba63eb
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 structures 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 d8761fd067be -r 5567b7c1b303 .hgignore
--- a/.hgignore Mon Aug 16 15:31:05 2010 +0100
+++ b/.hgignore Mon Aug 16 15:31:05 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 d8761fd067be -r 5567b7c1b303 tools/libxl/Makefile
--- a/tools/libxl/Makefile      Mon Aug 16 15:31:05 2010 +0100
+++ b/tools/libxl/Makefile      Mon Aug 16 15:31:05 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: libxltypes.idl 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 d8761fd067be -r 5567b7c1b303 tools/libxl/gentypes.py
--- a/tools/libxl/gentypes.py   Mon Aug 16 15:31:05 2010 +0100
+++ b/tools/libxl/gentypes.py   Mon Aug 16 15:31:05 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 d8761fd067be -r 5567b7c1b303 tools/libxl/libxl.c
--- a/tools/libxl/libxl.c       Mon Aug 16 15:31:05 2010 +0100
+++ b/tools/libxl/libxl.c       Mon Aug 16 15:31:05 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 d8761fd067be -r 5567b7c1b303 tools/libxl/libxl.h
--- a/tools/libxl/libxl.h       Mon Aug 16 15:31:05 2010 +0100
+++ b/tools/libxl/libxl.h       Mon Aug 16 15:31:05 2010 +0100
@@ -142,8 +142,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 uint64_t *libxl_cpumap;
 
diff -r d8761fd067be -r 5567b7c1b303 tools/libxl/libxltypes.idl
--- a/tools/libxl/libxltypes.idl        Mon Aug 16 15:31:05 2010 +0100
+++ b/tools/libxl/libxltypes.idl        Mon Aug 16 15:31:05 2010 +0100
@@ -12,10 +12,10 @@ 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")
 
-libxl_cpumap = Builtin("cpumap")
+libxl_cpumap = Builtin("cpumap", destructor_fn="free")
 
 libxl_hwcap = Builtin("hwcap")
 
diff -r d8761fd067be -r 5567b7c1b303 tools/libxl/libxltypes.py
--- a/tools/libxl/libxltypes.py Mon Aug 16 15:31:05 2010 +0100
+++ b/tools/libxl/libxltypes.py Mon Aug 16 15:31:05 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

<Prev in Thread] Current Thread [Next in Thread>