From 6c85cd862d4b2db5509a05a7612adf6822aaad18 Mon Sep 17 00:00:00 2001 From: bashbaug Date: Wed, 19 Jun 2019 17:09:53 -0700 Subject: [PATCH 1/6] basic ICD loader env var support for OCL_ICD_VENDORS --- CMakeLists.txt | 8 ++- loader/icd.h | 2 + loader/icd_cmake_config.h.in | 2 + loader/icd_envvars.h | 106 +++++++++++++++++++++++++++++++++++ loader/linux/icd_linux.c | 15 ++++- 5 files changed, 130 insertions(+), 3 deletions(-) create mode 100644 loader/icd_cmake_config.h.in create mode 100644 loader/icd_envvars.h diff --git a/CMakeLists.txt b/CMakeLists.txt index b3f8c0b3..0138afab 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -33,6 +33,12 @@ find_package (Threads REQUIRED) # advance. Use it with discretion. option (BUILD_SHARED_LIBS "Build shared libs" ON) +include(CheckFunctionExists) +check_function_exists(secure_getenv HAVE_SECURE_GETENV) +check_function_exists(__secure_getenv HAVE___SECURE_GETENV) +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/loader/icd_cmake_config.h.in + ${CMAKE_CURRENT_BINARY_DIR}/icd_cmake_config.h) + set (OPENCL_ICD_LOADER_SOURCES loader/icd.c loader/icd_dispatch.c) @@ -108,7 +114,7 @@ endif () include_directories (${OPENCL_ICD_LOADER_HEADERS_DIR}) add_definitions (-DCL_TARGET_OPENCL_VERSION=220) -target_include_directories (OpenCL PRIVATE loader) +target_include_directories (OpenCL PRIVATE ${CMAKE_CURRENT_BINARY_DIR} loader) target_link_libraries (OpenCL ${CMAKE_DL_LIBS}) include (CTest) diff --git a/loader/icd.h b/loader/icd.h index a1b69692..7de9801d 100644 --- a/loader/icd.h +++ b/loader/icd.h @@ -19,6 +19,8 @@ #ifndef _ICD_H_ #define _ICD_H_ +#include "icd_cmake_config.h" + #ifndef CL_USE_DEPRECATED_OPENCL_1_0_APIS #define CL_USE_DEPRECATED_OPENCL_1_0_APIS #endif diff --git a/loader/icd_cmake_config.h.in b/loader/icd_cmake_config.h.in new file mode 100644 index 00000000..3bbc4612 --- /dev/null +++ b/loader/icd_cmake_config.h.in @@ -0,0 +1,2 @@ +#cmakedefine HAVE_SECURE_GETENV +#cmakedefine HAVE___SECURE_GETENV diff --git a/loader/icd_envvars.h b/loader/icd_envvars.h new file mode 100644 index 00000000..0a20fef4 --- /dev/null +++ b/loader/icd_envvars.h @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2016-2019 The Khronos Group Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * OpenCL is a trademark of Apple Inc. used under license by Khronos. + */ + +#ifndef _ICD_ENVVARS_H_ +#define _ICD_ENVVARS_H_ + +// Environment variables +#if defined(__linux__) || defined(__APPLE__) + +static inline char *khrIcd_getenv(const char *name) { + // No allocation of memory necessary for Linux. + return getenv(name); +} + +static inline char *khrIcd_secure_getenv(const char *name) { +#if defined(__APPLE__) + // Apple does not appear to have a secure getenv implementation. + // The main difference between secure getenv and getenv is that secure getenv + // returns NULL if the process is being run with elevated privileges by a normal user. + // The idea is to prevent the reading of malicious environment variables by a process + // that can do damage. + // This algorithm is derived from glibc code that sets an internal + // variable (__libc_enable_secure) if the process is running under setuid or setgid. + return geteuid() != getuid() || getegid() != getgid() ? NULL : khrIcd_getenv(name); +#else +// Linux +#ifdef HAVE_SECURE_GETENV + return secure_getenv(name); +#elif defined(HAVE___SECURE_GETENV) + return __secure_getenv(name); +#else +#pragma message( \ + "Warning: Falling back to non-secure getenv for environmental lookups! Consider" \ + " updating to a different libc.") + return khrIcd_getenv(name); +#endif +#endif +} + +static inline void khrIcd_free_getenv(char *val) { + // No freeing of memory necessary for Linux, but we should at least touch + // val to get rid of compiler warnings. + (void)val; +} + +#elif defined(WIN32) + +static inline char *khrIcd_getenv(const char *name) { + char *retVal; + DWORD valSize; + + valSize = GetEnvironmentVariableA(name, NULL, 0); + + // valSize DOES include the null terminator, so for any set variable + // will always be at least 1. If it's 0, the variable wasn't set. + if (valSize == 0) return NULL; + + // Allocate the space necessary for the registry entry + retVal = (char *)malloc(valSize); + + if (NULL != retVal) { + GetEnvironmentVariableA(name, retVal, valSize); + } + + return retVal; +} + +static inline char *khrIcd_secure_getenv(const char *name) { + // No secure version for Windows as far as I know + return khrIcd_getenv(name); +} + +static inline void khrIcd_free_getenv(char *val) { + free((void *)val); +} + +#else + +static inline char *khrIcd_getenv(const char *name) { + // stub func + (void)name; + return NULL; +} +static inline void khrIcd_free_getenv(char *val) { + // stub func + (void)val; +} + +#endif + +#endif \ No newline at end of file diff --git a/loader/linux/icd_linux.c b/loader/linux/icd_linux.c index f6bb7b67..6f127e39 100644 --- a/loader/linux/icd_linux.c +++ b/loader/linux/icd_linux.c @@ -16,7 +16,14 @@ * OpenCL is a trademark of Apple Inc. used under license by Khronos. */ +// for secure_getenv(): +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif + #include "icd.h" +#include "icd_envvars.h" + #include #include #include @@ -38,11 +45,15 @@ void khrIcdOsVendorsEnumerate(void) { DIR *dir = NULL; struct dirent *dirEntry = NULL; + char* vendorPath = khrIcd_secure_getenv("OCL_ICD_VENDORS"); + if (vendorPath == NULL) + { #ifdef __ANDROID__ - char *vendorPath = "/system/vendor/Khronos/OpenCL/vendors/"; + vendorPath = "/system/vendor/Khronos/OpenCL/vendors/"; #else - char *vendorPath = "/etc/OpenCL/vendors/"; + vendorPath = "/etc/OpenCL/vendors/"; #endif // ANDROID + } // open the directory dir = opendir(vendorPath); From 167dd91dfe5d3254379d1b20ab21c169de06eacf Mon Sep 17 00:00:00 2001 From: bashbaug Date: Fri, 21 Jun 2019 12:12:13 -0700 Subject: [PATCH 2/6] added envvars source files --- CMakeLists.txt | 2 + loader/icd.h | 2 - loader/icd_envvars.h | 86 +--------------------------- loader/linux/icd_linux.c | 5 -- loader/linux/icd_linux_envvars.c | 62 ++++++++++++++++++++ loader/windows/icd_windows_envvars.c | 47 +++++++++++++++ 6 files changed, 114 insertions(+), 90 deletions(-) create mode 100644 loader/linux/icd_linux_envvars.c create mode 100644 loader/windows/icd_windows_envvars.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 0138afab..a6104bc4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -46,6 +46,7 @@ set (OPENCL_ICD_LOADER_SOURCES if (WIN32) list (APPEND OPENCL_ICD_LOADER_SOURCES loader/windows/icd_windows.c + loader/windows/icd_windows_envvars.c loader/windows/icd_windows_hkr.c loader/windows/icd_windows_dxgk.c loader/windows/OpenCL.def @@ -59,6 +60,7 @@ if (WIN32) else () list (APPEND OPENCL_ICD_LOADER_SOURCES loader/linux/icd_linux.c + loader/linux/icd_linux_envvars.c loader/linux/icd_exports.map) endif () diff --git a/loader/icd.h b/loader/icd.h index 7de9801d..a1b69692 100644 --- a/loader/icd.h +++ b/loader/icd.h @@ -19,8 +19,6 @@ #ifndef _ICD_H_ #define _ICD_H_ -#include "icd_cmake_config.h" - #ifndef CL_USE_DEPRECATED_OPENCL_1_0_APIS #define CL_USE_DEPRECATED_OPENCL_1_0_APIS #endif diff --git a/loader/icd_envvars.h b/loader/icd_envvars.h index 0a20fef4..0d34d3d6 100644 --- a/loader/icd_envvars.h +++ b/loader/icd_envvars.h @@ -19,88 +19,8 @@ #ifndef _ICD_ENVVARS_H_ #define _ICD_ENVVARS_H_ -// Environment variables -#if defined(__linux__) || defined(__APPLE__) +char *khrIcd_getenv(const char *name); +char *khrIcd_secure_getenv(const char *name); +void khrIcd_free_getenv(char *val); -static inline char *khrIcd_getenv(const char *name) { - // No allocation of memory necessary for Linux. - return getenv(name); -} - -static inline char *khrIcd_secure_getenv(const char *name) { -#if defined(__APPLE__) - // Apple does not appear to have a secure getenv implementation. - // The main difference between secure getenv and getenv is that secure getenv - // returns NULL if the process is being run with elevated privileges by a normal user. - // The idea is to prevent the reading of malicious environment variables by a process - // that can do damage. - // This algorithm is derived from glibc code that sets an internal - // variable (__libc_enable_secure) if the process is running under setuid or setgid. - return geteuid() != getuid() || getegid() != getgid() ? NULL : khrIcd_getenv(name); -#else -// Linux -#ifdef HAVE_SECURE_GETENV - return secure_getenv(name); -#elif defined(HAVE___SECURE_GETENV) - return __secure_getenv(name); -#else -#pragma message( \ - "Warning: Falling back to non-secure getenv for environmental lookups! Consider" \ - " updating to a different libc.") - return khrIcd_getenv(name); -#endif #endif -} - -static inline void khrIcd_free_getenv(char *val) { - // No freeing of memory necessary for Linux, but we should at least touch - // val to get rid of compiler warnings. - (void)val; -} - -#elif defined(WIN32) - -static inline char *khrIcd_getenv(const char *name) { - char *retVal; - DWORD valSize; - - valSize = GetEnvironmentVariableA(name, NULL, 0); - - // valSize DOES include the null terminator, so for any set variable - // will always be at least 1. If it's 0, the variable wasn't set. - if (valSize == 0) return NULL; - - // Allocate the space necessary for the registry entry - retVal = (char *)malloc(valSize); - - if (NULL != retVal) { - GetEnvironmentVariableA(name, retVal, valSize); - } - - return retVal; -} - -static inline char *khrIcd_secure_getenv(const char *name) { - // No secure version for Windows as far as I know - return khrIcd_getenv(name); -} - -static inline void khrIcd_free_getenv(char *val) { - free((void *)val); -} - -#else - -static inline char *khrIcd_getenv(const char *name) { - // stub func - (void)name; - return NULL; -} -static inline void khrIcd_free_getenv(char *val) { - // stub func - (void)val; -} - -#endif - -#endif \ No newline at end of file diff --git a/loader/linux/icd_linux.c b/loader/linux/icd_linux.c index 6f127e39..74f90f98 100644 --- a/loader/linux/icd_linux.c +++ b/loader/linux/icd_linux.c @@ -16,11 +16,6 @@ * OpenCL is a trademark of Apple Inc. used under license by Khronos. */ -// for secure_getenv(): -#ifndef _GNU_SOURCE -#define _GNU_SOURCE -#endif - #include "icd.h" #include "icd_envvars.h" diff --git a/loader/linux/icd_linux_envvars.c b/loader/linux/icd_linux_envvars.c new file mode 100644 index 00000000..4af5a082 --- /dev/null +++ b/loader/linux/icd_linux_envvars.c @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2016-2019 The Khronos Group Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * OpenCL is a trademark of Apple Inc. used under license by Khronos. + */ + +// for secure_getenv(): +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif + +#include "icd_cmake_config.h" + +#include + +char *khrIcd_getenv(const char *name) { + // No allocation of memory necessary for Linux. + return getenv(name); +} + +char *khrIcd_secure_getenv(const char *name) { +#if defined(__APPLE__) + // Apple does not appear to have a secure getenv implementation. + // The main difference between secure getenv and getenv is that secure getenv + // returns NULL if the process is being run with elevated privileges by a normal user. + // The idea is to prevent the reading of malicious environment variables by a process + // that can do damage. + // This algorithm is derived from glibc code that sets an internal + // variable (__libc_enable_secure) if the process is running under setuid or setgid. + return geteuid() != getuid() || getegid() != getgid() ? NULL : khrIcd_getenv(name); +#else +// Linux +#ifdef HAVE_SECURE_GETENV + return secure_getenv(name); +#elif defined(HAVE___SECURE_GETENV) + return __secure_getenv(name); +#else +#pragma message( \ + "Warning: Falling back to non-secure getenv for environmental lookups! Consider" \ + " updating to a different libc.") + return khrIcd_getenv(name); +#endif +#endif +} + +void khrIcd_free_getenv(char *val) { + // No freeing of memory necessary for Linux, but we should at least touch + // val to get rid of compiler warnings. + (void)val; +} diff --git a/loader/windows/icd_windows_envvars.c b/loader/windows/icd_windows_envvars.c new file mode 100644 index 00000000..223604e8 --- /dev/null +++ b/loader/windows/icd_windows_envvars.c @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2016-2019 The Khronos Group Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * OpenCL is a trademark of Apple Inc. used under license by Khronos. + */ + +#include + +char *khrIcd_getenv(const char *name) { + char *retVal; + DWORD valSize; + + valSize = GetEnvironmentVariableA(name, NULL, 0); + + // valSize DOES include the null terminator, so for any set variable + // will always be at least 1. If it's 0, the variable wasn't set. + if (valSize == 0) return NULL; + + // Allocate the space necessary for the registry entry + retVal = (char *)malloc(valSize); + + if (NULL != retVal) { + GetEnvironmentVariableA(name, retVal, valSize); + } + + return retVal; +} + +char *khrIcd_secure_getenv(const char *name) { + return khrIcd_getenv(name); +} + +void khrIcd_free_getenv(char *val) { + free((void *)val); +} From 5012c897b64970abf6273790d792f2fe99fb11a4 Mon Sep 17 00:00:00 2001 From: bashbaug Date: Fri, 21 Jun 2019 16:06:42 -0700 Subject: [PATCH 3/6] added OCL_ICD_FILENAMES support --- loader/icd.c | 47 +++++++++ loader/icd.h | 5 +- loader/linux/icd_linux.c | 159 ++++++++++++++++--------------- loader/windows/icd_windows.c | 91 +++++++++--------- test/driver_stub/driver_stub.def | 1 - 5 files changed, 180 insertions(+), 123 deletions(-) diff --git a/loader/icd.c b/loader/icd.c index 8e142c48..4be74b43 100644 --- a/loader/icd.c +++ b/loader/icd.c @@ -18,6 +18,7 @@ #include "icd.h" #include "icd_dispatch.h" +#include "icd_envvars.h" #include #include @@ -188,6 +189,52 @@ void khrIcdVendorAdd(const char *libraryName) } } +#if defined(__linux__) || defined(__APPLE__) +#define PATH_SEPARATOR ':' +#elif defined(_WIN32) +#define PATH_SEPARATOR ';' +#endif + +// Get next file or dirname given a string list or registry key path. +// Note: the input string may be modified! +static char *loader_get_next_path(char *path) { + size_t len; + char *next; + + if (path == NULL) return NULL; + next = strchr(path, PATH_SEPARATOR); + if (next == NULL) { + len = strlen(path); + next = path + len; + } else { + *next = '\0'; + next++; + } + + return next; +} + +void khrIcdVendorsEnumerateEnv(void) +{ + char* icdFilenames = khrIcd_secure_getenv("OCL_ICD_FILENAMES"); + char* cur_file = NULL; + char* next_file = NULL; + if (icdFilenames) + { + KHR_ICD_TRACE("Found OCL_ICD_FILENAMES environment variable.\n"); + + next_file = icdFilenames; + while (NULL != next_file && *next_file != '\0') { + cur_file = next_file; + next_file = loader_get_next_path(cur_file); + + khrIcdVendorAdd(cur_file); + } + + khrIcd_free_getenv(icdFilenames); + } +} + void khrIcdContextPropertiesGetPlatform(const cl_context_properties *properties, cl_platform_id *outPlatform) { if (properties == NULL && khrIcdVendors != NULL) diff --git a/loader/icd.h b/loader/icd.h index a1b69692..d091ec61 100644 --- a/loader/icd.h +++ b/loader/icd.h @@ -101,6 +101,9 @@ void khrIcdInitialize(void); // n.b, this call is OS-specific void khrIcdOsVendorsEnumerateOnce(void); +// read vendors from environment variables +void khrIcdVendorsEnumerateEnv(void); + // add a vendor's implementation to the list of libraries void khrIcdVendorAdd(const char *libraryName); @@ -122,7 +125,7 @@ void khrIcdContextPropertiesGetPlatform( cl_platform_id *outPlatform); // internal tracing macros -#if 0 +#if 1 #include #define KHR_ICD_TRACE(...) \ do \ diff --git a/loader/linux/icd_linux.c b/loader/linux/icd_linux.c index 74f90f98..ef07a795 100644 --- a/loader/linux/icd_linux.c +++ b/loader/linux/icd_linux.c @@ -40,106 +40,111 @@ void khrIcdOsVendorsEnumerate(void) { DIR *dir = NULL; struct dirent *dirEntry = NULL; - char* vendorPath = khrIcd_secure_getenv("OCL_ICD_VENDORS"); - if (vendorPath == NULL) - { + char* vendorPath = #ifdef __ANDROID__ - vendorPath = "/system/vendor/Khronos/OpenCL/vendors/"; + "/system/vendor/Khronos/OpenCL/vendors/"; #else - vendorPath = "/etc/OpenCL/vendors/"; + "/etc/OpenCL/vendors/"; #endif // ANDROID + char* envPath = NULL; + + khrIcdVendorsEnumerateEnv(); + + envPath = khrIcd_secure_getenv("OCL_ICD_VENDORS"); + if (NULL != envPath) + { + vendorPath = envPath; } - // open the directory dir = opendir(vendorPath); if (NULL == dir) { - KHR_ICD_TRACE("Failed to open path %s\n", vendorPath); - goto Cleanup; + KHR_ICD_TRACE("Failed to open path %s, continuing\n", vendorPath); } - - // attempt to load all files in the directory - for (dirEntry = readdir(dir); dirEntry; dirEntry = readdir(dir) ) + else { - switch(dirEntry->d_type) + // attempt to load all files in the directory + for (dirEntry = readdir(dir); dirEntry; dirEntry = readdir(dir) ) { - case DT_UNKNOWN: - case DT_REG: - case DT_LNK: + switch(dirEntry->d_type) { - const char* extension = ".icd"; - FILE *fin = NULL; - char* fileName = NULL; - char* buffer = NULL; - long bufferSize = 0; - - // make sure the file name ends in .icd - if (strlen(extension) > strlen(dirEntry->d_name) ) - { - break; - } - if (strcmp(dirEntry->d_name + strlen(dirEntry->d_name) - strlen(extension), extension) ) - { - break; - } - - // allocate space for the full path of the vendor library name - fileName = malloc(strlen(dirEntry->d_name) + strlen(vendorPath) + 1); - if (!fileName) + case DT_UNKNOWN: + case DT_REG: + case DT_LNK: { - KHR_ICD_TRACE("Failed allocate space for ICD file path\n"); - break; - } - sprintf(fileName, "%s%s", vendorPath, dirEntry->d_name); + const char* extension = ".icd"; + FILE *fin = NULL; + char* fileName = NULL; + char* buffer = NULL; + long bufferSize = 0; + + // make sure the file name ends in .icd + if (strlen(extension) > strlen(dirEntry->d_name) ) + { + break; + } + if (strcmp(dirEntry->d_name + strlen(dirEntry->d_name) - strlen(extension), extension) ) + { + break; + } + + // allocate space for the full path of the vendor library name + fileName = malloc(strlen(dirEntry->d_name) + strlen(vendorPath) + 1); + if (!fileName) + { + KHR_ICD_TRACE("Failed allocate space for ICD file path\n"); + break; + } + sprintf(fileName, "%s%s", vendorPath, dirEntry->d_name); + + // open the file and read its contents + fin = fopen(fileName, "r"); + if (!fin) + { + free(fileName); + break; + } + fseek(fin, 0, SEEK_END); + bufferSize = ftell(fin); + + buffer = malloc(bufferSize+1); + if (!buffer) + { + free(fileName); + fclose(fin); + break; + } + memset(buffer, 0, bufferSize+1); + fseek(fin, 0, SEEK_SET); + if (bufferSize != (long)fread(buffer, 1, bufferSize, fin) ) + { + free(fileName); + free(buffer); + fclose(fin); + break; + } + // ignore a newline at the end of the file + if (buffer[bufferSize-1] == '\n') buffer[bufferSize-1] = '\0'; + + // load the string read from the file + khrIcdVendorAdd(buffer); - // open the file and read its contents - fin = fopen(fileName, "r"); - if (!fin) - { - free(fileName); - break; - } - fseek(fin, 0, SEEK_END); - bufferSize = ftell(fin); - - buffer = malloc(bufferSize+1); - if (!buffer) - { - free(fileName); - fclose(fin); - break; - } - memset(buffer, 0, bufferSize+1); - fseek(fin, 0, SEEK_SET); - if (bufferSize != (long)fread(buffer, 1, bufferSize, fin) ) - { free(fileName); free(buffer); fclose(fin); - break; } - // ignore a newline at the end of the file - if (buffer[bufferSize-1] == '\n') buffer[bufferSize-1] = '\0'; - - // load the string read from the file - khrIcdVendorAdd(buffer); - - free(fileName); - free(buffer); - fclose(fin); + break; + default: + break; } - break; - default: - break; } - } -Cleanup: + closedir(dir); + } - // free resources and exit - if (dir) + if (NULL != envPath) { - closedir(dir); + khrIcd_free_getenv(envPath); } } diff --git a/loader/windows/icd_windows.c b/loader/windows/icd_windows.c index ec86184b..145a05e5 100644 --- a/loader/windows/icd_windows.c +++ b/loader/windows/icd_windows.c @@ -40,6 +40,8 @@ BOOL CALLBACK khrIcdOsVendorsEnumerate(PINIT_ONCE InitOnce, PVOID Parameter, PVO HKEY platformsKey = NULL; DWORD dwIndex; + khrIcdVendorsEnumerateEnv(); + if (!khrIcdOsVendorsEnumerateDXGK()) { KHR_ICD_TRACE("Failed to load via DXGK interface on RS4, continuing\n"); @@ -59,59 +61,60 @@ BOOL CALLBACK khrIcdOsVendorsEnumerate(PINIT_ONCE InitOnce, PVOID Parameter, PVO if (ERROR_SUCCESS != result) { KHR_ICD_TRACE("Failed to open platforms key %s, continuing\n", platformsName); - return TRUE; } - - // for each value - for (dwIndex = 0;; ++dwIndex) + else { - char cszLibraryName[1024] = {0}; - DWORD dwLibraryNameSize = sizeof(cszLibraryName); - DWORD dwLibraryNameType = 0; - DWORD dwValue = 0; - DWORD dwValueSize = sizeof(dwValue); - - // read the value name - KHR_ICD_TRACE("Reading value %d...\n", dwIndex); - result = RegEnumValueA( - platformsKey, - dwIndex, - cszLibraryName, - &dwLibraryNameSize, - NULL, - &dwLibraryNameType, - (LPBYTE)&dwValue, - &dwValueSize); - // if RegEnumKeyEx fails, we are done with the enumeration - if (ERROR_SUCCESS != result) + // for each value + for (dwIndex = 0;; ++dwIndex) { - KHR_ICD_TRACE("Failed to read value %d, done reading key.\n", dwIndex); - break; - } - KHR_ICD_TRACE("Value %s found...\n", cszLibraryName); + char cszLibraryName[1024] = {0}; + DWORD dwLibraryNameSize = sizeof(cszLibraryName); + DWORD dwLibraryNameType = 0; + DWORD dwValue = 0; + DWORD dwValueSize = sizeof(dwValue); + + // read the value name + KHR_ICD_TRACE("Reading value %d...\n", dwIndex); + result = RegEnumValueA( + platformsKey, + dwIndex, + cszLibraryName, + &dwLibraryNameSize, + NULL, + &dwLibraryNameType, + (LPBYTE)&dwValue, + &dwValueSize); + // if RegEnumKeyEx fails, we are done with the enumeration + if (ERROR_SUCCESS != result) + { + KHR_ICD_TRACE("Failed to read value %d, done reading key.\n", dwIndex); + break; + } + KHR_ICD_TRACE("Value %s found...\n", cszLibraryName); - // Require that the value be a DWORD and equal zero - if (REG_DWORD != dwLibraryNameType) - { - KHR_ICD_TRACE("Value not a DWORD, skipping\n"); - continue; + // Require that the value be a DWORD and equal zero + if (REG_DWORD != dwLibraryNameType) + { + KHR_ICD_TRACE("Value not a DWORD, skipping\n"); + continue; + } + if (dwValue) + { + KHR_ICD_TRACE("Value not zero, skipping\n"); + continue; + } + + // add the library + khrIcdVendorAdd(cszLibraryName); } - if (dwValue) + + result = RegCloseKey(platformsKey); + if (ERROR_SUCCESS != result) { - KHR_ICD_TRACE("Value not zero, skipping\n"); - continue; + KHR_ICD_TRACE("Failed to close platforms key %s, ignoring\n", platformsName); } - - // add the library - khrIcdVendorAdd(cszLibraryName); } - result = RegCloseKey(platformsKey); - if (ERROR_SUCCESS != result) - { - KHR_ICD_TRACE("Failed to close platforms key %s, ignoring\n", platformsName); - } - return TRUE; } diff --git a/test/driver_stub/driver_stub.def b/test/driver_stub/driver_stub.def index 5b238e8e..1ec27601 100644 --- a/test/driver_stub/driver_stub.def +++ b/test/driver_stub/driver_stub.def @@ -1,3 +1,2 @@ EXPORTS clGetExtensionFunctionAddress -clIcdGetPlatformIDsKHR From 663c28eab2179c6b452d67b14f31f7f750c169f1 Mon Sep 17 00:00:00 2001 From: bashbaug Date: Fri, 21 Jun 2019 16:18:42 -0700 Subject: [PATCH 4/6] added README section describing debug environment variables --- README.md | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 27c1de71..ee8499a6 100644 --- a/README.md +++ b/README.md @@ -115,4 +115,13 @@ Please create a GitHub issue to report an issue or ask questions. ## Contributing Contributions to the OpenCL ICD Loader are welcomed and encouraged. -You will be prompted with a one-time "click-through" CLA dialog as part of submitting your pull request or other contribution to GitHub. \ No newline at end of file +You will be prompted with a one-time "click-through" CLA dialog as part of submitting your pull request or other contribution to GitHub. + +## Table of Debug Environment Variables + +The following debug environment variables are available for use with the OpenCL ICD loader: + +| Environment Variable | Behavior | Example Format | +|:---------------------------------:|---------------------|----------------------| +| OCL_ICD_FILENAMES | Specifies a list of additional ICDs to load. The ICDs will be enumerated first, before any ICDs discovered via default mechanisms. | `export OCL_ICD_FILENAMES=libVendorA.so:libVendorB.so`

