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- // entrypoint to check and initialize trace.
36- void khrIcdInitializeTrace (void )
35+ static inline 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+
43+ // Set a given flag if the given environement variable is true
44+ static void khrInitializeFlagWithEnv (int * flag , const char * variable )
3745{
38- 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 ))
46+ char * variableStr = khrIcd_getenv (variable );
47+ if (khrIcdCheckEnvTrue (variableStr ))
48+ {
49+ * flag = 1 ;
50+ }
51+ if (variableStr )
4352 {
44- khrEnableTrace = 1 ;
53+ khrIcd_free_getenv ( variableStr ) ;
4554 }
4655}
4756
57+ void khrIcdInitializeEnvOptions (void )
58+ {
59+ khrInitializeFlagWithEnv (& khrEnableTrace , "OCL_ICD_ENABLE_TRACE" );
60+ khrInitializeFlagWithEnv (& khrDisableLibraryUnloading , "OCL_ICD_DISABLE_DYNAMIC_LIBRARY_UNLOADING" );
61+ khrInitializeFlagWithEnv (& khrForceLegacyTermination , "OCL_ICD_FORCE_LEGACY_TERMINATION" );
62+ }
63+
4864// entrypoint to initialize the ICD and add all vendors
4965void khrIcdInitialize (void )
5066{
@@ -186,6 +202,14 @@ void khrIcdVendorAdd(const char *libraryName)
186202#endif
187203
188204 // call clGetPlatformInfo on the returned platform to get the suffix
205+
206+ KHR_ICD2_DISPATCH (platforms [i ])-> clGetPlatformInfo (
207+ platforms [i ],
208+ CL_PLATFORM_UNLOADABLE_KHR ,
209+ sizeof (vendor -> unloadable ),
210+ & vendor -> unloadable ,
211+ NULL );
212+
189213 result = KHR_ICD2_DISPATCH (platforms [i ])-> clGetPlatformInfo (
190214 platforms [i ],
191215 CL_PLATFORM_ICD_SUFFIX_KHR ,
@@ -230,11 +254,13 @@ void khrIcdVendorAdd(const char *libraryName)
230254 vendor -> suffix = suffix ;
231255
232256 // 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 ;
257+ if (lastVendor ) {
258+ lastVendor -> next = vendor ;
259+ vendor -> prev = lastVendor ;
260+ } else {
261+ khrIcdVendors = vendor ;
237262 }
263+ lastVendor = vendor ;
238264
239265 KHR_ICD_TRACE ("successfully added vendor %s with suffix %s\n" , libraryName , suffix );
240266
@@ -259,6 +285,8 @@ void khrIcdLayerAdd(const char *libraryName)
259285 cl_int result = CL_SUCCESS ;
260286 pfn_clGetLayerInfo p_clGetLayerInfo = NULL ;
261287 pfn_clInitLayer p_clInitLayer = NULL ;
288+ pfn_clInitLayerWithProperties p_clInitLayerWithProperties = NULL ;
289+ pfn_clDeinitLayer p_clDeinitLayer = NULL ;
262290 struct KHRLayer * layerIterator = NULL ;
263291 struct KHRLayer * layer = NULL ;
264292 cl_layer_api_version api_version = 0 ;
@@ -300,14 +328,6 @@ void khrIcdLayerAdd(const char *libraryName)
300328 goto Done ;
301329 }
302330
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-
311331 result = p_clGetLayerInfo (CL_LAYER_API_VERSION , sizeof (api_version ), & api_version , NULL );
312332 if (CL_SUCCESS != result )
313333 {
@@ -321,6 +341,31 @@ void khrIcdLayerAdd(const char *libraryName)
321341 goto Done ;
322342 }
323343
344+ // Support old version of layers, which should rely on at_exit for termination.
345+ // In this case use clInitLayer to initialize layers
346+ if (khrForceLegacyTermination )
347+ {
348+ p_clInitLayer = (pfn_clInitLayer )(size_t )khrIcdOsLibraryGetFunctionAddress (library , "clInitLayer" );
349+ if (!p_clInitLayer )
350+ {
351+ KHR_ICD_TRACE ("failed to get function address clInitLayer\n" );
352+ goto Done ;
353+ }
354+ } else { // New scheme, relies on clInitLayerWithProperties and the optional clDeinitLayer for termination
355+ p_clInitLayerWithProperties = (pfn_clInitLayerWithProperties )(size_t )khrIcdOsLibraryGetFunctionAddress (library , "clInitLayerWithProperties" );
356+ if (!p_clInitLayerWithProperties )
357+ {
358+ KHR_ICD_TRACE ("failed to get function address clInitLayerWithProperties\n" );
359+ goto Done ;
360+ }
361+
362+ p_clDeinitLayer = (pfn_clDeinitLayer )(size_t )khrIcdOsLibraryGetFunctionAddress (library , "clDeinitLayer" );
363+ if (!p_clDeinitLayer )
364+ {
365+ KHR_ICD_TRACE ("layer does not support clDeinitLayer\n" );
366+ }
367+ }
368+
324369 layer = (struct KHRLayer * )calloc (sizeof (struct KHRLayer ), 1 );
325370 if (!layer )
326371 {
@@ -338,9 +383,10 @@ void khrIcdLayerAdd(const char *libraryName)
338383 goto Done ;
339384 }
340385 memcpy (layer -> libraryName , libraryName , sz_name );
341- layer -> p_clGetLayerInfo = ( void * )( size_t ) p_clGetLayerInfo ;
386+ layer -> p_clGetLayerInfo = p_clGetLayerInfo ;
342387 }
343388#endif
389+ layer -> p_clDeinitLayer = p_clDeinitLayer ;
344390
345391 if (khrFirstLayer ) {
346392 targetDispatch = & (khrFirstLayer -> dispatch );
@@ -349,11 +395,21 @@ void khrIcdLayerAdd(const char *libraryName)
349395 }
350396
351397 loaderDispatchNumEntries = sizeof (khrMainDispatch )/sizeof (void * );
352- result = p_clInitLayer (
353- loaderDispatchNumEntries ,
354- targetDispatch ,
355- & layerDispatchNumEntries ,
356- & layerDispatch );
398+ if (khrForceLegacyTermination )
399+ {
400+ result = p_clInitLayer (
401+ loaderDispatchNumEntries ,
402+ targetDispatch ,
403+ & layerDispatchNumEntries ,
404+ & layerDispatch );
405+ } else {
406+ result = p_clInitLayerWithProperties (
407+ loaderDispatchNumEntries ,
408+ targetDispatch ,
409+ & layerDispatchNumEntries ,
410+ & layerDispatch ,
411+ NULL );
412+ }
357413 if (CL_SUCCESS != result )
358414 {
359415 KHR_ICD_TRACE ("failed to initialize layer\n" );
@@ -472,3 +528,50 @@ void khrIcdContextPropertiesGetPlatform(const cl_context_properties *properties,
472528 }
473529}
474530
531+ #if defined(CL_ENABLE_LAYERS )
532+ static struct KHRLayer deinitLayer = {0 };
533+ #endif
534+
535+ void khrIcdDeinitialize (void ) {
536+ if (khrForceLegacyTermination )
537+ {
538+ KHR_ICD_TRACE ("ICD Loader deinitialization disabled\n" );
539+ return ;
540+ }
541+
542+ KHR_ICD_TRACE ("ICD Loader deinitialization\n" );
543+
544+ #if defined(CL_ENABLE_LAYERS )
545+ // free layers first in reverse order of their creation (front to back)
546+ // they may still need to use vendors while terminating
547+ KHR_ICD_TRACE ("Finalizing and unloading layers\n" );
548+ struct KHRLayer * head = khrFirstLayer ;
549+ deinitLayer .dispatch = khrDeinitDispatch ;
550+ khrFirstLayer = & deinitLayer ;
551+
552+ while (head ) {
553+ struct KHRLayer * cur = head ;
554+ #ifdef CL_LAYER_INFO
555+ free (cur -> libraryName );
556+ #endif
557+ if (cur -> p_clDeinitLayer )
558+ cur -> p_clDeinitLayer ();
559+ if (!khrDisableLibraryUnloading )
560+ khrIcdOsLibraryUnload (cur -> library );
561+ head = cur -> next ;
562+ free (cur );
563+ }
564+ #endif // defined(CL_ENABLE_LAYERS)
565+
566+ // free vendor in reverse order of their creation (back to front)
567+ KHR_ICD_TRACE ("Finalizing and unloading vendors\n" );
568+ while (lastVendor ) {
569+ KHRicdVendor * cur = lastVendor ;
570+ free (cur -> suffix );
571+ if (cur -> unloadable && !khrDisableLibraryUnloading )
572+ khrIcdOsLibraryUnload (cur -> library );
573+ lastVendor = cur -> prev ;
574+ free (cur );
575+ }
576+ khrIcdVendors = NULL ;
577+ }
0 commit comments