Update nikhiljnv:new_para_virtual with Khronos master
Merge branch 'master' of https://github.com/KhronosGroup/OpenCL-ICD-Loader into KhronosGroup-master
diff --git a/CMakeLists.txt b/CMakeLists.txt
index b3f8c0b..21da30d 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,6 +1,7 @@
cmake_minimum_required (VERSION 2.8.11)
project (OPENCL_ICD_LOADER)
+include (GNUInstallDirs)
find_package (Threads REQUIRED)
# The option below allows building the ICD Loader library as a shared library
@@ -33,15 +34,28 @@
# 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)
+ 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_hkr.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_hkr.h
loader/windows/OpenCL.def
loader/windows/OpenCL.rc)
# Only add the DXSDK include directory if the environment variable is
@@ -53,6 +67,7 @@
else ()
list (APPEND OPENCL_ICD_LOADER_SOURCES
loader/linux/icd_linux.c
+ loader/linux/icd_linux_envvars.c
loader/linux/icd_exports.map)
endif ()
@@ -108,7 +123,7 @@
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)
@@ -117,6 +132,6 @@
endif()
install (TARGETS OpenCL
- RUNTIME DESTINATION bin
- ARCHIVE DESTINATION lib
- LIBRARY DESTINATION lib)
+ RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
+ ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
+ LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR})
diff --git a/README.md b/README.md
index d520ac0..099f3a6 100644
--- a/README.md
+++ b/README.md
@@ -121,3 +121,12 @@
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.
+
+## 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`<br/><br/>`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` |
diff --git a/loader/icd.c b/loader/icd.c
index 8e142c4..ea8306a 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 <stdlib.h>
#include <string.h>
@@ -188,6 +189,46 @@
}
}
+// 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 a1b6969..34751e9 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 <CL/cl.h>
#include <CL/cl_ext.h>
-#ifdef _WIN32
-#include <tchar.h>
-#endif
-
/*
* type definitions
*/
@@ -101,6 +99,9 @@
// 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);
diff --git a/loader/icd_cmake_config.h.in b/loader/icd_cmake_config.h.in
new file mode 100644
index 0000000..3bbc461
--- /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 0000000..0d34d3d
--- /dev/null
+++ b/loader/icd_envvars.h
@@ -0,0 +1,26 @@
+/*
+ * 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_
+
+char *khrIcd_getenv(const char *name);
+char *khrIcd_secure_getenv(const char *name);
+void khrIcd_free_getenv(char *val);
+
+#endif
diff --git a/loader/icd_platform.h b/loader/icd_platform.h
new file mode 100644
index 0000000..b16d0db
--- /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 a36655e..809f095 100644
--- a/loader/linux/icd_linux.c
+++ b/loader/linux/icd_linux.c
@@ -17,6 +17,8 @@
*/
#include "icd.h"
+#include "icd_envvars.h"
+
#include <dlfcn.h>
#include <stdio.h>
#include <string.h>
@@ -38,102 +40,106 @@
{
DIR *dir = NULL;
struct dirent *dirEntry = NULL;
-#ifdef __ANDROID__
- char *vendorPath = "/system/vendor/Khronos/OpenCL/vendors/";
-#else
- char *vendorPath = "/etc/OpenCL/vendors/";
-#endif // ANDROID
+ char* vendorPath = ICD_VENDOR_PATH;
+ char* envPath = NULL;
- // open the directory
+ khrIcdVendorsEnumerateEnv();
+
+ envPath = khrIcd_secure_getenv("OCL_ICD_VENDORS");
+ if (NULL != envPath)
+ {
+ vendorPath = envPath;
+ }
+
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;
+ case DT_UNKNOWN:
+ case DT_REG:
+ case DT_LNK:
+ {
+ 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;
- }
+ // 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);
+ // 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);
+ // 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) )
- {
+ 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;
}
- // 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;
}
+
+ closedir(dir);
}
-Cleanup:
-
- // free resources and exit
- if (dir)
+ if (NULL != envPath)
{
- closedir(dir);
+ khrIcd_free_getenv(envPath);
}
}
diff --git a/loader/linux/icd_linux_envvars.c b/loader/linux/icd_linux_envvars.c
new file mode 100644
index 0000000..4af5a08
--- /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 <stdlib.h>
+
+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/OpenCL.rc b/loader/windows/OpenCL.rc
index 330da28..e70ef06 100644
--- a/loader/windows/OpenCL.rc
+++ b/loader/windows/OpenCL.rc
@@ -20,7 +20,7 @@
#define OPENCL_ICD_LOADER_VERSION_MAJOR 2
#define OPENCL_ICD_LOADER_VERSION_MINOR 2
-#define OPENCL_ICD_LOADER_VERSION_REV 2
+#define OPENCL_ICD_LOADER_VERSION_REV 3
#ifdef RC_INVOKED
diff --git a/loader/windows/icd_windows.c b/loader/windows/icd_windows.c
index 6f7d880..22b296b 100644
--- a/loader/windows/icd_windows.c
+++ b/loader/windows/icd_windows.c
@@ -93,6 +93,8 @@
HKEY platformsKey = NULL;
DWORD dwIndex;
+ khrIcdVendorsEnumerateEnv();
+
if (!khrIcdOsVendorsEnumerateDXGK())
{
KHR_ICD_TRACE("Failed to load via DXGK interface on RS4, continuing\n");
@@ -113,13 +115,14 @@
{
KHR_ICD_TRACE("Failed to open platforms key %s, continuing\n", platformsName);
}
- else {
+ else
+ {
// for each value
for (dwIndex = 0;; ++dwIndex)
{
- char cszLibraryName[MAX_PATH] = {0};
+ char cszLibraryName[1024] = {0};
DWORD dwLibraryNameSize = sizeof(cszLibraryName);
- DWORD dwLibraryNameType = 0;
+ DWORD dwLibraryNameType = 0;
DWORD dwValue = 0;
DWORD dwValueSize = sizeof(dwValue);
@@ -135,7 +138,7 @@
(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;
@@ -143,7 +146,7 @@
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;
diff --git a/loader/windows/icd_windows_envvars.c b/loader/windows/icd_windows_envvars.c
new file mode 100644
index 0000000..c68cab6
--- /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 <windows.h>
+
+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);
+}
diff --git a/test/driver_stub/driver_stub.def b/test/driver_stub/driver_stub.def
index 5b238e8..1ec2760 100644
--- a/test/driver_stub/driver_stub.def
+++ b/test/driver_stub/driver_stub.def
@@ -1,3 +1,2 @@
EXPORTS
clGetExtensionFunctionAddress
-clIcdGetPlatformIDsKHR