diff --git a/projects/rocprofiler-systems/source/lib/rocprof-sys/library/components/pthread_create_gotcha.cpp b/projects/rocprofiler-systems/source/lib/rocprof-sys/library/components/pthread_create_gotcha.cpp index 4ab2279696..06f20f445f 100644 --- a/projects/rocprofiler-systems/source/lib/rocprof-sys/library/components/pthread_create_gotcha.cpp +++ b/projects/rocprofiler-systems/source/lib/rocprof-sys/library/components/pthread_create_gotcha.cpp @@ -62,6 +62,9 @@ namespace component { using bundle_t = tim::lightweight_tuple; using category_region_t = tim::lightweight_tuple>; +// The maximum limit for the number of threads is set at 4096. declared and stored in the +// set_storage struct's `types.hpp` file. +constexpr size_t allowed_max_threads = 4096; namespace { @@ -181,7 +184,21 @@ pthread_create_gotcha::wrapper::operator()() const auto _coverage = (get_mode() == Mode::Coverage); const auto& _parent_info = thread_info::get(m_config.parent_tid, InternalTID); const auto& _info = thread_info::init(m_config.offset); - auto _dtor = [&]() { + auto _sequent_value = _info->index_data ? _info->index_data->sequent_value : -1; + if(static_cast(_sequent_value) >= allowed_max_threads) + { + static std::once_flag thread_limit_warning_flag; + std::call_once(thread_limit_warning_flag, []() { + ROCPROFSYS_WARNING_F( + 1, + "[rocprof-sys][WARNING] Maximum allowed thread limit (%zu) " + "reached. Further thread creation and profiling will be " + "disabled to prevent resource exhaustion.\n", + allowed_max_threads); + }); + return m_routine(m_arg); + } + auto _dtor = [&]() { set_thread_state(ThreadState::Internal); if(_is_sampling) { diff --git a/projects/rocprofiler-systems/tests/source/CMakeLists.txt b/projects/rocprofiler-systems/tests/source/CMakeLists.txt index 27364bdc95..0746f43b35 100644 --- a/projects/rocprofiler-systems/tests/source/CMakeLists.txt +++ b/projects/rocprofiler-systems/tests/source/CMakeLists.txt @@ -40,30 +40,47 @@ set(_thread_limit_environment "ROCPROFSYS_VERBOSE=2" "ROCPROFSYS_TIMEMORY_COMPONENTS=wall_clock,peak_rss,page_rss" ) +# Maximum allowed threads +set(ALLOWED_MAX_THREADS 4096) -math(EXPR THREAD_LIMIT_TEST_VALUE "${ROCPROFSYS_MAX_THREADS} + 24") -math(EXPR THREAD_LIMIT_TEST_VALUE_PLUS_ONE "${THREAD_LIMIT_TEST_VALUE} + 1") +math(EXPR THREAD_VAL_1 "${ROCPROFSYS_MAX_THREADS} + 24") +math(EXPR THREAD_VAL_2 "${ALLOWED_MAX_THREADS} + 1") -set(_thread_limit_pass_regex "\\|${THREAD_LIMIT_TEST_VALUE}>>>") -set(_thread_limit_fail_regex - "\\|${THREAD_LIMIT_TEST_VALUE_PLUS_ONE}>>>|ROCPROFSYS_ABORT_FAIL_REGEX" -) +set(THREAD_VALUES ${THREAD_VAL_1} ${THREAD_VAL_2}) -rocprofiler_systems_add_test( - SKIP_BASELINE - NAME thread-limit - TARGET thread-limit - LABELS "max-threads" - REWRITE_ARGS -e -v 2 -i 1024 --label return args - RUNTIME_ARGS -e -v 1 -i 1024 --label return args - RUN_ARGS 35 2 ${THREAD_LIMIT_TEST_VALUE} - REWRITE_TIMEOUT 180 - RUNTIME_TIMEOUT 360 - RUNTIME_PASS_REGEX "${_thread_limit_pass_regex}" - SAMPLING_PASS_REGEX "${_thread_limit_pass_regex}" - REWRITE_RUN_PASS_REGEX "${_thread_limit_pass_regex}" - RUNTIME_FAIL_REGEX "${_thread_limit_fail_regex}" - SAMPLING_FAIL_REGEX "${_thread_limit_fail_regex}" - REWRITE_RUN_FAIL_REGEX "${_thread_limit_fail_regex}" - ENVIRONMENT "${_thread_limit_environment}" -) +# Loop over thread values +foreach(THREADS IN LISTS THREAD_VALUES) + set(THREAD_PASS_VALUE ${THREADS}) + math(EXPR THREAD_FAIL_VALUE "${THREADS} + 1") + if(${THREADS} GREATER_EQUAL ${ALLOWED_MAX_THREADS}) + math(EXPR THREAD_PASS_VALUE "${ALLOWED_MAX_THREADS} - 1") + math(EXPR THREAD_FAIL_VALUE "${THREADS}") + endif() + + set(_thread_limit_pass_regex "\\|${THREAD_PASS_VALUE}>>>") + set(_thread_limit_fail_regex "\\|${THREAD_FAIL_VALUE}>>>|ROCPROFSYS_ABORT_FAIL_REGEX") + + # Unique test name + set(_test_name thread-limit-${THREADS}) + + # Add test + rocprofiler_systems_add_test( + SKIP_BASELINE + NAME ${_test_name} + TARGET thread-limit + LABELS "max-threads" + REWRITE_ARGS -e -v 2 -i 1024 --label return args + RUNTIME_ARGS -e -v 1 -i 1024 --label return args + RUN_ARGS 35 2 ${THREADS} + SAMPLING_TIMEOUT 180 + REWRITE_TIMEOUT 180 + RUNTIME_TIMEOUT 360 + RUNTIME_PASS_REGEX "${_thread_limit_pass_regex}" + SAMPLING_PASS_REGEX "${_thread_limit_pass_regex}" + REWRITE_RUN_PASS_REGEX "${_thread_limit_pass_regex}" + RUNTIME_FAIL_REGEX "${_thread_limit_fail_regex}" + SAMPLING_FAIL_REGEX "${_thread_limit_fail_regex}" + REWRITE_RUN_FAIL_REGEX "${_thread_limit_fail_regex}" + ENVIRONMENT "${_thread_limit_environment}" + ) +endforeach()