/* Plugin for offload execution on Intel MIC devices.

   Copyright (C) 2014-2016 Free Software Foundation, Inc.

   Contributed by Ilya Verbin <ilya.verbin@intel.com>.

   This file is part of the GNU Offloading and Multi Processing Library
   (libgomp).

   Libgomp is free software; you can redistribute it and/or modify it
   under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 3, or (at your option)
   any later version.

   Libgomp is distributed in the hope that it will be useful, but WITHOUT ANY
   WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
   FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
   more details.

   Under Section 7 of GPL version 3, you are granted additional
   permissions described in the GCC Runtime Library Exception, version
   3.1, as published by the Free Software Foundation.

   You should have received a copy of the GNU General Public License and
   a copy of the GCC Runtime Library Exception along with this program;
   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
   <http://www.gnu.org/licenses/>.  */

/* Host side part of a libgomp plugin.  */

#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <utility>
#include <vector>
#include <map>
#include "libgomp-plugin.h"
#include "compiler_if_host.h"
#include "main_target_image.h"
#include "gomp-constants.h"

#define OFFLOAD_ACTIVE_WAIT_ENV	"OFFLOAD_ACTIVE_WAIT"

#ifdef DEBUG
#define TRACE(...)					    \
{							    \
fprintf (stderr, "HOST:\t%s:%s ", __FILE__, __FUNCTION__);  \
fprintf (stderr, __VA_ARGS__);				    \
fprintf (stderr, "\n");					    \
}
#else
#define TRACE { }
#endif


/* Start/end addresses of functions and global variables on a device.  */
typedef std::vector<addr_pair> AddrVect;

/* Addresses for one image and all devices.  */
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[];
};

/* 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;

/* Total number of shared libraries with offloading to Intel MIC.  */
static int num_images;

/* Two dimensional array: one key is a pointer to image,
   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;

static VarDesc vd_host2tgt = {
  { 1, 1 },		      /* dst, src			      */
  { 1, 0 },		      /* in, out			      */
  1,			      /* alloc_if			      */
  1,			      /* free_if			      */
  4,			      /* align				      */
  0,			      /* mic_offset			      */
  { 0, 0, 0, 0, 0, 0, 0, 0 }, /* is_static, is_static_dstn, has_length,
				 is_stack_buf, sink_addr, alloc_disp,
				 is_noncont_src, is_noncont_dst	      */
  0,			      /* offset				      */
  0,			      /* size				      */
  1,			      /* count				      */
  0,			      /* alloc				      */
  0,			      /* into				      */
  0			      /* ptr				      */
};

static VarDesc vd_tgt2host = {
  { 1, 1 },		      /* dst, src			      */
  { 0, 1 },		      /* in, out			      */
  1,			      /* alloc_if			      */
  1,			      /* free_if			      */
  4,			      /* align				      */
  0,			      /* mic_offset			      */
  { 0, 0, 0, 0, 0, 0, 0, 0 }, /* is_static, is_static_dstn, has_length,
				 is_stack_buf, sink_addr, alloc_disp,
				 is_noncont_src, is_noncont_dst	      */
  0,			      /* offset				      */
  0,			      /* size				      */
  1,			      /* count				      */
  0,			      /* alloc				      */
  0,			      /* into				      */
  0			      /* ptr				      */
};


__attribute__((constructor))
static void
init (void)
{
  const char *active_wait = getenv (OFFLOAD_ACTIVE_WAIT_ENV);

  /* Disable active wait by default to avoid useless CPU usage.  */
  if (!active_wait)
    setenv (OFFLOAD_ACTIVE_WAIT_ENV, "0", 0);

  address_table = new ImgDevAddrMap;
  image_descriptors = new ImgDescMap;
  num_devices = _Offload_number_of_devices ();
}

extern "C" const char *
GOMP_OFFLOAD_get_name (void)
{
  const char *res = "intelmic";
  TRACE ("(): return %s", res);
  return res;
}

