Added OpenCL Universal Driver Support for Win10 RS3 (#21)
[platform/upstream/OpenCL-ICD-Loader.git] / icd_linux.c
1 /*
2  * Copyright (c) 2016 The Khronos Group Inc.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a copy
5  * of this software source and associated documentation files (the "Materials"),
6  * to deal in the Materials without restriction, including without limitation
7  * the rights to use, copy, modify, compile, merge, publish, distribute,
8  * sublicense, and/or sell copies of the Materials, and to permit persons to
9  * whom the Materials are furnished to do so, subject the following terms and
10  * conditions:
11  *
12  * All modifications to the Materials used to create a binary that is
13  * distributed to third parties shall be provided to Khronos with an
14  * unrestricted license to use for the purposes of implementing bug fixes and
15  * enhancements to the Materials;
16  *
17  * If the binary is used as part of an OpenCL(TM) implementation, whether binary
18  * is distributed together with or separately to that implementation, then
19  * recipient must become an OpenCL Adopter and follow the published OpenCL
20  * conformance process for that implementation, details at:
21  * http://www.khronos.org/conformance/;
22  *
23  * The above copyright notice, the OpenCL trademark license, and this permission
24  * notice shall be included in all copies or substantial portions of the
25  * Materials.
26  *
27  * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
28  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
29  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
30  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
31  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
32  * OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS IN
33  * THE MATERIALS.
34  *
35  * OpenCL is a trademark of Apple Inc. used under license by Khronos.
36  */
37
38 #include "icd.h"
39 #include <dlfcn.h>
40 #include <stdio.h>
41 #include <string.h>
42 #include <stdlib.h>
43 #include <sys/types.h>
44 #include <dirent.h>
45 #include <pthread.h>
46
47 static pthread_once_t initialized = PTHREAD_ONCE_INIT;
48
49 /*
50  * 
51  * Vendor enumeration functions
52  *
53  */
54
55 // go through the list of vendors in the two configuration files
56 void khrIcdOsVendorsEnumerate(void)
57 {
58     DIR *dir = NULL;
59     struct dirent *dirEntry = NULL;
60 #ifdef __ANDROID__
61     char *vendorPath = "/system/vendor/Khronos/OpenCL/vendors/";
62 #else
63     char *vendorPath = "/etc/OpenCL/vendors/";
64 #endif // ANDROID
65
66     // open the directory
67     dir = opendir(vendorPath);
68     if (NULL == dir) 
69     {
70         KHR_ICD_TRACE("Failed to open path %s\n", vendorPath);
71         goto Cleanup;
72     }
73
74     // attempt to load all files in the directory
75     for (dirEntry = readdir(dir); dirEntry; dirEntry = readdir(dir) )
76     {
77         switch(dirEntry->d_type)
78         {
79         case DT_UNKNOWN:
80         case DT_REG:
81         case DT_LNK:
82             {
83                 const char* extension = ".icd";
84                 FILE *fin = NULL;
85                 char* fileName = NULL;
86                 char* buffer = NULL;
87                 long bufferSize = 0;
88
89                 // make sure the file name ends in .icd
90                 if (strlen(extension) > strlen(dirEntry->d_name) )
91                 {
92                     break;
93                 }
94                 if (strcmp(dirEntry->d_name + strlen(dirEntry->d_name) - strlen(extension), extension) ) 
95                 {
96                     break;
97                 }
98
99                 // allocate space for the full path of the vendor library name
100                 fileName = malloc(strlen(dirEntry->d_name) + strlen(vendorPath) + 1);
101                 if (!fileName) 
102                 {
103                     KHR_ICD_TRACE("Failed allocate space for ICD file path\n");
104                     break;
105                 }
106                 sprintf(fileName, "%s%s", vendorPath, dirEntry->d_name);
107
108                 // open the file and read its contents
109                 fin = fopen(fileName, "r");
110                 if (!fin)
111                 {
112                     free(fileName);
113                     break;
114                 }
115                 fseek(fin, 0, SEEK_END);
116                 bufferSize = ftell(fin);
117
118                 buffer = malloc(bufferSize+1);
119                 if (!buffer)
120                 {
121                     free(fileName);
122                     fclose(fin);
123                     break;
124                 }                
125                 memset(buffer, 0, bufferSize+1);
126                 fseek(fin, 0, SEEK_SET);                       
127                 if (bufferSize != (long)fread(buffer, 1, bufferSize, fin) )
128                 {
129                     free(fileName);
130                     free(buffer);
131                     fclose(fin);
132                     break;
133                 }
134                 // ignore a newline at the end of the file
135                 if (buffer[bufferSize-1] == '\n') buffer[bufferSize-1] = '\0';
136
137                 // load the string read from the file
138                 khrIcdVendorAdd(buffer);
139                 
140                 free(fileName);
141                 free(buffer);
142                 fclose(fin);
143             }
144             break;
145         default:
146             break;
147         }
148     }
149
150 Cleanup:
151
152     // free resources and exit
153     if (dir) 
154     {
155         closedir(dir);
156     }
157 }
158
159 // go through the list of vendors only once
160 void khrIcdOsVendorsEnumerateOnce(void)
161 {
162     pthread_once(&initialized, khrIcdOsVendorsEnumerate);
163 }
164
165 /*
166  * 
167  * Dynamic library loading functions
168  *
169  */
170
171 // dynamically load a library.  returns NULL on failure
172 void *khrIcdOsLibraryLoad(const char *libraryName)
173 {
174     return dlopen (libraryName, RTLD_NOW);
175 }
176
177 // get a function pointer from a loaded library.  returns NULL on failure.
178 void *khrIcdOsLibraryGetFunctionAddress(void *library, const char *functionName)
179 {
180     return dlsym(library, functionName);
181 }
182
183 // unload a library
184 void khrIcdOsLibraryUnload(void *library)
185 {
186     dlclose(library);
187 }
188