debuggers.hg

changeset 22078:fa82b0540e8c

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.

[PATCH 05 of 16 of
libxl: autogenerate type definitions and destructor functions]

Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
Signed-off-by: Ian Jackson <ian.jackson@eu.citrix.com>
author Ian Campbell <ian.campbell@citrix.com>
date Thu Aug 19 15:20:22 2010 +0100 (2010-08-19)
parents e2aa1eaa7bf5
children d2f576d5cff5
files .hgignore tools/libxl/Makefile tools/libxl/gentypes.py tools/libxl/libxl.c tools/libxl/libxl.h tools/libxl/libxl.idl tools/libxl/libxltypes.py
line diff
     1.1 --- a/.hgignore	Thu Aug 19 15:15:55 2010 +0100
     1.2 +++ b/.hgignore	Thu Aug 19 15:20:22 2010 +0100
     1.3 @@ -182,6 +182,7 @@
     1.4  ^tools/libxen/test/test_bindings$
     1.5  ^tools/libxen/test/test_event_handling$
     1.6  ^tools/libxl/_.*\.h$
     1.7 +^tools/libxl/_.*\.c$
     1.8  ^tools/libxl/libxlu_cfg_y\.output$
     1.9  ^tools/libxl/xl$
    1.10  ^tools/libaio/src/.*\.ol$
     2.1 --- a/tools/libxl/Makefile	Thu Aug 19 15:15:55 2010 +0100
     2.2 +++ b/tools/libxl/Makefile	Thu Aug 19 15:20:22 2010 +0100
     2.3 @@ -25,6 +25,7 @@ LIBXL_OBJS-y += libxl_noblktap2.o
     2.4  endif
     2.5  
     2.6  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)
     2.7 +LIBXL_OBJS += _libxl_types.o
     2.8  
     2.9  AUTOINCS= libxlu_cfg_y.h libxlu_cfg_l.h
    2.10  AUTOSRCS= libxlu_cfg_y.c libxlu_cfg_l.c
    2.11 @@ -64,9 +65,10 @@ libxl.h: _libxl_types.h
    2.12  
    2.13  $(LIBXL_OBJS:%.o=%.c) $(LIBXLU_OBJS:%.o=%.c) $(XL_OBJS:%.o=%.c): libxl.h
    2.14  
    2.15 -_libxl_types.h: libxl.idl gentypes.py libxltypes.py
    2.16 -	python gentypes.py libxl.idl  __libxl_types.h
    2.17 +_libxl_types.h _libxl_types.c: libxl.idl gentypes.py libxltypes.py
    2.18 +	python gentypes.py libxl.idl __libxl_types.h __libxl_types.c
    2.19  	mv __libxl_types.h _libxl_types.h
    2.20 +	mv __libxl_types.c _libxl_types.c
    2.21  
    2.22  libxenlight.so: libxenlight.so.$(MAJOR)
    2.23  	ln -sf $< $@
    2.24 @@ -116,6 +118,7 @@ install: all
    2.25  .PHONY: clean
    2.26  clean:
    2.27  	$(RM) -f _*.h *.o *.so* *.a $(CLIENTS) $(DEPS)
    2.28 +	$(RM) -f _*.c
    2.29  #	$(RM) -f $(AUTOSRCS) $(AUTOINCS)
    2.30  
    2.31  distclean: clean
     3.1 --- a/tools/libxl/gentypes.py	Thu Aug 19 15:15:55 2010 +0100
     3.2 +++ b/tools/libxl/gentypes.py	Thu Aug 19 15:20:22 2010 +0100
     3.3 @@ -59,16 +59,53 @@ def libxl_C_type_define(ty, indent = "")
     3.4          raise NotImplementedError("%s" % type(ty))
     3.5      return s.replace("\n", "\n%s" % indent)
     3.6  
     3.7 +def libxl_C_type_destroy(ty, v, reference, indent = "    ", parent = None):
     3.8 +    if reference:
     3.9 +        deref = v + "->"
    3.10 +    else:
    3.11 +        deref = v + "."
    3.12 +
    3.13 +    s = ""
    3.14 +    if isinstance(ty, libxltypes.KeyedUnion):
    3.15 +        if parent is None:
    3.16 +            raise Exception("KeyedUnion type must have a parent")
    3.17 +        for f in ty.fields:
    3.18 +            keyvar_expr = f.keyvar_expr % (parent + ty.keyvar_name)
    3.19 +            s += "if (" + keyvar_expr + ") {\n"
    3.20 +            s += libxl_C_type_destroy(f.type, deref + f.name, False, indent + "    ", deref)
    3.21 +            s += "}\n"
    3.22 +    elif isinstance(ty, libxltypes.Reference):
    3.23 +        s += libxl_C_type_destroy(ty.ref_type, v, True, indent, v)
    3.24 +    elif isinstance(ty, libxltypes.Struct) and (parent is None or ty.destructor_fn is None):
    3.25 +        for f in [f for f in ty.fields if not f.const]:
    3.26 +
    3.27 +            if f.name is None: # Anonynous struct
    3.28 +                s += libxl_C_type_destroy(f.type, deref, False, "", deref)
    3.29 +            else:
    3.30 +                s += libxl_C_type_destroy(f.type, deref + f.name, False, "", deref)
    3.31 +    else:
    3.32 +        if ty.passby == libxltypes.PASS_BY_REFERENCE and not reference:
    3.33 +            makeref = "&"
    3.34 +        else:
    3.35 +            makeref = ""
    3.36 +
    3.37 +        if ty.destructor_fn is not None:
    3.38 +            s += "%s(%s);\n" % (ty.destructor_fn, makeref + v)
    3.39 +            
    3.40 +    if s != "":
    3.41 +        s = indent + s
    3.42 +    return s.replace("\n", "\n%s" % indent).rstrip(indent)
    3.43 +
    3.44  if __name__ == '__main__':
    3.45 -    if len(sys.argv) < 3:
    3.46 -        print >>sys.stderr, "Usage: gentypes.py <idl> <header>"
    3.47 +    if len(sys.argv) < 4:
    3.48 +        print >>sys.stderr, "Usage: gentypes.py <idl> <header> <implementation>"
    3.49          sys.exit(1)
    3.50  
    3.51      idl = sys.argv[1]
    3.52      (_,types) = libxltypes.parse(idl)
    3.53                      
    3.54      header = sys.argv[2]
    3.55 -    print "outputting libxl types to %s" % header
    3.56 +    print "outputting libxl type definitions to %s" % header
    3.57  
    3.58      f = open(header, "w")
    3.59      
    3.60 @@ -84,8 +121,39 @@ if __name__ == '__main__':
    3.61   
    3.62  """ % " ".join(sys.argv))
    3.63          
    3.64 -    for t in types:
    3.65 -        f.write(libxl_C_type_define(t) + ";\n")
    3.66 +    for ty in types:
    3.67 +        f.write(libxl_C_type_define(ty) + ";\n")
    3.68 +        if ty.destructor_fn is not None:
    3.69 +            f.write("void %s(%s *p);\n" % (ty.destructor_fn, ty.typename))
    3.70          f.write("\n")
    3.71  
    3.72      f.write("""#endif /* __LIBXL_TYPES_H */\n""")
    3.73 +    f.close()
    3.74 +    
    3.75 +    impl = sys.argv[3]
    3.76 +    print "outputting libxl type implementations to %s" % impl
    3.77 +
    3.78 +    f = open(impl, "w")
    3.79 +    f.write("""
    3.80 +/* DO NOT EDIT.
    3.81 + *
    3.82 + * This file is autogenerated by
    3.83 + * "%s"
    3.84 + */
    3.85 +
    3.86 +#include "libxl_osdeps.h"
    3.87 +
    3.88 +#include <stdint.h>
    3.89 +#include <stdlib.h>
    3.90 +
    3.91 +#include "libxl.h"
    3.92 +
    3.93 +""" % " ".join(sys.argv))
    3.94 +
    3.95 +    for ty in [t for t in types if t.autogenerate_destructor]:
    3.96 +        f.write("void %s(%s *p)\n" % (ty.destructor_fn, ty.typename))
    3.97 +        f.write("{\n")
    3.98 +        f.write(libxl_C_type_destroy(ty, "p", True))
    3.99 +        f.write("}\n")
   3.100 +        f.write("\n")
   3.101 +    f.close()
     4.1 --- a/tools/libxl/libxl.c	Thu Aug 19 15:15:55 2010 +0100
     4.2 +++ b/tools/libxl/libxl.c	Thu Aug 19 15:20:22 2010 +0100
     4.3 @@ -73,6 +73,33 @@ int libxl_ctx_free(libxl_ctx *ctx)
     4.4      return 0;
     4.5  }
     4.6  
     4.7 +void libxl_string_list_destroy(libxl_string_list sl)
     4.8 +{
     4.9 +    int i;
    4.10 +
    4.11 +    if (!sl)
    4.12 +        return;
    4.13 +
    4.14 +    for (i = 0; sl[i] != NULL; i++)
    4.15 +        free(sl[i]);
    4.16 +    free(sl);
    4.17 +}
    4.18 +
    4.19 +void libxl_key_value_list_destroy(libxl_key_value_list kvl)
    4.20 +{
    4.21 +    int i;
    4.22 +
    4.23 +    if (!kvl)
    4.24 +        return;
    4.25 +
    4.26 +    for (i = 0; kvl[i] != NULL; i += 2) {
    4.27 +        free(kvl[i]);
    4.28 +        if (kvl[i + 1])
    4.29 +            free(kvl[i + 1]);
    4.30 +    }
    4.31 +    free(kvl);
    4.32 +}
    4.33 +
    4.34  /******************************************************************************/
    4.35  
    4.36  int libxl_domain_make(libxl_ctx *ctx, libxl_domain_create_info *info,
     5.1 --- a/tools/libxl/libxl.h	Thu Aug 19 15:15:55 2010 +0100
     5.2 +++ b/tools/libxl/libxl.h	Thu Aug 19 15:20:22 2010 +0100
     5.3 @@ -142,8 +142,10 @@ typedef uint8_t libxl_uuid[16];
     5.4  typedef uint8_t libxl_mac[6];
     5.5  
     5.6  typedef char **libxl_string_list;
     5.7 +void libxl_string_list_destroy(libxl_string_list sl);
     5.8  
     5.9  typedef char **libxl_key_value_list;
    5.10 +void libxl_key_value_list_destroy(libxl_key_value_list kvl);
    5.11  
    5.12  typedef uint64_t *libxl_cpumap;
    5.13  
     6.1 --- a/tools/libxl/libxl.idl	Thu Aug 19 15:15:55 2010 +0100
     6.2 +++ b/tools/libxl/libxl.idl	Thu Aug 19 15:20:22 2010 +0100
     6.3 @@ -12,10 +12,10 @@ libxl_console_constype = Builtin("consol
     6.4  libxl_disk_phystype = Builtin("disk_phystype")
     6.5  libxl_nic_type = Builtin("nic_type")
     6.6  
     6.7 -libxl_string_list = Builtin("string_list")
     6.8 -libxl_key_value_list = Builtin("key_value_list")
     6.9 +libxl_string_list = Builtin("string_list", destructor_fn="libxl_string_list_destroy")
    6.10 +libxl_key_value_list = Builtin("key_value_list", destructor_fn="libxl_key_value_list_destroy")
    6.11  
    6.12 -libxl_cpumap = Builtin("cpumap")
    6.13 +libxl_cpumap = Builtin("cpumap", destructor_fn="free")
    6.14  
    6.15  libxl_hwcap = Builtin("hwcap")
    6.16  
     7.1 --- a/tools/libxl/libxltypes.py	Thu Aug 19 15:15:55 2010 +0100
     7.2 +++ b/tools/libxl/libxltypes.py	Thu Aug 19 15:20:22 2010 +0100
     7.3 @@ -1,10 +1,17 @@
     7.4  import sys
     7.5  
     7.6 +PASS_BY_VALUE = 1
     7.7 +PASS_BY_REFERENCE = 2
     7.8 +
     7.9  class Type(object):
    7.10      def __init__(self, typename, **kwargs):
    7.11          self.comment = kwargs.setdefault('comment', None)
    7.12          self.namespace = kwargs.setdefault('namespace', "libxl_")
    7.13  
    7.14 +        self.passby = kwargs.setdefault('passby', PASS_BY_VALUE)
    7.15 +        if self.passby not in [PASS_BY_VALUE, PASS_BY_REFERENCE]:
    7.16 +            raise ValueError
    7.17 +
    7.18          if typename is None: # Anonymous type
    7.19              self.typename = None
    7.20          elif self.namespace is None: # e.g. system provided types
    7.21 @@ -12,14 +19,23 @@ class Type(object):
    7.22          else:
    7.23              self.typename = self.namespace + typename
    7.24  
    7.25 +        if self.typename is not None:
    7.26 +            self.destructor_fn = kwargs.setdefault('destructor_fn', self.typename + "_destroy")
    7.27 +        else:
    7.28 +            self.destructor_fn = kwargs.setdefault('destructor_fn', None)
    7.29 +
    7.30 +        self.autogenerate_destructor = kwargs.setdefault('autogenerate_destructor', True)
    7.31 +
    7.32  class Builtin(Type):
    7.33      """Builtin type"""
    7.34      def __init__(self, typename, **kwargs):
    7.35 +        kwargs.setdefault('destructor_fn', None)
    7.36          Type.__init__(self, typename, **kwargs)
    7.37  
    7.38  class UInt(Type):
    7.39      def __init__(self, w, **kwargs):
    7.40          kwargs.setdefault('namespace', None)
    7.41 +        kwargs.setdefault('destructor_fn', None)
    7.42          Type.__init__(self, "uint%d_t" % w, **kwargs)
    7.43  
    7.44          self.width = w
    7.45 @@ -27,6 +43,7 @@ class UInt(Type):
    7.46  class BitField(Type):
    7.47      def __init__(self, ty, w, **kwargs):
    7.48          kwargs.setdefault('namespace', None)
    7.49 +        kwargs.setdefault('destructor_fn', None)
    7.50          Type.__init__(self, ty.typename, **kwargs)
    7.51  
    7.52          self.width = w
    7.53 @@ -63,10 +80,16 @@ class Aggregate(Type):
    7.54  
    7.55  class Struct(Aggregate):
    7.56      def __init__(self, name, fields, **kwargs):
    7.57 +        kwargs.setdefault('passby', PASS_BY_REFERENCE)
    7.58          Aggregate.__init__(self, "struct", name, fields, **kwargs)
    7.59  
    7.60  class Union(Aggregate):
    7.61      def __init__(self, name, fields, **kwargs):
    7.62 +        # Generally speaking some intelligence is required to free a
    7.63 +        # union therefore any specific instance of this class will
    7.64 +        # need to provide an explicit destructor function.
    7.65 +        kwargs.setdefault('passby', PASS_BY_REFERENCE)
    7.66 +        kwargs.setdefault('destructor_fn', None)
    7.67          Aggregate.__init__(self, "union", name, fields, **kwargs)
    7.68  
    7.69  class KeyedUnion(Aggregate):
    7.70 @@ -87,7 +110,14 @@ class KeyedUnion(Aggregate):
    7.71  class Reference(Type):
    7.72      """A reference to another type"""
    7.73      def __init__(self, ty, **kwargs):
    7.74 +        self.ref_type = ty
    7.75 +        
    7.76          # Ugh
    7.77 +        
    7.78 +        kwargs.setdefault('destructor_fn', "free")
    7.79 +        kwargs.setdefault('autogenerate_destructor', False)
    7.80 +        kwargs.setdefault('passby', PASS_BY_VALUE)
    7.81 +        
    7.82          kwargs.setdefault('namespace', ty.namespace)
    7.83          typename = ty.typename[len(kwargs['namespace']):]
    7.84          Type.__init__(self, typename + " *", **kwargs)
    7.85 @@ -112,7 +142,7 @@ uint64 = UInt(64)
    7.86  
    7.87  domid = UInt(32)
    7.88  
    7.89 -string = Builtin("char *", namespace = None)
    7.90 +string = Builtin("char *", namespace = None, destructor_fn = "free")
    7.91  
    7.92  inaddr_ip = Builtin("struct in_addr", namespace = None)
    7.93