extern "C" unsigned int
GOMP_OFFLOAD_get_caps (void)
{
  unsigned int res = GOMP_OFFLOAD_CAP_OPENMP_400;
  TRACE ("(): return %x", res);
  return res;
}

extern "C" int
GOMP_OFFLOAD_get_type (void)
{
  enum offload_target_type res = OFFLOAD_TARGET_TYPE_INTEL_MIC;
  TRACE ("(): return %d", res);
  return res;
}

extern "C" int
GOMP_OFFLOAD_get_num_devices (void)
{
  TRACE ("(): return %d", num_devices);
  return num_devices;
}

static bool
offload (const char *file, uint64_t line, int device, const char *name,
	 int num_vars, VarDesc *vars, const void **async_data)
{
  OFFLOAD ofld = __offload_target_acquire1 (&device, file, line);
  if (ofld)
    {
      if (async_data == NULL)
	return __offload_offload1 (ofld, name, 0, num_vars, vars, NULL, 0,
				   NULL, NULL);
      else
	{
	  OffloadFlags flags;
	  flags.flags = 0;
	  flags.bits.omp_async = 1;
	  return __offload_offload3 (ofld, name, 0, num_vars, vars, NULL, 0,
				     NULL, async_data, 0, NULL, flags, NULL);
	}
    }
  else
    {
      GOMP_PLUGIN_error ("%s:%d: Offload target acquire failed\n", file, line);
      return false;
    }
}

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

  /* liboffloadmic will call GOMP_PLUGIN_target_task_completion when
     asynchronous task on target is completed.  */
  __offload_register_task_callback (GOMP_PLUGIN_target_task_completion);
}

/* liboffloadmic loads and runs offload_target_main on all available devices
   during a first call to offload ().  */
extern "C" bool
GOMP_OFFLOAD_init_device (int device)
{
  TRACE ("(device = %d)", device);
  pthread_once (&main_image_is_registered, register_main_image);
  return offload (__FILE__, __LINE__, device, "__offload_target_init_proc", 0,
		  NULL, NULL);
}

extern "C" bool
GOMP_OFFLOAD_fini_device (int device)
{
  TRACE ("(device = %d)", device);

  /* liboffloadmic will finalize target processes on all available devices.  */
  __offload_unregister_image (&main_target_image);
  return true;
}

/* Indicate which GOMP_REQUIRES_* features are supported, currently none.  */

extern "C" bool
GOMP_OFFLOAD_supported_features (unsigned int *mask)
{
  return (*mask == 0);
}

static bool
get_target_table (int device, int &num_funcs, int &num_vars, void **&table)
{
  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);

  if (!offload (__FILE__, __LINE__, device, "__offload_target_table_p1", 2,
		vd1, NULL))
    return false;

  int table_size = num_funcs + 2 * num_vars;
  if (table_size > 0)
    {
      table = new void * [table_size];

      VarDesc vd2;
      vd2 = vd_tgt2host;
      vd2.ptr = table;
      vd2.size = table_size * sizeof (void *);

      return offload (__FILE__, __LINE__, device, "__offload_target_table_p2",
		      1, &vd2, NULL);
    }
  return true;
}

/* Offload TARGET_IMAGE to all available devices and fill address_table with
   corresponding target addresses.  */

