Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: add an OpenCL ICD loader extension to shut down and free memory #224

Open
wants to merge 10 commits into
base: main
Choose a base branch
from
25 changes: 25 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,31 @@ if((CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME OR OPENCL_ICD_LOADER_BUILD_TESTING)
add_subdirectory (test)
endif()

if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME)
find_package(Python3 COMPONENTS Interpreter)
set(OPENCL_ICD_LOADER_XML_PATH CACHE FILEPATH "Path to cl.xml for OpenCL ICD Loader code generation")
set(OPENCL_ICD_LOADER_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/generated)
add_custom_target(icd_loader_generate
COMMAND ${CMAKE_COMMAND} -E make_directory ${OPENCL_ICD_LOADER_OUTPUT_DIRECTORY}
COMMAND ${CMAKE_COMMAND} -E chdir ${CMAKE_CURRENT_SOURCE_DIR}/scripts
${Python3_EXECUTABLE} gen_loader.py
-registry ${OPENCL_ICD_LOADER_XML_PATH}
-o ${OPENCL_ICD_LOADER_OUTPUT_DIRECTORY}
COMMAND ${CMAKE_COMMAND} -E chdir ${CMAKE_CURRENT_SOURCE_DIR}/scripts
${Python3_EXECUTABLE} gen_print_layer.py
-registry ${OPENCL_ICD_LOADER_XML_PATH}
-o ${OPENCL_ICD_LOADER_OUTPUT_DIRECTORY}
)
add_custom_target(icd_loader_copy
COMMAND ${CMAKE_COMMAND} -E copy
${OPENCL_ICD_LOADER_OUTPUT_DIRECTORY}/icd_dispatch_generated.c
${CMAKE_CURRENT_SOURCE_DIR}/loader
COMMAND ${CMAKE_COMMAND} -E copy
${OPENCL_ICD_LOADER_OUTPUT_DIRECTORY}/icd_print_layer_generated.c
${CMAKE_CURRENT_SOURCE_DIR}/test/layer
)
endif()

include (GNUInstallDirs)

install(
Expand Down
66 changes: 64 additions & 2 deletions loader/icd.c
Original file line number Diff line number Diff line change
Expand Up @@ -303,10 +303,10 @@ void khrIcdLayerAdd(const char *libraryName)
if (khrFirstLayer) {
targetDispatch = &(khrFirstLayer->dispatch);
} else {
targetDispatch = &khrMasterDispatch;
targetDispatch = &khrActualDispatch;
}

loaderDispatchNumEntries = sizeof(khrMasterDispatch)/sizeof(void*);
loaderDispatchNumEntries = sizeof(khrActualDispatch)/sizeof(void*);
result = p_clInitLayer(
loaderDispatchNumEntries,
targetDispatch,
Expand Down Expand Up @@ -430,3 +430,65 @@ void khrIcdContextPropertiesGetPlatform(const cl_context_properties *properties,
}
}

#if defined(CL_ENABLE_LAYERS)
extern struct _cl_icd_dispatch khrShutdownDispatch;
static struct KHRLayer shutdown_layer = {0};
#endif

void khrIcdShutdown(void)
{
KHRicdVendor* prevVendor = NULL;
KHRicdVendor* vendor = NULL;

#if defined(CL_ENABLE_LAYERS)
struct KHRLayer* layer = khrFirstLayer;
struct KHRLayer* nextLayer = NULL;
#endif

KHR_ICD_TRACE("Shutdown starting\n");

#if defined(CL_ENABLE_LAYERS)
KHR_ICD_TRACE("Installing shutdown layer\n");
shutdown_layer.dispatch = khrShutdownDispatch;
khrFirstLayer = &shutdown_layer;
#endif

#if defined(CL_ENABLE_LAYERS)
// Layers are freed in the reverse order they were added,
// so front-to-back.
KHR_ICD_TRACE("Cleaning up Layers\n");
// Handle the case where shutdown is called twice:
if (layer != &shutdown_layer) {
while (layer) {
nextLayer = layer->next;
#if defined(CL_LAYER_INFO)
free(layer->libraryName);
#endif
free(layer);
layer = nextLayer;
}
}
#endif

// Vendors are freed in the reverse order they were added,
// so back-to-front.
KHR_ICD_TRACE("Cleaning up Vendors\n");
while (khrIcdVendors) {
if (khrIcdVendors->next == NULL) {
vendor = khrIcdVendors;
khrIcdVendors = NULL;
} else {
prevVendor = khrIcdVendors;
vendor = khrIcdVendors->next;
while (vendor->next) {
prevVendor = vendor;
vendor = vendor->next;
}
prevVendor->next = NULL;
}
free(vendor->suffix);
free(vendor);
}

KHR_ICD_TRACE("Shutdown complete\n");
}
6 changes: 4 additions & 2 deletions loader/icd.h
Original file line number Diff line number Diff line change
Expand Up @@ -117,14 +117,14 @@ struct KHRLayer
#ifdef CL_LAYER_INFO
// The layer library name
char *libraryName;
// the pointer to the clGetLayerInfo funciton
// the pointer to the clGetLayerInfo function
void *p_clGetLayerInfo;
#endif
};

// the global layer state
extern struct KHRLayer * khrFirstLayer;
extern struct _cl_icd_dispatch khrMasterDispatch;
extern struct _cl_icd_dispatch khrActualDispatch;
#endif // defined(CL_ENABLE_LAYERS)

/*
Expand Down Expand Up @@ -175,6 +175,8 @@ void khrIcdContextPropertiesGetPlatform(
const cl_context_properties *properties,
cl_platform_id *outPlatform);

void khrIcdShutdown(void);

// internal tracing macros
#define KHR_ICD_TRACE(...) \
do \
Expand Down
10 changes: 10 additions & 0 deletions loader/icd_dispatch.c
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,13 @@ clGetICDLoaderInfoOCLICD(
return CL_SUCCESS;
}

// !!! TODO: Switch this to use the function typedef when it's in the headers!
static cl_int CL_API_CALL clShutdownOCLICD(void)
{
khrIcdShutdown();
return CL_SUCCESS;
}

static void* khrIcdGetExtensionFunctionAddress(const char* function_name)
{
// Most extensions, including multi-vendor KHR and EXT extensions,
Expand Down Expand Up @@ -139,6 +146,9 @@ static void* khrIcdGetExtensionFunctionAddress(const char* function_name)
// cl_icdl
KHR_ICD_CHECK_EXTENSION_FUNCTION(clGetICDLoaderInfoOCLICD);

// cl_icd_shutdown
KHR_ICD_CHECK_EXTENSION_FUNCTION(clShutdownOCLICD);

#undef KHR_ICD_CHECK_EXTENSION_FUNCTION

return NULL;
Expand Down
Loading