Use QueryAdapter APIs as per MS directives
[platform/upstream/OpenCL-ICD-Loader.git] / loader / linux / icd_linux.c
1 /*
2  * Copyright (c) 2016-2019 The Khronos Group Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  * OpenCL is a trademark of Apple Inc. used under license by Khronos.
17  */
18
19 #include "icd.h"
20 #include <dlfcn.h>
21 #include <stdio.h>
22 #include <string.h>
23 #include <stdlib.h>
24 #include <sys/types.h>
25 #include <dirent.h>
26 #include <pthread.h>
27
28 static pthread_once_t initialized = PTHREAD_ONCE_INIT;
29
30 /*
31  * 
32  * Vendor enumeration functions
33  *
34  */
35
36 // go through the list of vendors in the two configuration files
37 void khrIcdOsVendorsEnumerate(void)
38 {
39     DIR *dir = NULL;
40     struct dirent *dirEntry = NULL;
41 #ifdef __ANDROID__
42     char *vendorPath = "/system/vendor/Khronos/OpenCL/vendors/";
43 #else
44     char *vendorPath = "/etc/OpenCL/vendors/";
45 #endif // ANDROID
46
47     // open the directory
48     dir = opendir(vendorPath);
49     if (NULL == dir) 
50     {
51         KHR_ICD_TRACE("Failed to open path %s\n", vendorPath);
52         goto Cleanup;
53     }
54
55     // attempt to load all files in the directory
56     for (dirEntry = readdir(dir); dirEntry; dirEntry = readdir(dir) )
57     {
58         switch(dirEntry->d_type)
59         {
60         case DT_UNKNOWN:
61         case DT_REG:
62         case DT_LNK:
63             {
64                 const char* extension = ".icd";
65                 FILE *fin = NULL;
66                 char* fileName = NULL;
67                 char* buffer = NULL;
68                 long bufferSize = 0;
69
70                 // make sure the file name ends in .icd
71                 if (strlen(extension) > strlen(dirEntry->d_name) )
72                 {
73                     break;
74                 }
75                 if (strcmp(dirEntry->d_name + strlen(dirEntry->d_name) - strlen(extension), extension) ) 
76                 {
77                     break;
78                 }
79
80                 // allocate space for the full path of the vendor library name
81                 fileName = malloc(strlen(dirEntry->d_name) + strlen(vendorPath) + 1);
82                 if (!fileName) 
83                 {
84                     KHR_ICD_TRACE("Failed allocate space for ICD file path\n");
85                     break;
86                 }
87                 sprintf(fileName, "%s%s", vendorPath, dirEntry->d_name);
88
89                 // open the file and read its contents
90                 fin = fopen(fileName, "r");
91                 if (!fin)
92                 {
93                     free(fileName);
94                     break;
95                 }
96                 fseek(fin, 0, SEEK_END);
97                 bufferSize = ftell(fin);
98
99                 buffer = malloc(bufferSize+1);
100                 if (!buffer)
101                 {
102                     free(fileName);
103                     fclose(fin);
104                     break;
105                 }                
106                 memset(buffer, 0, bufferSize+1);
107                 fseek(fin, 0, SEEK_SET);                       
108                 if (bufferSize != (long)fread(buffer, 1, bufferSize, fin) )
109                 {
110                     free(fileName);
111                     free(buffer);
112                     fclose(fin);
113                     break;
114                 }
115                 // ignore a newline at the end of the file
116                 if (buffer[bufferSize-1] == '\n') buffer[bufferSize-1] = '\0';
117
118                 // load the string read from the file
119                 khrIcdVendorAdd(buffer);
120                 
121                 free(fileName);
122                 free(buffer);
123                 fclose(fin);
124             }
125             break;
126         default:
127             break;
128         }
129     }
130
131 Cleanup:
132
133     // free resources and exit
134     if (dir) 
135     {
136         closedir(dir);
137     }
138 }
139
140 // go through the list of vendors only once
141 void khrIcdOsVendorsEnumerateOnce(void)
142 {
143     pthread_once(&initialized, khrIcdOsVendorsEnumerate);
144 }
145
146 /*
147  * 
148  * Dynamic library loading functions
149  *
150  */
151
152 // dynamically load a library.  returns NULL on failure
153 void *khrIcdOsLibraryLoad(const char *libraryName)
154 {
155     return dlopen (libraryName, RTLD_NOW);
156 }
157
158 // get a function pointer from a loaded library.  returns NULL on failure.
159 void *khrIcdOsLibraryGetFunctionAddress(void *library, const char *functionName)
160 {
161     return dlsym(library, functionName);
162 }
163
164 // unload a library
165 void khrIcdOsLibraryUnload(void *library)
166 {
167     dlclose(library);
168 }
169
170 // implement device type platform behavior
171 void khrIcdDeviceTypeGetPlatform(cl_device_type device_type, cl_platform_id *outPlatform)
172 {
173 }