Skip to content

Commit 22e8624

Browse files
committed
Deinitialization support.
Co-authored-by: Ben Ashbaugh <ben.ashbaugh@intel.com>
1 parent 634ef47 commit 22e8624

12 files changed

Lines changed: 564 additions & 61 deletions

File tree

include/cl_khr_icd2.h

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,31 @@
1818

1919
#include <CL/cl.h>
2020

21+
#if !defined(CL_PLATFORM_UNLOADABLE_KHR)
22+
#define CL_PLATFORM_UNLOADABLE_KHR 0x0921
23+
#endif
24+
25+
#if defined(CL_ENABLE_LAYERS) && !defined(CL_LAYER_PROPERTIES_LIST_END)
26+
typedef cl_properties cl_layer_properties;
27+
28+
#define CL_LAYER_PROPERTIES_LIST_END ((cl_layer_properties)0)
29+
30+
typedef cl_int CL_API_CALL
31+
clInitLayerWithProperties_t(
32+
cl_uint num_entries,
33+
const cl_icd_dispatch *target_dispatch,
34+
cl_uint *num_entries_ret,
35+
const cl_icd_dispatch **layer_dispatch_ret,
36+
const cl_layer_properties *properties);
37+
38+
typedef clInitLayerWithProperties_t *pfn_clInitLayerWithProperties;
39+
40+
typedef cl_int CL_API_CALL
41+
clDeinitLayer_t(void);
42+
43+
typedef clDeinitLayer_t *pfn_clDeinitLayer;
44+
#endif //defined(CL_ENABLE_LAYERS) && !defined(CL_LAYER_PROPERTIES_LIST_END)
45+
2146
#if !defined(CL_ICD2_TAG_KHR)
2247
#if INTPTR_MAX == INT32_MAX
2348
#define CL_ICD2_TAG_KHR ((intptr_t)0x434C3331)

loader/cllayerinfo.c

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919
#include "icd.h"
2020
#include <stdio.h>
2121
#include <stdlib.h>
22-
#include <CL/cl_layer.h>
2322
#if defined(_WIN32)
2423
#include <io.h>
2524
#include <share.h>
@@ -90,7 +89,7 @@ static void restore_outputs(void)
9089
void printLayerInfo(const struct KHRLayer *layer)
9190
{
9291
cl_layer_api_version api_version = 0;
93-
pfn_clGetLayerInfo p_clGetLayerInfo = (pfn_clGetLayerInfo)(size_t)layer->p_clGetLayerInfo;
92+
pfn_clGetLayerInfo p_clGetLayerInfo = layer->p_clGetLayerInfo;
9493
cl_int result = CL_SUCCESS;
9594
size_t sz;
9695

@@ -113,20 +112,26 @@ void printLayerInfo(const struct KHRLayer *layer)
113112
}
114113
}
115114

116-
int main (int argc, char *argv[])
115+
static void run_silently(void (*pfn)(void))
117116
{
118-
(void)argc;
119-
(void)argv;
120117
silence_layers();
121118
atexit(restore_outputs);
122-
khrIcdInitialize();
119+
pfn();
123120
restore_outputs();
124121
atexit(silence_layers);
122+
}
123+
124+
int main (int argc, char *argv[])
125+
{
126+
(void)argc;
127+
(void)argv;
128+
run_silently(&khrIcdInitialize);
125129
const struct KHRLayer *layer = khrFirstLayer;
126130
while (layer)
127131
{
128132
printLayerInfo(layer);
129133
layer = layer->next;
130134
}
135+
run_silently(&khrIcdDeinitialize);
131136
return 0;
132137
}

loader/icd.c

Lines changed: 155 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -19,30 +19,72 @@
1919
#include "icd.h"
2020
#include "icd_dispatch.h"
2121
#include "icd_envvars.h"
22-
#if defined(CL_ENABLE_LAYERS)
23-
#include <CL/cl_layer.h>
24-
#endif // defined(CL_ENABLE_LAYERS)
2522
#include <stdlib.h>
2623
#include <string.h>
2724

2825
KHRicdVendor *khrIcdVendors = NULL;
26+
static KHRicdVendor *lastVendor = NULL;
2927
int khrEnableTrace = 0;
28+
static int khrDisableLibraryUnloading = 0;
29+
static int khrForceLegacyTermination = 0;
3030

3131
#if defined(CL_ENABLE_LAYERS)
3232
struct KHRLayer *khrFirstLayer = NULL;
3333
#endif // defined(CL_ENABLE_LAYERS)
3434

