diff mbox

Implement GOMP_OFFLOAD_unload_image in intelmic plugin

Message ID 20150908194117.GB17925@msticlxl57.ims.intel.com
State New
Headers show

Commit Message

Ilya Verbin Sept. 8, 2015, 7:41 p.m. UTC
Hi!

This patch supports unloading of target images from the device.
Unfortunately __offload_unregister_image requires the whole descriptor for
unloading, which must contain target code inside, for this reason the plugin
keeps descriptors for all offloaded images in memory.
Also the patch removes useless variable names, intended for debug purposes.
Regtested with make check-target-libgomp and using a dlopen/dlclose test.
OK for trunk?


liboffloadmic/
	* plugin/libgomp-plugin-intelmic.cpp (struct TargetImageDesc): New.
	(ImgDescMap): New typedef.
	(image_descriptors): New static var.
	(init): Allocate image_descriptors.
	(offload): Remove vars2 argument.  Pass NULL to __offload_offload1
	instead of vars2.
	(unregister_main_image): New static function.
	(register_main_image): Call unregister_main_image at exit.
	(GOMP_OFFLOAD_init_device): Print device number, fix offload args.
	(GOMP_OFFLOAD_fini_device): Likewise.
	(get_target_table): Remove vd1g and vd2g, don't pass them to offload.
	(offload_image): Remove declaration of the struct TargetImage.
	Free table.  Insert new descriptor into image_descriptors.
	(GOMP_OFFLOAD_unload_image): Call __offload_unregister_image, free
	the corresponding descriptor, and remove it from address_table and
	image_descriptors.
	(GOMP_OFFLOAD_alloc): Print device number, remove vd1g.
	(GOMP_OFFLOAD_free): Likewise.
	(GOMP_OFFLOAD_host2dev): Print device number, remove vd1g and vd2g.
	(GOMP_OFFLOAD_dev2host): Likewise.
	(GOMP_OFFLOAD_run): Print device number, remove vd1g.
	* plugin/offload_target_main.cpp (__offload_target_table_p1): Remove
	vd2, don't pass it to __offload_target_enter.
	(__offload_target_table_p2): Likewise.
	(__offload_target_alloc): Likewise.
	(__offload_target_free): Likewise.
	(__offload_target_host2tgt_p1): Likewise.
	(__offload_target_host2tgt_p2): Likewise.
	(__offload_target_tgt2host_p1): Likewise.
	(__offload_target_tgt2host_p2): Likewise.
	(__offload_target_run): Likewise.




  -- Ilya
diff mbox

Patch

diff --git a/liboffloadmic/plugin/libgomp-plugin-intelmic.cpp b/liboffloadmic/plugin/libgomp-plugin-intelmic.cpp
index fde7d9e..a2260e5 100644
--- a/liboffloadmic/plugin/libgomp-plugin-intelmic.cpp
+++ b/liboffloadmic/plugin/libgomp-plugin-intelmic.cpp
@@ -64,6 +64,17 @@  typedef std::vector<AddrVect> DevAddrVect;
 /* Addresses for all images and all devices.  */
 typedef std::map<const void *, DevAddrVect> ImgDevAddrMap;
 
+/* Image descriptor needed by __offload_[un]register_image.  */
+struct TargetImageDesc {
+  int64_t size;
+  /* 10 characters is enough for max int value.  */
+  char name[sizeof ("lib0000000000.so")];
+  char data[];
+} __attribute__ ((packed));
+
+/* Image descriptors, indexed by a pointer obtained from libgomp.  */
+typedef std::map<const void *, TargetImageDesc *> ImgDescMap;
+
 
 /* Total number of available devices.  */
 static int num_devices;
@@ -75,6 +86,9 @@  static int num_images;
    second key is number of device.  Contains a vector of pointer pairs.  */
 static ImgDevAddrMap *address_table;
 
+/* Descriptors of all images, registered in liboffloadmic.  */
+static ImgDescMap *image_descriptors;
+
 /* Thread-safe registration of the main image.  */
 static pthread_once_t main_image_is_registered = PTHREAD_ONCE_INIT;
 
@@ -150,6 +164,7 @@  init (void)
 
 out:
   address_table = new ImgDevAddrMap;
+  image_descriptors = new ImgDescMap;
   num_devices = _Offload_number_of_devices ();
 }
 
