Beispiel #1
0
/* deserializes a single file from the binary. */
static size_t
deserialize_file(unsigned char* buffer, char* basedir, size_t offset)
{
  unsigned char* orig_buffer = buffer;
  size_t len;

  char* relpath = NULL;
  BUFFER_READ_STR2(relpath, len);
  assert(len > 0);

  char* content = NULL;
  BUFFER_READ_STR2(content, len);
  assert(len > 0);

  char *p = basedir + offset;
  strcpy(p, relpath);
  free(relpath);

  char *fullpath = basedir;
  if (pocl_exists(fullpath))
    goto RET;

  char* dir = strdup(basedir);
  char* dirpath = dirname(dir);
  if (!pocl_exists(dirpath))
    pocl_mkdir_p(dirpath);
  free(dir);

  pocl_write_file(fullpath, content, len, 0, 0);

RET:
  free(content);
  return (buffer - orig_buffer);
}
Beispiel #2
0
void pocl_cache_init_topdir() {

    if (cache_topdir_initialized)
        return;

    const char *tmp_path = pocl_get_string_option("POCL_CACHE_DIR", NULL);
    int needed;

    if (tmp_path && (pocl_exists(tmp_path))) {
        needed = snprintf(cache_topdir, POCL_FILENAME_LENGTH, "%s", tmp_path);
    } else     {
#ifdef POCL_ANDROID
        char* process_name = pocl_get_process_name();
        needed = snprintf(cache_topdir, POCL_FILENAME_LENGTH,
                          "/data/data/%s/cache/", process_name);
        free(process_name);

        if (!pocl_exists(cache_topdir))
            needed = snprintf(cache_topdir,
                              POCL_FILENAME_LENGTH,
                              "/sdcard/pocl/kcache");
#elif defined(_MSC_VER) || defined(__MINGW32__)
        tmp_path = getenv("LOCALAPPDATA");
        if (!tmp_path)
            tmp_path = getenv("TEMP");
        assert(tmp_path);
        needed = snprintf(cache_topdir, POCL_FILENAME_LENGTH,
                          "%s\\pocl", tmp_path);
#else
        // "If $XDG_CACHE_HOME is either not set or empty, a default equal to
        // $HOME/.cache should be used."
        // http://standards.freedesktop.org/basedir-spec/latest/
        tmp_path = getenv("XDG_CACHE_HOME");

        if (tmp_path && tmp_path[0] != '\0') {
            needed = snprintf(cache_topdir, POCL_FILENAME_LENGTH,
                              "%s/pocl/kcache", tmp_path);
        }
        else if ((tmp_path = getenv("HOME")) != NULL) {
            needed = snprintf(cache_topdir, POCL_FILENAME_LENGTH,
                              "%s/.cache/pocl/kcache", tmp_path);
        }
        else {
            needed = snprintf(cache_topdir, POCL_FILENAME_LENGTH,
                              "/tmp/pocl/kcache");
        }
#endif
    }

    if (needed >= POCL_FILENAME_LENGTH) {
        POCL_ABORT("pocl: cache path longer than maximum filename length");
    }

    assert(strlen(cache_topdir) > 0);
    if (pocl_mkdir_p(cache_topdir))
        POCL_ABORT("Could not create topdir for cache");
    cache_topdir_initialized = 1;

}
Beispiel #3
0
int pocl_cache_device_cachedir_exists(cl_program   program,
                                      unsigned device_i) {
    char device_cachedir_path[POCL_FILENAME_LENGTH];
    program_device_dir(device_cachedir_path, program, device_i, "");

    return pocl_exists(device_cachedir_path);
}
Beispiel #4
0
char* pocl_cache_read_buildlog(cl_program program,
                               unsigned device_i) {
    char buildlog_path[POCL_FILENAME_LENGTH];
    if (program->build_hash[device_i][0] == 0)
        return NULL;
    program_device_dir(buildlog_path, program,
                       device_i, POCL_BUILDLOG_FILENAME);

    if (!pocl_exists(buildlog_path))
      return strdup("");

    char* res=NULL;
    uint64_t filesize;
    if (pocl_read_file(buildlog_path, &res, &filesize))
        return NULL;
    return res;
}
Beispiel #5
0
int 
pocl_write_file(const char *path, const char* content,
                uint64_t    count,
                int         append,
                int         dont_rewrite) 
{
  assert(path);
  assert(content);
  
  if (pocl_exists(path)) 
    {
      if (dont_rewrite) 
        {
          if (!append)
            return 0;
        } 
      else 
        {
          int res = pocl_remove(path);
          if (res)
            return res;
        }
    }
  
  FILE *f;
  if (append)
    f = fopen(path, "a");
  else
    f = fopen(path, "w");
  
  if (f == NULL)
    return -1;
  
  if (fwrite(content, 1, (size_t)count, f) < (size_t)count)
    return -1;
  
  return fclose(f);
}
Beispiel #6
0
int 
pocl_write_file(const char *path, const char* content,
                uint64_t    count,
                int         append,
                int         dont_rewrite) 
{
  assert(path);
  assert(content);
  
  if (pocl_exists(path)) 
    {
      if (dont_rewrite) 
        {
          if (!append)
            return 0;
        } 
      else 
        {
          int res = pocl_remove(path);
          if (res)
            {
              POCL_MSG_ERR ("pocl_remove(%s) failed\n", path);
              return res;
            }
        }
    }
  
  FILE *f;
  if (append)
    f = fopen(path, "a");
  else
    f = fopen(path, "w");

  if (f == NULL)
    {
      POCL_MSG_ERR ("fopen(%s) failed\n", path);
      return -1;
    }

  if (fwrite (content, 1, (size_t)count, f) < (size_t)count)
    {
      POCL_MSG_ERR ("fwrite(%s) failed\n", path);
      return -1;
    }

  if (fflush (f))
    {
      POCL_MSG_ERR ("fflush() failed\n");
      return errno;
    }

#ifdef HAVE_FDATASYNC
  if (fdatasync (fileno (f)))
    {
      POCL_MSG_ERR ("fdatasync() failed\n");
      return errno;
    }
#elif defined(HAVE_FSYNC)
  if (fsync (fileno (f)))
    {
      POCL_MSG_ERR ("fsync() failed\n");
      return errno;
    }
#endif

  return fclose(f);
}
Beispiel #7
0
/* creates either a program with binaries, or an empty program. The latter
 * is useful for clLinkProgram() which needs an empty program to put the
 * compiled results in.
 */