35+
static int khrIcdCheckEnvTrue(const char *variable)
36+
{
37+
return (variable && (strcmp(variable, "True") == 0 ||
38+
strcmp(variable, "true") == 0 ||
39+
strcmp(variable, "T") == 0 ||
40+
strcmp(variable, "1") == 0));
41+
}
42+
3543
// entrypoint to check and initialize trace.
36-
void khrIcdInitializeTrace(void)
44+
static void khrIcdInitializeTrace(void)
3745
{
3846
char *enableTrace = khrIcd_getenv("OCL_ICD_ENABLE_TRACE");
39-
if (enableTrace && (strcmp(enableTrace, "True") == 0 ||
40-
strcmp(enableTrace, "true") == 0 ||
41-
strcmp(enableTrace, "T") == 0 ||
42-
strcmp(enableTrace, "1") == 0))
47+
if (khrIcdCheckEnvTrue(enableTrace))
4348
{
4449
khrEnableTrace = 1;
4550
}
51+
if (enableTrace)
52+
{
53+
khrIcd_free_getenv(enableTrace);
54+
}
55+
}
56+
57+
static void khrIcdInitializeLibraryUnloading(void)
58+
{
59+
char *disableLibraryUnloading = khrIcd_getenv("OCL_ICD_DISABLE_DYNAMIC_LIBRARY_UNLOADING");
60+
if (khrIcdCheckEnvTrue(disableLibraryUnloading))
61+
{
62+
khrDisableLibraryUnloading = 1;
63+
}
64+
if (disableLibraryUnloading)
65+
{
66+
khrIcd_free_getenv(disableLibraryUnloading);
67+
}
68+
}
69+
70+
static void khrIcdInitializeLegacyTermination(void)
71+
{
72+
char *forceLegacyTermination = khrIcd_getenv("OCL_ICD_FORCE_LEGACY_TERMINATION");
73+
if (khrIcdCheckEnvTrue(forceLegacyTermination))
74+
{
75+
khrForceLegacyTermination = 1;
76+
}
77+
if (forceLegacyTermination)
78+
{
79+
khrIcd_free_getenv(forceLegacyTermination);
80+
}
81+
}
82+
83+
void khrIcdInitializeEnvOptions(void)
84+
{
85+
khrIcdInitializeTrace();
86+
khrIcdInitializeLibraryUnloading();
87+
khrIcdInitializeLegacyTermination();
4688
}
4789

4890
// entrypoint to initialize the ICD and add all vendors
@@ -186,6 +228,14 @@ void khrIcdVendorAdd(const char *libraryName)
186228
#endif
187229

188230
// call clGetPlatformInfo on the returned platform to get the suffix
231+
232+
KHR_ICD2_DISPATCH(platforms[i])->clGetPlatformInfo(
233+
platforms[i],
234+
CL_PLATFORM_UNLOADABLE_KHR,
235+
sizeof(vendor->unloadable),
236+
&vendor->unloadable,
237+
NULL);
238+
189239
result = KHR_ICD2_DISPATCH(platforms[i])->clGetPlatformInfo(
190240
platforms[i],
191241
CL_PLATFORM_ICD_SUFFIX_KHR,
@@ -230,11 +280,13 @@ void khrIcdVendorAdd(const char *libraryName)
230280
vendor->suffix = suffix;
231281

232282
// add this vendor to the list of vendors at the tail
233-
{
234-
KHRicdVendor **prevNextPointer = NULL;
235-
for (prevNextPointer = &khrIcdVendors; *prevNextPointer; prevNextPointer = &( (*prevNextPointer)->next) );
236-
*prevNextPointer = vendor;
283+
if (lastVendor) {
284+
lastVendor->next = vendor;
285+
vendor->prev = lastVendor;
286+
} else {
287+
khrIcdVendors = vendor;
237288
}
289+
lastVendor = vendor;
238290

239291
KHR_ICD_TRACE("successfully added vendor %s with suffix %s\n", libraryName, suffix);
240292

@@ -259,6 +311,8 @@ void khrIcdLayerAdd(const char *libraryName)
259311
cl_int result = CL_SUCCESS;
260312
pfn_clGetLayerInfo p_clGetLayerInfo = NULL;
261313
pfn_clInitLayer p_clInitLayer = NULL;
314+
pfn_clInitLayerWithProperties p_clInitLayerWithProperties = NULL;
315+
pfn_clDeinitLayer p_clDeinitLayer = NULL;
262316
struct KHRLayer *layerIterator = NULL;
263317
struct KHRLayer *layer = NULL;
264318
cl_layer_api_version api_version = 0;
@@ -300,14 +354,6 @@ void khrIcdLayerAdd(const char *libraryName)
300354
goto Done;
301355
}
302356

303-
// use that function to get the clInitLayer function pointer
304-
p_clInitLayer = (pfn_clInitLayer)(size_t)khrIcdOsLibraryGetFunctionAddress(library, "clInitLayer");
305-
if (!p_clInitLayer)
306-
{
307-
KHR_ICD_TRACE("failed to get function address clInitLayer\n");
308-
goto Done;
309-
}
310-
311357
result = p_clGetLayerInfo(CL_LAYER_API_VERSION, sizeof(api_version), &api_version, NULL);
312358
if (CL_SUCCESS != result)
313359
{
@@ -321,6 +367,31 @@ void khrIcdLayerAdd(const char *libraryName)
321367
goto Done;
322368
}
323369

370+
// Support old version of layers, which should rely on at_exit for termination.
371+
// In this case use clInitLayer to initialize layers
372+
if (khrForceLegacyTermination)
373+
{
374+
p_clInitLayer = (pfn_clInitLayer)(size_t)khrIcdOsLibraryGetFunctionAddress(library, "clInitLayer");
375+
if (!p_clInitLayer)
376+
{
377+
KHR_ICD_TRACE("failed to get function address clInitLayer\n");
378+
goto Done;
379+
}
380+
} else { // New scheme, relies on clInitLayerWithProperties and the optional clDeinitLayer for termination
381+
p_clInitLayerWithProperties = (pfn_clInitLayerWithProperties)(size_t)khrIcdOsLibraryGetFunctionAddress(library, "clInitLayerWithProperties");
382+
if (!p_clInitLayerWithProperties)
383+
{
384+
KHR_ICD_TRACE("failed to get function address clInitLayerWithProperties\n");
385+
goto Done;
386+
}
387+
388+
p_clDeinitLayer = (pfn_clDeinitLayer)(size_t)khrIcdOsLibraryGetFunctionAddress(library, "clDeinitLayer");
389+
if (!p_clDeinitLayer)
390+
{
391+
KHR_ICD_TRACE("layer does not support clDeinitLayer\n");
392+
}
393+
}
394+
324395
layer = (struct KHRLayer*)calloc(sizeof(struct KHRLayer), 1);
325396
if (!layer)
326397
{
@@ -338,9 +409,10 @@ void khrIcdLayerAdd(const char *libraryName)
338409
goto Done;
339410
}
340411
memcpy(layer->libraryName, libraryName, sz_name);
341-
layer->p_clGetLayerInfo = (void *)(size_t)p_clGetLayerInfo;
412+
layer->p_clGetLayerInfo = p_clGetLayerInfo;
342413
}
343414
#endif
415+
layer->p_clDeinitLayer = p_clDeinitLayer;
344416

