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
2825KHRicdVendor * khrIcdVendors = NULL ;
26+ static KHRicdVendor * lastVendor = NULL ;
2927int khrEnableTrace = 0 ;
28+ static int khrDisableLibraryUnloading = 0 ;
29+ static int khrForceLegacyTermination = 0 ;
3030
3131#if defined(CL_ENABLE_LAYERS )
3232struct 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 ("failed to get function address 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