Blame ocl_icd_loader.c

Packit 6d72ef
/**
Packit 6d72ef
Copyright (c) 2012, Brice Videau <brice.videau@imag.fr>
Packit 6d72ef
Copyright (c) 2012, Vincent Danjean <Vincent.Danjean@ens-lyon.org>
Packit 6d72ef
All rights reserved.
Packit 6d72ef
Packit 6d72ef
Redistribution and use in source and binary forms, with or without
Packit 6d72ef
modification, are permitted provided that the following conditions are met:
Packit 6d72ef
Packit 6d72ef
1. Redistributions of source code must retain the above copyright notice, this
Packit 6d72ef
   list of conditions and the following disclaimer.
Packit 6d72ef
2. Redistributions in binary form must reproduce the above copyright notice,
Packit 6d72ef
   this list of conditions and the following disclaimer in the documentation
Packit 6d72ef
   and/or other materials provided with the distribution.
Packit 6d72ef
Packit 6d72ef
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
Packit 6d72ef
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
Packit 6d72ef
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
Packit 6d72ef
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
Packit 6d72ef
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
Packit 6d72ef
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
Packit 6d72ef
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
Packit 6d72ef
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
Packit 6d72ef
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
Packit 6d72ef
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Packit 6d72ef
*/
Packit 6d72ef
Packit 6d72ef
#include <dirent.h>
Packit 6d72ef
#include <stdio.h>
Packit 6d72ef
#include <stdlib.h>
Packit 6d72ef
#include <string.h>
Packit 6d72ef
#include <dlfcn.h>
Packit 6d72ef
#include <sys/types.h>
Packit 6d72ef
#include <sys/stat.h>
Packit 6d72ef
#include <fcntl.h>
Packit 6d72ef
#include <errno.h>
Packit 6d72ef
#include "config.h"
Packit 6d72ef
#ifdef USE_PTHREAD
Packit 6d72ef
#  include <pthread.h>
Packit 6d72ef
#endif
Packit 6d72ef
#pragma GCC diagnostic push
Packit 6d72ef
#  pragma GCC diagnostic ignored "-Wcpp"
Packit 6d72ef
#  define CL_USE_DEPRECATED_OPENCL_1_1_APIS
Packit 6d72ef
#  include <CL/opencl.h>
Packit 6d72ef
#pragma GCC diagnostic pop
Packit 6d72ef
Packit 6d72ef
#pragma GCC visibility push(hidden)
Packit 6d72ef
Packit 6d72ef
#include "ocl_icd_loader.h"
Packit 6d72ef
#define DEBUG_OCL_ICD_PROVIDE_DUMP_FIELD
Packit 6d72ef
#include "ocl_icd_debug.h"
Packit 6d72ef
Packit 6d72ef
int debug_ocl_icd_mask=0;
Packit 6d72ef
Packit 6d72ef
typedef __typeof__(clGetPlatformInfo) *clGetPlatformInfo_fn;
Packit 6d72ef
Packit 6d72ef
inline void dump_vendor_icd(const char* info, const struct vendor_icd *v) {
Packit 6d72ef
  debug(D_DUMP, "%s %p={ num=%i, handle=%p, f=%p}\n", info,
Packit 6d72ef
	v, v->num_platforms, v->dl_handle, v->ext_fn_ptr);
Packit 6d72ef
}
Packit 6d72ef
Packit 6d72ef
struct vendor_icd *_icds=NULL;
Packit 6d72ef
struct platform_icd *_picds=NULL;
Packit 6d72ef
static cl_uint _num_icds = 0;
Packit 6d72ef
cl_uint _num_picds = 0;
Packit 6d72ef
Packit 6d72ef
#ifdef DEBUG_OCL_ICD
Packit 6d72ef
#  define _clS(x) [-x] = #x
Packit 6d72ef
#  define MAX_CL_ERRORS (-CL_INVALID_DEVICE_PARTITION_COUNT)
Packit 6d72ef
static char const * const clErrorStr[MAX_CL_ERRORS+1] = {
Packit 6d72ef
  _clS(CL_SUCCESS),
Packit 6d72ef
  _clS(CL_DEVICE_NOT_FOUND),
Packit 6d72ef
  _clS(CL_DEVICE_NOT_AVAILABLE),
Packit 6d72ef
  _clS(CL_COMPILER_NOT_AVAILABLE),
Packit 6d72ef
  _clS(CL_MEM_OBJECT_ALLOCATION_FAILURE),
Packit 6d72ef
  _clS(CL_OUT_OF_RESOURCES),
Packit 6d72ef
  _clS(CL_OUT_OF_HOST_MEMORY),
Packit 6d72ef
  _clS(CL_PROFILING_INFO_NOT_AVAILABLE),
Packit 6d72ef
  _clS(CL_MEM_COPY_OVERLAP),
Packit 6d72ef
  _clS(CL_IMAGE_FORMAT_MISMATCH),
Packit 6d72ef
  _clS(CL_IMAGE_FORMAT_NOT_SUPPORTED),
Packit 6d72ef
  _clS(CL_BUILD_PROGRAM_FAILURE),
Packit 6d72ef
  _clS(CL_MAP_FAILURE),
Packit 6d72ef
  _clS(CL_MISALIGNED_SUB_BUFFER_OFFSET),
Packit 6d72ef
  _clS(CL_EXEC_STATUS_ERROR_FOR_EVENTS_IN_WAIT_LIST),
Packit 6d72ef
  _clS(CL_COMPILE_PROGRAM_FAILURE),
Packit 6d72ef
  _clS(CL_LINKER_NOT_AVAILABLE),
Packit 6d72ef
  _clS(CL_LINK_PROGRAM_FAILURE),
Packit 6d72ef
  _clS(CL_DEVICE_PARTITION_FAILED),
Packit 6d72ef
  _clS(CL_KERNEL_ARG_INFO_NOT_AVAILABLE),
Packit 6d72ef
  _clS(CL_INVALID_VALUE),
Packit 6d72ef
  _clS(CL_INVALID_DEVICE_TYPE),
Packit 6d72ef
  _clS(CL_INVALID_PLATFORM),
Packit 6d72ef
  _clS(CL_INVALID_DEVICE),
Packit 6d72ef
  _clS(CL_INVALID_CONTEXT),
Packit 6d72ef
  _clS(CL_INVALID_QUEUE_PROPERTIES),
Packit 6d72ef
  _clS(CL_INVALID_COMMAND_QUEUE),
Packit 6d72ef
  _clS(CL_INVALID_HOST_PTR),
Packit 6d72ef
  _clS(CL_INVALID_MEM_OBJECT),
Packit 6d72ef
  _clS(CL_INVALID_IMAGE_FORMAT_DESCRIPTOR),
Packit 6d72ef
  _clS(CL_INVALID_IMAGE_SIZE),
Packit 6d72ef
  _clS(CL_INVALID_SAMPLER),
Packit 6d72ef
  _clS(CL_INVALID_BINARY),
Packit 6d72ef
  _clS(CL_INVALID_BUILD_OPTIONS),
Packit 6d72ef
  _clS(CL_INVALID_PROGRAM),
Packit 6d72ef
  _clS(CL_INVALID_PROGRAM_EXECUTABLE),
Packit 6d72ef
  _clS(CL_INVALID_KERNEL_NAME),
Packit 6d72ef
  _clS(CL_INVALID_KERNEL_DEFINITION),
Packit 6d72ef
  _clS(CL_INVALID_KERNEL),
Packit 6d72ef
  _clS(CL_INVALID_ARG_INDEX),
Packit 6d72ef
  _clS(CL_INVALID_ARG_VALUE),
Packit 6d72ef
  _clS(CL_INVALID_ARG_SIZE),
Packit 6d72ef
  _clS(CL_INVALID_KERNEL_ARGS),
Packit 6d72ef
  _clS(CL_INVALID_WORK_DIMENSION),
Packit 6d72ef
  _clS(CL_INVALID_WORK_GROUP_SIZE),
Packit 6d72ef
  _clS(CL_INVALID_WORK_ITEM_SIZE),
Packit 6d72ef
  _clS(CL_INVALID_GLOBAL_OFFSET),
Packit 6d72ef
  _clS(CL_INVALID_EVENT_WAIT_LIST),
Packit 6d72ef
  _clS(CL_INVALID_EVENT),
Packit 6d72ef
  _clS(CL_INVALID_OPERATION),
Packit 6d72ef
  _clS(CL_INVALID_GL_OBJECT),
Packit 6d72ef
  _clS(CL_INVALID_BUFFER_SIZE),
Packit 6d72ef
  _clS(CL_INVALID_MIP_LEVEL),
Packit 6d72ef
  _clS(CL_INVALID_GLOBAL_WORK_SIZE),
Packit 6d72ef
  _clS(CL_INVALID_PROPERTY),
Packit 6d72ef
  _clS(CL_INVALID_IMAGE_DESCRIPTOR),
Packit 6d72ef
  _clS(CL_INVALID_COMPILER_OPTIONS),
Packit 6d72ef
  _clS(CL_INVALID_LINKER_OPTIONS),
Packit 6d72ef
  _clS(CL_INVALID_DEVICE_PARTITION_COUNT)
Packit 6d72ef
};
Packit 6d72ef
#undef _clS
Packit 6d72ef
#endif
Packit 6d72ef
Packit 6d72ef
static char* _clerror2string (cl_int error) __attribute__((unused));
Packit 6d72ef
static char* _clerror2string (cl_int error) {
Packit 6d72ef
#ifdef DEBUG_OCL_ICD
Packit 6d72ef
  if (-error > MAX_CL_ERRORS || error > 0) {
Packit 6d72ef
    debug(D_WARN, "Unknown error code %d", error);
Packit 6d72ef
    RETURN_STR("OpenCL Error");
Packit 6d72ef
  }
Packit 6d72ef
  const char *ret=clErrorStr[-error];
Packit 6d72ef
  if (ret == NULL) {
Packit 6d72ef
    debug(D_WARN, "Unknown error code %d", error);
Packit 6d72ef
    RETURN_STR("OpenCL Error");
Packit 6d72ef
  }
Packit 6d72ef
  RETURN_STR(ret);
Packit 6d72ef
#else
Packit 6d72ef
  static char number[15];
Packit 6d72ef
  if (error==0) {
Packit 6d72ef
    RETURN_STR("CL_SUCCESS");
Packit 6d72ef
  }
Packit 6d72ef
  snprintf(number, 15, "%i", error);
Packit 6d72ef
  RETURN_STR(number);
Packit 6d72ef
#endif
Packit 6d72ef
}
Packit 6d72ef
Packit 6d72ef
static inline int _string_end_with_icd(const char* str) {
Packit 6d72ef
  size_t len = strlen(str);
Packit 6d72ef
  if( len<5 || strcmp(str + len - 4, ".icd" ) != 0 ) {
Packit 6d72ef
    return 0;
Packit 6d72ef
  }
Packit 6d72ef
  return 1;
Packit 6d72ef
}
Packit 6d72ef
Packit 6d72ef
static inline int _string_with_slash(const char* str) {
Packit 6d72ef
  return strchr(str, '/') != NULL;
Packit 6d72ef
}
Packit 6d72ef
Packit 6d72ef
static inline unsigned int _find_num_icds(DIR *dir) {
Packit 6d72ef
  unsigned int num_icds = 0;
Packit 6d72ef
  struct dirent *ent;
Packit 6d72ef
  while( (ent=readdir(dir)) != NULL ){
Packit 6d72ef
    if (_string_end_with_icd(ent->d_name)) {
Packit 6d72ef
      num_icds++;
Packit 6d72ef
    }
Packit 6d72ef
  }
Packit 6d72ef
  rewinddir(dir);
Packit 6d72ef
  RETURN(num_icds);
Packit 6d72ef
}
Packit 6d72ef
Packit 6d72ef
static inline unsigned int _load_icd(int num_icds, const char* lib_path) {
Packit 6d72ef
  unsigned int ret=0;
Packit 6d72ef
  debug(D_LOG, "Loading ICD '%s'", lib_path);
Packit 6d72ef
Packit 6d72ef
  _icds[num_icds].dl_handle = dlopen(lib_path, RTLD_LAZY|RTLD_LOCAL);//|RTLD_DEEPBIND);
Packit 6d72ef
  if(_icds[num_icds].dl_handle != NULL) {
Packit 6d72ef
    debug(D_LOG, "ICD[%i] loaded", num_icds);
Packit 6d72ef
    ret=1;
Packit 6d72ef
  } else {
Packit 6d72ef
    debug(D_WARN, "error while dlopening the IDL: '%s',\n  => skipping ICD", dlerror());
Packit 6d72ef
  }
Packit 6d72ef
  return ret;
Packit 6d72ef
}
Packit 6d72ef
Packit 6d72ef
static inline unsigned int _open_driver(unsigned int num_icds,
Packit 6d72ef
					const char*dir_path, const char*file_path) {
Packit 6d72ef
  char * lib_path;
Packit 6d72ef
  char * err;
Packit 6d72ef
  unsigned int lib_path_length;
Packit 6d72ef
  if (dir_path != NULL) {
Packit 6d72ef
    lib_path_length = strlen(dir_path) + strlen(file_path) + 2;
Packit 6d72ef
    lib_path = malloc(lib_path_length*sizeof(char));
Packit 6d72ef
    sprintf(lib_path,"%s/%s", dir_path, file_path);
Packit 6d72ef
  } else {
Packit 6d72ef
    lib_path_length = strlen(file_path) + 1;
Packit 6d72ef
    lib_path = malloc(lib_path_length*sizeof(char));
Packit 6d72ef
    sprintf(lib_path,"%s", file_path);
Packit 6d72ef
  }
Packit 6d72ef
  debug(D_LOG, "Considering file '%s'", lib_path);
Packit 6d72ef
  FILE *f = fopen(lib_path,"r");
Packit 6d72ef
  free(lib_path);
Packit 6d72ef
  if (f==NULL) {
Packit 6d72ef
    RETURN(num_icds);
Packit 6d72ef
  }
Packit 6d72ef
Packit 6d72ef
  fseek(f, 0, SEEK_END);
Packit 6d72ef
  lib_path_length = ftell(f)+1;
Packit 6d72ef
  fseek(f, 0, SEEK_SET);
Packit 6d72ef
  if(lib_path_length == 1) {
Packit 6d72ef
    debug(D_WARN, "File contents too short, skipping ICD");
Packit 6d72ef
    fclose(f);
Packit 6d72ef
    RETURN(num_icds);
Packit 6d72ef
  }
Packit 6d72ef
  lib_path = malloc(lib_path_length*sizeof(char));
Packit 6d72ef
  err = fgets(lib_path, lib_path_length, f);
Packit 6d72ef
  fclose(f);
Packit 6d72ef
  if( err == NULL ) {
Packit 6d72ef
    free(lib_path);
Packit 6d72ef
    debug(D_WARN, "Error while loading file contents, skipping ICD");
Packit 6d72ef
    RETURN(num_icds);
Packit 6d72ef
  }
Packit 6d72ef
Packit 6d72ef
  lib_path_length = strnlen(lib_path, lib_path_length);
Packit 6d72ef
Packit 6d72ef
  if( lib_path[lib_path_length-1] == '\n' )
Packit 6d72ef
    lib_path[lib_path_length-1] = '\0';
Packit 6d72ef
Packit 6d72ef
  num_icds += _load_icd(num_icds, lib_path);
Packit 6d72ef
Packit 6d72ef
  free(lib_path);
Packit 6d72ef
  RETURN(num_icds);
Packit 6d72ef
}
Packit 6d72ef
Packit 6d72ef
static inline unsigned int _open_drivers(DIR *dir, const char* dir_path) {
Packit 6d72ef
  unsigned int num_icds = 0;
Packit 6d72ef
  struct dirent *ent;
Packit 6d72ef
  while( (ent=readdir(dir)) != NULL ){
Packit 6d72ef
    if(! _string_end_with_icd(ent->d_name)) {
Packit 6d72ef
      continue;
Packit 6d72ef
    }
Packit 6d72ef
    num_icds = _open_driver(num_icds, dir_path, ent->d_name);
Packit 6d72ef
Packit 6d72ef
  }
Packit 6d72ef
  RETURN(num_icds);
Packit 6d72ef
}
Packit 6d72ef
Packit 6d72ef
static void* _get_function_addr(void* dlh, clGetExtensionFunctionAddress_fn fn, const char*name) {
Packit 6d72ef
  void *addr1;
Packit 6d72ef
  debug(D_LOG,"Looking for function %s",name);
Packit 6d72ef
  addr1=dlsym(dlh, name);
Packit 6d72ef
  if (addr1 == NULL) {
Packit 6d72ef
    debug(D_WARN, "Missing global symbol '%s' in ICD, should be skipped", name);
Packit 6d72ef
  }
Packit 6d72ef
  void* addr2=NULL;
Packit 6d72ef
  if (fn) {
Packit 6d72ef
    addr2=(*fn)(name);
Packit 6d72ef
    if (addr2 == NULL) {
Packit 6d72ef
      debug(D_WARN, "Missing function '%s' in ICD, should be skipped", name);
Packit 6d72ef
    }
Packit 6d72ef
#ifdef DEBUG_OCL_ICD
Packit 6d72ef
    if (addr1 && addr2 && addr1!=addr2) {
Packit 6d72ef
      debug(D_WARN, "Function and symbol '%s' have different addresses (%p != %p)!", name, addr2, addr1);
Packit 6d72ef
    }
Packit 6d72ef
#endif
Packit 6d72ef
  }
Packit 6d72ef
  if (!addr2) addr2=addr1;
Packit 6d72ef
  RETURN(addr2);
Packit 6d72ef
}
Packit 6d72ef
Packit 6d72ef
static int _allocate_platforms(int req) {
Packit 6d72ef
  static cl_uint allocated=0;
Packit 6d72ef
  debug(D_LOG,"Requesting allocation for %d platforms",req);
Packit 6d72ef
  if (allocated - _num_picds < req) {
Packit 6d72ef
    if (allocated==0) {
Packit 6d72ef
      _picds=(struct platform_icd*)malloc(req*sizeof(struct platform_icd));
Packit 6d72ef
    } else {
Packit 6d72ef
      req = req - (allocated - _num_picds);
Packit 6d72ef
      _picds=(struct platform_icd*)realloc(_picds, (allocated+req)*sizeof(struct platform_icd));
Packit 6d72ef
    }
Packit 6d72ef
    allocated += req;
Packit 6d72ef
  }
Packit 6d72ef
  RETURN(allocated - _num_picds);
Packit 6d72ef
}
Packit 6d72ef
Packit 6d72ef
static char* _malloc_clGetPlatformInfo(clGetPlatformInfo_fn plt_info_ptr,
Packit 6d72ef
		 cl_platform_id pid, cl_platform_info cname, char* sname) {
Packit 6d72ef
  cl_int error;
Packit 6d72ef
  size_t param_value_size_ret;
Packit 6d72ef
  error = plt_info_ptr(pid, cname, 0, NULL, &param_value_size_ret);
Packit 6d72ef
  if (error != CL_SUCCESS) {
Packit 6d72ef
    debug(D_WARN, "Error %s while requesting %s in platform %p",
Packit 6d72ef
	  _clerror2string(error), sname, pid);
Packit 6d72ef
    return NULL;
Packit 6d72ef
  }
Packit 6d72ef
  char *param_value = (char *)malloc(sizeof(char)*param_value_size_ret);
Packit 6d72ef
  if (param_value == NULL) {
Packit 6d72ef
    debug(D_WARN, "Error in malloc while requesting %s in platform %p",
Packit 6d72ef
	  sname, pid);
Packit 6d72ef
    return NULL;
Packit 6d72ef
  }
Packit 6d72ef
  error = plt_info_ptr(pid, cname, param_value_size_ret, param_value, NULL);
Packit 6d72ef
  if (error != CL_SUCCESS){
Packit 6d72ef
    free(param_value);
Packit 6d72ef
    debug(D_WARN, "Error %s while requesting %s in platform %p",
Packit 6d72ef
	  _clerror2string(error), sname, pid);
Packit 6d72ef
    return NULL;
Packit 6d72ef
  }
Packit 6d72ef
  RETURN_STR(param_value);
Packit 6d72ef
}
Packit 6d72ef
Packit 6d72ef
static void _count_devices(struct platform_icd *p) {
Packit 6d72ef
  cl_int error;
Packit 6d72ef
Packit 6d72ef
  /* Ensure they are 0 in case of errors */
Packit 6d72ef
  p->ngpus = p->ncpus = p->ndevs = 0;
Packit 6d72ef
Packit 6d72ef
  error = clGetDeviceIDs(p->pid, CL_DEVICE_TYPE_GPU, 0, NULL, &(p->ngpus));
Packit 6d72ef
  if (error != CL_SUCCESS && error != CL_DEVICE_NOT_FOUND){
Packit 6d72ef
    debug(D_WARN, "Error %s while counting GPU devices in platform %p",
Packit 6d72ef
	  _clerror2string(error), p->pid);
Packit 6d72ef
  }
Packit 6d72ef
Packit 6d72ef
  error = clGetDeviceIDs(p->pid, CL_DEVICE_TYPE_CPU, 0, NULL, &(p->ncpus));
Packit 6d72ef
  if (error != CL_SUCCESS && error != CL_DEVICE_NOT_FOUND){
Packit 6d72ef
    debug(D_WARN, "Error %s while counting CPU devices in platform %p",
Packit 6d72ef
	  _clerror2string(error), p->pid);
Packit 6d72ef
  }
Packit 6d72ef
Packit 6d72ef
  error = clGetDeviceIDs(p->pid, CL_DEVICE_TYPE_ALL, 0, NULL, &(p->ndevs));
Packit 6d72ef
  if (error != CL_SUCCESS && error != CL_DEVICE_NOT_FOUND){
Packit 6d72ef
    debug(D_WARN, "Error %s while counting ALL devices in platform %p",
Packit 6d72ef
	  _clerror2string(error), p->pid);
Packit 6d72ef
  }
Packit 6d72ef
Packit 6d72ef
}
Packit 6d72ef
Packit 6d72ef
static int _cmp_platforms(const void *_a, const void *_b) {
Packit 6d72ef
	const struct platform_icd *a=(const struct platform_icd *)_a;
Packit 6d72ef
	const struct platform_icd *b=(const struct platform_icd *)_b;
Packit 6d72ef
Packit 6d72ef
	/* sort first platforms handling max gpu */
Packit 6d72ef
	if (a->ngpus > b->ngpus) return -1;
Packit 6d72ef
	if (a->ngpus < b->ngpus) return 1;
Packit 6d72ef
	/* sort next platforms handling max cpu */
Packit 6d72ef
	if (a->ncpus > b->ncpus) return -1;
Packit 6d72ef
	if (a->ncpus < b->ncpus) return 1;
Packit 6d72ef
	/* sort then platforms handling max devices */
Packit 6d72ef
	if (a->ndevs > b->ndevs) return -1;
Packit 6d72ef
	if (a->ndevs < b->ndevs) return 1;
Packit 6d72ef
	/* else consider platforms equal */
Packit 6d72ef
	return 0;
Packit 6d72ef
}
Packit 6d72ef
Packit 6d72ef
static void _sort_platforms(struct platform_icd *picds, int npicds) {
Packit 6d72ef
	debug(D_WARN, "Nb platefroms: %i", npicds);
Packit 6d72ef
	if (npicds > 1) {
Packit 6d72ef
		char* ocl_sort=getenv("OCL_ICD_PLATFORM_SORT");
Packit 6d72ef
		if (ocl_sort!=NULL && !strcmp(ocl_sort, "none")) {
Packit 6d72ef
			debug(D_LOG, "Platform not sorted");
Packit 6d72ef
		} else {
Packit 6d72ef
			if (ocl_sort!=NULL && strcmp(ocl_sort, "devices")) {
Packit 6d72ef
				debug(D_WARN, "Unknown platform sort algorithm requested: %s", ocl_sort);
Packit 6d72ef
				debug(D_WARN, "Switching do the 'devices' algorithm");
Packit 6d72ef
			}
Packit 6d72ef
			int i;
Packit 6d72ef
			debug(D_LOG, "Platform sorted by GPU, CPU, DEV");
Packit 6d72ef
			for (i=0; i
Packit 6d72ef
				_count_devices(&picds[i]);
Packit 6d72ef
			}
Packit 6d72ef
			qsort(picds, npicds, sizeof(*picds),
Packit 6d72ef
			      &_cmp_platforms);
Packit 6d72ef
		}
Packit 6d72ef
	}
Packit 6d72ef
}
Packit 6d72ef
Packit 6d72ef
#define ASSUME_ICD_EXTENSION_UNKNOWN ((int)-1)
Packit 6d72ef
#define ASSUME_ICD_EXTENSION_NO ((int)0)
Packit 6d72ef
#define ASSUME_ICD_EXTENSION_YES ((int)1)
Packit 6d72ef
#define ASSUME_ICD_EXTENSION_YES_AND_QUIET ((int)2)
Packit 6d72ef
Packit 6d72ef
Packit 6d72ef
static int _assume_ICD_extension() {
Packit 6d72ef
	static int val=ASSUME_ICD_EXTENSION_UNKNOWN;
Packit 6d72ef
	if (val == ASSUME_ICD_EXTENSION_UNKNOWN) {
Packit 6d72ef
		const char* str=getenv("OCL_ICD_ASSUME_ICD_EXTENSION");
Packit 6d72ef
		if (! str || str[0]==0) {
Packit 6d72ef
			val=ASSUME_ICD_EXTENSION_NO;
Packit 6d72ef
		} else if (strcmp(str, "debug")==0) {
Packit 6d72ef
			val=ASSUME_ICD_EXTENSION_YES;
Packit 6d72ef
		} else {
Packit 6d72ef
			val=ASSUME_ICD_EXTENSION_YES_AND_QUIET;
Packit 6d72ef
		}
Packit 6d72ef
	}
Packit 6d72ef
	return val;
Packit 6d72ef
}
Packit 6d72ef
Packit 6d72ef
static inline void _find_and_check_platforms(cl_uint num_icds) {
Packit 6d72ef
  cl_uint i;
Packit 6d72ef
  _num_icds = 0;
Packit 6d72ef
  for( i=0; i
Packit 6d72ef
    debug(D_LOG, "Checking ICD %i/%i", i, num_icds);
Packit 6d72ef
    dump_vendor_icd("before looking for platforms", &_icds[i]);
Packit 6d72ef
    struct vendor_icd *picd = &_icds[i];
Packit 6d72ef
    void* dlh = _icds[i].dl_handle;
Packit 6d72ef
    picd->ext_fn_ptr = _get_function_addr(dlh, NULL, "clGetExtensionFunctionAddress");
Packit 6d72ef
    clIcdGetPlatformIDsKHR_fn plt_fn_ptr =
Packit 6d72ef
      _get_function_addr(dlh, picd->ext_fn_ptr, "clIcdGetPlatformIDsKHR");
Packit 6d72ef
    if( picd->ext_fn_ptr == NULL
Packit 6d72ef
       || plt_fn_ptr == NULL) {
Packit 6d72ef
      debug(D_WARN, "Missing symbols in ICD, skipping it");
Packit 6d72ef
      continue;
Packit 6d72ef
    }
Packit 6d72ef
    clGetPlatformInfo_fn plt_info_ptr =
Packit 6d72ef
      _get_function_addr(dlh, picd->ext_fn_ptr,	"clGetPlatformInfo");
Packit 6d72ef
    if (plt_info_ptr == NULL) {
Packit 6d72ef
	    switch (_assume_ICD_extension()) {
Packit 6d72ef
	    case ASSUME_ICD_EXTENSION_NO:
Packit 6d72ef
		    debug(D_WARN, "Missing 'clGetPlatformInfo' symbol in ICD, skipping it (use OCL_ICD_ASSUME_ICD_EXTENSION to ignore this check)");
Packit 6d72ef
		    continue;
Packit 6d72ef
	    case ASSUME_ICD_EXTENSION_YES:
Packit 6d72ef
		    debug(D_LOG, "Missing 'clGetPlatformInfo' symbol in ICD, but still continuing due to OCL_ICD_ASSUME_ICD_EXTENSION");
Packit 6d72ef
		    /* Fall through */
Packit 6d72ef
	    case ASSUME_ICD_EXTENSION_YES_AND_QUIET:
Packit 6d72ef
		    /* Assuming an ICD extension, so we will try to
Packit 6d72ef
		     * find the ICD specific version of
Packit 6d72ef
		     * clGetPlatformInfo before knowing for sure that
Packit 6d72ef
		     * the cl_khr_icd is really present */
Packit 6d72ef
		    break;
Packit 6d72ef
	    default:
Packit 6d72ef
		    debug(D_ALWAYS, "Internal error in _assume_ICD_extension, please report");
Packit 6d72ef
		    break;
Packit 6d72ef
	    }
Packit 6d72ef
    }
Packit 6d72ef
    cl_uint num_platforms=0;
Packit 6d72ef
    cl_int error;
Packit 6d72ef
    error = (*plt_fn_ptr)(0, NULL, &num_platforms);
Packit 6d72ef
    if( error != CL_SUCCESS || num_platforms == 0) {
Packit 6d72ef
      debug(D_LOG, "No platform in ICD, skipping it");
Packit 6d72ef
      continue;
Packit 6d72ef
    }
Packit 6d72ef
    cl_platform_id *platforms = (cl_platform_id *) malloc( sizeof(cl_platform_id) * num_platforms);
Packit 6d72ef
    error = (*plt_fn_ptr)(num_platforms, platforms, NULL);
Packit 6d72ef
    if( error != CL_SUCCESS ){
Packit 6d72ef
      free(platforms);
Packit 6d72ef
      debug(D_WARN, "Error in loading ICD platforms, skipping ICD");
Packit 6d72ef
      continue;
Packit 6d72ef
    }
Packit 6d72ef
    cl_uint num_valid_platforms=0;
Packit 6d72ef
    cl_uint j;
Packit 6d72ef
    debug(D_LOG, "Try to load %d platforms", num_platforms);
Packit 6d72ef
    if (_allocate_platforms(num_platforms) < num_platforms) {
Packit 6d72ef
      free(platforms);
Packit 6d72ef
      debug(D_WARN, "Not enough platform allocated. Skipping ICD");
Packit 6d72ef
      continue;
Packit 6d72ef
    }
Packit 6d72ef
    for(j=0; j
Packit 6d72ef
      debug(D_LOG, "Checking platform %i", j);
Packit 6d72ef
      struct platform_icd *p=&_picds[_num_picds];
Packit 6d72ef
      char *param_value=NULL;
Packit 6d72ef
      p->extension_suffix=NULL;
Packit 6d72ef
      p->vicd=&_icds[i];
Packit 6d72ef
      p->pid=platforms[j];
Packit 6d72ef
Packit 6d72ef
      /* If clGetPlatformInfo is not exported and we are here, it
Packit 6d72ef
       * means that OCL_ICD_ASSUME_ICD_EXTENSION. Si we try to take it
Packit 6d72ef
       * from the dispatch * table. If that fails too, we have to
Packit 6d72ef
       * bail.
Packit 6d72ef
       */
Packit 6d72ef
      if (plt_info_ptr == NULL) {
Packit 6d72ef
        plt_info_ptr = p->pid->dispatch->clGetPlatformInfo;
Packit 6d72ef
        if (plt_info_ptr == NULL) {
Packit 6d72ef
          debug(D_WARN, "Missing clGetPlatformInfo even in ICD dispatch table, skipping it");
Packit 6d72ef
          continue;
Packit 6d72ef
        }
Packit 6d72ef
      }
Packit 6d72ef
Packit 6d72ef
#ifdef DEBUG_OCL_ICD
Packit 6d72ef
      if (debug_ocl_icd_mask & D_DUMP) {
Packit 6d72ef
        int log=debug_ocl_icd_mask & D_TRACE;
Packit 6d72ef
        debug_ocl_icd_mask &= ~D_TRACE;
Packit 6d72ef
	dump_platform(p->vicd->ext_fn_ptr, p->pid);
Packit 6d72ef
        debug_ocl_icd_mask |= log;
Packit 6d72ef
      }
Packit 6d72ef
#endif
Packit 6d72ef
      {
Packit 6d72ef
	      switch (_assume_ICD_extension()) {
Packit 6d72ef
	      case ASSUME_ICD_EXTENSION_NO:
Packit 6d72ef
		      /* checking the extension as required by the specs */
Packit 6d72ef
		      param_value=_malloc_clGetPlatformInfo(plt_info_ptr, p->pid, CL_PLATFORM_EXTENSIONS, "extensions");
Packit 6d72ef
		      if (param_value == NULL){
Packit 6d72ef
			      debug(D_WARN, "Skipping platform %i", j);
Packit 6d72ef
			      continue;
Packit 6d72ef
		      }
Packit 6d72ef
		      debug(D_DUMP, "Supported extensions: %s", param_value);
Packit 6d72ef
		      if( strstr(param_value, "cl_khr_icd") == NULL){
Packit 6d72ef
			      free(param_value);
Packit 6d72ef
			      debug(D_WARN, "Missing khr extension in platform %i, skipping it", j);
Packit 6d72ef
			      continue;
Packit 6d72ef
		      }
Packit 6d72ef
		      free(param_value);
Packit 6d72ef
		      break;
Packit 6d72ef
	      case ASSUME_ICD_EXTENSION_YES:
Packit 6d72ef
		      /* Allow to workaround a bug in the Intel ICD used
Packit 6d72ef
		       * with optirun :
Packit 6d72ef
		       * - https://software.intel.com/en-us/forums/opencl/topic/328091
Packit 6d72ef
		       * - https://sourceforge.net/p/virtualgl/bugs/54/
Packit 6d72ef
		       */
Packit 6d72ef
		      debug(D_LOG, "Assuming cl_khr_icd extension without checking for it");
Packit 6d72ef
		      /* Fall through */
Packit 6d72ef
	      case ASSUME_ICD_EXTENSION_YES_AND_QUIET:
Packit 6d72ef
		      /* Assuming an ICD extension, so we will try to
Packit 6d72ef
		       * find the ICD specific version of
Packit 6d72ef
		       * clGetPlatformInfo before knowing for sure that
Packit 6d72ef
		       * the cl_khr_icd is really present */
Packit 6d72ef
		      break;
Packit 6d72ef
	      default:
Packit 6d72ef
		      debug(D_ALWAYS, "Internal error in _assume_ICD_extension, please report");
Packit 6d72ef
		      break;
Packit 6d72ef
	      }
Packit 6d72ef
      }
Packit 6d72ef
      param_value=_malloc_clGetPlatformInfo(plt_info_ptr, p->pid, CL_PLATFORM_ICD_SUFFIX_KHR, "suffix");
Packit 6d72ef
      if (param_value == NULL){
Packit 6d72ef
	debug(D_WARN, "Skipping platform %i", j);
Packit 6d72ef
        continue;
Packit 6d72ef
      }
Packit 6d72ef
      p->extension_suffix = param_value;
Packit 6d72ef
      debug(D_DUMP|D_LOG, "Extension suffix: %s", param_value);
Packit 6d72ef
#ifdef DEBUG_OCL_ICD
Packit 6d72ef
      param_value=_malloc_clGetPlatformInfo(plt_info_ptr, p->pid, CL_PLATFORM_PROFILE, "profile");
Packit 6d72ef
      if (param_value != NULL){
Packit 6d72ef
        debug(D_DUMP, "Profile: %s", param_value);
Packit 6d72ef
	free(param_value);
Packit 6d72ef
      }
Packit 6d72ef
      param_value=_malloc_clGetPlatformInfo(plt_info_ptr, p->pid, CL_PLATFORM_VERSION, "version");
Packit 6d72ef
      p->version = param_value;
Packit 6d72ef
      if (param_value != NULL){
Packit 6d72ef
        debug(D_DUMP, "Version: %s", param_value);
Packit 6d72ef
	free(param_value);
Packit 6d72ef
      }
Packit 6d72ef
      param_value=_malloc_clGetPlatformInfo(plt_info_ptr, p->pid, CL_PLATFORM_NAME, "name");
Packit 6d72ef
      if (param_value != NULL){
Packit 6d72ef
        debug(D_DUMP, "Name: %s", param_value);
Packit 6d72ef
	free(param_value);
Packit 6d72ef
      }
Packit 6d72ef
      param_value=_malloc_clGetPlatformInfo(plt_info_ptr, p->pid, CL_PLATFORM_VENDOR, "vendor");
Packit 6d72ef
      if (param_value != NULL){
Packit 6d72ef
        debug(D_DUMP, "Vendor: %s", param_value);
Packit 6d72ef
	free(param_value);
Packit 6d72ef
      }
Packit 6d72ef
#endif
Packit 6d72ef
      num_valid_platforms++;
Packit 6d72ef
      _num_picds++;
Packit 6d72ef
    }
Packit 6d72ef
    if( num_valid_platforms != 0 ) {
Packit 6d72ef
      if ( _num_icds != i ) {
Packit 6d72ef
        picd->dl_handle = dlh;
Packit 6d72ef
      }
Packit 6d72ef
      dump_vendor_icd("after looking for platforms", &_icds[_num_icds]);
Packit 6d72ef
      _num_icds++;
Packit 6d72ef
      picd->num_platforms = num_valid_platforms;
Packit 6d72ef
    } else {
Packit 6d72ef
      dlclose(dlh);
Packit 6d72ef
    }
Packit 6d72ef
    free(platforms);
Packit 6d72ef
  }
Packit 6d72ef
  _sort_platforms(&_picds[0], _num_picds);
Packit 6d72ef
}
Packit 6d72ef
Packit 6d72ef
static void __initClIcd( void ) {
Packit 6d72ef
  debug_init();
Packit 6d72ef
  cl_uint num_icds = 0;
Packit 6d72ef
  int is_dir = 0;
Packit 6d72ef
  DIR *dir = NULL;
Packit 6d72ef
  const char* dir_path=getenv("OCL_ICD_VENDORS");
Packit 6d72ef
  const char* vendor_path=getenv("OPENCL_VENDOR_PATH");
Packit 6d72ef
  if (! vendor_path || vendor_path[0]==0) {
Packit 6d72ef
    vendor_path=ETC_OPENCL_VENDORS;
Packit 6d72ef
    debug(D_DUMP, "OPENCL_VENDOR_PATH unset or empty. Using hard-coded path '%s'", vendor_path);
Packit 6d72ef
  } else {
Packit 6d72ef
    debug(D_DUMP, "OPENCL_VENDOR_PATH set to '%s', using it", vendor_path);
Packit 6d72ef
  }
Packit 6d72ef
  if (! dir_path || dir_path[0]==0) {
Packit 6d72ef
    dir_path=vendor_path;
Packit 6d72ef
    debug(D_DUMP, "OCL_ICD_VENDORS empty or not defined, using vendors path '%s'", dir_path);
Packit 6d72ef
    is_dir=1;
Packit 6d72ef
  }
Packit 6d72ef
  if (!is_dir) {
Packit 6d72ef
    struct stat buf;
Packit 6d72ef
    int ret=stat(dir_path, &buf;;
Packit 6d72ef
    if (ret != 0 && errno != ENOENT) {
Packit 6d72ef
      debug(D_WARN, "Cannot stat '%s'. Aborting", dir_path);
Packit 6d72ef
    }
Packit 6d72ef
    if (ret == 0 && S_ISDIR(buf.st_mode)) {
Packit 6d72ef
      is_dir=1;
Packit 6d72ef
    }
Packit 6d72ef
  }
Packit 6d72ef
Packit 6d72ef
  if (!is_dir) {
Packit 6d72ef
    debug(D_LOG,"Only loading '%s' as an ICD", dir_path);
Packit 6d72ef
    num_icds = 1;
Packit 6d72ef
    dir=NULL;
Packit 6d72ef
  } else {
Packit 6d72ef
    debug(D_LOG,"Reading icd list from '%s'", dir_path);
Packit 6d72ef
    dir = opendir(dir_path);
Packit 6d72ef
    if(dir == NULL) {
Packit 6d72ef
      if (errno == ENOTDIR) {
Packit 6d72ef
        debug(D_DUMP, "%s is not a directory, trying to use it as a ICD libname",
Packit 6d72ef
	  dir_path);
Packit 6d72ef
      }
Packit 6d72ef
      goto abort;
Packit 6d72ef
    }
Packit 6d72ef
Packit 6d72ef
    num_icds = _find_num_icds(dir);
Packit 6d72ef
    if(num_icds == 0) {
Packit 6d72ef
      goto abort;
Packit 6d72ef
    }
Packit 6d72ef
  }
Packit 6d72ef
Packit 6d72ef
  _icds = (struct vendor_icd*)malloc(num_icds * sizeof(struct vendor_icd));
Packit 6d72ef
  if (_icds == NULL) {
Packit 6d72ef
    goto abort;
Packit 6d72ef
  }
Packit 6d72ef
Packit 6d72ef
  if (!is_dir) {
Packit 6d72ef
    if (_string_end_with_icd(dir_path)) {
Packit 6d72ef
      num_icds = 0;
Packit 6d72ef
      if (! _string_with_slash(dir_path)) {
Packit 6d72ef
	num_icds = _open_driver(0, vendor_path, dir_path);
Packit 6d72ef
      }
Packit 6d72ef
      if (num_icds == 0) {
Packit 6d72ef
	num_icds = _open_driver(0, NULL, dir_path);
Packit 6d72ef
      }
Packit 6d72ef
    } else {
Packit 6d72ef
      num_icds = _load_icd(0, dir_path);
Packit 6d72ef
    }
Packit 6d72ef
  } else {
Packit 6d72ef
    num_icds = _open_drivers(dir, dir_path);
Packit 6d72ef
  }
Packit 6d72ef
  if(num_icds == 0) {
Packit 6d72ef
    goto abort;
Packit 6d72ef
  }
Packit 6d72ef
Packit 6d72ef
  _find_and_check_platforms(num_icds);
Packit 6d72ef
  if(_num_icds == 0){
Packit 6d72ef
    goto abort;
Packit 6d72ef
  }
Packit 6d72ef
Packit 6d72ef
  if (_num_icds < num_icds) {
Packit 6d72ef
    _icds = (struct vendor_icd*)realloc(_icds, _num_icds * sizeof(struct vendor_icd));
Packit 6d72ef
  }
Packit 6d72ef
  debug(D_WARN, "%d valid vendor(s)!", _num_icds);
Packit 6d72ef
Packit 6d72ef
  if (dir != NULL){
Packit 6d72ef
    closedir(dir);
Packit 6d72ef
  }
Packit 6d72ef
  return;
Packit 6d72ef
 abort:
Packit 6d72ef
  _num_icds = 0;
Packit 6d72ef
  if (_icds) {
Packit 6d72ef
    free(_icds);
Packit 6d72ef
    _icds = NULL;
Packit 6d72ef
  }
Packit 6d72ef
  if (dir != NULL){
Packit 6d72ef
    closedir(dir);
Packit 6d72ef
  }
Packit 6d72ef
  return;
Packit 6d72ef
}
Packit 6d72ef
Packit 6d72ef
#ifdef USE_PTHREAD
Packit 6d72ef
static pthread_once_t once_init = PTHREAD_ONCE_INIT;
Packit 6d72ef
#else
Packit 6d72ef
static int gard=0;
Packit 6d72ef
#endif
Packit 6d72ef
volatile static __thread int in_init = 0;
Packit 6d72ef
volatile static cl_uint _initialized = 0;
Packit 6d72ef
Packit 6d72ef
static void _initClIcd_real( void ) {
Packit 6d72ef
#ifdef USE_PTHREAD
Packit 6d72ef
  if (in_init) {
Packit 6d72ef
    /* probably reentrency, in_init is a __thread variable */
Packit 6d72ef
    debug(D_WARN, "Executing init while already in init!");
Packit 6d72ef
  } else {
Packit 6d72ef
    in_init=1;
Packit 6d72ef
    __sync_synchronize();
Packit 6d72ef
    pthread_once(&once_init, &__initClIcd);
Packit 6d72ef
    __sync_synchronize();
Packit 6d72ef
    in_init=0;
Packit 6d72ef
  }
Packit 6d72ef
#else
Packit 6d72ef
  if (__sync_bool_compare_and_swap(&gard, 0, 1)) {
Packit 6d72ef
    in_init=1;
Packit 6d72ef
    __sync_synchronize();
Packit 6d72ef
    __initClIcd();
Packit 6d72ef
    __sync_synchronize();
Packit 6d72ef
    in_init=0;
Packit 6d72ef
  } else {
Packit 6d72ef
    if (in_init) {
Packit 6d72ef
      /* probably reentrency (could also be preemptive user-level threads). */
Packit 6d72ef
    } else {
Packit 6d72ef
      /* someone else started __initClIcd(). We wait until it ends. */
Packit 6d72ef
      debug(D_WARN, "Waiting end of init");
Packit 6d72ef
      while (!_initialized) {
Packit 6d72ef
	__sync_synchronize();
Packit 6d72ef
      }
Packit 6d72ef
      debug(D_WARN, "Wait done");
Packit 6d72ef
   }
Packit 6d72ef
  }
Packit 6d72ef
#endif
Packit 6d72ef
  _initialized = 1;
Packit 6d72ef
}
Packit 6d72ef
Packit 6d72ef
static inline void _initClIcd( void ) {
Packit 6d72ef
  if( __builtin_expect (_initialized, 1) )
Packit 6d72ef
    return;
Packit 6d72ef
  _initClIcd_real();
Packit 6d72ef
}
Packit 6d72ef
Packit 6d72ef
cl_platform_id __attribute__((visibility("internal")))
Packit 6d72ef
getDefaultPlatformID() {
Packit 6d72ef
  static cl_platform_id defaultPlatformID=NULL;
Packit 6d72ef
  static int defaultSet=0;
Packit 6d72ef
  _initClIcd();
Packit 6d72ef
  if (! defaultSet) {
Packit 6d72ef
    do {
Packit 6d72ef
      if(_num_picds == 0) {
Packit 6d72ef
	break;
Packit 6d72ef
      }
Packit 6d72ef
      const char *default_platform = getenv("OCL_ICD_DEFAULT_PLATFORM");
Packit 6d72ef
      int num_default_platform;
Packit 6d72ef
      char *end_scan;
Packit 6d72ef
      if (! default_platform) {
Packit 6d72ef
	num_default_platform = 0;
Packit 6d72ef
      } else {
Packit 6d72ef
	num_default_platform = strtol(default_platform, &end_scan, 10);
Packit 6d72ef
	if (*default_platform == '\0' || *end_scan != '\0') {
Packit 6d72ef
	  break;
Packit 6d72ef
	}
Packit 6d72ef
      }
Packit 6d72ef
      if (num_default_platform < 0 || num_default_platform >= _num_picds) {
Packit 6d72ef
	break;
Packit 6d72ef
      }
Packit 6d72ef
      defaultPlatformID=_picds[num_default_platform].pid;
Packit 6d72ef
    } while(0);
Packit 6d72ef
    defaultSet=1;
Packit 6d72ef
  }
Packit 6d72ef
  return defaultPlatformID;
Packit 6d72ef
}
Packit 6d72ef
Packit 6d72ef
#pragma GCC visibility pop
Packit 6d72ef
#define hidden_alias(name) \
Packit 6d72ef
  typeof(name) name##_hid __attribute__ ((alias (#name), visibility("hidden")))
Packit 6d72ef
Packit 6d72ef
typedef enum {
Packit 6d72ef
  CL_ICDL_OCL_VERSION=1,
Packit 6d72ef
  CL_ICDL_VERSION=2,
Packit 6d72ef
  CL_ICDL_NAME=3,
Packit 6d72ef
  CL_ICDL_VENDOR=4,
Packit 6d72ef
} cl_icdl_info;
Packit 6d72ef
Packit 6d72ef
static cl_int clGetICDLoaderInfoOCLICD(
Packit 6d72ef
  cl_icdl_info     param_name,
Packit 6d72ef
  size_t           param_value_size,
Packit 6d72ef
  void *           param_value,
Packit 6d72ef
  size_t *         param_value_size_ret)
Packit 6d72ef
{
Packit 6d72ef
  static const char cl_icdl_ocl_version[] = "OpenCL " OCL_ICD_OPENCL_VERSION;
Packit 6d72ef
  static const char cl_icdl_version[] = PACKAGE_VERSION;
Packit 6d72ef
  static const char cl_icdl_name[] = PACKAGE_NAME;
Packit 6d72ef
  static const char cl_icdl_vendor[] = "OCL Icd free software";
Packit 6d72ef
Packit 6d72ef
  size_t size_string;
Packit 6d72ef
  const char * string_p;
Packit 6d72ef
#define oclcase(name, NAME) \
Packit 6d72ef
  case CL_ICDL_##NAME: \
Packit 6d72ef
    string_p = cl_icdl_##name; \
Packit 6d72ef
    size_string = sizeof(cl_icdl_##name); \
Packit 6d72ef
    break
Packit 6d72ef
Packit 6d72ef
  switch ( param_name ) {
Packit 6d72ef
    oclcase(ocl_version,OCL_VERSION);
Packit 6d72ef
    oclcase(version,VERSION);
Packit 6d72ef
    oclcase(name,NAME);
Packit 6d72ef
    oclcase(vendor,VENDOR);
Packit 6d72ef
    default:
Packit 6d72ef
      return CL_INVALID_VALUE;
Packit 6d72ef
      break;
Packit 6d72ef
  }
Packit 6d72ef
#undef oclcase
Packit 6d72ef
  if( param_value != NULL ) {
Packit 6d72ef
    if( size_string > param_value_size )
Packit 6d72ef
      return CL_INVALID_VALUE;
Packit 6d72ef
    memcpy(param_value, string_p, size_string);
Packit 6d72ef
  }
Packit 6d72ef
  if( param_value_size_ret != NULL )
Packit 6d72ef
    *param_value_size_ret = size_string;
Packit 6d72ef
  return CL_SUCCESS;
Packit 6d72ef
}
Packit 6d72ef
Packit 6d72ef
CL_API_ENTRY void * CL_API_CALL
Packit 6d72ef
clGetExtensionFunctionAddress(const char * func_name) CL_API_SUFFIX__VERSION_1_0 {
Packit 6d72ef
  debug_trace();
Packit 6d72ef
  _initClIcd();
Packit 6d72ef
  if( func_name == NULL )
Packit 6d72ef
    return NULL;
Packit 6d72ef
  cl_uint suffix_length;
Packit 6d72ef
  cl_uint i;
Packit 6d72ef
  void * return_value=NULL;
Packit 6d72ef
  struct func_desc const * fn=&function_description[0];
Packit 6d72ef
  int lenfn=strlen(func_name);
Packit 6d72ef
  if (lenfn > 3 &&
Packit 6d72ef
      (strcmp(func_name+lenfn-3, "KHR")==0 || strcmp(func_name+lenfn-3, "EXT")==0)) {
Packit 6d72ef
    while (fn->name != NULL) {
Packit 6d72ef
      if (strcmp(func_name, fn->name)==0)
Packit 6d72ef
        RETURN(fn->addr);
Packit 6d72ef
      fn++;
Packit 6d72ef
    }
Packit 6d72ef
  }
Packit 6d72ef
  for(i=0; i<_num_picds; i++) {
Packit 6d72ef
    suffix_length = strlen(_picds[i].extension_suffix);
Packit 6d72ef
    if( suffix_length > strlen(func_name) )
Packit 6d72ef
      continue;
Packit 6d72ef
    if(strcmp(_picds[i].extension_suffix, &func_name[strlen(func_name)-suffix_length]) == 0)
Packit 6d72ef
      RETURN((*_picds[i].vicd->ext_fn_ptr)(func_name));
Packit 6d72ef
  }
Packit 6d72ef
  if(strcmp(func_name, "clGetICDLoaderInfoOCLICD") == 0) {
Packit 6d72ef
    return (void*)(void*(*)(void))(&clGetICDLoaderInfoOCLICD);
Packit 6d72ef
  }
Packit 6d72ef
  RETURN(return_value);
Packit 6d72ef
}
Packit 6d72ef
hidden_alias(clGetExtensionFunctionAddress);
Packit 6d72ef
Packit 6d72ef
CL_API_ENTRY cl_int CL_API_CALL
Packit 6d72ef
clGetPlatformIDs(cl_uint          num_entries,
Packit 6d72ef
                 cl_platform_id * platforms,
Packit 6d72ef
                 cl_uint *        num_platforms) CL_API_SUFFIX__VERSION_1_0 {
Packit 6d72ef
  debug_trace();
Packit 6d72ef
  _initClIcd();
Packit 6d72ef
  if( platforms == NULL && num_platforms == NULL )
Packit 6d72ef
    RETURN(CL_INVALID_VALUE);
Packit 6d72ef
  if( num_entries == 0 && platforms != NULL )
Packit 6d72ef
    RETURN(CL_INVALID_VALUE);
Packit 6d72ef
  if( _num_icds == 0 || _num_picds == 0 ) {
Packit 6d72ef
    if ( num_platforms != NULL )
Packit 6d72ef
      *num_platforms = 0;
Packit 6d72ef
    RETURN(CL_PLATFORM_NOT_FOUND_KHR);
Packit 6d72ef
  }
Packit 6d72ef
Packit 6d72ef
  cl_uint i;
Packit 6d72ef
  if( num_platforms != NULL ){
Packit 6d72ef
    *num_platforms = _num_picds;
Packit 6d72ef
  }
Packit 6d72ef
  if( platforms != NULL ) {
Packit 6d72ef
    cl_uint n_platforms = _num_picds < num_entries ? _num_picds : num_entries;
Packit 6d72ef
    for( i=0; i
Packit 6d72ef
      *(platforms++) = _picds[i].pid;
Packit 6d72ef
    }
Packit 6d72ef
  }
Packit 6d72ef
  return CL_SUCCESS;
Packit 6d72ef
}
Packit 6d72ef
hidden_alias(clGetPlatformIDs);
Packit 6d72ef
Packit 6d72ef
#define RETURN_WITH_ERRCODE(errvar, errvalue, retvalue) \
Packit 6d72ef
  do { \
Packit 6d72ef
    if(errvar) { \
Packit 6d72ef
      *errvar=errvalue; \
Packit 6d72ef
    } \
Packit 6d72ef
    RETURN(NULL); \
Packit 6d72ef
  } while(0)
Packit 6d72ef
Packit 6d72ef
#define CHECK_PLATFORM(__pid) \
Packit 6d72ef
  ({ \
Packit 6d72ef
    cl_platform_id _pid=(__pid); \
Packit 6d72ef
    int good=0; \
Packit 6d72ef
    cl_uint j; \
Packit 6d72ef
    for( j=0; j<_num_picds; j++) { \
Packit 6d72ef
      if( _picds[j].pid == _pid) { \
Packit 6d72ef
        good=1; \
Packit 6d72ef
        break; \
Packit 6d72ef
      } \
Packit 6d72ef
    } \
Packit 6d72ef
    good; \
Packit 6d72ef
  })
Packit 6d72ef
Packit 6d72ef
CL_API_ENTRY cl_context CL_API_CALL
Packit 6d72ef
clCreateContext(const cl_context_properties *  properties ,
Packit 6d72ef
                cl_uint                        num_devices ,
Packit 6d72ef
                const cl_device_id *           devices ,
Packit 6d72ef
                void (CL_CALLBACK *  pfn_notify )(const char *, const void *, size_t, void *),
Packit 6d72ef
                void *                         user_data ,
Packit 6d72ef
                cl_int *                       errcode_ret ){
Packit 6d72ef
  debug_trace();
Packit 6d72ef
  _initClIcd();
Packit 6d72ef
  cl_uint i=0;
Packit 6d72ef
  if( properties != NULL){
Packit 6d72ef
    while( properties[i] != 0 ) {
Packit 6d72ef
      if( properties[i] == CL_CONTEXT_PLATFORM ) {
Packit 6d72ef
        if((struct _cl_platform_id *) properties[i+1] == NULL) {
Packit 6d72ef
          if(errcode_ret) {
Packit 6d72ef
            *errcode_ret = CL_INVALID_PLATFORM;
Packit 6d72ef
          }
Packit 6d72ef
          RETURN(NULL);
Packit 6d72ef
        } else {
Packit 6d72ef
          if( !CHECK_PLATFORM((cl_platform_id) properties[i+1]) ) {
Packit 6d72ef
	    RETURN_WITH_ERRCODE(errcode_ret, CL_INVALID_PLATFORM, NULL);
Packit 6d72ef
          }
Packit 6d72ef
        }
Packit 6d72ef
        RETURN(((struct _cl_platform_id *) properties[i+1])
Packit 6d72ef
          ->dispatch->clCreateContext(properties, num_devices, devices,
Packit 6d72ef
                        pfn_notify, user_data, errcode_ret));
Packit 6d72ef
      }
Packit 6d72ef
      i += 2;
Packit 6d72ef
    }
Packit 6d72ef
  }
Packit 6d72ef
  if(devices == NULL || num_devices == 0) {
Packit 6d72ef
    RETURN_WITH_ERRCODE(errcode_ret, CL_INVALID_VALUE, NULL);
Packit 6d72ef
  }
Packit 6d72ef
  if((struct _cl_device_id *)devices[0] == NULL) {
Packit 6d72ef
    RETURN_WITH_ERRCODE(errcode_ret, CL_INVALID_DEVICE, NULL);
Packit 6d72ef
  }
Packit 6d72ef
  RETURN(((struct _cl_device_id *)devices[0])
Packit 6d72ef
    ->dispatch->clCreateContext(properties, num_devices, devices,
Packit 6d72ef
                  pfn_notify, user_data, errcode_ret));
Packit 6d72ef
}
Packit 6d72ef
hidden_alias(clCreateContext);
Packit 6d72ef
Packit 6d72ef
CL_API_ENTRY cl_context CL_API_CALL
Packit 6d72ef
clCreateContextFromType(const cl_context_properties *  properties ,
Packit 6d72ef
                        cl_device_type                 device_type ,
Packit 6d72ef
                        void (CL_CALLBACK *      pfn_notify )(const char *, const void *, size_t, void *),
Packit 6d72ef
                        void *                         user_data ,
Packit 6d72ef
                        cl_int *                       errcode_ret ){
Packit 6d72ef
  debug_trace();
Packit 6d72ef
  _initClIcd();
Packit 6d72ef
  if(_num_picds == 0) {
Packit 6d72ef
    goto out;
Packit 6d72ef
  }
Packit 6d72ef
  cl_uint i=0;
Packit 6d72ef
  if( properties != NULL){
Packit 6d72ef
    while( properties[i] != 0 ) {
Packit 6d72ef
      if( properties[i] == CL_CONTEXT_PLATFORM ) {
Packit 6d72ef
	if( (struct _cl_platform_id *) properties[i+1] == NULL ) {
Packit 6d72ef
	  goto out;
Packit 6d72ef
        } else {
Packit 6d72ef
          if( !CHECK_PLATFORM((cl_platform_id) properties[i+1]) ) {
Packit 6d72ef
            goto out;
Packit 6d72ef
          }
Packit 6d72ef
        }
Packit 6d72ef
        return ((struct _cl_platform_id *) properties[i+1])
Packit 6d72ef
          ->dispatch->clCreateContextFromType(properties, device_type,
Packit 6d72ef
                        pfn_notify, user_data, errcode_ret);
Packit 6d72ef
      }
Packit 6d72ef
      i += 2;
Packit 6d72ef
    }
Packit 6d72ef
  } else {
Packit 6d72ef
    cl_platform_id default_platform=getDefaultPlatformID();
Packit 6d72ef
    RETURN(default_platform->dispatch->clCreateContextFromType
Packit 6d72ef
	(properties, device_type, pfn_notify, user_data, errcode_ret));
Packit 6d72ef
  }
Packit 6d72ef
 out:
Packit 6d72ef
  RETURN_WITH_ERRCODE(errcode_ret, CL_INVALID_PLATFORM, NULL);
Packit 6d72ef
}
Packit 6d72ef
hidden_alias(clCreateContextFromType);
Packit 6d72ef
Packit 6d72ef
CL_API_ENTRY cl_int CL_API_CALL
Packit 6d72ef
clGetGLContextInfoKHR(const cl_context_properties *  properties ,
Packit 6d72ef
                      cl_gl_context_info             param_name ,
Packit 6d72ef
                      size_t                         param_value_size ,
Packit 6d72ef
                      void *                         param_value ,
Packit 6d72ef
                      size_t *                       param_value_size_ret ){
Packit 6d72ef
  debug_trace();
Packit 6d72ef
  _initClIcd();
Packit 6d72ef
  cl_uint i=0;
Packit 6d72ef
  if( properties != NULL){
Packit 6d72ef
    while( properties[i] != 0 ) {
Packit 6d72ef
      if( properties[i] == CL_CONTEXT_PLATFORM ) {
Packit 6d72ef
        if( (struct _cl_platform_id *) properties[i+1] == NULL ) {
Packit 6d72ef
	  RETURN(CL_INVALID_PLATFORM);
Packit 6d72ef
        } else {
Packit 6d72ef
          if( !CHECK_PLATFORM((cl_platform_id) properties[i+1]) ) {
Packit 6d72ef
	    RETURN(CL_INVALID_PLATFORM);
Packit 6d72ef
          }
Packit 6d72ef
        }
Packit 6d72ef
        RETURN(((struct _cl_platform_id *) properties[i+1])
Packit 6d72ef
	  ->dispatch->clGetGLContextInfoKHR(properties, param_name,
Packit 6d72ef
                        param_value_size, param_value, param_value_size_ret));
Packit 6d72ef
      }
Packit 6d72ef
      i += 2;
Packit 6d72ef
    }
Packit 6d72ef
  }
Packit 6d72ef
  RETURN(CL_INVALID_PLATFORM);
Packit 6d72ef
}
Packit 6d72ef
hidden_alias(clGetGLContextInfoKHR);
Packit 6d72ef
Packit 6d72ef
CL_API_ENTRY cl_int CL_API_CALL
Packit 6d72ef
clWaitForEvents(cl_uint              num_events ,
Packit 6d72ef
                const cl_event *     event_list ){
Packit 6d72ef
  debug_trace();
Packit 6d72ef
  if( num_events == 0 || event_list == NULL )
Packit 6d72ef
    RETURN(CL_INVALID_VALUE);
Packit 6d72ef
  if( (struct _cl_event *)event_list[0] == NULL )
Packit 6d72ef
    RETURN(CL_INVALID_EVENT);
Packit 6d72ef
  RETURN(((struct _cl_event *)event_list[0])
Packit 6d72ef
    ->dispatch->clWaitForEvents(num_events, event_list));
Packit 6d72ef
}
Packit 6d72ef
hidden_alias(clWaitForEvents);
Packit 6d72ef
Packit 6d72ef
CL_API_ENTRY cl_int CL_API_CALL
Packit 6d72ef
clUnloadCompiler( void ){
Packit 6d72ef
  debug_trace();
Packit 6d72ef
  RETURN(CL_SUCCESS);
Packit 6d72ef
}
Packit 6d72ef
hidden_alias(clUnloadCompiler);