@@ -186,11 +201,11 @@  GOMP_OFFLOAD_get_num_devices (void)
 
 static void
 offload (const char *file, uint64_t line, int device, const char *name,
-	 int num_vars, VarDesc *vars, VarDesc2 *vars2)
+	 int num_vars, VarDesc *vars)
 {
   OFFLOAD ofld = __offload_target_acquire1 (&device, file, line);
   if (ofld)
-    __offload_offload1 (ofld, name, 0, num_vars, vars, vars2, 0, NULL, NULL);
+    __offload_offload1 (ofld, name, 0, num_vars, vars, NULL, 0, NULL, NULL);
   else
     {
       fprintf (stderr, "%s:%d: Offload target acquire failed\n", file, line);
@@ -199,9 +214,23 @@  offload (const char *file, uint64_t line, int device, const char *name,
 }
 
 static void
+unregister_main_image ()
+{
+  __offload_unregister_image (&main_target_image);
+}
+
+static void
 register_main_image ()
 {
+  /* Do not check the return value, because old versions of liboffloadmic did
+     not have return values.  */
   __offload_register_image (&main_target_image);
+
+  if (atexit (unregister_main_image) != 0)
+    {
+      fprintf (stderr, "%s: atexit failed\n", __FILE__);
+      exit (1);
+    }
 }
 
 /* liboffloadmic loads and runs offload_target_main on all available devices
@@ -209,16 +238,15 @@  register_main_image ()
 extern "C" void
 GOMP_OFFLOAD_init_device (int device)
 {
-  TRACE ("");
+  TRACE ("(device = %d)", device);
   pthread_once (&main_image_is_registered, register_main_image);
-  offload (__FILE__, __LINE__, device, "__offload_target_init_proc", 0,
-	   NULL, NULL);
+  offload (__FILE__, __LINE__, device, "__offload_target_init_proc", 0, NULL);
 }
 
 extern "C" void
 GOMP_OFFLOAD_fini_device (int device)
 {
-  TRACE ("");
+  TRACE ("(device = %d)", device);
   /* Unreachable for GOMP_OFFLOAD_CAP_OPENMP_400.  */
   abort ();
 }
@@ -231,10 +259,7 @@  get_target_table (int device, int &num_funcs, int &num_vars, void **&table)
   vd1[0].size = sizeof (num_funcs);
   vd1[1].ptr = &num_vars;
   vd1[1].size = sizeof (num_vars);
-  VarDesc2 vd1g[2] = { { "num_funcs", 0 }, { "num_vars", 0 } };
-
-  offload (__FILE__, __LINE__, device, "__offload_target_table_p1", 2,
-	   vd1, vd1g);
+  offload (__FILE__, __LINE__, device, "__offload_target_table_p1", 2, vd1);
 
   int table_size = num_funcs + 2 * num_vars;
   if (table_size > 0)
@@ -245,10 +270,8 @@  get_target_table (int device, int &num_funcs, int &num_vars, void **&table)
       vd2 = vd_tgt2host;
       vd2.ptr = table;
       vd2.size = table_size * sizeof (void *);
-      VarDesc2 vd2g = { "table", 0 };
-
       offload (__FILE__, __LINE__, device, "__offload_target_table_p2", 1,
-	       &vd2, &vd2g);
+	       &vd2);
     }
 }
 
@@ -258,13 +281,6 @@  get_target_table (int device, int &num_funcs, int &num_vars, void **&table)
 static void
 offload_image (const void *target_image)
 {
-  struct TargetImage {
-    int64_t size;
-    /* 10 characters is enough for max int value.  */
-    char name[sizeof ("lib0000000000.so")];
-    char data[];
-  } __attribute__ ((packed));
-
   void *image_start = ((void **) target_image)[0];
   void *image_end   = ((void **) target_image)[1];
 
@@ -272,9 +288,9 @@  offload_image (const void *target_image)
 	 target_image, image_start, image_end);
 
   int64_t image_size = (uintptr_t) image_end - (uintptr_t) image_start;