static bool
offload_image (const void *target_image)
{
  void *image_start = ((void **) target_image)[0];
  void *image_end   = ((void **) target_image)[1];

  TRACE ("(target_image = %p { %p, %p })",
	 target_image, image_start, image_end);

  int64_t image_size = (uintptr_t) image_end - (uintptr_t) image_start;
  TargetImageDesc *image = (TargetImageDesc *) malloc (offsetof (TargetImageDesc, data)
						       + image_size);
  if (!image)
    {
      GOMP_PLUGIN_error ("%s: Can't allocate memory\n", __FILE__);
      return false;
    }

  image->size = image_size;
  sprintf (image->name, "lib%010d.so", num_images++);
  memcpy (image->data, image_start, image->size);

  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.  */
  DevAddrVect dev_table;
  bool ret = true;
  for (int dev = 0; dev < num_devices; dev++)
    {
      int num_funcs = 0;
      int num_vars = 0;
      void **table = NULL;

      ret &= get_target_table (dev, num_funcs, num_vars, table);

      AddrVect curr_dev_table;

      for (int i = 0; i < num_funcs; i++)
	{
	  addr_pair tgt_addr;
	  tgt_addr.start = (uintptr_t) table[i];
	  tgt_addr.end = tgt_addr.start + 1;
	  TRACE ("() func %d:\t0x%llx..0x%llx", i,
		 tgt_addr.start, tgt_addr.end);
	  curr_dev_table.push_back (tgt_addr);
	}

      for (int i = 0; i < num_vars; i++)
	{
	  addr_pair tgt_addr;
	  tgt_addr.start = (uintptr_t) table[num_funcs+i*2];
	  tgt_addr.end = tgt_addr.start + (uintptr_t) table[num_funcs+i*2+1];
	  TRACE ("() var %d:\t0x%llx..0x%llx", i, tgt_addr.start, tgt_addr.end);
	  curr_dev_table.push_back (tgt_addr);
	}

      dev_table.push_back (curr_dev_table);
      delete [] table;
    }

  address_table->insert (std::make_pair (target_image, dev_table));
  image_descriptors->insert (std::make_pair (target_image, image));
  return ret;
}

/* Return the libgomp version number we're compatible with.  There is
   no requirement for cross-version compatibility.  */

extern "C" unsigned
GOMP_OFFLOAD_version (void)
{
  return GOMP_VERSION;
}

extern "C" int
GOMP_OFFLOAD_load_image (int device, const unsigned version,
			 const void *target_image, addr_pair **result)
{
  TRACE ("(device = %d, target_image = %p)", device, target_image);

  if (GOMP_VERSION_DEV (version) > GOMP_VERSION_INTEL_MIC)
    {
      GOMP_PLUGIN_error ("Offload data incompatible with intelmic plugin"
			 " (expected %u, received %u)",
			 GOMP_VERSION_INTEL_MIC, GOMP_VERSION_DEV (version));
      return -1;
    }

  /* If target_image is already present in address_table, then there is no need
     to offload it.  */
  if (address_table->count (target_image) == 0)
    {
      /* If fail, return -1 as error code.  */
      if (!offload_image (target_image))
	return -1;
    }

  AddrVect *curr_dev_table = &(*address_table)[target_image][device];
  int table_size = curr_dev_table->size ();
  addr_pair *table = (addr_pair *) malloc (table_size * sizeof (addr_pair));
  if (table == NULL)
    {
      GOMP_PLUGIN_error ("%s: Can't allocate memory\n", __FILE__);
      return -1;
    }

  std::copy (curr_dev_table->begin (), curr_dev_table->end (), table);
  *result = table;
  return table_size;
}

