/*===--------------------------------------------------------------------------
 *              ATMI (Asynchronous Task and Memory Interface)
 *
 * This file is distributed under the MIT License. See LICENSE.txt for details.
 *===------------------------------------------------------------------------*/
#include <assert.h>
#include "atl_internal.h"
#include "atmi.h"

/* Null kernel */
#ifdef __cplusplus
#define _CPPSTRING_ "C"
#endif
#ifndef __cplusplus
#define _CPPSTRING_
#endif
extern _CPPSTRING_ void __sync_kernel() {}
extern _CPPSTRING_ void __sync_kernel_wrapper() { __sync_kernel(); }
static int cpu_initalized = 0;

typedef struct pif_kernel_table_s {
  atmi_devtype_t devtype;
  atmi_generic_fp cpu_kernel;
  const char *gpu_kernel;
} pif_kernel_table_t;

pif_kernel_table_t __sync_kernel_pif_fn_table[] = {
    {.devtype = ATMI_DEVTYPE_CPU,
     .cpu_kernel = (atmi_generic_fp)__sync_kernel_wrapper,
     .gpu_kernel = 0},
};

static int __sync_kernel_CPU_FK = 0;
static atmi_kernel_t __sync_kernel_obj;
extern _CPPSTRING_ atmi_task_handle_t __sync_kernel_pif(atmi_lparm_t *lparm) {
  int k_id = lparm->kernel_id;
  assert(k_id == 0);
  atmi_devtype_t devtype = __sync_kernel_pif_fn_table[k_id].devtype;
  if (devtype == ATMI_DEVTYPE_GPU) {
  } else if (devtype == ATMI_DEVTYPE_CPU) {
    /* Kernel initialization has to be done before kernel arguments are
     * set/inspected */
    const char *kernel_name = "__sync_kernel";
    const int num_args = 0;
    if (__sync_kernel_CPU_FK == 0) {
      atmi_kernel_create_empty(&__sync_kernel_obj, num_args, NULL);
      atmi_kernel_add_cpu_impl(
          __sync_kernel_obj,
          (atmi_generic_fp)(__sync_kernel_pif_fn_table[0].cpu_kernel), 0);
      __sync_kernel_CPU_FK = 1;
    }
    if (cpu_initalized == 0) {
      atmi_init(ATMI_DEVTYPE_CPU);
      cpu_initalized = 1;
    }
    return atmi_task_launch(lparm, __sync_kernel_obj, NULL);
  }
}