`set OCL_ICD_FILENAMES=vendor_a.dll;vendor_b.dll` | +| OCL_ICD_VENDORS | On Linux and Android, specifies a directory to scan for ICDs to enumerate in place of the default `/etc/OpenCL/vendors'. | `export OCL_ICD_VENDORS=/my/local/icd/search/path` | From 399f19e78cacc7b0f33a0016379f30254d38290d Mon Sep 17 00:00:00 2001 From: bashbaug Date: Mon, 24 Jun 2019 22:38:16 -0700 Subject: [PATCH 5/6] refactored platform specific defines into icd_platform.h --- CMakeLists.txt | 10 +++++++-- loader/icd.c | 6 ------ loader/icd.h | 6 ++---- loader/icd_platform.h | 39 ++++++++++++++++++++++++++++++++++++ loader/linux/icd_linux.c | 7 +------ loader/windows/icd_windows.c | 6 +++--- 6 files changed, 53 insertions(+), 21 deletions(-) create mode 100644 loader/icd_platform.h diff --git a/CMakeLists.txt b/CMakeLists.txt index a6104bc4..768d3002 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -41,14 +41,20 @@ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/loader/icd_cmake_config.h.in set (OPENCL_ICD_LOADER_SOURCES loader/icd.c - loader/icd_dispatch.c) + loader/icd.h + loader/icd_dispatch.c + loader/icd_dispatch.h + loader/icd_envvars.h + loader/icd_platform.h) if (WIN32) list (APPEND OPENCL_ICD_LOADER_SOURCES loader/windows/icd_windows.c + loader/windows/icd_windows_dxgk.c + loader/windows/icd_windows_dxgk.h loader/windows/icd_windows_envvars.c loader/windows/icd_windows_hkr.c - loader/windows/icd_windows_dxgk.c + loader/windows/icd_windows_hkr.h loader/windows/OpenCL.def loader/windows/OpenCL.rc) # Only add the DXSDK include directory if the environment variable is diff --git a/loader/icd.c b/loader/icd.c index 4be74b43..ea8306ab 100644 --- a/loader/icd.c +++ b/loader/icd.c @@ -189,12 +189,6 @@ void khrIcdVendorAdd(const char *libraryName) } } -#if defined(__linux__) || defined(__APPLE__) -#define PATH_SEPARATOR ':' -#elif defined(_WIN32) -#define PATH_SEPARATOR ';' -#endif - // Get next file or dirname given a string list or registry key path. // Note: the input string may be modified! static char *loader_get_next_path(char *path) { diff --git a/loader/icd.h b/loader/icd.h index d091ec61..01a33fd5 100644 --- a/loader/icd.h +++ b/loader/icd.h @@ -19,6 +19,8 @@ #ifndef _ICD_H_ #define _ICD_H_ +#include "icd_platform.h" + #ifndef CL_USE_DEPRECATED_OPENCL_1_0_APIS #define CL_USE_DEPRECATED_OPENCL_1_0_APIS #endif @@ -34,10 +36,6 @@ #include #include -#ifdef _WIN32 -#include -#endif - /* * type definitions */ diff --git a/loader/icd_platform.h b/loader/icd_platform.h new file mode 100644 index 00000000..b16d0dbe --- /dev/null +++ b/loader/icd_platform.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2016-2019 The Khronos Group Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * OpenCL is a trademark of Apple Inc. used under license by Khronos. + */ + +#ifndef _ICD_PLATFORM_H_ +#define _ICD_PLATFORM_H_ + +#if defined(__linux__) || defined(__APPLE__) + +#define PATH_SEPARATOR ':' +#define DIRECTORY_SYMBOL '/' +#ifdef __ANDROID__ +#define ICD_VENDOR_PATH "/system/vendor/Khronos/OpenCL/vendors/"; +#else +#define ICD_VENDOR_PATH "/etc/OpenCL/vendors/"; +#endif // ANDROID + +#elif defined(_WIN32) + +#define PATH_SEPARATOR ';' +#define DIRECTORY_SYMBOL '\\' + +#endif + +#endif diff --git a/loader/linux/icd_linux.c b/loader/linux/icd_linux.c index ef07a795..f6ae7902 100644 --- a/loader/linux/icd_linux.c +++ b/loader/linux/icd_linux.c @@ -40,12 +40,7 @@ void khrIcdOsVendorsEnumerate(void) { DIR *dir = NULL; struct dirent *dirEntry = NULL; - char* vendorPath = -#ifdef __ANDROID__ - "/system/vendor/Khronos/OpenCL/vendors/"; -#else - "/etc/OpenCL/vendors/"; -#endif // ANDROID + char* vendorPath = ICD_VENDOR_PATH; char* envPath = NULL; khrIcdVendorsEnumerateEnv(); diff --git a/loader/windows/icd_windows.c b/loader/windows/icd_windows.c index 145a05e5..9c878175 100644 --- a/loader/windows/icd_windows.c +++ b/loader/windows/icd_windows.c @@ -69,7 +69,7 @@ BOOL CALLBACK khrIcdOsVendorsEnumerate(PINIT_ONCE InitOnce, PVOID Parameter, PVO { char cszLibraryName[1024] = {0}; DWORD dwLibraryNameSize = sizeof(cszLibraryName); - DWORD dwLibraryNameType = 0; + DWORD dwLibraryNameType = 0; DWORD dwValue = 0; DWORD dwValueSize = sizeof(dwValue); @@ -85,7 +85,7 @@ BOOL CALLBACK khrIcdOsVendorsEnumerate(PINIT_ONCE InitOnce, PVOID Parameter, PVO (LPBYTE)&dwValue, &dwValueSize); // if RegEnumKeyEx fails, we are done with the enumeration - if (ERROR_SUCCESS != result) + if (ERROR_SUCCESS != result) { KHR_ICD_TRACE("Failed to read value %d, done reading key.\n", dwIndex); break; @@ -93,7 +93,7 @@ BOOL CALLBACK khrIcdOsVendorsEnumerate(PINIT_ONCE InitOnce, PVOID Parameter, PVO KHR_ICD_TRACE("Value %s found...\n", cszLibraryName); // Require that the value be a DWORD and equal zero - if (REG_DWORD != dwLibraryNameType) + if (REG_DWORD != dwLibraryNameType) { KHR_ICD_TRACE("Value not a DWORD, skipping\n"); continue; From ed3e2a673a9b1f88620acb43b63c9b4541a12d8b Mon Sep 17 00:00:00 2001 From: bashbaug Date: Mon, 24 Jun 2019 22:41:59 -0700 Subject: [PATCH 6/6] disable tracing --- loader/icd.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/loader/icd.h b/loader/icd.h index 01a33fd5..34751e95 100644 --- a/loader/icd.h +++ b/loader/icd.h @@ -123,7 +123,7 @@ void khrIcdContextPropertiesGetPlatform( cl_platform_id *outPlatform); // internal tracing macros -#if 1 +#if 0 #include #define KHR_ICD_TRACE(...) \ do \