extern "C" bool
GOMP_OFFLOAD_unload_image (int device, unsigned version,
			   const void *target_image)
{
  if (GOMP_VERSION_DEV (version) > GOMP_VERSION_INTEL_MIC)
    {
      GOMP_PLUGIN_error ("Offload data incompatible with intelmic plugin"
			 " (expected %u, received %u)",
			 GOMP_VERSION_INTEL_MIC, GOMP_VERSION_DEV (version));
      return false;
    }

  TRACE ("(device = %d, target_image = %p)", device, target_image);

  /* 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);
      image_descriptors->erase (target_image);
    }
  return true;
}

extern "C" void *
GOMP_OFFLOAD_alloc (int device, size_t size)
{
  TRACE ("(device = %d, size = %d)", device, size);

  void *tgt_ptr;
  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 *);

  if (!offload (__FILE__, __LINE__, device, "__offload_target_alloc", 2,
		vd, NULL))
    return NULL;

  return tgt_ptr;
}

extern "C" bool
GOMP_OFFLOAD_free (int device, void *tgt_ptr)
{
  TRACE ("(device = %d, tgt_ptr = %p)", device, tgt_ptr);

  VarDesc vd = vd_host2tgt;
  vd.ptr = &tgt_ptr;
  vd.size = sizeof (void *);

  return offload (__FILE__, __LINE__, device, "__offload_target_free", 1,
		  &vd, NULL);
}

extern "C" bool
GOMP_OFFLOAD_host2dev (int device, void *tgt_ptr, const void *host_ptr,
		       size_t size)
{
  TRACE ("(device = %d, tgt_ptr = %p, host_ptr = %p, size = %d)",
	 device, tgt_ptr, host_ptr, size);
  if (!size)
    return true;

  VarDesc vd1[2] = { vd_host2tgt, vd_host2tgt };
  vd1[0].ptr = &tgt_ptr;
  vd1[0].size = sizeof (void *);
  vd1[1].ptr = &size;
  vd1[1].size = sizeof (size);

  if (!offload (__FILE__, __LINE__, device, "__offload_target_host2tgt_p1", 2,
		vd1, NULL))
    return false;

  VarDesc vd2 = vd_host2tgt;
  vd2.ptr = (void *) host_ptr;
  vd2.size = size;

  return offload (__FILE__, __LINE__, device, "__offload_target_host2tgt_p2", 1,
		  &vd2, NULL);
}

extern "C" bool
GOMP_OFFLOAD_dev2host (int device, void *host_ptr, const void *tgt_ptr,
		       size_t size)
{
  TRACE ("(device = %d, host_ptr = %p, tgt_ptr = %p, size = %d)",
	 device, host_ptr, tgt_ptr, size);
  if (!size)
    return true;

  VarDesc vd1[2] = { vd_host2tgt, vd_host2tgt };
  vd1[0].ptr = &tgt_ptr;
  vd1[0].size = sizeof (void *);
  vd1[1].ptr = &size;
  vd1[1].size = sizeof (size);

  if (!offload (__FILE__, __LINE__, device, "__offload_target_tgt2host_p1", 2,
		vd1, NULL))
    return false;

  VarDesc vd2 = vd_tgt2host;
  vd2.ptr = (void *) host_ptr;
  vd2.size = size;

  return offload (__FILE__, __LINE__, device, "__offload_target_tgt2host_p2", 1,
		  &vd2, NULL);
}

extern "C" bool
GOMP_OFFLOAD_dev2dev (int device, void *dst_ptr, const void *src_ptr,
		      size_t size)
{
  TRACE ("(device = %d, dst_ptr = %p, src_ptr = %p, size = %d)",
	 device, dst_ptr, src_ptr, size);
  if (!size)
    return true;

  VarDesc vd[3] = { vd_host2tgt, vd_host2tgt, vd_host2tgt };
  vd[0].ptr = &dst_ptr;
  vd[0].size = sizeof (void *);
  vd[1].ptr = &src_ptr;
  vd[1].size = sizeof (void *);
  vd[2].ptr = &size;
  vd[2].size = sizeof (size);

  return offload (__FILE__, __LINE__, device, "__offload_target_tgt2tgt", 3,
		  vd, NULL);
}

extern "C" void
GOMP_OFFLOAD_async_run (int device, void *tgt_fn, void *tgt_vars,
			void **, void *async_data)
{
  TRACE ("(device = %d, tgt_fn = %p, tgt_vars = %p, async_data = %p)", device,
	 tgt_fn, tgt_vars, async_data);

  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,
	   (const void **) async_data);
}

extern "C" void
GOMP_OFFLOAD_run (int device, void *tgt_fn, void *tgt_vars, void **)
{
  TRACE ("(device = %d, tgt_fn = %p, tgt_vars = %p)", device, tgt_fn, tgt_vars);

  GOMP_OFFLOAD_async_run (device, tgt_fn, tgt_vars, NULL, NULL);
}