cl_program
create_program_skeleton (cl_context context, cl_uint num_devices,
                         const cl_device_id *device_list,
                         const size_t *lengths, const unsigned char **binaries,
                         cl_int *binary_status, cl_int *errcode_ret,
                         int allow_empty_binaries)
{
  cl_program program;
  unsigned i,j;
  int errcode, is_spirv_opencl;
  cl_device_id *unique_devlist = NULL;

  POCL_GOTO_ERROR_COND((context == NULL), CL_INVALID_CONTEXT);

  POCL_GOTO_ERROR_COND((device_list == NULL), CL_INVALID_VALUE);

  POCL_GOTO_ERROR_COND((num_devices == 0), CL_INVALID_VALUE);

  if (!allow_empty_binaries)
    {
      POCL_GOTO_ERROR_COND ((lengths == NULL), CL_INVALID_VALUE);

      for (i = 0; i < num_devices; ++i)
        {
          POCL_GOTO_ERROR_ON ((lengths[i] == 0 || binaries[i] == NULL),
                              CL_INVALID_VALUE,
                              "%i-th binary is NULL or its length==0\n", i);
        }
    }

  // check for duplicates in device_list[].
  for (i = 0; i < context->num_devices; i++)
    {
      int count = 0;
      for (j = 0; j < num_devices; j++)
        {
          count += context->devices[i] == device_list[j];
        }
      // duplicate devices
      POCL_GOTO_ERROR_ON((count > 1), CL_INVALID_DEVICE,
        "device %s specified multiple times\n", context->devices[i]->long_name);
    }

  // convert subdevices to devices and remove duplicates
  cl_uint real_num_devices = 0;
  unique_devlist = pocl_unique_device_list(device_list, num_devices, &real_num_devices);
  num_devices = real_num_devices;
  device_list = unique_devlist;

  // check for invalid devices in device_list[].
  for (i = 0; i < num_devices; i++)
    {
      int found = 0;
      for (j = 0; j < context->num_devices; j++)
        {
          found |= context->devices[j] == device_list[i];
        }
      POCL_GOTO_ERROR_ON((!found), CL_INVALID_DEVICE,
        "device not found in the device list of the context\n");
    }

  if ((program = (cl_program) calloc (1, sizeof (struct _cl_program))) == NULL)
    {
      errcode = CL_OUT_OF_HOST_MEMORY;
      goto ERROR;
    }
  
  POCL_INIT_OBJECT(program);

  if ((program->binary_sizes =
       (size_t*) calloc (num_devices, sizeof(size_t))) == NULL ||
      (program->binaries = (unsigned char**)
       calloc (num_devices, sizeof(unsigned char*))) == NULL ||
      (program->pocl_binaries = (unsigned char**)
       calloc (num_devices, sizeof(unsigned char*))) == NULL ||
      (program->pocl_binary_sizes =
             (size_t*) calloc (num_devices, sizeof(size_t))) == NULL ||
      (program->build_log = (char**)
       calloc (num_devices, sizeof(char*))) == NULL ||
      ((program->llvm_irs =
        (void**) calloc (num_devices, sizeof(void*))) == NULL) ||
      ((program->build_hash = (SHA1_digest_t*)
        calloc (num_devices, sizeof(SHA1_digest_t))) == NULL))
    {
      errcode = CL_OUT_OF_HOST_MEMORY;
      goto ERROR_CLEAN_PROGRAM_AND_BINARIES;
    }

  program->context = context;
  program->num_devices = num_devices;
  program->devices = unique_devlist;
  program->build_status = CL_BUILD_NONE;
  program->binary_type = CL_PROGRAM_BINARY_TYPE_NONE;
  char program_bc_path[POCL_FILENAME_LENGTH];

  if (allow_empty_binaries && (lengths == NULL) && (binaries == NULL))
    goto SUCCESS;

  for (i = 0; i < num_devices; ++i)
    {
      /* LLVM IR */
      if (!strncmp((const char *)binaries[i], "BC", 2))
        {
          program->binary_sizes[i] = lengths[i];
          program->binaries[i] = (unsigned char*) malloc(lengths[i]);
          memcpy (program->binaries[i], binaries[i], lengths[i]);
          if (binary_status != NULL)
            binary_status[i] = CL_SUCCESS;
        }
      /* SPIR-V binary needs to be converted, and requires
       * linking of the converted BC */
#ifdef OCS_AVAILABLE
      else if (bitcode_is_spirv ((const char *)binaries[i], lengths[i], &is_spirv_opencl))
        {
          if (is_spirv_opencl == 0) {
            // SPIR-V but not OpenCL-type.
            POCL_GOTO_ERROR_ON (
                1, CL_BUILD_PROGRAM_FAILURE,
                "SPIR-V binary provided, but is not using Kernel mode."
                "Pocl can't process this binary.\n");
          }

          int no_spir
              = strstr (device_list[i]->extensions, "cl_khr_spir") == NULL;
          POCL_GOTO_ERROR_ON (
              no_spir, CL_BUILD_PROGRAM_FAILURE,
              "SPIR binary provided, but device has no SPIR support");
#ifdef ENABLE_SPIRV
          POCL_MSG_PRINT_LLVM (
              "SPIR-V binary detected, converting to LLVM SPIR\n");
          char program_bc_spirv[POCL_FILENAME_LENGTH];
          char program_bc_temp[POCL_FILENAME_LENGTH];
          pocl_cache_write_spirv (program_bc_spirv, (const char *)binaries[i],
                                  (uint64_t)lengths[i]);
          pocl_cache_tempname (program_bc_temp, ".bc", NULL);

          char *args[] = { LLVM_SPIRV,       "-r", "-o", program_bc_temp,
                           program_bc_spirv, NULL };

          errcode = pocl_run_command (args);
          assert (errcode == 0);
          /* load LLVM SPIR binary. */
          uint64_t fsize;
          char *content;
          pocl_read_file (program_bc_temp, &content, &fsize);
          program->binary_sizes[i] = fsize;
          program->binaries[i] = (unsigned char *)content;
          pocl_remove (program_bc_temp);
#else
          POCL_GOTO_ERROR_ON (
              1, CL_BUILD_PROGRAM_FAILURE,
              "SPIR binary provided, but this pocl has no SPIR-V support."
              "SPIR-V support requires llvm-spirv converter binary.\n");
#endif
        }
#endif
      /* Poclcc binary */
      else if (pocl_binary_check_binary(device_list[i], binaries[i]))
        {
          program->pocl_binary_sizes[i] = lengths[i];
          program->pocl_binaries[i] = (unsigned char*) malloc (lengths[i]);
          memcpy (program->pocl_binaries[i], binaries[i], lengths[i]);

          pocl_binary_set_program_buildhash (program, i, binaries[i]);
          int error = pocl_cache_create_program_cachedir
            (program, i, NULL, 0, program_bc_path);
          POCL_GOTO_ERROR_ON((error != 0), CL_BUILD_PROGRAM_FAILURE,
                             "Could not create program cachedir");
          POCL_GOTO_ERROR_ON(pocl_binary_deserialize (program, i),
                             CL_INVALID_BINARY,
                             "Could not unpack a pocl binary\n");
          /* read program.bc, can be useful later */
          if (pocl_exists (program_bc_path))
            {
              pocl_read_file (program_bc_path,
                              (char **)(&program->binaries[i]),
                              (uint64_t *)(&program->binary_sizes[i]));
            }

          if (binary_status != NULL)
            binary_status[i] = CL_SUCCESS;
        }
      /* Unknown binary */
      else
        {
          POCL_MSG_WARN ("Could not recognize binary\n");
          if (binary_status != NULL)
            binary_status[i] = CL_INVALID_BINARY;
          errcode = CL_INVALID_BINARY;
          goto ERROR_CLEAN_PROGRAM_AND_BINARIES;
        }
    }

SUCCESS:
  POCL_RETAIN_OBJECT(context);

  if (errcode_ret != NULL)
    *errcode_ret = CL_SUCCESS;
  return program;

ERROR_CLEAN_PROGRAM_AND_BINARIES:
  if (program->binaries)
    for (i = 0; i < num_devices; ++i)
      POCL_MEM_FREE(program->binaries[i]);
  POCL_MEM_FREE(program->binaries);
  POCL_MEM_FREE(program->binary_sizes);
  if (program->pocl_binaries)
    for (i = 0; i < num_devices; ++i)
      POCL_MEM_FREE(program->pocl_binaries[i]);
  POCL_MEM_FREE(program->pocl_binaries);
  POCL_MEM_FREE(program->pocl_binary_sizes);
/*ERROR_CLEAN_PROGRAM:*/
  POCL_MEM_FREE(program);
ERROR:
  POCL_MEM_FREE(unique_devlist);
    if(errcode_ret != NULL)
      {
        *errcode_ret = errcode;
      }
    return NULL;
}