-  TargetImage *image
-    = (TargetImage *) malloc (sizeof (int64_t) + sizeof ("lib0000000000.so")
-			      + image_size);
+  TargetImageDesc *image
+    = (TargetImageDesc *) malloc (sizeof (int64_t) + sizeof ("lib0000000000.so")
+				  + image_size);
   if (!image)
     {
       fprintf (stderr, "%s: Can't allocate memory\n", __FILE__);
@@ -287,6 +303,8 @@  offload_image (const void *target_image)
 
   TRACE ("() __offload_register_image %s { %p, %d }",
 	 image->name, image_start, image->size);
+  /* Do not check the return value, because old versions of liboffloadmic did
+     not have return values.  */
   __offload_register_image (image);
 
   /* Receive tables for target_image from all devices.  */
@@ -321,11 +339,11 @@  offload_image (const void *target_image)
 	}
 
       dev_table.push_back (curr_dev_table);
+      delete [] table;
     }
 
   address_table->insert (std::make_pair (target_image, dev_table));
-
-  free (image);
+  image_descriptors->insert (std::make_pair (target_image, image));
 }
 
 /* Return the libgomp version number we're compatible with.  There is
@@ -376,26 +394,30 @@  GOMP_OFFLOAD_unload_image (int device, unsigned version,
 
   TRACE ("(device = %d, target_image = %p)", device, target_image);
 
-  /* TODO: Currently liboffloadmic doesn't support __offload_unregister_image
-     for libraries.  */
+  /* liboffloadmic unloads the image from all available devices.  */
+  if (image_descriptors->count (target_image) > 0)
+    {
+      TargetImageDesc *image_desc = (*image_descriptors)[target_image];
+      __offload_unregister_image (image_desc);
+      free (image_desc);
 
-  address_table->erase (target_image);
+      address_table->erase (target_image);
+      image_descriptors->erase (target_image);
+    }
 }
 
 extern "C" void *
 GOMP_OFFLOAD_alloc (int device, size_t size)
 {
-  TRACE ("(size = %d)", size);
+  TRACE ("(device = %d, size = %d)", device, size);
 
   void *tgt_ptr;
-  VarDesc vd1[2] = { vd_host2tgt, vd_tgt2host };
-  vd1[0].ptr = &size;
-  vd1[0].size = sizeof (size);
-  vd1[1].ptr = &tgt_ptr;
-  vd1[1].size = sizeof (void *);
-  VarDesc2 vd1g[2] = { { "size", 0 }, { "tgt_ptr", 0 } };
-
-  offload (__FILE__, __LINE__, device, "__offload_target_alloc", 2, vd1, vd1g);
+  VarDesc vd[2] = { vd_host2tgt, vd_tgt2host };
+  vd[0].ptr = &size;
+  vd[0].size = sizeof (size);
+  vd[1].ptr = &tgt_ptr;
+  vd[1].size = sizeof (void *);
+  offload (__FILE__, __LINE__, device, "__offload_target_alloc", 2, vd);
 
   return tgt_ptr;
 }