345417
if (khrFirstLayer) {
346418
targetDispatch = &(khrFirstLayer->dispatch);
@@ -349,11 +421,21 @@ void khrIcdLayerAdd(const char *libraryName)
349421
}
350422

351423
loaderDispatchNumEntries = sizeof(khrMainDispatch)/sizeof(void*);
352-
result = p_clInitLayer(
353-
loaderDispatchNumEntries,
354-
targetDispatch,
355-
&layerDispatchNumEntries,
356-
&layerDispatch);
424+
if (khrForceLegacyTermination)
425+
{
426+
result = p_clInitLayer(
427+
loaderDispatchNumEntries,
428+
targetDispatch,
429+
&layerDispatchNumEntries,
430+
&layerDispatch);
431+
} else {
432+
result = p_clInitLayerWithProperties(
433+
loaderDispatchNumEntries,
434+
targetDispatch,
435+
&layerDispatchNumEntries,
436+
&layerDispatch,
437+
NULL);
438+
}
357439
if (CL_SUCCESS != result)
358440
{
359441
KHR_ICD_TRACE("failed to initialize layer\n");
@@ -472,3 +554,50 @@ void khrIcdContextPropertiesGetPlatform(const cl_context_properties *properties,
472554
}
473555
}
474556

557+
#if defined(CL_ENABLE_LAYERS)
558+
static struct KHRLayer deinitLayer = {0};
559+
#endif
560+
561+
void khrIcdDeinitialize(void) {
562+
if (khrForceLegacyTermination)
563+
{
564+
KHR_ICD_TRACE("ICD Loader deinitialization disabled\n");
565+
return;
566+
}
567+
568+
KHR_ICD_TRACE("ICD Loader deinitialization\n");
569+
570+
#if defined(CL_ENABLE_LAYERS)
571+
// free layers first in reverse order of their creation (front to back)
572+
// they may still need to use vendors while terminating
573+
KHR_ICD_TRACE("Finalizing and unloading layers\n");
574+
struct KHRLayer *head = khrFirstLayer;
575+
deinitLayer.dispatch = khrDeinitDispatch;
576+
khrFirstLayer = &deinitLayer;
577+
578+
while(head) {
579+
struct KHRLayer *cur = head;
580+
#ifdef CL_LAYER_INFO
581+
free(cur->libraryName);
582+
#endif
583+
if (cur->p_clDeinitLayer)
584+
cur->p_clDeinitLayer();
585+
if (!khrDisableLibraryUnloading)
586+
khrIcdOsLibraryUnload(cur->library);
587+
head = cur->next;
588+
free(cur);
589+
}
590+
#endif // defined(CL_ENABLE_LAYERS)
591+
592+
// free vendor in reverse order of their creation (back to front)
593+
KHR_ICD_TRACE("Finalizing and unloading vendors\n");
594+
while (lastVendor) {
595+
KHRicdVendor *cur = lastVendor;
596+
free(cur->suffix);
597+
if (cur->unloadable && !khrDisableLibraryUnloading)
598+
khrIcdOsLibraryUnload(cur->library);
599+
lastVendor = cur->prev;
600+
free(cur);
601+
}
602+
khrIcdVendors = NULL;
603+
}

0 commit comments

Comments
 (0)