diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c index cd613f7..94bdbba 100644 --- a/tools/libxl/libxl.c +++ b/tools/libxl/libxl.c @@ -63,6 +63,12 @@ int libxl_ctx_alloc(libxl_ctx **pctx, int version, * only as an initialiser, not as an expression. */ memcpy(&ctx->lock, &mutex_value, sizeof(ctx->lock)); + if(pthread_key_create(&ctx->tls_key, NULL) < 0) { + LIBXL__LOG_ERRNOVAL(ctx, LIBXL__LOG_ERROR, errno, + "cannot create tls key"); + return ERROR_FAIL; + } + if ( stat(XENSTORE_PID_FILE, &stat_buf) != 0 ) { LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "Is xenstore daemon running?\n" "failed to stat %s", XENSTORE_PID_FILE); diff --git a/tools/libxl/libxl_internal.c b/tools/libxl/libxl_internal.c index 34edaf3..815021d 100644 --- a/tools/libxl/libxl_internal.c +++ b/tools/libxl/libxl_internal.c @@ -19,6 +19,7 @@ #include #include +#include #include #include #include @@ -70,12 +71,17 @@ void libxl__free_all(libxl__gc *gc) void *ptr; int i; + gc->nested--; + if (gc->nested > 0) + return; + for (i = 0; i < gc->alloc_maxsize; i++) { ptr = gc->alloc_ptrs[i]; gc->alloc_ptrs[i] = NULL; free(ptr); } free(gc->alloc_ptrs); + pthread_setspecific(CTX->tls_key, NULL); } void *libxl__zalloc(libxl__gc *gc, int bytes) diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h index b479c49..6daa511 100644 --- a/tools/libxl/libxl_internal.h +++ b/tools/libxl/libxl_internal.h @@ -91,6 +91,8 @@ struct libxl__ctx { xc_interface *xch; struct xs_handle *xsh; + pthread_key_t tls_key; + pthread_mutex_t lock; /* protects data structures hanging off the ctx */ /* Always use CTX_LOCK and CTX_UNLOCK to manipulate this. * @@ -138,9 +140,9 @@ typedef struct { int alloc_maxsize; void **alloc_ptrs; libxl_ctx *owner; + int nested; } libxl__gc; -#define LIBXL_INIT_GC(ctx) (libxl__gc){ .alloc_maxsize = 0, .alloc_ptrs = 0, .owner = ctx } static inline libxl_ctx *libxl__gc_owner(libxl__gc *gc) { return gc->owner; @@ -670,7 +672,18 @@ libxl__device_model_version_running(libxl__gc *gc, uint32_t domid); * as a local variable. */ -#define GC_INIT(ctx) libxl__gc gc[1] = { LIBXL_INIT_GC(ctx) } +#define GC_INIT(ctx) \ + libxl__gc *gc = (libxl__gc *) pthread_getspecific(ctx->tls_key); \ + if (gc == NULL) { \ + gc = (libxl__gc *) alloca(sizeof(libxl__gc)); \ + gc->alloc_maxsize = 0; \ + gc->alloc_ptrs = 0; \ + gc->owner = ctx; \ + gc->nested = 1; \ + pthread_setspecific(ctx->tls_key, gc); \ + } else { \ + gc->nested++; \ + } #define GC_FREE libxl__free_all(gc) #define CTX libxl__gc_owner(gc)