@@ -403,21 +425,20 @@  GOMP_OFFLOAD_alloc (int device, size_t size)
 extern "C" void
 GOMP_OFFLOAD_free (int device, void *tgt_ptr)
 {
-  TRACE ("(tgt_ptr = %p)", tgt_ptr);
+  TRACE ("(device = %d, tgt_ptr = %p)", device, tgt_ptr);
 
-  VarDesc vd1 = vd_host2tgt;
-  vd1.ptr = &tgt_ptr;
-  vd1.size = sizeof (void *);
-  VarDesc2 vd1g = { "tgt_ptr", 0 };
-
-  offload (__FILE__, __LINE__, device, "__offload_target_free", 1, &vd1, &vd1g);
+  VarDesc vd = vd_host2tgt;
+  vd.ptr = &tgt_ptr;
+  vd.size = sizeof (void *);
+  offload (__FILE__, __LINE__, device, "__offload_target_free", 1, &vd);
 }
 
 extern "C" void *
 GOMP_OFFLOAD_host2dev (int device, void *tgt_ptr, const void *host_ptr,
 		       size_t size)
 {
-  TRACE ("(tgt_ptr = %p, host_ptr = %p, size = %d)", tgt_ptr, host_ptr, size);
+  TRACE ("(device = %d, tgt_ptr = %p, host_ptr = %p, size = %d)",
+	 device, tgt_ptr, host_ptr, size);
   if (!size)
     return tgt_ptr;
 
@@ -426,18 +447,12 @@  GOMP_OFFLOAD_host2dev (int device, void *tgt_ptr, const void *host_ptr,
   vd1[0].size = sizeof (void *);
   vd1[1].ptr = &size;
   vd1[1].size = sizeof (size);
-  VarDesc2 vd1g[2] = { { "tgt_ptr", 0 }, { "size", 0 } };
-
-  offload (__FILE__, __LINE__, device, "__offload_target_host2tgt_p1", 2,
-	   vd1, vd1g);
+  offload (__FILE__, __LINE__, device, "__offload_target_host2tgt_p1", 2, vd1);
 
   VarDesc vd2 = vd_host2tgt;
   vd2.ptr = (void *) host_ptr;
   vd2.size = size;
-  VarDesc2 vd2g = { "var", 0 };
-
-  offload (__FILE__, __LINE__, device, "__offload_target_host2tgt_p2", 1,
-	   &vd2, &vd2g);
+  offload (__FILE__, __LINE__, device, "__offload_target_host2tgt_p2", 1, &vd2);
 
   return tgt_ptr;
 }
@@ -446,7 +461,8 @@  extern "C" void *
 GOMP_OFFLOAD_dev2host (int device, void *host_ptr, const void *tgt_ptr,
 		       size_t size)
 {
-  TRACE ("(host_ptr = %p, tgt_ptr = %p, size = %d)", host_ptr, tgt_ptr, size);
+  TRACE ("(device = %d, host_ptr = %p, tgt_ptr = %p, size = %d)",
+	 device, host_ptr, tgt_ptr, size);
   if (!size)
     return host_ptr;
 
@@ -455,18 +471,12 @@  GOMP_OFFLOAD_dev2host (int device, void *host_ptr, const void *tgt_ptr,
   vd1[0].size = sizeof (void *);
   vd1[1].ptr = &size;
   vd1[1].size = sizeof (size);
-  VarDesc2 vd1g[2] = { { "tgt_ptr", 0 }, { "size", 0 } };
-
-  offload (__FILE__, __LINE__, device, "__offload_target_tgt2host_p1", 2,
-	   vd1, vd1g);
+  offload (__FILE__, __LINE__, device, "__offload_target_tgt2host_p1", 2, vd1);
 
   VarDesc vd2 = vd_tgt2host;
   vd2.ptr = (void *) host_ptr;
   vd2.size = size;
-  VarDesc2 vd2g = { "var", 0 };
-
-  offload (__FILE__, __LINE__, device, "__offload_target_tgt2host_p2", 1,
-	   &vd2, &vd2g);
+  offload (__FILE__, __LINE__, device, "__offload_target_tgt2host_p2", 1, &vd2);
 
   return host_ptr;
 }
@@ -474,14 +484,12 @@  GOMP_OFFLOAD_dev2host (int device, void *host_ptr, const void *tgt_ptr,
 extern "C" void
 GOMP_OFFLOAD_run (int device, void *tgt_fn, void *tgt_vars)
 {
-  TRACE ("(tgt_fn = %p, tgt_vars = %p)", tgt_fn, tgt_vars);
-
-  VarDesc vd1[2] = { vd_host2tgt, vd_host2tgt };
-  vd1[0].ptr = &tgt_fn;
-  vd1[0].size = sizeof (void *);
-  vd1[1].ptr = &tgt_vars;
-  vd1[1].size = sizeof (void *);
-  VarDesc2 vd1g[2] = { { "tgt_fn", 0 }, { "tgt_vars", 0 } };
-
-  offload (__FILE__, __LINE__, device, "__offload_target_run", 2, vd1, vd1g);
+  TRACE ("(device = %d, tgt_fn = %p, tgt_vars = %p)", device, tgt_fn, tgt_vars);
+
+  VarDesc vd[2] = { vd_host2tgt, vd_host2tgt };
+  vd[0].ptr = &tgt_fn;
+  vd[0].size = sizeof (void *);
+  vd[1].ptr = &tgt_vars;
+  vd[1].size = sizeof (void *);
+  offload (__FILE__, __LINE__, device, "__offload_target_run", 2, vd);
 }
diff --git a/liboffloadmic/plugin/offload_target_main.cpp b/liboffloadmic/plugin/offload_target_main.cpp
index 3fead01..612f992 100644
--- a/liboffloadmic/plugin/offload_target_main.cpp
+++ b/liboffloadmic/plugin/offload_target_main.cpp
@@ -139,14 +139,13 @@  __offload_target_table_p1 (OFFLOAD ofldt)
   int num_vars = (var_table_end - var_table_begin) / 2;
   TRACE ("(num_funcs = %d, num_vars = %d)", num_funcs, num_vars);
 
-  VarDesc vd1[2] = { vd_tgt2host, vd_tgt2host };
-  vd1[0].ptr = &num_funcs;
-  vd1[0].size = sizeof (num_funcs);
-  vd1[1].ptr = &num_vars;
-  vd1[1].size = sizeof (num_vars);
-  VarDesc2 vd2[2] = { { "num_funcs", 0 }, { "num_vars", 0 } };
-
-  __offload_target_enter (ofldt, 2, vd1, vd2);
+  VarDesc vd[2] = { vd_tgt2host, vd_tgt2host };
+  vd[0].ptr = &num_funcs;
+  vd[0].size = sizeof (num_funcs);
+  vd[1].ptr = &num_vars;
+  vd[1].size = sizeof (num_vars);
+
+  __offload_target_enter (ofldt, 2, vd, NULL);
   __offload_target_leave (ofldt);
 }
 
@@ -166,13 +165,11 @@  __offload_target_table_p2 (OFFLOAD ofldt)
   void **table = (void **) malloc (table_size);
   TRACE ("(table_size = %d)", table_size);
 
-  VarDesc vd1;
-  vd1 = vd_tgt2host;
-  vd1.ptr = table;
-  vd1.size = table_size;
-  VarDesc2 vd2 = { "table", 0 };
+  VarDesc vd = vd_tgt2host;
+  vd.ptr = table;
+  vd.size = table_size;
 
-  __offload_target_enter (ofldt, 1, &vd1, &vd2);
+  __offload_target_enter (ofldt, 1, &vd, NULL);
 
   void **p;
   int i = 0;
@@ -193,14 +190,13 @@  __offload_target_alloc (OFFLOAD ofldt)
   size_t size = 0;
   void *ptr = NULL;
 
-  VarDesc vd1[2] = { vd_host2tgt, vd_tgt2host };
-  vd1[0].ptr = &size;
-  vd1[0].size = sizeof (size);
-  vd1[1].ptr = &ptr;
-  vd1[1].size = sizeof (void *);
-  VarDesc2 vd2[2] = { { "size", 0 }, { "ptr", 0 } };
+  VarDesc vd[2] = { vd_host2tgt, vd_tgt2host };
+  vd[0].ptr = &size;
+  vd[0].size = sizeof (size);
+  vd[1].ptr = &ptr;
+  vd[1].size = sizeof (void *);
 
-  __offload_target_enter (ofldt, 2, vd1, vd2);
+  __offload_target_enter (ofldt, 2, vd, NULL);
   ptr = malloc (size);
   TRACE ("(size = %d): ptr = %p", size, ptr);
   __offload_target_leave (ofldt);
@@ -212,12 +208,11 @@  __offload_target_free (OFFLOAD ofldt)
 {
   void *ptr = 0;
 
-  VarDesc vd1 = vd_host2tgt;
-  vd1.ptr = &ptr;
-  vd1.size = sizeof (void *);
-  VarDesc2 vd2 = { "ptr", 0 };
+  VarDesc vd = vd_host2tgt;
+  vd.ptr = &ptr;
+  vd.size = sizeof (void *);
 
-  __offload_target_enter (ofldt, 1, &vd1, &vd2);
+  __offload_target_enter (ofldt, 1, &vd, NULL);
   TRACE ("(ptr = %p)", ptr);
   free (ptr);
   __offload_target_leave (ofldt);
@@ -231,14 +226,13 @@  __offload_target_host2tgt_p1 (OFFLOAD ofldt)
   void *var_ptr = NULL;
   size_t var_size = 0;
 
-  VarDesc vd1[2] = { vd_host2tgt, vd_host2tgt };
-  vd1[0].ptr = &var_ptr;
-  vd1[0].size = sizeof (void *);
-  vd1[1].ptr = &var_size;
-  vd1[1].size = sizeof (var_size);
-  VarDesc2 vd2[2] = { { "var_ptr", 0 }, { "var_size", 0 } };
+  VarDesc vd[2] = { vd_host2tgt, vd_host2tgt };
+  vd[0].ptr = &var_ptr;
+  vd[0].size = sizeof (void *);
+  vd[1].ptr = &var_size;
+  vd[1].size = sizeof (var_size);
 
-  __offload_target_enter (ofldt, 2, vd1, vd2);
+  __offload_target_enter (ofldt, 2, vd, NULL);
   TRACE ("(var_ptr = %p, var_size = %d)", var_ptr, var_size);
   last_var_ptr = var_ptr;
   last_var_size = var_size;
@@ -252,12 +246,11 @@  __offload_target_host2tgt_p2 (OFFLOAD ofldt)
   TRACE ("(last_var_ptr = %p, last_var_size = %d)",
 	 last_var_ptr, last_var_size);
 
-  VarDesc vd1 = vd_host2tgt;
-  vd1.ptr = last_var_ptr;
-  vd1.size = last_var_size;
-  VarDesc2 vd2 = { "var", 0 };
+  VarDesc vd = vd_host2tgt;
+  vd.ptr = last_var_ptr;
+  vd.size = last_var_size;
 
-  __offload_target_enter (ofldt, 1, &vd1, &vd2);
+  __offload_target_enter (ofldt, 1, &vd, NULL);
   __offload_target_leave (ofldt);
 }
 
@@ -269,14 +262,13 @@  __offload_target_tgt2host_p1 (OFFLOAD ofldt)
   void *var_ptr = NULL;
   size_t var_size = 0;
 
-  VarDesc vd1[2] = { vd_host2tgt, vd_host2tgt };
-  vd1[0].ptr = &var_ptr;
-  vd1[0].size = sizeof (void *);
-  vd1[1].ptr = &var_size;
-  vd1[1].size = sizeof (var_size);
-  VarDesc2 vd2[2] = { { "var_ptr", 0 }, { "var_size", 0 } };
+  VarDesc vd[2] = { vd_host2tgt, vd_host2tgt };
+  vd[0].ptr = &var_ptr;
+  vd[0].size = sizeof (void *);
+  vd[1].ptr = &var_size;
+  vd[1].size = sizeof (var_size);
 
-  __offload_target_enter (ofldt, 2, vd1, vd2);
+  __offload_target_enter (ofldt, 2, vd, NULL);
   TRACE ("(var_ptr = %p, var_size = %d)", var_ptr, var_size);
   last_var_ptr = var_ptr;
   last_var_size = var_size;
@@ -290,12 +282,11 @@  __offload_target_tgt2host_p2 (OFFLOAD ofldt)
   TRACE ("(last_var_ptr = %p, last_var_size = %d)",
 	 last_var_ptr, last_var_size);
 
-  VarDesc vd1 = vd_tgt2host;
-  vd1.ptr = last_var_ptr;
-  vd1.size = last_var_size;
-  VarDesc2 vd2 = { "var", 0 };
+  VarDesc vd = vd_tgt2host;
+  vd.ptr = last_var_ptr;
+  vd.size = last_var_size;
 
-  __offload_target_enter (ofldt, 1, &vd1, &vd2);
+  __offload_target_enter (ofldt, 1, &vd, NULL);
   __offload_target_leave (ofldt);
 }
 
@@ -306,14 +297,13 @@  __offload_target_run (OFFLOAD ofldt)
   void *fn_ptr;
   void *vars_ptr;
 
-  VarDesc vd1[2] = { vd_host2tgt, vd_host2tgt };
-  vd1[0].ptr = &fn_ptr;
-  vd1[0].size = sizeof (void *);
-  vd1[1].ptr = &vars_ptr;
-  vd1[1].size = sizeof (void *);
-  VarDesc2 vd2[2] = { { "fn_ptr", 0 }, { "vars_ptr", 0 } };
+  VarDesc vd[2] = { vd_host2tgt, vd_host2tgt };
+  vd[0].ptr = &fn_ptr;
+  vd[0].size = sizeof (void *);
+  vd[1].ptr = &vars_ptr;
+  vd[1].size = sizeof (void *);
 
-  __offload_target_enter (ofldt, 2, vd1, vd2);
+  __offload_target_enter (ofldt, 2, vd, NULL);
   TRACE ("(fn_ptr = %p, vars_ptr = %p)", fn_ptr, vars_ptr);
   void (*fn)(void *) = (void (*)(void *)) fn_ptr;
   fn (vars_ptr);