Blame ocl_icd_loader.c

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