diff --git a/doc/loader_api.md b/doc/loader_api.md index 210cbcae..2d55d0ea 100644 --- a/doc/loader_api.md +++ b/doc/loader_api.md @@ -70,4 +70,17 @@ This does not unload the tracing layer library such that one can call `zelEnable NOTE: The each call to `zelEnableTracingLayer` tracks a reference count of how many calls to enable have been seen. The Tracing Layer intercepts will not be removed until the reference count has reached 0 indicating that all users of the tracing layer have called `zelDisableTracingLayer`. +### zelGetTracingLayerState + +Queries the current enabled state of the tracing layer at runtime. + +This function allows applications to check whether the tracing layer is currently active, returning the state through a boolean pointer. + +- __*enabled__ Pointer to a boolean that will be set to `true` if the tracing layer is currently enabled, or `false` if it is disabled. + +The function returns: +- `ZE_RESULT_SUCCESS` on successful query +- `ZE_RESULT_ERROR_INVALID_NULL_POINTER` if the `enabled` pointer is null + +This is a read-only, thread-safe operation that can be called multiple times concurrently. The tracing layer state is global to the process and reflects the current reference count maintained by `zelEnableTracingLayer` and `zelDisableTracingLayer` - the layer is considered enabled when the reference count is greater than zero. diff --git a/include/loader/ze_loader.h b/include/loader/ze_loader.h index 74485ba1..55cf6449 100644 --- a/include/loader/ze_loader.h +++ b/include/loader/ze_loader.h @@ -199,6 +199,28 @@ zelRegisterTeardownCallback( ZE_DLLEXPORT ze_result_t ZE_APICALL zelDisableTracingLayer(); +/** + * @brief Retrieves the current enabled state of the Level Zero tracing layer. + * + * This function queries whether the tracing layer is active and writes the result + * to the provided boolean pointer. + * + * @param enabled + * Pointer to a boolean that will be set to true if the tracing layer is + * currently enabled, or false if it is disabled. Must be a valid, non-null + * pointer. + * + * @return + * ZE_RESULT_SUCCESS on success. + * ZE_RESULT_ERROR_INVALID_NULL_POINTER if `enabled` is null. + * Other ze_result_t error codes may be returned for implementation-specific failures. + * + * @note The tracing layer state is global to the process. The function is read-only + * and thread-safe; multiple callers can query the state concurrently. + */ +ZE_DLLEXPORT ze_result_t ZE_APICALL +zelGetTracingLayerState(bool* enabled); // Pointer to bool to receive tracing layer state + #if defined(__cplusplus) } // extern "C" #endif diff --git a/source/lib/ze_lib.cpp b/source/lib/ze_lib.cpp index 0b26af38..e9590592 100644 --- a/source/lib/ze_lib.cpp +++ b/source/lib/ze_lib.cpp @@ -635,6 +635,36 @@ zelEnableTracingLayer() return ZE_RESULT_SUCCESS; } +ze_result_t ZE_APICALL +zelGetTracingLayerState +( + bool* enabled // Pointer to bool to receive tracing layer state +) +{ + if (enabled == nullptr) { + return ZE_RESULT_ERROR_INVALID_NULL_POINTER; + } + #ifdef L0_STATIC_LOADER_BUILD + if(nullptr == ze_lib::context->loader) + return ZE_RESULT_ERROR_UNINITIALIZED; + typedef ze_result_t (ZE_APICALL *zelGetTracingLayerStateInternal_t)(bool* enabled); + auto getDynamicTracingState = reinterpret_cast( + GET_FUNCTION_PTR(ze_lib::context->loader, "zelGetTracingLayerState") ); + return getDynamicTracingState(enabled); + #else + if (ze_lib::context->dynamicTracingSupported == false) { + return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE; + } + if (loader::context) { + *enabled = loader::context->tracingLayerEnabled; + } + if (!*enabled) { + *enabled = (ze_lib::context->tracingLayerEnableCounter.load() > 0); + } + #endif + return ZE_RESULT_SUCCESS; +} + ze_result_t ZE_APICALL zelDisableTracingLayer() { diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index dd10c27e..878cb379 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -211,6 +211,42 @@ endif() add_test(NAME tests_loader_teardown_check COMMAND tests --gtest_filter=*GivenLoaderNotInDestructionStateWhenCallingzelCheckIsLoaderInTearDownThenFalseIsReturned) set_property(TEST tests_loader_teardown_check PROPERTY ENVIRONMENT "ZE_ENABLE_LOADER_DEBUG_TRACE=1;ZE_ENABLE_NULL_DRIVER=1") +add_test(NAME tests_tracing_layer_state_null_pointer COMMAND tests --gtest_filter=*TracingLayerState.GivenNullPointerWhenCallingzelGetTracingLayerStateThenErrorInvalidNullPointerIsReturned) +set_property(TEST tests_tracing_layer_state_null_pointer PROPERTY ENVIRONMENT "ZE_ENABLE_LOADER_DEBUG_TRACE=1;ZE_ENABLE_NULL_DRIVER=1") + +add_test(NAME tests_tracing_layer_state_valid_pointer COMMAND tests --gtest_filter=*TracingLayerState.GivenValidPointerWhenCallingzelGetTracingLayerStateThenSuccessIsReturned) +set_property(TEST tests_tracing_layer_state_valid_pointer PROPERTY ENVIRONMENT "ZE_ENABLE_LOADER_DEBUG_TRACE=1;ZE_ENABLE_NULL_DRIVER=1") + +add_test(NAME tests_tracing_layer_state_not_enabled COMMAND tests --gtest_filter=*TracingLayerState.GivenTracingLayerNotEnabledWhenCallingzelGetTracingLayerStateThenFalseIsReturned) +set_property(TEST tests_tracing_layer_state_not_enabled PROPERTY ENVIRONMENT "ZE_ENABLE_LOADER_DEBUG_TRACE=1;ZE_ENABLE_NULL_DRIVER=1") + +add_test(NAME tests_tracing_layer_state_enabled COMMAND tests --gtest_filter=*TracingLayerState.GivenTracingLayerEnabledWhenCallingzelGetTracingLayerStateThenTrueIsReturned) +set_property(TEST tests_tracing_layer_state_enabled PROPERTY ENVIRONMENT "ZE_ENABLE_LOADER_DEBUG_TRACE=1;ZE_ENABLE_NULL_DRIVER=1") + +add_test(NAME tests_tracing_layer_state_enabled_then_disabled COMMAND tests --gtest_filter=*TracingLayerState.GivenTracingLayerEnabledThenDisabledWhenCallingzelGetTracingLayerStateThenFalseIsReturned) +set_property(TEST tests_tracing_layer_state_enabled_then_disabled PROPERTY ENVIRONMENT "ZE_ENABLE_LOADER_DEBUG_TRACE=1;ZE_ENABLE_NULL_DRIVER=1") + +add_test(NAME tests_tracing_layer_state_multiple_enable COMMAND tests --gtest_filter=*TracingLayerState.GivenMultipleEnableCallsWhenCallingzelGetTracingLayerStateThenTrueIsReturned) +set_property(TEST tests_tracing_layer_state_multiple_enable PROPERTY ENVIRONMENT "ZE_ENABLE_LOADER_DEBUG_TRACE=1;ZE_ENABLE_NULL_DRIVER=1") + +add_test(NAME tests_tracing_layer_state_multiple_enable_partial_disable COMMAND tests --gtest_filter=*TracingLayerState.GivenMultipleEnableAndPartialDisableWhenCallingzelGetTracingLayerStateThenTrueIsReturned) +set_property(TEST tests_tracing_layer_state_multiple_enable_partial_disable PROPERTY ENVIRONMENT "ZE_ENABLE_LOADER_DEBUG_TRACE=1;ZE_ENABLE_NULL_DRIVER=1") + +add_test(NAME tests_tracing_layer_state_multiple_calls_enabled COMMAND tests --gtest_filter=*TracingLayerState.GivenMultipleCallsTozelGetTracingLayerStateWhenTracingEnabledThenAllReturnTrue) +set_property(TEST tests_tracing_layer_state_multiple_calls_enabled PROPERTY ENVIRONMENT "ZE_ENABLE_LOADER_DEBUG_TRACE=1;ZE_ENABLE_NULL_DRIVER=1") + +add_test(NAME tests_tracing_layer_state_multiple_calls_disabled COMMAND tests --gtest_filter=*TracingLayerState.GivenMultipleCallsTozelGetTracingLayerStateWhenTracingDisabledThenAllReturnFalse) +set_property(TEST tests_tracing_layer_state_multiple_calls_disabled PROPERTY ENVIRONMENT "ZE_ENABLE_LOADER_DEBUG_TRACE=1;ZE_ENABLE_NULL_DRIVER=1") + +add_test(NAME tests_tracing_layer_state_enabled_via_environment COMMAND tests --gtest_filter=*TracingLayerState.GivenTracingLayerEnabledViaEnvironmentWhenCallingzelGetTracingLayerStateThenTrueIsReturned) +set_property(TEST tests_tracing_layer_state_enabled_via_environment PROPERTY ENVIRONMENT "ZE_ENABLE_LOADER_DEBUG_TRACE=1;ZE_ENABLE_NULL_DRIVER=1") + +add_test(NAME tests_tracing_layer_state_enabled_via_environment_and_dynamic COMMAND tests --gtest_filter=*TracingLayerState.GivenTracingLayerEnabledViaEnvironmentWhenCallingzelEnableTracingLayerThenStateRemainsTrue) +set_property(TEST tests_tracing_layer_state_enabled_via_environment_and_dynamic PROPERTY ENVIRONMENT "ZE_ENABLE_LOADER_DEBUG_TRACE=1;ZE_ENABLE_NULL_DRIVER=1") + +add_test(NAME tests_tracing_layer_state_enabled_via_environment_disable_dynamic COMMAND tests --gtest_filter=*TracingLayerState.GivenTracingLayerEnabledViaEnvironmentAndDynamicallyWhenDisablingDynamicTracingThenStateRemainsTrue) +set_property(TEST tests_tracing_layer_state_enabled_via_environment_disable_dynamic PROPERTY ENVIRONMENT "ZE_ENABLE_LOADER_DEBUG_TRACE=1;ZE_ENABLE_NULL_DRIVER=1") + add_test(NAME test_zello_world_legacy COMMAND zello_world --enable_legacy_init --enable_null_driver --force_loader_intercepts --enable_validation_layer --enable_tracing_layer --enable_tracing_layer_runtime) set_property(TEST test_zello_world_legacy PROPERTY ENVIRONMENT "ZE_ENABLE_LOADER_DEBUG_TRACE=1") @@ -670,6 +706,8 @@ else() set_property(TEST init_driver_unit_tests PROPERTY ENVIRONMENT "ZE_ENABLE_LOADER_DEBUG_TRACE=1;ZE_ENABLE_NULL_DRIVER=1;") endif() + + # These tests are currently not supported on Windows. The reason is that the std::cerr is not being redirected to a pipe in Windows to be then checked against the expected output. if(NOT MSVC) add_test(NAME tests_event_deadlock COMMAND tests --gtest_filter=*GivenLevelZeroLoaderPresentWhenCallingzeCommandListAppendMemoryCopyWithCircularDependencyOnEventsThenValidationLayerPrintsWarningOfDeadlock*) diff --git a/test/loader_api.cpp b/test/loader_api.cpp index f0eb815f..b2b0f0f2 100644 --- a/test/loader_api.cpp +++ b/test/loader_api.cpp @@ -556,6 +556,221 @@ TEST( EXPECT_FALSE(zelCheckIsLoaderInTearDown()); } +TEST( + TracingLayerState, + GivenNullPointerWhenCallingzelGetTracingLayerStateThenErrorInvalidNullPointerIsReturned) { + + EXPECT_EQ(ZE_RESULT_ERROR_INVALID_NULL_POINTER, zelGetTracingLayerState(nullptr)); +} + +TEST( + TracingLayerState, + GivenValidPointerWhenCallingzelGetTracingLayerStateThenSuccessIsReturned) { + + uint32_t pCount = 0; + ze_init_driver_type_desc_t desc = {ZE_STRUCTURE_TYPE_INIT_DRIVER_TYPE_DESC}; + desc.flags = UINT32_MAX; + desc.pNext = nullptr; + EXPECT_EQ(ZE_RESULT_SUCCESS, zeInitDrivers(&pCount, nullptr, &desc)); + bool enabled = false; + EXPECT_EQ(ZE_RESULT_SUCCESS, zelGetTracingLayerState(&enabled)); +} + +TEST( + TracingLayerState, + GivenTracingLayerNotEnabledWhenCallingzelGetTracingLayerStateThenFalseIsReturned) { + + uint32_t pCount = 0; + ze_init_driver_type_desc_t desc = {ZE_STRUCTURE_TYPE_INIT_DRIVER_TYPE_DESC}; + desc.flags = UINT32_MAX; + desc.pNext = nullptr; + EXPECT_EQ(ZE_RESULT_SUCCESS, zeInitDrivers(&pCount, nullptr, &desc)); + bool enabled = true; + EXPECT_EQ(ZE_RESULT_SUCCESS, zelGetTracingLayerState(&enabled)); + EXPECT_FALSE(enabled); +} + +TEST( + TracingLayerState, + GivenTracingLayerEnabledWhenCallingzelGetTracingLayerStateThenTrueIsReturned) { + + uint32_t pCount = 0; + ze_init_driver_type_desc_t desc = {ZE_STRUCTURE_TYPE_INIT_DRIVER_TYPE_DESC}; + desc.flags = UINT32_MAX; + desc.pNext = nullptr; + EXPECT_EQ(ZE_RESULT_SUCCESS, zeInitDrivers(&pCount, nullptr, &desc)); + EXPECT_EQ(ZE_RESULT_SUCCESS, zelEnableTracingLayer()); + bool enabled = false; + EXPECT_EQ(ZE_RESULT_SUCCESS, zelGetTracingLayerState(&enabled)); + EXPECT_TRUE(enabled); + EXPECT_EQ(ZE_RESULT_SUCCESS, zelDisableTracingLayer()); +} + +TEST( + TracingLayerState, + GivenTracingLayerEnabledThenDisabledWhenCallingzelGetTracingLayerStateThenFalseIsReturned) { + + uint32_t pCount = 0; + ze_init_driver_type_desc_t desc = {ZE_STRUCTURE_TYPE_INIT_DRIVER_TYPE_DESC}; + desc.flags = UINT32_MAX; + desc.pNext = nullptr; + EXPECT_EQ(ZE_RESULT_SUCCESS, zeInitDrivers(&pCount, nullptr, &desc)); + EXPECT_EQ(ZE_RESULT_SUCCESS, zelEnableTracingLayer()); + bool enabled = false; + EXPECT_EQ(ZE_RESULT_SUCCESS, zelGetTracingLayerState(&enabled)); + EXPECT_TRUE(enabled); + EXPECT_EQ(ZE_RESULT_SUCCESS, zelDisableTracingLayer()); + enabled = true; + EXPECT_EQ(ZE_RESULT_SUCCESS, zelGetTracingLayerState(&enabled)); + EXPECT_FALSE(enabled); +} + +TEST( + TracingLayerState, + GivenMultipleEnableCallsWhenCallingzelGetTracingLayerStateThenTrueIsReturned) { + + uint32_t pCount = 0; + ze_init_driver_type_desc_t desc = {ZE_STRUCTURE_TYPE_INIT_DRIVER_TYPE_DESC}; + desc.flags = UINT32_MAX; + desc.pNext = nullptr; + EXPECT_EQ(ZE_RESULT_SUCCESS, zeInitDrivers(&pCount, nullptr, &desc)); + EXPECT_EQ(ZE_RESULT_SUCCESS, zelEnableTracingLayer()); + EXPECT_EQ(ZE_RESULT_SUCCESS, zelEnableTracingLayer()); + EXPECT_EQ(ZE_RESULT_SUCCESS, zelEnableTracingLayer()); + bool enabled = false; + EXPECT_EQ(ZE_RESULT_SUCCESS, zelGetTracingLayerState(&enabled)); + EXPECT_TRUE(enabled); + EXPECT_EQ(ZE_RESULT_SUCCESS, zelDisableTracingLayer()); + EXPECT_EQ(ZE_RESULT_SUCCESS, zelDisableTracingLayer()); + EXPECT_EQ(ZE_RESULT_SUCCESS, zelDisableTracingLayer()); +} + +TEST( + TracingLayerState, + GivenMultipleEnableAndPartialDisableWhenCallingzelGetTracingLayerStateThenTrueIsReturned) { + + uint32_t pCount = 0; + ze_init_driver_type_desc_t desc = {ZE_STRUCTURE_TYPE_INIT_DRIVER_TYPE_DESC}; + desc.flags = UINT32_MAX; + desc.pNext = nullptr; + EXPECT_EQ(ZE_RESULT_SUCCESS, zeInitDrivers(&pCount, nullptr, &desc)); + EXPECT_EQ(ZE_RESULT_SUCCESS, zelEnableTracingLayer()); + EXPECT_EQ(ZE_RESULT_SUCCESS, zelEnableTracingLayer()); + EXPECT_EQ(ZE_RESULT_SUCCESS, zelEnableTracingLayer()); + bool enabled = false; + EXPECT_EQ(ZE_RESULT_SUCCESS, zelGetTracingLayerState(&enabled)); + EXPECT_TRUE(enabled); + EXPECT_EQ(ZE_RESULT_SUCCESS, zelDisableTracingLayer()); + EXPECT_EQ(ZE_RESULT_SUCCESS, zelGetTracingLayerState(&enabled)); + EXPECT_TRUE(enabled); + EXPECT_EQ(ZE_RESULT_SUCCESS, zelDisableTracingLayer()); + EXPECT_EQ(ZE_RESULT_SUCCESS, zelGetTracingLayerState(&enabled)); + EXPECT_TRUE(enabled); + EXPECT_EQ(ZE_RESULT_SUCCESS, zelDisableTracingLayer()); + enabled = true; + EXPECT_EQ(ZE_RESULT_SUCCESS, zelGetTracingLayerState(&enabled)); + EXPECT_FALSE(enabled); +} + +TEST( + TracingLayerState, + GivenMultipleCallsTozelGetTracingLayerStateWhenTracingEnabledThenAllReturnTrue) { + + uint32_t pCount = 0; + ze_init_driver_type_desc_t desc = {ZE_STRUCTURE_TYPE_INIT_DRIVER_TYPE_DESC}; + desc.flags = UINT32_MAX; + desc.pNext = nullptr; + EXPECT_EQ(ZE_RESULT_SUCCESS, zeInitDrivers(&pCount, nullptr, &desc)); + EXPECT_EQ(ZE_RESULT_SUCCESS, zelEnableTracingLayer()); + bool enabled1 = false, enabled2 = false, enabled3 = false; + EXPECT_EQ(ZE_RESULT_SUCCESS, zelGetTracingLayerState(&enabled1)); + EXPECT_EQ(ZE_RESULT_SUCCESS, zelGetTracingLayerState(&enabled2)); + EXPECT_EQ(ZE_RESULT_SUCCESS, zelGetTracingLayerState(&enabled3)); + EXPECT_TRUE(enabled1); + EXPECT_TRUE(enabled2); + EXPECT_TRUE(enabled3); + EXPECT_EQ(ZE_RESULT_SUCCESS, zelDisableTracingLayer()); +} + +TEST( + TracingLayerState, + GivenMultipleCallsTozelGetTracingLayerStateWhenTracingDisabledThenAllReturnFalse) { + + uint32_t pCount = 0; + ze_init_driver_type_desc_t desc = {ZE_STRUCTURE_TYPE_INIT_DRIVER_TYPE_DESC}; + desc.flags = UINT32_MAX; + desc.pNext = nullptr; + EXPECT_EQ(ZE_RESULT_SUCCESS, zeInitDrivers(&pCount, nullptr, &desc)); + bool enabled1 = true, enabled2 = true, enabled3 = true; + EXPECT_EQ(ZE_RESULT_SUCCESS, zelGetTracingLayerState(&enabled1)); + EXPECT_EQ(ZE_RESULT_SUCCESS, zelGetTracingLayerState(&enabled2)); + EXPECT_EQ(ZE_RESULT_SUCCESS, zelGetTracingLayerState(&enabled3)); + EXPECT_FALSE(enabled1); + EXPECT_FALSE(enabled2); + EXPECT_FALSE(enabled3); +} + +TEST( + TracingLayerState, + GivenTracingLayerEnabledViaEnvironmentWhenCallingzelGetTracingLayerStateThenTrueIsReturned) { + + uint32_t pCount = 0; + ze_init_driver_type_desc_t desc = {ZE_STRUCTURE_TYPE_INIT_DRIVER_TYPE_DESC}; + desc.flags = UINT32_MAX; + desc.pNext = nullptr; + putenv_safe( const_cast( "ZE_ENABLE_TRACING_LAYER=1" ) ); + EXPECT_EQ(ZE_RESULT_SUCCESS, zeInitDrivers(&pCount, nullptr, &desc)); + bool enabled = false; + EXPECT_EQ(ZE_RESULT_SUCCESS, zelGetTracingLayerState(&enabled)); + EXPECT_TRUE(enabled); +} + +TEST( + TracingLayerState, + GivenTracingLayerEnabledViaEnvironmentWhenCallingzelEnableTracingLayerThenStateRemainsTrue) { + + uint32_t pCount = 0; + ze_init_driver_type_desc_t desc = {ZE_STRUCTURE_TYPE_INIT_DRIVER_TYPE_DESC}; + desc.flags = UINT32_MAX; + desc.pNext = nullptr; + putenv_safe( const_cast( "ZE_ENABLE_TRACING_LAYER=1" ) ); + EXPECT_EQ(ZE_RESULT_SUCCESS, zeInitDrivers(&pCount, nullptr, &desc)); + bool enabled = false; + EXPECT_EQ(ZE_RESULT_SUCCESS, zelGetTracingLayerState(&enabled)); + EXPECT_TRUE(enabled); + EXPECT_EQ(ZE_RESULT_SUCCESS, zelEnableTracingLayer()); + EXPECT_EQ(ZE_RESULT_SUCCESS, zelGetTracingLayerState(&enabled)); + EXPECT_TRUE(enabled); + EXPECT_EQ(ZE_RESULT_SUCCESS, zelDisableTracingLayer()); + EXPECT_EQ(ZE_RESULT_SUCCESS, zelGetTracingLayerState(&enabled)); + EXPECT_TRUE(enabled); +} + +TEST( + TracingLayerState, + GivenTracingLayerEnabledViaEnvironmentAndDynamicallyWhenDisablingDynamicTracingThenStateRemainsTrue) { + + uint32_t pCount = 0; + ze_init_driver_type_desc_t desc = {ZE_STRUCTURE_TYPE_INIT_DRIVER_TYPE_DESC}; + desc.flags = UINT32_MAX; + desc.pNext = nullptr; + putenv_safe( const_cast( "ZE_ENABLE_TRACING_LAYER=1" ) ); + EXPECT_EQ(ZE_RESULT_SUCCESS, zeInitDrivers(&pCount, nullptr, &desc)); + EXPECT_EQ(ZE_RESULT_SUCCESS, zelEnableTracingLayer()); + EXPECT_EQ(ZE_RESULT_SUCCESS, zelEnableTracingLayer()); + bool enabled = false; + EXPECT_EQ(ZE_RESULT_SUCCESS, zelGetTracingLayerState(&enabled)); + EXPECT_TRUE(enabled); + EXPECT_EQ(ZE_RESULT_SUCCESS, zelDisableTracingLayer()); + EXPECT_EQ(ZE_RESULT_SUCCESS, zelGetTracingLayerState(&enabled)); + EXPECT_TRUE(enabled); + EXPECT_EQ(ZE_RESULT_SUCCESS, zelDisableTracingLayer()); + EXPECT_EQ(ZE_RESULT_SUCCESS, zelGetTracingLayerState(&enabled)); + EXPECT_TRUE(enabled); +} + + + class CaptureOutput { private: int original_fd;