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>
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