From e50d6b6b9f5438ce0ba1b879b68c97280c634259 Mon Sep 17 00:00:00 2001 From: wujing Date: Mon, 23 Jun 2025 20:29:32 +0800 Subject: [PATCH 1/2] fix: build error caused by incorrect reference to transform header file Signed-off-by: wujing --- systrace/include/common/util.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/systrace/include/common/util.h b/systrace/include/common/util.h index ea166d5..c93e2d4 100644 --- a/systrace/include/common/util.h +++ b/systrace/include/common/util.h @@ -17,7 +17,7 @@ #include #include #include -#include +#include namespace systrace { @@ -293,4 +293,4 @@ void REGISTER_ENV(); } // namespace env void InitializeSystemUtilities(); } // namespace util -} // namespace systrace \ No newline at end of file +} // namespace systrace -- Gitee From f6056861eff320d8735f012d86286eb221a6cd07 Mon Sep 17 00:00:00 2001 From: wujing Date: Mon, 23 Jun 2025 20:56:03 +0800 Subject: [PATCH 2/2] style: formatting the code according to the openEuler coding standard Signed-off-by: wujing --- systrace/.clang-format | 123 +- systrace/client/sysTracecli.cpp | 29 +- systrace/include/common/constant.h | 12 +- systrace/include/common/logging.cc | 5 +- systrace/include/common/logging.h | 29 +- systrace/include/common/macro.h | 22 +- systrace/include/common/shared_constants.c | 77 +- systrace/include/common/shared_constants.h | 60 +- systrace/include/common/util.cc | 393 ++--- systrace/include/common/util.h | 453 +++-- systrace/server/monitor_server.cpp | 141 +- systrace/server/monitor_server.hpp | 13 +- systrace/src/ascend/hook.cc | 90 +- systrace/src/ascend/hook.h | 46 +- systrace/src/cann/cann_hook.c | 174 +- systrace/src/mspti/json_file_writer.h | 70 +- systrace/src/mspti/mspti_tracker.cpp | 40 +- systrace/src/mspti/mspti_tracker.hpp | 24 +- systrace/src/os/__compat.h | 59 +- systrace/src/os/__feat_probe.h | 12 +- systrace/src/os/__libbpf.h | 293 ++-- systrace/src/os/bpf_comm.h | 65 +- systrace/src/os/common.h | 20 +- systrace/src/os/os_cpu.bpf.c | 20 +- systrace/src/os/os_mem.bpf.c | 39 +- systrace/src/os/os_probe.c | 205 +-- systrace/src/os/os_probe.h | 4 +- systrace/src/trace/library_loader.cc | 16 +- systrace/src/trace/library_loader.h | 12 +- systrace/src/trace/systrace_manager.cc | 132 +- systrace/src/trace/systrace_manager.h | 20 +- systrace/thirdparty/uthash.h | 1759 ++++++++------------ 32 files changed, 1998 insertions(+), 2459 deletions(-) diff --git a/systrace/.clang-format b/systrace/.clang-format index 466d8df..c161fd3 100644 --- a/systrace/.clang-format +++ b/systrace/.clang-format @@ -1,5 +1,122 @@ -BasedOnStyle: LLVM +--- +BasedOnStyle: llvm +AccessModifierOffset: -4 +AlignAfterOpenBracket: Align +AlignConsecutiveAssignments: false +AlignConsecutiveDeclarations: false +AlignEscapedNewlines: Left +AlignOperands: true +AlignTrailingComments: false +# AllowAllArgumentsOnNextLine: true +AllowAllParametersOfDeclarationOnNextLine: true +# AllowAllConstructorInitializersOnNextLine: true +AllowShortBlocksOnASingleLine: false +AllowShortCaseLabelsOnASingleLine: false +AllowShortFunctionsOnASingleLine: None +AllowShortIfStatementsOnASingleLine: false +# AllowShortLambdasOnASingleLine: Empty +AllowShortLoopsOnASingleLine: false +AlwaysBreakAfterDefinitionReturnType: None +AlwaysBreakAfterReturnType: None +AlwaysBreakBeforeMultilineStrings: false +AlwaysBreakTemplateDeclarations: Yes +BinPackArguments: true +BinPackParameters: true +BraceWrapping: + # AfterCaseLabel: false + AfterClass: false + AfterControlStatement: false + AfterEnum: false + AfterFunction: true + AfterNamespace: true + AfterObjCDeclaration: false + AfterStruct: false + AfterUnion: false + AfterExternBlock: false + BeforeCatch: false + BeforeElse: false + IndentBraces: false + SplitEmptyFunction: true + SplitEmptyRecord: true + SplitEmptyNamespace: true +BreakBeforeBinaryOperators: None +BreakBeforeBraces: Custom +BreakBeforeInheritanceComma: false +BreakBeforeTernaryOperators: false +BreakConstructorInitializersBeforeComma: false +BreakConstructorInitializers: BeforeComma +BreakAfterJavaFieldAnnotations: false +BreakStringLiterals: false +ColumnLimit: 120 +CommentPragmas: "^ IWYU pragma:" +CompactNamespaces: false +ConstructorInitializerAllOnOneLineOrOnePerLine: false +ConstructorInitializerIndentWidth: 8 +ContinuationIndentWidth: 8 +Cpp11BracedListStyle: false +DerivePointerAlignment: false +DisableFormat: false +ExperimentalAutoDetectBinPacking: false +FixNamespaceComments: true + +# Taken from: +# git grep -h '^#define [^[:space:]]*for_each[^[:space:]]*(' include/ \ +# | sed "s,^#define \([^[:space:]]*for_each[^[:space:]]*\)(.*$, - '\1'," \ +# | sort | uniq +ForEachMacros: + - "linked_list_for_each_safe" + - "linked_list_for_each" + +IncludeBlocks: Preserve +IncludeCategories: + - Regex: ".*" + Priority: 1 +IncludeIsMainRegex: "(Test)?$" +IndentCaseLabels: true +IndentPPDirectives: None IndentWidth: 4 -BreakBeforeBraces: Allman -UseTab: Never +IndentWrappedFunctionNames: false +JavaScriptQuotes: Leave +JavaScriptWrapImports: true +KeepEmptyLinesAtTheStartOfBlocks: false +MacroBlockBegin: "" +MacroBlockEnd: "" +MaxEmptyLinesToKeep: 1 +NamespaceIndentation: Inner +ObjCBinPackProtocolList: Auto +ObjCBlockIndentWidth: 4 +ObjCSpaceAfterProperty: true +ObjCSpaceBeforeProtocolList: true + +# Taken from git's rules +PenaltyBreakAssignment: 10 +PenaltyBreakBeforeFirstCallParameter: 30 +PenaltyBreakComment: 10 +PenaltyBreakFirstLessLess: 0 +PenaltyBreakString: 10 +PenaltyExcessCharacter: 100 +PenaltyReturnTypeOnItsOwnLine: 60 + +PointerAlignment: Right +ReflowComments: false +SortIncludes: false +SortUsingDeclarations: false +SpaceAfterCStyleCast: false +# SpaceAfterLogicalNot: false +SpaceAfterTemplateKeyword: true +SpaceBeforeAssignmentOperators: true +SpaceBeforeCpp11BracedList: true +SpaceBeforeCtorInitializerColon: true +SpaceBeforeInheritanceColon: true +SpaceBeforeParens: ControlStatements +SpaceBeforeRangeBasedForLoopColon: true +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 1 +SpacesInAngles: false +SpacesInContainerLiterals: false +SpacesInCStyleCastParentheses: false +SpacesInParentheses: false +SpacesInSquareBrackets: false +Standard: Cpp11 TabWidth: 4 +UseTab: Never diff --git a/systrace/client/sysTracecli.cpp b/systrace/client/sysTracecli.cpp index 331b187..b6e80d0 100644 --- a/systrace/client/sysTracecli.cpp +++ b/systrace/client/sysTracecli.cpp @@ -6,7 +6,8 @@ #define SOCKET_PATH "/tmp/sysTrace_socket" -void print_help() { +void print_help() +{ std::cout << "Usage: sysTrace_client [args]\n" << "Commands:\n" << " set = - Enable/disable dump level\n" @@ -23,15 +24,13 @@ void print_help() { int main(int argc, char *argv[]) { - if (argc < 2 || std::string(argv[1]) == "help") - { + if (argc < 2 || std::string(argv[1]) == "help") { print_help(); return 0; } int sockfd = socket(AF_UNIX, SOCK_STREAM, 0); - if (sockfd == -1) - { + if (sockfd == -1) { perror("socket"); return 1; } @@ -41,33 +40,26 @@ int main(int argc, char *argv[]) addr.sun_family = AF_UNIX; strncpy(addr.sun_path, SOCKET_PATH, sizeof(addr.sun_path) - 1); - if (connect(sockfd, (struct sockaddr *)&addr, sizeof(addr)) == -1) - { + if (connect(sockfd, (struct sockaddr *)&addr, sizeof(addr)) == -1) { perror("connect"); close(sockfd); return 1; } std::string command; - if (std::string(argv[1]) == "print") - { + if (std::string(argv[1]) == "print") { command = "print"; if (argc >= 3) command += std::string(" ") + argv[2]; - } - else if (argc >= 3) - { + } else if (argc >= 3) { command = std::string(argv[1]) + " " + argv[2]; - } - else - { + } else { std::cerr << "Invalid command format\n"; close(sockfd); return 1; } - if (write(sockfd, command.c_str(), command.size()) == -1) - { + if (write(sockfd, command.c_str(), command.size()) == -1) { perror("write"); close(sockfd); return 1; @@ -75,8 +67,7 @@ int main(int argc, char *argv[]) char buffer[1024]; ssize_t n = read(sockfd, buffer, sizeof(buffer) - 1); - if (n > 0) - { + if (n > 0) { buffer[n] = '\0'; std::cout << buffer; } diff --git a/systrace/include/common/constant.h b/systrace/include/common/constant.h index 1bee6fa..17ba2af 100644 --- a/systrace/include/common/constant.h +++ b/systrace/include/common/constant.h @@ -7,13 +7,11 @@ namespace systrace namespace constant { -struct TorchTraceConstant -{ - public: - static constexpr int DEFAULT_TRACE_COUNT = 1000; - static constexpr std::string_view DEFAULT_TRACE_DUMP_PATH = - SYS_TRACE_ROOT_DIR "timeline"; -}; + struct TorchTraceConstant { + public: + static constexpr int DEFAULT_TRACE_COUNT = 1000; + static constexpr std::string_view DEFAULT_TRACE_DUMP_PATH = SYS_TRACE_ROOT_DIR "timeline"; + }; } // namespace constant } // namespace systrace \ No newline at end of file diff --git a/systrace/include/common/logging.cc b/systrace/include/common/logging.cc index f7dec97..276fb55 100644 --- a/systrace/include/common/logging.cc +++ b/systrace/include/common/logging.cc @@ -2,5 +2,8 @@ namespace systrace { -void setLoggingPath() { return; } +void setLoggingPath() +{ + return; +} } // namespace systrace \ No newline at end of file diff --git a/systrace/include/common/logging.h b/systrace/include/common/logging.h index dc7ef35..ce8f298 100644 --- a/systrace/include/common/logging.h +++ b/systrace/include/common/logging.h @@ -1,26 +1,19 @@ #pragma once -enum LogLevel -{ - INFO, - WARNING, - ERROR, - FATAL -}; +enum LogLevel { INFO, WARNING, ERROR, FATAL }; -#define LOG(level) \ - if (level == INFO) \ - std::cerr << "[INFO] "; \ - else if (level == WARNING) \ - std::cerr << "[WARNING] "; \ - else if (level == ERROR) \ - std::cerr << "[ERROR] "; \ - else if (level == FATAL) \ - std::cerr << "[FATAL] "; \ +#define LOG(level) \ + if (level == INFO) \ + std::cerr << "[INFO] "; \ + else if (level == WARNING) \ + std::cerr << "[WARNING] "; \ + else if (level == ERROR) \ + std::cerr << "[ERROR] "; \ + else if (level == FATAL) \ + std::cerr << "[FATAL] "; \ std::cerr -#define STLOG(level) \ - LOG(level) << ::systrace::util::config::GlobalConfig::Instance().rank_str +#define STLOG(level) LOG(level) << ::systrace::util::config::GlobalConfig::Instance().rank_str namespace systrace { diff --git a/systrace/include/common/macro.h b/systrace/include/common/macro.h index 56d60ab..7232ff0 100644 --- a/systrace/include/common/macro.h +++ b/systrace/include/common/macro.h @@ -1,17 +1,13 @@ #pragma once #define EXPOSE_API __attribute__((visibility("default"))) -#define SETUP_SYMBOL_FOR_LOAD_LIBRARY(handle, symbol, func_ptr, func_type, \ - msg) \ - do \ - { \ - func_ptr = (func_type)dlsym(handle, symbol); \ - const char *dlsym_error = dlerror(); \ - if (dlsym_error) \ - { \ - STLOG(WARNING) << "Load fn `" << symbol << "` error in " << msg \ - << dlsym_error; \ - is_usable_ = false; \ - return; \ - } \ +#define SETUP_SYMBOL_FOR_LOAD_LIBRARY(handle, symbol, func_ptr, func_type, msg) \ + do { \ + func_ptr = (func_type)dlsym(handle, symbol); \ + const char *dlsym_error = dlerror(); \ + if (dlsym_error) { \ + STLOG(WARNING) << "Load fn `" << symbol << "` error in " << msg << dlsym_error; \ + is_usable_ = false; \ + return; \ + } \ } while (0) diff --git a/systrace/include/common/shared_constants.c b/systrace/include/common/shared_constants.c index 7402089..b91afa9 100644 --- a/systrace/include/common/shared_constants.c +++ b/systrace/include/common/shared_constants.c @@ -11,43 +11,36 @@ static int shm_fd = -1; int init_shared_memory() { shm_fd = shm_open(SHM_NAME, O_CREAT | O_RDWR, 0666); - if (shm_fd == -1) - { + if (shm_fd == -1) { perror("shm_open failed"); return -1; } - if (ftruncate(shm_fd, sizeof(SharedData)) == -1) - { + if (ftruncate(shm_fd, sizeof(SharedData)) == -1) { perror("ftruncate failed"); close(shm_fd); return -1; } - shared_data = mmap(NULL, sizeof(SharedData), PROT_READ | PROT_WRITE, - MAP_SHARED, shm_fd, 0); - if (shared_data == MAP_FAILED) - { + shared_data = mmap(NULL, sizeof(SharedData), PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0); + if (shared_data == MAP_FAILED) { perror("mmap failed"); close(shm_fd); return -1; } static pthread_mutexattr_t mutex_attr; - if (pthread_mutexattr_init(&mutex_attr) != 0) - { + if (pthread_mutexattr_init(&mutex_attr) != 0) { perror("pthread_mutexattr_init failed"); return -1; } - if (pthread_mutexattr_setpshared(&mutex_attr, PTHREAD_PROCESS_SHARED) != 0) - { + if (pthread_mutexattr_setpshared(&mutex_attr, PTHREAD_PROCESS_SHARED) != 0) { perror("pthread_mutexattr_setpshared failed"); return -1; } - if (pthread_mutex_init(&shared_data->g_trace_mutex, &mutex_attr) != 0) - { + if (pthread_mutex_init(&shared_data->g_trace_mutex, &mutex_attr) != 0) { perror("pthread_mutex_init failed"); return -1; } @@ -70,10 +63,8 @@ int init_shared_memory() SharedData *get_shared_data() { - if (shared_data == NULL) - { - if (init_shared_memory() != 0) - { + if (shared_data == NULL) { + if (init_shared_memory() != 0) { return NULL; } } @@ -82,14 +73,12 @@ SharedData *get_shared_data() void cleanup_shared_memory() { - if (shared_data != NULL) - { + if (shared_data != NULL) { munmap(shared_data, sizeof(SharedData)); shared_data = NULL; } - if (shm_fd != -1) - { + if (shm_fd != -1) { close(shm_fd); shm_fd = -1; } @@ -97,24 +86,25 @@ void cleanup_shared_memory() shm_unlink(SHM_NAME); } -bool checkAndUpdateTimer(int level) { - SharedData* shared_data = get_shared_data(); +bool checkAndUpdateTimer(int level) +{ + SharedData *shared_data = get_shared_data(); if (!shared_data) { return false; } pthread_mutex_lock(&shared_data->g_trace_mutex); - bool* dump_flag = NULL; - unsigned int* interval = NULL; - bool* timer_active = NULL; - time_t* start_time = NULL; - const char* level_name = ""; + bool *dump_flag = NULL; + unsigned int *interval = NULL; + bool *timer_active = NULL; + time_t *start_time = NULL; + const char *level_name = ""; bool *dumped = false; bool *need_dump_once = NULL; - switch(level) { - case 1: // L1 + switch (level) { + case 1: // L1 dump_flag = &shared_data->g_dump_L1; interval = &shared_data->g_dump_L1_interval; timer_active = &shared_data->g_L1_timer_active; @@ -123,7 +113,7 @@ bool checkAndUpdateTimer(int level) { dumped = &shared_data->dumped_L1; need_dump_once = &shared_data->need_dump_L1_once; break; - case 2: // L2 + case 2: // L2 dump_flag = &shared_data->g_dump_L2; interval = &shared_data->g_dump_L2_interval; timer_active = &shared_data->g_L2_timer_active; @@ -138,16 +128,15 @@ bool checkAndUpdateTimer(int level) { } bool result = false; - + if (*dump_flag && !*timer_active) { *start_time = time(NULL); *timer_active = true; result = true; - } - else if (*timer_active) { + } else if (*timer_active) { time_t now = time(NULL); double elapsed = difftime(now, *start_time) / 60; - + if (elapsed >= *interval) { *dump_flag = false; *timer_active = false; @@ -158,14 +147,15 @@ bool checkAndUpdateTimer(int level) { result = true; } } - + pthread_mutex_unlock(&shared_data->g_trace_mutex); - + return result; } -bool need_dump_L1_once() { - SharedData* shared_data = get_shared_data(); +bool need_dump_L1_once() +{ + SharedData *shared_data = get_shared_data(); if (!shared_data) { return false; } @@ -173,12 +163,13 @@ bool need_dump_L1_once() { pthread_mutex_lock(&shared_data->g_trace_mutex); bool result = shared_data->need_dump_L1_once; pthread_mutex_unlock(&shared_data->g_trace_mutex); - + return result; } -bool need_dump_L2_once() { - SharedData* shared_data = get_shared_data(); +bool need_dump_L2_once() +{ + SharedData *shared_data = get_shared_data(); if (!shared_data) { return false; } diff --git a/systrace/include/common/shared_constants.h b/systrace/include/common/shared_constants.h index 831e334..84a3bdf 100644 --- a/systrace/include/common/shared_constants.h +++ b/systrace/include/common/shared_constants.h @@ -2,8 +2,7 @@ #define SHARED_CONSTANTS_H #ifdef __cplusplus -extern "C" -{ +extern "C" { #endif #include @@ -12,35 +11,34 @@ extern "C" #define SHM_NAME "/sysTrace_shared_mem" #define SYS_TRACE_ROOT_DIR "/home/sysTrace/" - extern int global_stage_id; - extern int global_stage_type; - - typedef struct - { - bool g_dump_L0; - bool g_dump_L1; - bool g_dump_L2; - unsigned int g_dump_L1_interval; - unsigned int g_dump_L2_interval; - bool g_L1_timer_active; - bool g_L2_timer_active; - bool dumped_L1; // Indicates if L1 has been dumped - bool dumped_L2; // Indicates if L2 has been dumped - bool need_dump_L1_once; // Indicates if L1 dump is needed once - bool need_dump_L2_once; // Indicates if L2 dump is needed once - time_t g_L1_start_time; - time_t g_L2_start_time; - pthread_mutex_t g_trace_mutex; - } SharedData; - - int init_shared_memory(); - - SharedData *get_shared_data(); - - void cleanup_shared_memory(); - bool checkAndUpdateTimer(int level); - bool need_dump_L1_once(); - bool need_dump_L2_once(); +extern int global_stage_id; +extern int global_stage_type; + +typedef struct { + bool g_dump_L0; + bool g_dump_L1; + bool g_dump_L2; + unsigned int g_dump_L1_interval; + unsigned int g_dump_L2_interval; + bool g_L1_timer_active; + bool g_L2_timer_active; + bool dumped_L1; // Indicates if L1 has been dumped + bool dumped_L2; // Indicates if L2 has been dumped + bool need_dump_L1_once; // Indicates if L1 dump is needed once + bool need_dump_L2_once; // Indicates if L2 dump is needed once + time_t g_L1_start_time; + time_t g_L2_start_time; + pthread_mutex_t g_trace_mutex; +} SharedData; + +int init_shared_memory(); + +SharedData *get_shared_data(); + +void cleanup_shared_memory(); +bool checkAndUpdateTimer(int level); +bool need_dump_L1_once(); +bool need_dump_L2_once(); #ifdef __cplusplus } diff --git a/systrace/include/common/util.cc b/systrace/include/common/util.cc index 4c2a6e0..8c436ad 100644 --- a/systrace/include/common/util.cc +++ b/systrace/include/common/util.cc @@ -14,270 +14,229 @@ namespace systrace namespace util { -namespace env -{ -std::string_view EnvVarRegistry::DEFAULT_VALUE_STRING = "NONE"; -int EnvVarRegistry::DEFAULT_VALUE_INT = 0; -bool EnvVarRegistry::DEFAULT_VALUE_BOOL = false; -} // namespace env -namespace fs_utils -{ - -int CreateDirectoryIfNotExists(const std::string &path) -{ - std::filesystem::path d_path(path); - try - { - if (!std::filesystem::exists(d_path)) - { - std::filesystem::create_directories(d_path); - } - if (!std::filesystem::is_directory(d_path)) - { - LOG(ERROR) << "Path exists but is not a directory: " << path; - return 1; - } - } - catch (const std::filesystem::filesystem_error &e) - { - LOG(ERROR) << "Failed to create directory " << path << ": " << e.what(); - return 1; - } - return 0; -} - -std::string GenerateClusterUniqueFilename(const std::string &suffix) -{ - try - { - char hostname[128]; - gethostname(hostname, sizeof(hostname)); - std::ostringstream oss; - oss << hostname << "--" << std::setw(5) << std::setfill('0') - << config::GlobalConfig::Instance().rank << suffix; - return oss.str(); - } - catch (const std::exception &e) + namespace env { - LOG(ERROR) << "Filename generation failed: " << e.what(); - return "error_" + std::to_string(std::time(nullptr)) + suffix; - } -} - -} // namespace fs_utils - -namespace config -{ - -class DeviceManager -{ - public: - static constexpr uint64_t MAX_DEVICES = 16; - static constexpr const char *DEVICE_PATH_PREFIX = "/dev/davinci"; - - static std::vector DetectAvailableDevices() + std::string_view EnvVarRegistry::DEFAULT_VALUE_STRING = "NONE"; + int EnvVarRegistry::DEFAULT_VALUE_INT = 0; + bool EnvVarRegistry::DEFAULT_VALUE_BOOL = false; + } // namespace env + namespace fs_utils { - std::vector available_devices; - available_devices.reserve(MAX_DEVICES); - for (uint64_t device_index = 0; device_index < MAX_DEVICES; - ++device_index) + int CreateDirectoryIfNotExists(const std::string &path) { - if (IsDevicePresent(device_index)) - { - available_devices.push_back(device_index); - if (config::GlobalConfig::Instance().local_rank == 0) - { - LOG(INFO) - << "Found device: " << GetDevicePath(device_index); + std::filesystem::path d_path(path); + try { + if (!std::filesystem::exists(d_path)) { + std::filesystem::create_directories(d_path); } + if (!std::filesystem::is_directory(d_path)) { + LOG(ERROR) << "Path exists but is not a directory: " << path; + return 1; + } + } catch (const std::filesystem::filesystem_error &e) { + LOG(ERROR) << "Failed to create directory " << path << ": " << e.what(); + return 1; } + return 0; } - std::sort(available_devices.begin(), available_devices.end()); - return available_devices; - } + std::string GenerateClusterUniqueFilename(const std::string &suffix) + { + try { + char hostname[128]; + gethostname(hostname, sizeof(hostname)); + std::ostringstream oss; + oss << hostname << "--" << std::setw(5) << std::setfill('0') << config::GlobalConfig::Instance().rank + << suffix; + return oss.str(); + } catch (const std::exception &e) { + LOG(ERROR) << "Filename generation failed: " << e.what(); + return "error_" + std::to_string(std::time(nullptr)) + suffix; + } + } - private: - static bool IsDevicePresent(uint64_t index) - { - return std::filesystem::exists(GetDevicePath(index)); - } + } // namespace fs_utils - static std::string GetDevicePath(uint64_t index) + namespace config { - return std::string(DEVICE_PATH_PREFIX) + std::to_string(index); - } -}; -namespace -{ + class DeviceManager { + public: + static constexpr uint64_t MAX_DEVICES = 16; + static constexpr const char *DEVICE_PATH_PREFIX = "/dev/davinci"; -GlobalConfig &config = GlobalConfig::Instance(); + static std::vector DetectAvailableDevices() + { + std::vector available_devices; + available_devices.reserve(MAX_DEVICES); + + for (uint64_t device_index = 0; device_index < MAX_DEVICES; ++device_index) { + if (IsDevicePresent(device_index)) { + available_devices.push_back(device_index); + if (config::GlobalConfig::Instance().local_rank == 0) { + LOG(INFO) << "Found device: " << GetDevicePath(device_index); + } + } + } -void LoadEnvironmentVariables() -{ - auto loadInt = [](const char *name) - { return env::EnvVarRegistry::GetEnvVar(name); }; + std::sort(available_devices.begin(), available_devices.end()); + return available_devices; + } - auto loadStr = [](const char *name) - { return env::EnvVarRegistry::GetEnvVar(name); }; + private: + static bool IsDevicePresent(uint64_t index) + { + return std::filesystem::exists(GetDevicePath(index)); + } - config.rank = loadInt("RANK"); - config.job_name = loadStr("ENV_ARGO_WORKFLOW_NAME"); - config.local_rank = loadInt("LOCAL_RANK"); - config.local_world_size = loadInt("LOCAL_WORLD_SIZE"); - config.world_size = loadInt("WORLD_SIZE"); - config.rank_str = "[RANK " + std::to_string(config.rank) + "] "; -} + static std::string GetDevicePath(uint64_t index) + { + return std::string(DEVICE_PATH_PREFIX) + std::to_string(index); + } + }; -void ValidateDeviceConfiguration() -{ - config.devices = DeviceManager::DetectAvailableDevices(); + namespace + { - if (config.devices.empty()) - { - config.enable = false; - LOG(WARNING) << "No devices found, disabling tracing"; - return; - } + GlobalConfig &config = GlobalConfig::Instance(); - if (config.local_world_size != config.devices.size()) - { - LOG(WARNING) << "Local world size mismatch, disabling hook"; - config.enable = false; - } -} + void LoadEnvironmentVariables() + { + auto loadInt = [](const char *name) { return env::EnvVarRegistry::GetEnvVar(name); }; -} // namespace + auto loadStr = [](const char *name) { return env::EnvVarRegistry::GetEnvVar(name); }; -void InitializeGlobalConfiguration() -{ - LOG(INFO) << "Initializing global configuration"; + config.rank = loadInt("RANK"); + config.job_name = loadStr("ENV_ARGO_WORKFLOW_NAME"); + config.local_rank = loadInt("LOCAL_RANK"); + config.local_world_size = loadInt("LOCAL_WORLD_SIZE"); + config.world_size = loadInt("WORLD_SIZE"); + config.rank_str = "[RANK " + std::to_string(config.rank) + "] "; + } - try - { - LoadEnvironmentVariables(); - ValidateDeviceConfiguration(); - LOG(INFO) << "Global configuration initialized successfully"; - } - catch (const std::exception &e) - { - LOG(ERROR) << "Global config initialization failed: " << e.what(); - throw; - } -} + void ValidateDeviceConfiguration() + { + config.devices = DeviceManager::DetectAvailableDevices(); -} // namespace config + if (config.devices.empty()) { + config.enable = false; + LOG(WARNING) << "No devices found, disabling tracing"; + return; + } -namespace environment -{ + if (config.local_world_size != config.devices.size()) { + LOG(WARNING) << "Local world size mismatch, disabling hook"; + config.enable = false; + } + } -bool IsValidEnvironmentVariableName(const std::string &name) -{ - if (name.empty() || !isalpha(name[0])) - { - return false; - } + } // namespace - for (char c : name) - { - if (!isalnum(c) && c != '_') + void InitializeGlobalConfiguration() { - return false; + LOG(INFO) << "Initializing global configuration"; + + try { + LoadEnvironmentVariables(); + ValidateDeviceConfiguration(); + LOG(INFO) << "Global configuration initialized successfully"; + } catch (const std::exception &e) { + LOG(ERROR) << "Global config initialization failed: " << e.what(); + throw; + } } - } - return true; -} -void RegisterRequiredEnvironmentVariables() -{ - try + } // namespace config + + namespace environment { - if (!IsValidEnvironmentVariableName("ENV_ARGO_WORKFLOW_NAME")) - { - throw std::invalid_argument( - "Invalid env var name: ENV_ARGO_WORKFLOW_NAME"); - } - REGISTER_ENVIRONMENT_VARIABLE( - "ENV_ARGO_WORKFLOW_NAME", - env::EnvVarRegistry::DEFAULT_VALUE_STRING); - if (!IsValidEnvironmentVariableName("SYSTRACE_SYMS_FILE")) + bool IsValidEnvironmentVariableName(const std::string &name) { - throw std::invalid_argument( - "Invalid env var name: SYSTRACE_SYMS_FILE"); - } - REGISTER_ENVIRONMENT_VARIABLE( - "SYSTRACE_SYMS_FILE", env::EnvVarRegistry::DEFAULT_VALUE_STRING); + if (name.empty() || !isalpha(name[0])) { + return false; + } - if (!IsValidEnvironmentVariableName("SYSTRACE_LOGGING_DIR")) - { - throw std::invalid_argument( - "Invalid env var name: SYSTRACE_LOGGING_DIR"); + for (char c : name) { + if (!isalnum(c) && c != '_') { + return false; + } + } + return true; } - REGISTER_ENVIRONMENT_VARIABLE( - "SYSTRACE_LOGGING_DIR", env::EnvVarRegistry::DEFAULT_VALUE_STRING); - if (!IsValidEnvironmentVariableName("SYSTRACE_HOST_TRACING_FUNC")) + void RegisterRequiredEnvironmentVariables() { - throw std::invalid_argument( - "Invalid env var name: SYSTRACE_HOST_TRACING_FUNC"); + try { + if (!IsValidEnvironmentVariableName("ENV_ARGO_WORKFLOW_NAME")) { + throw std::invalid_argument("Invalid env var name: ENV_ARGO_WORKFLOW_NAME"); + } + REGISTER_ENVIRONMENT_VARIABLE("ENV_ARGO_WORKFLOW_NAME", env::EnvVarRegistry::DEFAULT_VALUE_STRING); + + if (!IsValidEnvironmentVariableName("SYSTRACE_SYMS_FILE")) { + throw std::invalid_argument("Invalid env var name: SYSTRACE_SYMS_FILE"); + } + REGISTER_ENVIRONMENT_VARIABLE("SYSTRACE_SYMS_FILE", env::EnvVarRegistry::DEFAULT_VALUE_STRING); + + if (!IsValidEnvironmentVariableName("SYSTRACE_LOGGING_DIR")) { + throw std::invalid_argument("Invalid env var name: SYSTRACE_LOGGING_DIR"); + } + REGISTER_ENVIRONMENT_VARIABLE("SYSTRACE_LOGGING_DIR", env::EnvVarRegistry::DEFAULT_VALUE_STRING); + + if (!IsValidEnvironmentVariableName("SYSTRACE_HOST_TRACING_FUNC")) { + throw std::invalid_argument("Invalid env var name: SYSTRACE_HOST_TRACING_FUNC"); + } + REGISTER_ENVIRONMENT_VARIABLE("SYSTRACE_HOST_TRACING_FUNC", env::EnvVarRegistry::DEFAULT_VALUE_STRING); + + REGISTER_ENVIRONMENT_VARIABLE("RANK", 0); + REGISTER_ENVIRONMENT_VARIABLE("LOCAL_RANK", 0); + REGISTER_ENVIRONMENT_VARIABLE("LOCAL_WORLD_SIZE", 1); + REGISTER_ENVIRONMENT_VARIABLE("WORLD_SIZE", 1); + REGISTER_ENVIRONMENT_VARIABLE("SYSTRACE_LOGGING_APPEND", false); + } catch (const std::exception &e) { + LOG(ERROR) << "Environment variable registration failed: " << e.what(); + throw; + } } - REGISTER_ENVIRONMENT_VARIABLE( - "SYSTRACE_HOST_TRACING_FUNC", - env::EnvVarRegistry::DEFAULT_VALUE_STRING); - - REGISTER_ENVIRONMENT_VARIABLE("RANK", 0); - REGISTER_ENVIRONMENT_VARIABLE("LOCAL_RANK", 0); - REGISTER_ENVIRONMENT_VARIABLE("LOCAL_WORLD_SIZE", 1); - REGISTER_ENVIRONMENT_VARIABLE("WORLD_SIZE", 1); - REGISTER_ENVIRONMENT_VARIABLE("SYSTRACE_LOGGING_APPEND", false); - } - catch (const std::exception &e) + + } // namespace environment + + void InitializeSystemUtilities() { - LOG(ERROR) << "Environment variable registration failed: " << e.what(); - throw; + environment::RegisterRequiredEnvironmentVariables(); + config::InitializeGlobalConfiguration(); } -} -} // namespace environment + std::string GetPrimaryIP() + { + struct ifaddrs *ifaddr, *ifa; + std::string primaryIP; -void InitializeSystemUtilities() -{ - environment::RegisterRequiredEnvironmentVariables(); - config::InitializeGlobalConfiguration(); -} + if (getifaddrs(&ifaddr) == -1) { + perror("getifaddrs"); + return ""; + } -std::string GetPrimaryIP() -{ - struct ifaddrs *ifaddr, *ifa; - std::string primaryIP; + for (ifa = ifaddr; ifa != nullptr; ifa = ifa->ifa_next) { + if (ifa->ifa_addr == nullptr || ifa->ifa_addr->sa_family != AF_INET) { + continue; + } - if (getifaddrs(&ifaddr) == -1) { - perror("getifaddrs"); - return ""; - } + if (strcmp(ifa->ifa_name, "lo") == 0) { + continue; + } - for (ifa = ifaddr; ifa != nullptr; ifa = ifa->ifa_next) { - if (ifa->ifa_addr == nullptr || ifa->ifa_addr->sa_family != AF_INET) { - continue; - } + struct sockaddr_in *addr = (struct sockaddr_in *)ifa->ifa_addr; + char ip[INET_ADDRSTRLEN]; + inet_ntop(AF_INET, &addr->sin_addr, ip, INET_ADDRSTRLEN); - if (strcmp(ifa->ifa_name, "lo") == 0) { - continue; + primaryIP = ip; + break; } - struct sockaddr_in *addr = (struct sockaddr_in *)ifa->ifa_addr; - char ip[INET_ADDRSTRLEN]; - inet_ntop(AF_INET, &addr->sin_addr, ip, INET_ADDRSTRLEN); - - primaryIP = ip; - break; + freeifaddrs(ifaddr); + return primaryIP; } - - freeifaddrs(ifaddr); - return primaryIP; -} } // namespace util } // namespace systrace \ No newline at end of file diff --git a/systrace/include/common/util.h b/systrace/include/common/util.h index c93e2d4..56fa37a 100644 --- a/systrace/include/common/util.h +++ b/systrace/include/common/util.h @@ -23,274 +23,253 @@ namespace systrace { namespace util { -std::string GetPrimaryIP(); -namespace config -{ - -struct GlobalConfig -{ - uint32_t rank{0}; - uint32_t local_rank{0}; - uint32_t world_size{0}; - uint32_t local_world_size{0}; - std::string job_name; - bool enable{true}; - std::vector devices; - std::string rank_str; - - static GlobalConfig &Instance() + std::string GetPrimaryIP(); + namespace config { - static GlobalConfig instance; - return instance; - } - private: - GlobalConfig() = default; -}; + struct GlobalConfig { + uint32_t rank { 0 }; + uint32_t local_rank { 0 }; + uint32_t world_size { 0 }; + uint32_t local_world_size { 0 }; + std::string job_name; + bool enable { true }; + std::vector devices; + std::string rank_str; + + static GlobalConfig &Instance() + { + static GlobalConfig instance; + return instance; + } -void InitializeGlobalConfiguration(); + private: + GlobalConfig() = default; + }; -} // namespace config + void InitializeGlobalConfiguration(); -namespace fs_utils -{ + } // namespace config -std::string GenerateClusterUniqueFilename(const std::string &suffix); -int CreateDirectoryIfNotExists(const std::string &path); + namespace fs_utils + { -} // namespace fs_utils + std::string GenerateClusterUniqueFilename(const std::string &suffix); + int CreateDirectoryIfNotExists(const std::string &path); -namespace resource -{ -template class TimerPool -{ - public: - TimerPool() = default; - TimerPool(const TimerPool &) = delete; - TimerPool &operator=(const TimerPool &) = delete; + } // namespace fs_utils - template T *getObject() + namespace resource { - std::lock_guard lock(mutex_); + template + class TimerPool { + public: + TimerPool() = default; + TimerPool(const TimerPool &) = delete; + TimerPool &operator=(const TimerPool &) = delete; + + template + T *getObject() + { + std::lock_guard lock(mutex_); - T *obj = pool_.empty() ? nullptr : pool_.front(); - if (obj) - { - pool_.pop_front(); - } + T *obj = pool_.empty() ? nullptr : pool_.front(); + if (obj) { + pool_.pop_front(); + } - return obj ? obj : (Init ? new T() : nullptr); - } + return obj ? obj : (Init ? new T() : nullptr); + } - void returnObject(T *obj, int *size) - { - if (!obj) - { - if (size) - *size = 0; - return; - } - - std::lock_guard lock(mutex_); - pool_.push_back(obj); - if (size) - *size = static_cast(pool_.size()); - } - - void clear() + void returnObject(T *obj, int *size) + { + if (!obj) { + if (size) + *size = 0; + return; + } + + std::lock_guard lock(mutex_); + pool_.push_back(obj); + if (size) + *size = static_cast(pool_.size()); + } + + void clear() + { + std::lock_guard lock(mutex_); + for (auto obj : pool_) { + delete obj; + } + pool_.clear(); + } + + ~TimerPool() + { + clear(); + } + + private: + std::deque pool_; + std::mutex mutex_; + }; + + } // namespace resource + + namespace env { - std::lock_guard lock(mutex_); - for (auto obj : pool_) - { - delete obj; - } - pool_.clear(); - } - ~TimerPool() { clear(); } + class EnvVarRegistry { + public: + using VarType = std::variant; - private: - std::deque pool_; - std::mutex mutex_; -}; + static std::string_view DEFAULT_VALUE_STRING; + static int DEFAULT_VALUE_INT; + static bool DEFAULT_VALUE_BOOL; -} // namespace resource + static void RegisterEnv(const std::string &name, VarType default_value) + { + auto ®istry = GetRegistryManager(); + LOG(INFO) << "[ENV] Register ENV " << name << " with default " << VariantToString(default_value) + << std::endl; + registry[name] = std::move(default_value); + } -namespace env -{ + // Get an env var value, with optional printing + template + static T GetEnvVar(const std::string &name) + { + static_assert(is_supported_type(), "Unsupported type for environment variable"); + + auto ®istry = GetRegistryManager(); + bool set = false; + + // Try to get from environment first + T result = getEnvInner(name, &set); + if (set) { + LOG(INFO) << "[ENV] Get " << name << "=" << result << " from environment" << std::endl; + return result; + } + + // Try to get from registered defaults + if (auto it = registry.find(name); it != registry.end()) { + if (const T *val = std::get_if(&it->second)) { + LOG(INFO) << "[ENV] Get " << name << "=" << *val << " from register default" << std::endl; + return *val; + } + LOG(FATAL) << "[ENV] Wrong data type in `GetEnvVar`" << std::endl; + } + + // Fall back to static default + result = getDefault(); + LOG(WARNING) << "[ENV] Get not register env " << name << "=" << result << " from default" << std::endl; + return result; + } -class EnvVarRegistry -{ - public: - using VarType = std::variant; + template + static inline auto convert_to_variant(const T &s) + -> std::enable_if_t, VarType> + { + return std::string(s); + } - static std::string_view DEFAULT_VALUE_STRING; - static int DEFAULT_VALUE_INT; - static bool DEFAULT_VALUE_BOOL; + template + static inline auto convert_to_variant(const T &val) + -> std::enable_if_t, VarType> + { + return val; + } - static void RegisterEnv(const std::string &name, VarType default_value) - { - auto ®istry = GetRegistryManager(); - LOG(INFO) << "[ENV] Register ENV " << name << " with default " - << VariantToString(default_value) << std::endl; - registry[name] = std::move(default_value); - } - - // Get an env var value, with optional printing - template static T GetEnvVar(const std::string &name) - { - static_assert(is_supported_type(), - "Unsupported type for environment variable"); - - auto ®istry = GetRegistryManager(); - bool set = false; - - // Try to get from environment first - T result = getEnvInner(name, &set); - if (set) - { - LOG(INFO) << "[ENV] Get " << name << "=" << result - << " from environment" << std::endl; - return result; - } - - // Try to get from registered defaults - if (auto it = registry.find(name); it != registry.end()) - { - if (const T *val = std::get_if(&it->second)) + private: + template + static constexpr bool is_supported_type() { - LOG(INFO) << "[ENV] Get " << name << "=" << *val - << " from register default" << std::endl; - return *val; + return std::is_same_v || std::is_same_v || std::is_same_v; } - LOG(FATAL) << "[ENV] Wrong data type in `GetEnvVar`" << std::endl; - } - - // Fall back to static default - result = getDefault(); - LOG(WARNING) << "[ENV] Get not register env " << name << "=" << result - << " from default" << std::endl; - return result; - } - - template - static inline auto convert_to_variant(const T &s) - -> std::enable_if_t, VarType> - { - return std::string(s); - } - template - static inline auto convert_to_variant(const T &val) - -> std::enable_if_t, VarType> - { - return val; - } + static std::string toLower(const std::string &str) + { + std::string lower; + lower.reserve(str.size()); + std::transform(str.begin(), str.end(), std::back_inserter(lower), + [](unsigned char c) { return std::tolower(c); }); + return lower; + } - private: - template static constexpr bool is_supported_type() - { - return std::is_same_v || std::is_same_v || - std::is_same_v; - } + // 值解析器 + template + static T parseEnvValue(const char *env) + { + if constexpr (std::is_same_v) { + try { + return std::stoi(env); + } catch (...) { + return DEFAULT_VALUE_INT; + } + } else if constexpr (std::is_same_v) { + std::string lower = toLower(env); + if (lower == "true" || lower == "1") + return true; + if (lower == "false" || lower == "0") + return false; + return std::stoi(env) != 0; + } else if constexpr (std::is_same_v) { + return env; + } + } - static std::string toLower(const std::string &str) - { - std::string lower; - lower.reserve(str.size()); - std::transform(str.begin(), str.end(), std::back_inserter(lower), - [](unsigned char c) { return std::tolower(c); }); - return lower; - } - - // 值解析器 - template static T parseEnvValue(const char *env) - { - if constexpr (std::is_same_v) - { - try + // Get value from real environment + template + static T getEnvInner(const std::string &env_name, bool *set) { - return std::stoi(env); + const char *env = std::getenv(env_name.c_str()); + if (!env) { + *set = false; + return {}; + } + + *set = true; + return parseEnvValue(env); } - catch (...) + + // Default values for fallback + template + static T getDefault() { - return DEFAULT_VALUE_INT; + if constexpr (std::is_same_v) { + return DEFAULT_VALUE_INT; + } else if constexpr (std::is_same_v) { + return DEFAULT_VALUE_BOOL; + } else if constexpr (std::is_same_v) { + return std::string(DEFAULT_VALUE_STRING); + } } - } - else if constexpr (std::is_same_v) - { - std::string lower = toLower(env); - if (lower == "true" || lower == "1") - return true; - if (lower == "false" || lower == "0") - return false; - return std::stoi(env) != 0; - } - else if constexpr (std::is_same_v) - { - return env; - } - } - - // Get value from real environment - template - static T getEnvInner(const std::string &env_name, bool *set) - { - const char *env = std::getenv(env_name.c_str()); - if (!env) - { - *set = false; - return {}; - } - - *set = true; - return parseEnvValue(env); - } - - // Default values for fallback - template static T getDefault() - { - if constexpr (std::is_same_v) - { - return DEFAULT_VALUE_INT; - } - else if constexpr (std::is_same_v) - { - return DEFAULT_VALUE_BOOL; - } - else if constexpr (std::is_same_v) - { - return std::string(DEFAULT_VALUE_STRING); - } - } - - static inline std::unordered_map &GetRegistryManager() - { - static std::unordered_map registry_manager; - return registry_manager; - } - static std::string VariantToString(const VarType &var) - { - return std::visit( - [](const auto &value) + static inline std::unordered_map &GetRegistryManager() { - std::stringstream ss; - ss << value; - return ss.str(); - }, - var); - } -}; - -#define REGISTER_ENVIRONMENT_VARIABLE(name, value) \ - ::systrace::util::env::EnvVarRegistry::RegisterEnv( \ - name, \ - ::systrace::util::env::EnvVarRegistry::convert_to_variant(value)) - -void REGISTER_ENV(); - -} // namespace env -void InitializeSystemUtilities(); + static std::unordered_map registry_manager; + return registry_manager; + } + + static std::string VariantToString(const VarType &var) + { + return std::visit( + [](const auto &value) { + std::stringstream ss; + ss << value; + return ss.str(); + }, + var); + } + }; + +#define REGISTER_ENVIRONMENT_VARIABLE(name, value) \ + ::systrace::util::env::EnvVarRegistry::RegisterEnv( \ + name, ::systrace::util::env::EnvVarRegistry::convert_to_variant(value)) + + void REGISTER_ENV(); + + } // namespace env + void InitializeSystemUtilities(); } // namespace util } // namespace systrace diff --git a/systrace/server/monitor_server.cpp b/systrace/server/monitor_server.cpp index 2df6ab5..b26ab32 100644 --- a/systrace/server/monitor_server.cpp +++ b/systrace/server/monitor_server.cpp @@ -11,19 +11,16 @@ MonitorServer *MonitorServer::instance_ = nullptr; MonitorServer &MonitorServer::getInstance() { - std::call_once(init_flag_, - []() - { - instance_ = new MonitorServer(); - instance_->start(); - }); + std::call_once(init_flag_, []() { + instance_ = new MonitorServer(); + instance_->start(); + }); return *instance_; } MonitorServer::MonitorServer() { - if (init_shared_memory() != 0) - { + if (init_shared_memory() != 0) { throw std::runtime_error("Failed to initialize shared memory"); } } @@ -36,14 +33,12 @@ MonitorServer::~MonitorServer() void MonitorServer::start() { - if (server_fd_ != -1) - { + if (server_fd_ != -1) { return; } server_fd_ = socket(AF_UNIX, SOCK_STREAM, 0); - if (server_fd_ == -1) - { + if (server_fd_ == -1) { perror("socket"); throw std::runtime_error("Failed to create socket"); } @@ -54,16 +49,14 @@ void MonitorServer::start() unlink(SOCKET_PATH); - if (bind(server_fd_, (struct sockaddr *)&addr, sizeof(addr)) == -1) - { + if (bind(server_fd_, (struct sockaddr *)&addr, sizeof(addr)) == -1) { perror("bind"); close(server_fd_); server_fd_ = -1; throw std::runtime_error("Failed to bind socket"); } - if (listen(server_fd_, 5) == -1) - { + if (listen(server_fd_, 5) == -1) { perror("listen"); close(server_fd_); server_fd_ = -1; @@ -75,14 +68,12 @@ void MonitorServer::start() void MonitorServer::stop() { - if (server_fd_ != -1) - { + if (server_fd_ != -1) { close(server_fd_); server_fd_ = -1; } - if (server_thread_.joinable()) - { + if (server_thread_.joinable()) { server_thread_.join(); } @@ -91,15 +82,12 @@ void MonitorServer::stop() void MonitorServer::server_thread_func() { - while (true) - { + while (true) { struct sockaddr_un client_addr; socklen_t client_len = sizeof(client_addr); - int client_fd = - accept(server_fd_, (struct sockaddr *)&client_addr, &client_len); - if (client_fd == -1) - { + int client_fd = accept(server_fd_, (struct sockaddr *)&client_addr, &client_len); + if (client_fd == -1) { break; } @@ -111,26 +99,24 @@ void MonitorServer::handle_client(int client_fd) { char buffer[1024]; ssize_t n = read(client_fd, buffer, sizeof(buffer) - 1); - if (n <= 0) - { + if (n <= 0) { return; } buffer[n] = '\0'; std::string command(buffer); - auto send_response = [client_fd](const std::string &response) - { write(client_fd, response.c_str(), response.size()); }; + auto send_response = [client_fd](const std::string &response) { + write(client_fd, response.c_str(), response.size()); + }; process_command(command, send_response); } -void MonitorServer::process_command( - const std::string &cmd, - const std::function &send_response) +void MonitorServer::process_command(const std::string &cmd, + const std::function &send_response) { SharedData *shared_data = get_shared_data(); - if (!shared_data) - { + if (!shared_data) { send_response("Error: Shared memory not initialized\n"); return; } @@ -139,14 +125,12 @@ void MonitorServer::process_command( std::string action; iss >> action; - if (action == "set") - { + if (action == "set") { std::string level_value; iss >> level_value; size_t eq_pos = level_value.find('='); - if (eq_pos == std::string::npos) - { + if (eq_pos == std::string::npos) { send_response("Error: Invalid set command format. Use 'set " "='\n"); return; @@ -158,20 +142,13 @@ void MonitorServer::process_command( pthread_mutex_lock(&shared_data->g_trace_mutex); - if (level == "L0") - { + if (level == "L0") { shared_data->g_dump_L0 = value; - } - else if (level == "L1") - { + } else if (level == "L1") { shared_data->g_dump_L1 = value; - } - else if (level == "L2") - { + } else if (level == "L2") { shared_data->g_dump_L2 = value; - } - else - { + } else { pthread_mutex_unlock(&shared_data->g_trace_mutex); send_response("Error: Unknown level '" + level + "'\n"); return; @@ -179,15 +156,12 @@ void MonitorServer::process_command( pthread_mutex_unlock(&shared_data->g_trace_mutex); send_response("OK\n"); - } - else if (action == "interval") - { + } else if (action == "interval") { std::string level_value; iss >> level_value; size_t eq_pos = level_value.find('='); - if (eq_pos == std::string::npos) - { + if (eq_pos == std::string::npos) { send_response("Error: Invalid interval command format. Use " "'interval ='\n"); return; @@ -195,28 +169,20 @@ void MonitorServer::process_command( std::string level = level_value.substr(0, eq_pos); unsigned int value; - try - { + try { value = std::stoul(level_value.substr(eq_pos + 1)); - } - catch (...) - { + } catch (...) { send_response("Error: Invalid interval value\n"); return; } pthread_mutex_lock(&shared_data->g_trace_mutex); - if (level == "L1") - { + if (level == "L1") { shared_data->g_dump_L1_interval = value; - } - else if (level == "L2") - { + } else if (level == "L2") { shared_data->g_dump_L2_interval = value; - } - else - { + } else { pthread_mutex_unlock(&shared_data->g_trace_mutex); send_response("Error: Unknown level '" + level + "'\n"); return; @@ -224,9 +190,7 @@ void MonitorServer::process_command( pthread_mutex_unlock(&shared_data->g_trace_mutex); send_response("OK\n"); - } - else if (action == "print") - { + } else if (action == "print") { std::string level; iss >> level; @@ -234,35 +198,22 @@ void MonitorServer::process_command( pthread_mutex_lock(&shared_data->g_trace_mutex); - if (level.empty() || level == "all") - { + if (level.empty() || level == "all") { oss << "Current settings:\n" - << " L0: " << (shared_data->g_dump_L0 ? "true" : "false") - << "\n" - << " L1: " << (shared_data->g_dump_L1 ? "true" : "false") - << "\n" - << " L2: " << (shared_data->g_dump_L2 ? "true" : "false") - << "\n" + << " L0: " << (shared_data->g_dump_L0 ? "true" : "false") << "\n" + << " L1: " << (shared_data->g_dump_L1 ? "true" : "false") << "\n" + << " L2: " << (shared_data->g_dump_L2 ? "true" : "false") << "\n" << " L1_interval: " << shared_data->g_dump_L1_interval << "\n" << " L2_interval: " << shared_data->g_dump_L2_interval << "\n"; - } - else if (level == "L0") - { - oss << "L0: " << (shared_data->g_dump_L0 ? "true" : "false") - << "\n"; - } - else if (level == "L1") - { + } else if (level == "L0") { + oss << "L0: " << (shared_data->g_dump_L0 ? "true" : "false") << "\n"; + } else if (level == "L1") { oss << "L1: " << (shared_data->g_dump_L1 ? "true" : "false") << "\n" << "L1_interval: " << shared_data->g_dump_L1_interval << "\n"; - } - else if (level == "L2") - { + } else if (level == "L2") { oss << "L2: " << (shared_data->g_dump_L2 ? "true" : "false") << "\n" << "L2_interval: " << shared_data->g_dump_L2_interval << "\n"; - } - else - { + } else { pthread_mutex_unlock(&shared_data->g_trace_mutex); send_response("Error: Unknown level '" + level + "'\n"); return; @@ -270,9 +221,7 @@ void MonitorServer::process_command( pthread_mutex_unlock(&shared_data->g_trace_mutex); send_response(oss.str()); - } - else - { + } else { send_response("Error: Unknown command '" + action + "'\n"); } } \ No newline at end of file diff --git a/systrace/server/monitor_server.hpp b/systrace/server/monitor_server.hpp index 5af92bd..34c24cf 100644 --- a/systrace/server/monitor_server.hpp +++ b/systrace/server/monitor_server.hpp @@ -6,9 +6,8 @@ #include #include -class MonitorServer -{ - public: +class MonitorServer { +public: static MonitorServer &getInstance(); void start(); @@ -17,19 +16,17 @@ class MonitorServer MonitorServer(const MonitorServer &) = delete; MonitorServer &operator=(const MonitorServer &) = delete; - private: +private: MonitorServer(); ~MonitorServer(); void server_thread_func(); void handle_client(int client_fd); - void process_command( - const std::string &cmd, - const std::function &send_response); + void process_command(const std::string &cmd, const std::function &send_response); static constexpr const char *SOCKET_PATH = "/tmp/sysTrace_socket"; - int server_fd_{-1}; + int server_fd_ { -1 }; std::thread server_thread_; static MonitorServer *instance_; diff --git a/systrace/src/ascend/hook.cc b/systrace/src/ascend/hook.cc index c168128..5abb35f 100644 --- a/systrace/src/ascend/hook.cc +++ b/systrace/src/ascend/hook.cc @@ -5,69 +5,53 @@ #include #ifdef __cplusplus -extern "C" -{ +extern "C" { #endif - static void *load_symbol(const char *func_name) - { - if (!g_hal_lib) - { - g_hal_lib = dlopen("libascendcl.so", RTLD_LAZY); - if (!g_hal_lib) - { - fprintf(stderr, "[Hook] Failed to dlopen libascendcl.so: %s\n", - dlerror()); - return nullptr; - } +static void *load_symbol(const char *func_name) +{ + if (!g_hal_lib) { + g_hal_lib = dlopen("libascendcl.so", RTLD_LAZY); + if (!g_hal_lib) { + fprintf(stderr, "[Hook] Failed to dlopen libascendcl.so: %s\n", dlerror()); + return nullptr; } + } - void *func = dlsym(g_hal_lib, func_name); - if (!func) - { - fprintf(stderr, "[Hook] Failed to dlsym %s: %s\n", func_name, - dlerror()); - } - else - { - std::cout << "[Hook] Successfully hooked " << func_name - << std::endl; - } - return func; + void *func = dlsym(g_hal_lib, func_name); + if (!func) { + fprintf(stderr, "[Hook] Failed to dlsym %s: %s\n", func_name, dlerror()); + } else { + std::cout << "[Hook] Successfully hooked " << func_name << std::endl; } + return func; +} -#define HOOKED_FUNCTION(func_ptr, func_name, ...) \ - if (!func_ptr) \ - { \ - func_ptr = (decltype(func_ptr))load_symbol(func_name); \ - if (!func_ptr) \ - return -1; \ - } \ - ::systrace::SysTrace::getInstance(); \ +#define HOOKED_FUNCTION(func_ptr, func_name, ...) \ + if (!func_ptr) { \ + func_ptr = (decltype(func_ptr))load_symbol(func_name); \ + if (!func_ptr) \ + return -1; \ + } \ + ::systrace::SysTrace::getInstance(); \ return func_ptr(__VA_ARGS__); - EXPOSE_API aclError aclInit(const char *configPath) - { - HOOKED_FUNCTION(orig_aclInit, "aclInit", configPath); - } +EXPOSE_API aclError aclInit(const char *configPath) +{ + HOOKED_FUNCTION(orig_aclInit, "aclInit", configPath); +} - EXPOSE_API aclError aclrtMapMem(void *virPtr, size_t size, size_t offset, - aclrtDrvMemHandle handle, uint64_t flags) - { - HOOKED_FUNCTION(orig_aclrtMapMem, "aclrtMapMem", virPtr, size, offset, - handle, flags); - } +EXPOSE_API aclError aclrtMapMem(void *virPtr, size_t size, size_t offset, aclrtDrvMemHandle handle, uint64_t flags) +{ + HOOKED_FUNCTION(orig_aclrtMapMem, "aclrtMapMem", virPtr, size, offset, handle, flags); +} - EXPOSE_API aclError aclrtLaunchKernel(aclrtFuncHandle func, int workDim, - void **workGroup, - size_t *localWorkSize, - aclrtStream stream, void *event, - void *config) - { - HOOKED_FUNCTION(orig_aclrtLaunchKernel, "aclrtLaunchKernel", func, - workDim, workGroup, localWorkSize, stream, event, - config); - } +EXPOSE_API aclError aclrtLaunchKernel(aclrtFuncHandle func, int workDim, void **workGroup, size_t *localWorkSize, + aclrtStream stream, void *event, void *config) +{ + HOOKED_FUNCTION(orig_aclrtLaunchKernel, "aclrtLaunchKernel", func, workDim, workGroup, localWorkSize, stream, event, + config); +} #ifdef __cplusplus } diff --git a/systrace/src/ascend/hook.h b/systrace/src/ascend/hook.h index adbe0a0..c9caea1 100644 --- a/systrace/src/ascend/hook.h +++ b/systrace/src/ascend/hook.h @@ -5,37 +5,31 @@ #include #ifdef __cplusplus -extern "C" -{ +extern "C" { #endif - typedef int aclError; - typedef void *aclrtStream; - typedef void *aclrtFuncHandle; - typedef void *aclrtDrvMemHandle; +typedef int aclError; +typedef void *aclrtStream; +typedef void *aclrtFuncHandle; +typedef void *aclrtDrvMemHandle; - typedef aclError (*aclInitFn)(const char *); - typedef aclError (*aclrtMapMemFn)(void *, size_t, size_t, aclrtDrvMemHandle, - uint64_t); - typedef aclError (*aclrtLaunchKernelFn)(aclrtFuncHandle, int, void **, - size_t *, aclrtStream, void *, - void *); +typedef aclError (*aclInitFn)(const char *); +typedef aclError (*aclrtMapMemFn)(void *, size_t, size_t, aclrtDrvMemHandle, uint64_t); +typedef aclError (*aclrtLaunchKernelFn)(aclrtFuncHandle, int, void **, size_t *, aclrtStream, void *, void *); - extern void *ascend_hal_handle; - extern aclInitFn orig_aclInit; - extern aclrtMapMemFn orig_aclrtMapMem; - extern aclrtLaunchKernelFn orig_aclrtLaunchKernel; +extern void *ascend_hal_handle; +extern aclInitFn orig_aclInit; +extern aclrtMapMemFn orig_aclrtMapMem; +extern aclrtLaunchKernelFn orig_aclrtLaunchKernel; - aclError aclInit(const char *configPath); - aclError aclrtMapMem(void *virPtr, size_t size, size_t offset, - aclrtDrvMemHandle handle, uint64_t flags); - aclError aclrtLaunchKernel(aclrtFuncHandle func, int workDim, - void **workGroup, size_t *localWorkSize, - aclrtStream stream, void *event, void *config); +aclError aclInit(const char *configPath); +aclError aclrtMapMem(void *virPtr, size_t size, size_t offset, aclrtDrvMemHandle handle, uint64_t flags); +aclError aclrtLaunchKernel(aclrtFuncHandle func, int workDim, void **workGroup, size_t *localWorkSize, + aclrtStream stream, void *event, void *config); - static void *g_hal_lib = nullptr; - aclInitFn orig_aclInit = nullptr; - aclrtMapMemFn orig_aclrtMapMem = nullptr; - aclrtLaunchKernelFn orig_aclrtLaunchKernel = nullptr; +static void *g_hal_lib = nullptr; +aclInitFn orig_aclInit = nullptr; +aclrtMapMemFn orig_aclrtMapMem = nullptr; +aclrtLaunchKernelFn orig_aclrtLaunchKernel = nullptr; #ifdef __cplusplus } #endif \ No newline at end of file diff --git a/systrace/src/cann/cann_hook.c b/systrace/src/cann/cann_hook.c index a74b2cb..72406a7 100644 --- a/systrace/src/cann/cann_hook.c +++ b/systrace/src/cann/cann_hook.c @@ -37,8 +37,7 @@ typedef int drvError_t; -typedef enum aclrtMemMallocPolicy -{ +typedef enum aclrtMemMallocPolicy { ACL_MEM_MALLOC_HUGE_FIRST, ACL_MEM_MALLOC_HUGE_ONLY, ACL_MEM_MALLOC_NORMAL_ONLY, @@ -48,19 +47,14 @@ typedef enum aclrtMemMallocPolicy ACL_MEM_TYPE_LOW_BAND_WIDTH = 0x0100, ACL_MEM_TYPE_HIGH_BAND_WIDTH = 0x1000, } aclrtMemMallocPolicy; -typedef drvError_t (*halMemAllocFunc_t)(void **pp, unsigned long long size, - unsigned long long flag); +typedef drvError_t (*halMemAllocFunc_t)(void **pp, unsigned long long size, unsigned long long flag); typedef drvError_t (*halMemFreeFunc_t)(void *pp); -typedef drvError_t (*halMemCreateFunc_t)(void **handle, size_t size, void *prop, - uint64_t flag); +typedef drvError_t (*halMemCreateFunc_t)(void **handle, size_t size, void *prop, uint64_t flag); typedef drvError_t (*halMemReleaseFunc_t)(void *handle); -typedef drvError_t (*aclrtMallocFunc_t)(void **devPtr, size_t size, - aclrtMemMallocPolicy policy); -typedef drvError_t (*aclrtMallocCachedFunc_t)(void **devPtr, size_t size, - aclrtMemMallocPolicy policy); -typedef drvError_t (*aclrtMallocAlign32Func_t)(void **devPtr, size_t size, - aclrtMemMallocPolicy policy); +typedef drvError_t (*aclrtMallocFunc_t)(void **devPtr, size_t size, aclrtMemMallocPolicy policy); +typedef drvError_t (*aclrtMallocCachedFunc_t)(void **devPtr, size_t size, aclrtMemMallocPolicy policy); +typedef drvError_t (*aclrtMallocAlign32Func_t)(void **devPtr, size_t size, aclrtMemMallocPolicy policy); typedef drvError_t (*aclrtFreeFunc_t)(void *devPtr); static halMemAllocFunc_t orig_halMemAlloc = NULL; @@ -78,8 +72,7 @@ static pthread_mutex_t file_mutex = PTHREAD_MUTEX_INITIALIZER; extern int global_stage_id; extern int global_stage_type; -typedef struct -{ +typedef struct { ProcMem *proc_mem; time_t last_log_time; } ThreadData; @@ -87,10 +80,8 @@ typedef struct static void *load_symbol(void *lib, const char *symbol_name) { void *sym = dlsym(lib, symbol_name); - if (!sym) - { - fprintf(stderr, "Failed to find symbol %s: %s\n", symbol_name, - dlerror()); + if (!sym) { + fprintf(stderr, "Failed to find symbol %s: %s\n", symbol_name, dlerror()); } return sym; } @@ -101,11 +92,9 @@ static void free_proc_mem(ProcMem *proc_mem) return; // 释放分配记录 - for (size_t i = 0; i < proc_mem->n_mem_alloc_stacks; i++) - { + for (size_t i = 0; i < proc_mem->n_mem_alloc_stacks; i++) { MemAllocEntry *entry = proc_mem->mem_alloc_stacks[i]; - for (size_t j = 0; j < entry->n_stack_frames; j++) - { + for (size_t j = 0; j < entry->n_stack_frames; j++) { free((void *)entry->stack_frames[j]->so_name); free(entry->stack_frames[j]); } @@ -115,8 +104,7 @@ static void free_proc_mem(ProcMem *proc_mem) free(proc_mem->mem_alloc_stacks); // 释放释放记录 - for (size_t i = 0; i < proc_mem->n_mem_free_stacks; i++) - { + for (size_t i = 0; i < proc_mem->n_mem_free_stacks; i++) { free(proc_mem->mem_free_stacks[i]); } free(proc_mem->mem_free_stacks); @@ -131,15 +119,17 @@ static void free_proc_mem(ProcMem *proc_mem) static void free_thread_data(void *data) { ThreadData *td = (ThreadData *)data; - if (td && td->proc_mem) - { + if (td && td->proc_mem) { free_proc_mem(td->proc_mem); free(td->proc_mem); } free(td); } -static inline uint32_t get_current_pid() { return (uint32_t)getpid(); } +static inline uint32_t get_current_pid() +{ + return (uint32_t)getpid(); +} static void make_key() { @@ -153,8 +143,7 @@ static ThreadData *get_thread_data() pthread_once(&key_once, make_key); td = pthread_getspecific(thread_data_key); - if (!td) - { + if (!td) { td = calloc(1, sizeof(ThreadData)); td->proc_mem = calloc(1, sizeof(ProcMem)); proc_mem__init(td->proc_mem); @@ -170,53 +159,42 @@ static const char *get_so_name(uint64_t ip) { Dl_info info; const char *so_name; - if (dladdr((void *)ip, &info)) - { + if (dladdr((void *)ip, &info)) { so_name = strrchr(info.dli_fname, '/'); return (so_name != NULL) ? so_name + 1 : info.dli_fname; } return "unknown"; } -static void get_log_filename(time_t current, uint32_t pid, char *buf, - size_t buf_size) +static void get_log_filename(time_t current, uint32_t pid, char *buf, size_t buf_size) { const char *rank_str = getenv("RANK"); int rank = rank_str ? atoi(rank_str) : 0; struct tm *tm = localtime(¤t); const char *dir_path = SYS_TRACE_ROOT_DIR "cann"; - if (access(dir_path, F_OK) != 0) - { - if (mkdir(dir_path, 0755) != 0 && errno != EEXIST) - { + if (access(dir_path, F_OK) != 0) { + if (mkdir(dir_path, 0755) != 0 && errno != EEXIST) { perror("Failed to create directory"); - snprintf(buf, buf_size, "mem_trace_%04d%02d%02d_%02d_%u_rank%d.pb", - tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, - tm->tm_hour, pid, rank); + snprintf(buf, buf_size, "mem_trace_%04d%02d%02d_%02d_%u_rank%d.pb", tm->tm_year + 1900, tm->tm_mon + 1, + tm->tm_mday, tm->tm_hour, pid, rank); return; } } - snprintf(buf, buf_size, "%s/mem_trace_%04d%02d%02d_%02d_%u_rank%d.pb", - dir_path, tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, - tm->tm_hour, pid, rank); + snprintf(buf, buf_size, "%s/mem_trace_%04d%02d%02d_%02d_%u_rank%d.pb", dir_path, tm->tm_year + 1900, tm->tm_mon + 1, + tm->tm_mday, tm->tm_hour, pid, rank); } static char is_ready_to_write(ThreadData *td, time_t *current) { ProcMem *proc_mem = td->proc_mem; - if (!proc_mem || - (proc_mem->n_mem_alloc_stacks + proc_mem->n_mem_free_stacks == 0)) - { + if (!proc_mem || (proc_mem->n_mem_alloc_stacks + proc_mem->n_mem_free_stacks == 0)) { return 0; } *current = time(NULL); - if (proc_mem->n_mem_alloc_stacks + proc_mem->n_mem_free_stacks < - LOG_ITEMS_MIN) - { - if (*current - td->last_log_time < LOG_INTERVAL_SEC) - { + if (proc_mem->n_mem_alloc_stacks + proc_mem->n_mem_free_stacks < LOG_ITEMS_MIN) { + if (*current - td->last_log_time < LOG_INTERVAL_SEC) { return 0; } } @@ -226,49 +204,40 @@ static char is_ready_to_write(ThreadData *td, time_t *current) static void write_protobuf_to_file() { - if (!checkAndUpdateTimer(2)) - { - return; + if (!checkAndUpdateTimer(2)) { + return; } time_t current; uint8_t *buf; ThreadData *td = get_thread_data(); - if (!td) - { + if (!td) { return; } - if (!is_ready_to_write(td, ¤t)) - { + if (!is_ready_to_write(td, ¤t)) { return; } - if (pthread_mutex_trylock(&file_mutex) == 0) - { // pthread_mutex_trylock or pthread_mutex_lock + if (pthread_mutex_trylock(&file_mutex) == 0) { // pthread_mutex_trylock or pthread_mutex_lock char filename[256]; - get_log_filename(current, td->proc_mem->pid, filename, - sizeof(filename)); + get_log_filename(current, td->proc_mem->pid, filename, sizeof(filename)); size_t len = proc_mem__get_packed_size(td->proc_mem); buf = malloc(len); proc_mem__pack(td->proc_mem, buf); FILE *fp = fopen(filename, "ab"); - if (fp) - { + if (fp) { fwrite(buf, len, 1, fp); fclose(fp); } pthread_mutex_unlock(&file_mutex); - } - else - { + } else { return; } - if (buf) - { + if (buf) { free(buf); } @@ -276,15 +245,15 @@ static void write_protobuf_to_file() td->last_log_time = current; } -static void exit_handler(void) { write_protobuf_to_file(); } +static void exit_handler(void) +{ + write_protobuf_to_file(); +} int init_mem_trace() { - void *lib = - dlopen("/usr/local/Ascend/ascend-toolkit/latest/lib64/libascendcl.so", - RTLD_LAZY); - if (!lib) - { + void *lib = dlopen("/usr/local/Ascend/ascend-toolkit/latest/lib64/libascendcl.so", RTLD_LAZY); + if (!lib) { fprintf(stderr, "dlopen failed: %s\n", dlerror()); return -1; } @@ -294,16 +263,12 @@ int init_mem_trace() orig_halMemCreate = (halMemCreateFunc_t)load_symbol(lib, "halMemCreate"); orig_halMemRelease = (halMemReleaseFunc_t)load_symbol(lib, "halMemRelease"); orig_aclrtMalloc = (aclrtMallocFunc_t)load_symbol(lib, "aclrtMalloc"); - orig_aclrtMallocCached = - (aclrtMallocCachedFunc_t)load_symbol(lib, "aclrtMallocCached"); - orig_aclrtMallocAlign32 = - (aclrtMallocAlign32Func_t)load_symbol(lib, "aclrtMallocAlign32"); + orig_aclrtMallocCached = (aclrtMallocCachedFunc_t)load_symbol(lib, "aclrtMallocCached"); + orig_aclrtMallocAlign32 = (aclrtMallocAlign32Func_t)load_symbol(lib, "aclrtMallocAlign32"); orig_aclrtFree = (aclrtFreeFunc_t)load_symbol(lib, "aclrtFree"); - if (!orig_halMemAlloc || !orig_halMemFree || !orig_aclrtMalloc || - !orig_aclrtFree || !orig_halMemCreate || !orig_halMemRelease || - !orig_aclrtMallocCached || orig_aclrtMallocAlign32) - { + if (!orig_halMemAlloc || !orig_halMemFree || !orig_aclrtMalloc || !orig_aclrtFree || !orig_halMemCreate || + !orig_halMemRelease || !orig_aclrtMallocCached || orig_aclrtMallocAlign32) { return -1; } @@ -315,8 +280,7 @@ int init_mem_trace() unw_word_t get_so_base(unw_word_t addr) { Dl_info info; - if (dladdr((void *)addr, &info) != 0) - { + if (dladdr((void *)addr, &info) != 0) { return (unw_word_t)info.dli_fbase; } return 0; @@ -334,8 +298,7 @@ static void collect_stack_frames(MemAllocEntry *entry) unw_init_local(&cursor, &context); entry->stack_frames = calloc(max_frames, sizeof(StackFrame *)); - while (unw_step(&cursor) > 0 && frame_count < max_frames) - { + while (unw_step(&cursor) > 0 && frame_count < max_frames) { unw_get_reg(&cursor, UNW_REG_IP, &ip); // Get the SO name and base address for this IP @@ -344,8 +307,7 @@ static void collect_stack_frames(MemAllocEntry *entry) StackFrame *frame = malloc(sizeof(StackFrame)); stack_frame__init(frame); - frame->address = - ip - so_base; // Store offset within SO instead of virtual address + frame->address = ip - so_base; // Store offset within SO instead of virtual address frame->so_name = strdup(so_name); entry->stack_frames[frame_count] = frame; @@ -357,9 +319,8 @@ static void collect_stack_frames(MemAllocEntry *entry) static void add_mem_alloc_entry(void *pp, size_t size) { - if (!checkAndUpdateTimer(2)) - { - return; + if (!checkAndUpdateTimer(2)) { + return; } ThreadData *td = get_thread_data(); @@ -376,17 +337,14 @@ static void add_mem_alloc_entry(void *pp, size_t size) td->proc_mem->n_mem_alloc_stacks++; td->proc_mem->mem_alloc_stacks = - realloc(td->proc_mem->mem_alloc_stacks, - td->proc_mem->n_mem_alloc_stacks * sizeof(MemAllocEntry *)); - td->proc_mem->mem_alloc_stacks[td->proc_mem->n_mem_alloc_stacks - 1] = - entry; + realloc(td->proc_mem->mem_alloc_stacks, td->proc_mem->n_mem_alloc_stacks * sizeof(MemAllocEntry *)); + td->proc_mem->mem_alloc_stacks[td->proc_mem->n_mem_alloc_stacks - 1] = entry; } static void add_mem_free_entry(void *pp) { - if (!checkAndUpdateTimer(2)) - { - return; + if (!checkAndUpdateTimer(2)) { + return; } ThreadData *td = get_thread_data(); @@ -398,21 +356,17 @@ static void add_mem_free_entry(void *pp) td->proc_mem->n_mem_free_stacks++; td->proc_mem->mem_free_stacks = - realloc(td->proc_mem->mem_free_stacks, - td->proc_mem->n_mem_free_stacks * sizeof(MemFreeEntry *)); + realloc(td->proc_mem->mem_free_stacks, td->proc_mem->n_mem_free_stacks * sizeof(MemFreeEntry *)); td->proc_mem->mem_free_stacks[td->proc_mem->n_mem_free_stacks - 1] = entry; } -drvError_t halMemAlloc(void **pp, unsigned long long size, - unsigned long long flag) +drvError_t halMemAlloc(void **pp, unsigned long long size, unsigned long long flag) { - if (!orig_halMemAlloc) - { + if (!orig_halMemAlloc) { init_mem_trace(); } int ret = orig_halMemAlloc(pp, size, flag); - if (ret == 0 && pp && *pp) - { + if (ret == 0 && pp && *pp) { add_mem_alloc_entry(*pp, size); } @@ -423,13 +377,11 @@ drvError_t halMemAlloc(void **pp, unsigned long long size, drvError_t halMemFree(void *pp) { - if (!orig_halMemFree) - { + if (!orig_halMemFree) { init_mem_trace(); } int ret = orig_halMemFree(pp); - if (ret == 0 && pp) - { + if (ret == 0 && pp) { add_mem_free_entry(pp); } diff --git a/systrace/src/mspti/json_file_writer.h b/systrace/src/mspti/json_file_writer.h index 7de2112..d8ff8d5 100644 --- a/systrace/src/mspti/json_file_writer.h +++ b/systrace/src/mspti/json_file_writer.h @@ -18,21 +18,21 @@ private: std::mutex buffermtx; std::mutex bufferMarkerMtx; std::mutex threadmtx; - std::atomic opened; + std::atomic opened; std::unique_ptr> markerActivityBuffer; std::thread writerThread; std::condition_variable cv; std::atomic stop; public: - MSPTIHcclFileWriter(const std::string& filename) { + MSPTIHcclFileWriter(const std::string &filename) + { // obtain environment variable LOCAL_RANK // to determine the rank of the process // and append it to the filename - const char* path = std::getenv("METRIC_PATH"); + const char *path = std::getenv("METRIC_PATH"); std::string savePath = path ? path : SYS_TRACE_ROOT_DIR "mspti/"; - if (systrace::util::fs_utils::CreateDirectoryIfNotExists(savePath)) - { + if (systrace::util::fs_utils::CreateDirectoryIfNotExists(savePath)) { STLOG(ERROR) << "[MSPTI] Failed to create dump directory"; return; } @@ -44,12 +44,12 @@ public: std::string filenameWithRank = saveFilename; this->markerActivityBuffer = std::make_unique>(); - const char* localRankCStr = std::getenv("RANK"); + const char *localRankCStr = std::getenv("RANK"); if (localRankCStr == nullptr) { localRankCStr = "-1"; } std::string localRank = localRankCStr; - auto rank = std::stoi(localRank); + auto rank = std::stoi(localRank); if (saveFilename.length() >= 4 && saveFilename.substr(saveFilename.length() - 4) == ".csv") { std::string baseName = saveFilename.substr(0, saveFilename.length() - 4); filenameWithRank = baseName + "." + std::to_string(rank) + ".csv"; @@ -66,14 +66,17 @@ public: } else { this->file.open(filenameWithRank, std::ios::out | std::ios::app); this->opened.store(true); - this->file << "Flag,Id,Kind,Name,SourceKind,Timestamp,msptiObjectId_Ds_DeviceId,msptiObjectId_Ds_StreamId,msptiObjectId_Pt_ProcessId,msptiObjectId_Pt_ThreadId" << std::endl; + this->file + << "Flag,Id,Kind,Name,SourceKind,Timestamp,msptiObjectId_Ds_DeviceId,msptiObjectId_Ds_StreamId,msptiObjectId_Pt_ProcessId,msptiObjectId_Pt_ThreadId" + << std::endl; } - + this->stop.store(false); this->run(); } - void stopWriter() { + void stopWriter() + { if (this->file.is_open()) { { std::unique_lock lock(this->threadmtx); @@ -82,7 +85,7 @@ public: } this->cv.notify_all(); this->hcclActivityFormatToCSV(); - if (this->writerThread.joinable()){ + if (this->writerThread.joinable()) { this->writerThread.join(); } // write the remaining buffer @@ -92,39 +95,42 @@ public: } } - ~MSPTIHcclFileWriter() { + ~MSPTIHcclFileWriter() + { this->stopWriter(); } - bool fileExists(const std::string& fp) { + bool fileExists(const std::string &fp) + { std::ifstream file(fp.c_str()); return file.good() && file.is_open(); } - - void bufferMarkerActivity(msptiActivityMarker* activity) { + void bufferMarkerActivity(msptiActivityMarker *activity) + { std::lock_guard lock(this->bufferMarkerMtx); this->markerActivityBuffer->push_back(*activity); } - void run() { + void run() + { // a thread to periodically flush // the buffer to the file // watch the conditional variable for signal - this->writerThread = std::thread([this](){ + this->writerThread = std::thread([this]() { while (!this->stop.load()) { std::unique_lock lock(this->threadmtx); - if (this->cv.wait_for(lock, std::chrono::seconds(5)) == std::cv_status::timeout){ + if (this->cv.wait_for(lock, std::chrono::seconds(5)) == std::cv_status::timeout) { this->hcclActivityFormatToCSV(); } else if (this->stop.load()) { break; }; } }); - } - void replaceCommasWithExclamation(const char* input, char* output) { + void replaceCommasWithExclamation(const char *input, char *output) + { for (int i = 0; input[i] != '\0'; i++) { if (input[i] == ',') { output[i] = '!'; @@ -135,7 +141,8 @@ public: output[strlen(input)] = '\0'; } - void hcclActivityFormatToCSV() { + void hcclActivityFormatToCSV() + { if (!checkAndUpdateTimer(1) && !need_dump_L1_once()) { return; } @@ -145,21 +152,22 @@ public: for (auto activity : *this->markerActivityBuffer) { char result[strlen(activity.name) + 1]; this->replaceCommasWithExclamation(activity.name, result); - // "Flag,Id,Kind,Name,SourceKind,Timestamp,msptiObjectId_Ds_DeviceId,msptiObjectId_Ds_StreamId,msptiObjectId_Pt_ProcessId,msptiObjectId_Pt_ThreadId"; + // "Flag,Id,Kind,Name,SourceKind,Timestamp,msptiObjectId_Ds_DeviceId,msptiObjectId_Ds_StreamId,msptiObjectId_Pt_ProcessId,msptiObjectId_Pt_ThreadId"; if (activity.sourceKind == MSPTI_ACTIVITY_SOURCE_KIND_HOST) { - this->file << activity.flag << "," << activity.id << "," << activity.kind << "," << result << "," << \ - activity.sourceKind<< "," << activity.timestamp << "," << activity.objectId.pt.processId << "," << activity.objectId.pt.threadId << "," << \ - activity.objectId.pt.processId << "," << activity.objectId.pt.threadId << std::endl; - }else if(activity.sourceKind == MSPTI_ACTIVITY_SOURCE_KIND_DEVICE) { - this->file << activity.flag << "," << activity.id << "," << activity.kind << "," << result << "," << \ - activity.sourceKind<< "," << activity.timestamp << "," << activity.objectId.ds.deviceId << "," << activity.objectId.ds.streamId << "," << \ - activity.objectId.ds.deviceId << "," << activity.objectId.ds.streamId << std::endl; + this->file << activity.flag << "," << activity.id << "," << activity.kind << "," << result << "," + << activity.sourceKind << "," << activity.timestamp << "," + << activity.objectId.pt.processId << "," << activity.objectId.pt.threadId << "," + << activity.objectId.pt.processId << "," << activity.objectId.pt.threadId << std::endl; + } else if (activity.sourceKind == MSPTI_ACTIVITY_SOURCE_KIND_DEVICE) { + this->file << activity.flag << "," << activity.id << "," << activity.kind << "," << result << "," + << activity.sourceKind << "," << activity.timestamp << "," + << activity.objectId.ds.deviceId << "," << activity.objectId.ds.streamId << "," + << activity.objectId.ds.deviceId << "," << activity.objectId.ds.streamId << std::endl; } } this->markerActivityBuffer->clear(); SharedData *shared_data = get_shared_data(); - if (!shared_data) - { + if (!shared_data) { return; } shared_data->dumped_L1 = true; diff --git a/systrace/src/mspti/mspti_tracker.cpp b/systrace/src/mspti/mspti_tracker.cpp index 15c596a..b7a2fe4 100644 --- a/systrace/src/mspti/mspti_tracker.cpp +++ b/systrace/src/mspti/mspti_tracker.cpp @@ -13,16 +13,14 @@ using namespace systrace::util; inline uint8_t *align_buffer(uint8_t *buffer, size_t align) { - return reinterpret_cast( - (reinterpret_cast(buffer) + (align - 1)) & ~(align - 1)); + return reinterpret_cast((reinterpret_cast(buffer) + (align - 1)) & ~(align - 1)); } MSPTITracker::MSPTITracker() { std::cout << "Logging initialized from preloaded library." << std::endl; - std::string file_name = "hccl_activity-" + systrace::util::GetPrimaryIP() + "-.csv"; - hcclFileWriter = - std::make_unique(file_name); + std::string file_name = "hccl_activity-" + systrace::util::GetPrimaryIP() + "-.csv"; + hcclFileWriter = std::make_unique(file_name); msptiSubscribe(&subscriber, nullptr, nullptr); msptiActivityRegisterCallbacks(UserBufferRequest, UserBufferComplete); mspti_monitor_thread = std::thread(&MSPTITracker::collect, this); @@ -35,8 +33,7 @@ void MSPTITracker::collect() if (should_collect && !is_collecting_.load()) { msptiActivityEnable(MSPTI_ACTIVITY_KIND_MARKER); is_collecting_.store(true); - } - else if (!should_collect && is_collecting_.load()) { + } else if (!should_collect && is_collecting_.load()) { msptiActivityDisable(MSPTI_ACTIVITY_KIND_MARKER); is_collecting_.store(false); } @@ -65,22 +62,19 @@ MSPTITracker &MSPTITracker::getInstance() void MSPTITracker::finish() { std::cout << "Finishing MSPTI Tracker" << std::endl; - if (hcclFileWriter) - { + if (hcclFileWriter) { hcclFileWriter->stopWriter(); } } void MSPTITracker::readActivityMarker(msptiActivityMarker *activity) { - if (hcclFileWriter) - { + if (hcclFileWriter) { hcclFileWriter->bufferMarkerActivity(activity); } } -void MSPTITracker::UserBufferRequest(uint8_t **buffer, size_t *size, - size_t *maxNumRecords) +void MSPTITracker::UserBufferRequest(uint8_t **buffer, size_t *size, size_t *maxNumRecords) { auto &instance = getInstance(); std::lock_guard lock(mtx); @@ -92,26 +86,18 @@ void MSPTITracker::UserBufferRequest(uint8_t **buffer, size_t *size, *maxNumRecords = 0; } -void MSPTITracker::UserBufferComplete(uint8_t *buffer, size_t size, - size_t validSize) +void MSPTITracker::UserBufferComplete(uint8_t *buffer, size_t size, size_t validSize) { auto &instance = getInstance(); - if (validSize > 0) - { + if (validSize > 0) { msptiActivity *pRecord = nullptr; msptiResult status = MSPTI_SUCCESS; - do - { + do { std::lock_guard lock(mtx); status = msptiActivityGetNextRecord(buffer, validSize, &pRecord); - if (status == MSPTI_SUCCESS && - pRecord->kind == MSPTI_ACTIVITY_KIND_MARKER) - { - instance.readActivityMarker( - reinterpret_cast(pRecord)); - } - else if (status == MSPTI_ERROR_MAX_LIMIT_REACHED) - { + if (status == MSPTI_SUCCESS && pRecord->kind == MSPTI_ACTIVITY_KIND_MARKER) { + instance.readActivityMarker(reinterpret_cast(pRecord)); + } else if (status == MSPTI_ERROR_MAX_LIMIT_REACHED) { break; } } while (status == MSPTI_SUCCESS); diff --git a/systrace/src/mspti/mspti_tracker.hpp b/systrace/src/mspti/mspti_tracker.hpp index 1109fdc..1c0247d 100644 --- a/systrace/src/mspti/mspti_tracker.hpp +++ b/systrace/src/mspti/mspti_tracker.hpp @@ -4,34 +4,34 @@ #include #include -class MSPTITracker -{ - private: +class MSPTITracker { +private: static std::mutex mtx; msptiSubscriberHandle subscriber; std::unique_ptr hcclFileWriter; - std::atomic requestedCount{0}; + std::atomic requestedCount { 0 }; std::thread mspti_monitor_thread; - std::atomic is_collecting_{false}; - std::atomic should_run_{true}; + std::atomic is_collecting_ { false }; + std::atomic should_run_ { true }; MSPTITracker(); ~MSPTITracker(); - public: +public: MSPTITracker(const MSPTITracker &) = delete; MSPTITracker &operator=(const MSPTITracker &) = delete; static MSPTITracker &getInstance(); - msptiSubscriberHandle *getSubscriber() { return &subscriber; } + msptiSubscriberHandle *getSubscriber() + { + return &subscriber; + } void finish(); void readActivityMarker(msptiActivityMarker *activity); - static void UserBufferRequest(uint8_t **buffer, size_t *size, - size_t *maxNumRecords); - static void UserBufferComplete(uint8_t *buffer, size_t size, - size_t validSize); + static void UserBufferRequest(uint8_t **buffer, size_t *size, size_t *maxNumRecords); + static void UserBufferComplete(uint8_t *buffer, size_t size, size_t validSize); void collect(); }; \ No newline at end of file diff --git a/systrace/src/os/__compat.h b/systrace/src/os/__compat.h index ff53b34..c97162e 100644 --- a/systrace/src/os/__compat.h +++ b/systrace/src/os/__compat.h @@ -48,8 +48,7 @@ struct { typedef int (*bpf_buffer_sample_fn)(void *ctx, void *data, u32 size); typedef void (*bpf_buffer_lost_fn)(void *ctx, int cpu, u64 cnt); -struct bpf_buffer -{ +struct bpf_buffer { struct bpf_map *map; void *inner; bpf_buffer_sample_fn fn; @@ -91,10 +90,9 @@ static inline int bpf_buffer__reset(struct bpf_map *map, struct bpf_map *heap) return type; } -#define MAX_RB_MAP_SZ 32 +#define MAX_RB_MAP_SZ 32 static inline int bpf_buffer__set_max_entries(struct bpf_map *map, struct bpf_buffer *buffer, unsigned char map_size_mb) { - if (buffer == NULL || buffer->type != BPF_MAP_TYPE_RINGBUF) { return 0; } @@ -124,7 +122,8 @@ static inline struct bpf_buffer *bpf_buffer__new(struct bpf_map *map, struct bpf return buffer; } -static inline struct bpf_buffer *bpf_buffer__new_shared(struct bpf_map *map, struct bpf_map *heap, struct bpf_buffer **buffer_ptr) +static inline struct bpf_buffer *bpf_buffer__new_shared(struct bpf_map *map, struct bpf_map *heap, + struct bpf_buffer **buffer_ptr) { struct bpf_buffer *buffer; @@ -138,7 +137,8 @@ static inline struct bpf_buffer *bpf_buffer__new_shared(struct bpf_map *map, str return buffer; } -static inline int bpf_buffer__open(struct bpf_buffer *buffer, bpf_buffer_sample_fn sample_cb, bpf_buffer_lost_fn lost_cb, void *ctx) +static inline int bpf_buffer__open(struct bpf_buffer *buffer, bpf_buffer_sample_fn sample_cb, + bpf_buffer_lost_fn lost_cb, void *ctx) { int fd, type; void *inner; @@ -151,16 +151,16 @@ static inline int bpf_buffer__open(struct bpf_buffer *buffer, bpf_buffer_sample_ type = buffer->type; switch (type) { - case BPF_MAP_TYPE_PERF_EVENT_ARRAY: - buffer->fn = sample_cb; - buffer->ctx = ctx; - inner = perf_buffer__new(fd, PERF_BUFFER_PAGES, __perfbuf_sample_fn, lost_cb, buffer, NULL); - break; - case BPF_MAP_TYPE_RINGBUF: - inner = ring_buffer__new(fd, (ring_buffer_sample_fn) sample_cb, ctx, NULL); - break; - default: - return 0; + case BPF_MAP_TYPE_PERF_EVENT_ARRAY: + buffer->fn = sample_cb; + buffer->ctx = ctx; + inner = perf_buffer__new(fd, PERF_BUFFER_PAGES, __perfbuf_sample_fn, lost_cb, buffer, NULL); + break; + case BPF_MAP_TYPE_RINGBUF: + inner = ring_buffer__new(fd, (ring_buffer_sample_fn)sample_cb, ctx, NULL); + break; + default: + return 0; } long err = libbpf_get_error(inner); @@ -174,14 +174,13 @@ static inline int bpf_buffer__open(struct bpf_buffer *buffer, bpf_buffer_sample_ static inline int bpf_buffer__poll(struct bpf_buffer *buffer, int timeout_ms) { - switch (buffer->type) - { - case BPF_MAP_TYPE_PERF_EVENT_ARRAY: - return perf_buffer__poll((struct perf_buffer *)buffer->inner, timeout_ms); - case BPF_MAP_TYPE_RINGBUF: - return ring_buffer__poll((struct ring_buffer *)buffer->inner, timeout_ms); - default: - return -EINVAL; + switch (buffer->type) { + case BPF_MAP_TYPE_PERF_EVENT_ARRAY: + return perf_buffer__poll((struct perf_buffer *)buffer->inner, timeout_ms); + case BPF_MAP_TYPE_RINGBUF: + return ring_buffer__poll((struct ring_buffer *)buffer->inner, timeout_ms); + default: + return -EINVAL; } } @@ -192,12 +191,12 @@ static inline void bpf_buffer__free(struct bpf_buffer *buffer) } switch (buffer->type) { - case BPF_MAP_TYPE_PERF_EVENT_ARRAY: - perf_buffer__free((struct perf_buffer *)buffer->inner); - break; - case BPF_MAP_TYPE_RINGBUF: - ring_buffer__free((struct ring_buffer *)buffer->inner); - break; + case BPF_MAP_TYPE_PERF_EVENT_ARRAY: + perf_buffer__free((struct perf_buffer *)buffer->inner); + break; + case BPF_MAP_TYPE_RINGBUF: + ring_buffer__free((struct ring_buffer *)buffer->inner); + break; } free(buffer); } diff --git a/systrace/src/os/__feat_probe.h b/systrace/src/os/__feat_probe.h index d64eac6..3935482 100644 --- a/systrace/src/os/__feat_probe.h +++ b/systrace/src/os/__feat_probe.h @@ -24,8 +24,7 @@ #ifdef BPF_PROG_KERN #include "vmlinux.h" #elif defined(BPF_PROG_USER) -struct bpf_ringbuf { -}; +struct bpf_ringbuf {}; #endif #if !defined(BPF_PROG_KERN) && !defined(BPF_PROG_USER) @@ -41,10 +40,10 @@ struct bpf_ringbuf { /* BPF_MAP_TYPE_RINGBUF original defined in /usr/include/linux/bpf.h, which from kernel-headers if BPF_MAP_TYPE_RINGBUF wasn't defined, this kernel does not support using ringbuf */ #ifndef BPF_MAP_TYPE_RINGBUF -#define BPF_MAP_TYPE_RINGBUF 27 // defined here to avoid compile error in lower kernel version -#define IS_RINGBUF_DEFINED 0 +#define BPF_MAP_TYPE_RINGBUF 27 // defined here to avoid compile error in lower kernel version +#define IS_RINGBUF_DEFINED 0 #else -#define IS_RINGBUF_DEFINED 1 +#define IS_RINGBUF_DEFINED 1 #endif #if defined(BPF_PROG_KERN) || defined(BPF_PROG_USER) @@ -58,7 +57,8 @@ static inline char probe_ringbuf() } #endif #if !defined(BPF_PROG_KERN) && !defined(BPF_PROG_USER) -static inline bool probe_ringbuf() { +static inline bool probe_ringbuf() +{ int map_fd; if ((map_fd = bpf_map_create(BPF_MAP_TYPE_RINGBUF, NULL, 0, 0, getpagesize(), NULL)) < 0) { diff --git a/systrace/src/os/__libbpf.h b/systrace/src/os/__libbpf.h index b8de750..523f781 100644 --- a/systrace/src/os/__libbpf.h +++ b/systrace/src/os/__libbpf.h @@ -17,7 +17,7 @@ #pragma once -#if !defined( BPF_PROG_KERN ) && !defined( BPF_PROG_USER ) +#if !defined(BPF_PROG_KERN) && !defined(BPF_PROG_USER) #include #include @@ -26,7 +26,7 @@ #include "common.h" #include "__compat.h" -#define EBPF_RLIM_LIMITED RLIM_INFINITY +#define EBPF_RLIM_LIMITED RLIM_INFINITY #define EBPF_RLIM_INFINITY (~0UL) #ifndef EINTR #define EINTR 4 @@ -43,8 +43,8 @@ static __always_inline int libbpf_print_fn(enum libbpf_print_level level, const static __always_inline int set_memlock_rlimit(unsigned long limit) { struct rlimit rlim_new = { - .rlim_cur = limit, - .rlim_max = limit, + .rlim_cur = limit, + .rlim_max = limit, }; if (setrlimit(RLIMIT_MEMLOCK, (const struct rlimit *)&rlim_new) != 0) { @@ -59,173 +59,167 @@ static __always_inline int set_memlock_rlimit(unsigned long limit) #define GET_PROG_FD(probe_name, prog_name) bpf_program__fd(probe_name##_skel->progs.prog_name) #define GET_PROGRAM_OBJ(probe_name, prog_name) (probe_name##_skel->progs.prog_name) -#define GET_MAP_FD_BY_SKEL(skel, probe_name, map_name) \ - bpf_map__fd(((struct probe_name##_bpf *)(skel))->maps.map_name) -#define GET_PROG_OBJ_BY_SKEL(skel, probe_name) \ - (((struct probe_name##_bpf *)(skel))->obj) - -#define BPF_OBJ_GET_MAP_FD(obj, map_name) \ - ({ \ - int __fd = -1; \ - struct bpf_map *__map = bpf_object__find_map_by_name((obj), (map_name)); \ - if (__map) { \ - __fd = bpf_map__fd(__map); \ - } \ - __fd; \ - }) - -#define BPF_OBJ_PIN_MAP_PATH(obj, map_name, path) \ - ({ \ - int __ret = -1; \ - struct bpf_map *__map = bpf_object__find_map_by_name((obj), (map_name)); \ - if (__map) { \ - __ret = bpf_map__set_pin_path(__map, path); \ - } \ - __ret; \ - }) - - -#define __MAP_SET_PIN_PATH(probe_name, map_name, map_path) \ - do { \ - int ret; \ - struct bpf_map *__map; \ - \ - __map = GET_MAP_OBJ(probe_name, map_name); \ - ret = bpf_map__set_pin_path(__map, map_path); \ +#define GET_MAP_FD_BY_SKEL(skel, probe_name, map_name) bpf_map__fd(((struct probe_name##_bpf *)(skel))->maps.map_name) +#define GET_PROG_OBJ_BY_SKEL(skel, probe_name) (((struct probe_name##_bpf *)(skel))->obj) + +#define BPF_OBJ_GET_MAP_FD(obj, map_name) \ + ({ \ + int __fd = -1; \ + struct bpf_map *__map = bpf_object__find_map_by_name((obj), (map_name)); \ + if (__map) { \ + __fd = bpf_map__fd(__map); \ + } \ + __fd; \ + }) + +#define BPF_OBJ_PIN_MAP_PATH(obj, map_name, path) \ + ({ \ + int __ret = -1; \ + struct bpf_map *__map = bpf_object__find_map_by_name((obj), (map_name)); \ + if (__map) { \ + __ret = bpf_map__set_pin_path(__map, path); \ + } \ + __ret; \ + }) + +#define __MAP_SET_PIN_PATH(probe_name, map_name, map_path) \ + do { \ + int ret; \ + struct bpf_map *__map; \ + \ + __map = GET_MAP_OBJ(probe_name, map_name); \ + ret = bpf_map__set_pin_path(__map, map_path); \ printf("======>SHARE map(" #map_name ") set pin path \"%s\"(ret=%d).\n", map_path, ret); \ } while (0) -#define GET_PROC_MAP_PIN_PATH(app_name) ("/sys/fs/bpf/sysTrace/__"#app_name"_proc_map") - -#define INIT_BPF_APP(app_name, limit) \ - static char __init = 0; \ - do { \ - if (!__init) { \ - /* Set up libbpf printfs and printf printf callback */ \ - (void)libbpf_set_print(libbpf_print_fn); \ - \ - /* Bump RLIMIT_MEMLOCK allow BPF sub-system to do anything */ \ - if (set_memlock_rlimit(limit) == 0) { \ +#define GET_PROC_MAP_PIN_PATH(app_name) ("/sys/fs/bpf/sysTrace/__" #app_name "_proc_map") + +#define INIT_BPF_APP(app_name, limit) \ + static char __init = 0; \ + do { \ + if (!__init) { \ + /* Set up libbpf printfs and printf printf callback */ \ + (void)libbpf_set_print(libbpf_print_fn); \ + \ + /* Bump RLIMIT_MEMLOCK allow BPF sub-system to do anything */ \ + if (set_memlock_rlimit(limit) == 0) { \ printf("BPF app(" #app_name ") failed to set mem limit.\n"); \ - return -1; \ - } \ - __init = 1; \ - } \ + return -1; \ + } \ + __init = 1; \ + } \ } while (0) -#define LOAD(app_name, probe_name, end) \ - struct probe_name##_bpf *probe_name##_skel = NULL; \ - struct bpf_link *probe_name##_link[PATH_NUM] __maybe_unused = {NULL}; \ - int probe_name##_link_current = 0; \ - do { \ - int err; \ - /* Open load and verify BPF application */ \ - probe_name##_skel = probe_name##_bpf__open(); \ - if (!probe_name##_skel) { \ - printf("Failed to open BPF " #probe_name " skeleton\n"); \ - goto end; \ - } \ - if (probe_name##_bpf__load(probe_name##_skel)) { \ - printf("Failed to load BPF " #probe_name " skeleton\n"); \ - goto end; \ - } \ - /* Attach tracepoint handler */ \ - err = probe_name##_bpf__attach(probe_name##_skel); \ - if (err) { \ - printf("Failed to attach BPF " #probe_name " skeleton\n"); \ - probe_name##_bpf__destroy(probe_name##_skel); \ - probe_name##_skel = NULL; \ - goto end; \ - } \ +#define LOAD(app_name, probe_name, end) \ + struct probe_name##_bpf *probe_name##_skel = NULL; \ + struct bpf_link *probe_name##_link[PATH_NUM] __maybe_unused = { NULL }; \ + int probe_name##_link_current = 0; \ + do { \ + int err; \ + /* Open load and verify BPF application */ \ + probe_name##_skel = probe_name##_bpf__open(); \ + if (!probe_name##_skel) { \ + printf("Failed to open BPF " #probe_name " skeleton\n"); \ + goto end; \ + } \ + if (probe_name##_bpf__load(probe_name##_skel)) { \ + printf("Failed to load BPF " #probe_name " skeleton\n"); \ + goto end; \ + } \ + /* Attach tracepoint handler */ \ + err = probe_name##_bpf__attach(probe_name##_skel); \ + if (err) { \ + printf("Failed to attach BPF " #probe_name " skeleton\n"); \ + probe_name##_bpf__destroy(probe_name##_skel); \ + probe_name##_skel = NULL; \ + goto end; \ + } \ printf("Succeed to load and attach BPF " #probe_name " skeleton\n"); \ } while (0) -#define __OPEN_OPTS(probe_name, end, load, opts) \ - struct probe_name##_bpf *probe_name##_skel = NULL; \ - struct bpf_link *probe_name##_link[PATH_NUM] __maybe_unused = {NULL}; \ - int probe_name##_link_current = 0; \ - do { \ - if (load) \ - {\ - /* Open load and verify BPF application */ \ - probe_name##_skel = probe_name##_bpf__open_opts(opts); \ - if (!probe_name##_skel) { \ - printf("Failed to open BPF " #probe_name " skeleton\n"); \ - goto end; \ - } \ - }\ +#define __OPEN_OPTS(probe_name, end, load, opts) \ + struct probe_name##_bpf *probe_name##_skel = NULL; \ + struct bpf_link *probe_name##_link[PATH_NUM] __maybe_unused = { NULL }; \ + int probe_name##_link_current = 0; \ + do { \ + if (load) { \ + /* Open load and verify BPF application */ \ + probe_name##_skel = probe_name##_bpf__open_opts(opts); \ + if (!probe_name##_skel) { \ + printf("Failed to open BPF " #probe_name " skeleton\n"); \ + goto end; \ + } \ + } \ } while (0) #define OPEN(probe_name, end, load) __OPEN_OPTS(probe_name, end, load, NULL) #define OPEN_OPTS(probe_name, end, load) __OPEN_OPTS(probe_name, end, load, &probe_name##_open_opts) -#define MAP_SET_PIN_PATH(probe_name, map_name, map_path, load) \ - do { \ - if (load) \ - { \ +#define MAP_SET_PIN_PATH(probe_name, map_name, map_path, load) \ + do { \ + if (load) { \ __MAP_SET_PIN_PATH(probe_name, map_name, map_path); \ - } \ + } \ } while (0) -#define MAP_INIT_BPF_BUFFER(probe_name, map_name, buffer, load) \ - do { \ - if (load) { \ +#define MAP_INIT_BPF_BUFFER(probe_name, map_name, buffer, load) \ + do { \ + if (load) { \ buffer = bpf_buffer__new(probe_name##_skel->maps.map_name, probe_name##_skel->maps.heap); \ - if (buffer == NULL) { \ - printf("Failed to initialize bpf_buffer for " #map_name " in " #probe_name "\n"); \ - } \ - } \ + if (buffer == NULL) { \ + printf("Failed to initialize bpf_buffer for " #map_name " in " #probe_name "\n"); \ + } \ + } \ } while (0) -#define MAP_INIT_BPF_BUFFER_SHARED(probe_name, map_name, buffer_ptr, load) \ - do { \ - if (load) { \ - (void)bpf_buffer__new_shared(probe_name##_skel->maps.map_name, probe_name##_skel->maps.heap, (buffer_ptr)); \ - if (*(buffer_ptr) == NULL) { \ - printf("Failed to initialize bpf_buffer for " #map_name " in " #probe_name "\n"); \ - } \ - } \ +#define MAP_INIT_BPF_BUFFER_SHARED(probe_name, map_name, buffer_ptr, load) \ + do { \ + if (load) { \ + (void)bpf_buffer__new_shared(probe_name##_skel->maps.map_name, probe_name##_skel->maps.heap, \ + (buffer_ptr)); \ + if (*(buffer_ptr) == NULL) { \ + printf("Failed to initialize bpf_buffer for " #map_name " in " #probe_name "\n"); \ + } \ + } \ } while (0) -#define LOAD_ATTACH(app_name, probe_name, end, load) \ - do { \ - if (load) \ - { \ - int err; \ - if (probe_name##_bpf__load(probe_name##_skel)) { \ - printf("Failed to load BPF " #probe_name " skeleton\n"); \ - goto end; \ - } \ - /* Attach tracepoint handler */ \ - err = probe_name##_bpf__attach(probe_name##_skel); \ - if (err) { \ - printf("Failed to attach BPF " #probe_name " skeleton\n"); \ - probe_name##_bpf__destroy(probe_name##_skel); \ - probe_name##_skel = NULL; \ - goto end; \ - } \ +#define LOAD_ATTACH(app_name, probe_name, end, load) \ + do { \ + if (load) { \ + int err; \ + if (probe_name##_bpf__load(probe_name##_skel)) { \ + printf("Failed to load BPF " #probe_name " skeleton\n"); \ + goto end; \ + } \ + /* Attach tracepoint handler */ \ + err = probe_name##_bpf__attach(probe_name##_skel); \ + if (err) { \ + printf("Failed to attach BPF " #probe_name " skeleton\n"); \ + probe_name##_bpf__destroy(probe_name##_skel); \ + probe_name##_skel = NULL; \ + goto end; \ + } \ printf("Succeed to load and attach BPF " #probe_name " skeleton\n"); \ - } \ + } \ } while (0) -#define UNLOAD(probe_name) \ - do { \ - int err; \ - if (probe_name##_skel != NULL) { \ - probe_name##_bpf__destroy(probe_name##_skel); \ - } \ - for (int i = 0; i < probe_name##_link_current; i++) { \ - err = bpf_link__destroy(probe_name##_link[i]); \ - if (err < 0) { \ +#define UNLOAD(probe_name) \ + do { \ + int err; \ + if (probe_name##_skel != NULL) { \ + probe_name##_bpf__destroy(probe_name##_skel); \ + } \ + for (int i = 0; i < probe_name##_link_current; i++) { \ + err = bpf_link__destroy(probe_name##_link[i]); \ + if (err < 0) { \ printf("Failed to detach BPF " #probe_name " %d\n", err); \ - break; \ - } \ - } \ + break; \ + } \ + } \ } while (0) -#define INIT_OPEN_OPTS(probe_name) \ - LIBBPF_OPTS(bpf_object_open_opts, probe_name##_open_opts) +#define INIT_OPEN_OPTS(probe_name) LIBBPF_OPTS(bpf_object_open_opts, probe_name##_open_opts) static __always_inline __maybe_unused void poll_pb(struct perf_buffer *pb, int timeout_ms) { @@ -237,7 +231,7 @@ static __always_inline __maybe_unused void poll_pb(struct perf_buffer *pb, int t return; } -#define SKEL_MAX_NUM 20 +#define SKEL_MAX_NUM 20 typedef void (*skel_destroy_fn)(void *); struct __bpf_skel_s { @@ -247,11 +241,11 @@ struct __bpf_skel_s { size_t _link_num; }; struct bpf_prog_s { - struct perf_buffer* pb; - struct ring_buffer* rb; + struct perf_buffer *pb; + struct ring_buffer *rb; struct bpf_buffer *buffer; - struct perf_buffer* pbs[SKEL_MAX_NUM]; - struct ring_buffer* rbs[SKEL_MAX_NUM]; + struct perf_buffer *pbs[SKEL_MAX_NUM]; + struct ring_buffer *rbs[SKEL_MAX_NUM]; struct bpf_buffer *buffers[SKEL_MAX_NUM]; struct __bpf_skel_s skels[SKEL_MAX_NUM]; const char *custom_btf_paths[SKEL_MAX_NUM]; @@ -298,7 +292,7 @@ static __always_inline __maybe_unused void unload_bpf_prog(struct bpf_prog_s **u perf_buffer__free(prog->pbs[i]); } -#if (CURRENT_LIBBPF_VERSION >= LIBBPF_VERSION(0, 8)) +#if (CURRENT_LIBBPF_VERSION >= LIBBPF_VERSION(0, 8)) if (prog->rbs[i]) { ring_buffer__free(prog->rbs[i]); } @@ -315,7 +309,7 @@ static __always_inline __maybe_unused void unload_bpf_prog(struct bpf_prog_s **u perf_buffer__free(prog->pb); } -#if (CURRENT_LIBBPF_VERSION >= LIBBPF_VERSION(0, 8)) +#if (CURRENT_LIBBPF_VERSION >= LIBBPF_VERSION(0, 8)) if (prog->rb) { ring_buffer__free(prog->rb); } @@ -329,6 +323,5 @@ static __always_inline __maybe_unused void unload_bpf_prog(struct bpf_prog_s **u return; } - #endif #endif diff --git a/systrace/src/os/bpf_comm.h b/systrace/src/os/bpf_comm.h index 2665881..e3f8840 100644 --- a/systrace/src/os/bpf_comm.h +++ b/systrace/src/os/bpf_comm.h @@ -19,10 +19,10 @@ #include "os_probe.h" -#define MAX_SIZE_OF_PROC 128 -#define MAX_SIZE_OF_THREAD (128 * MAX_SIZE_OF_PROC) -#define PF_IDLE 0x00000002 /* IDLE thread */ -#define PF_KTHREAD 0x00200000 /* kernel thread */ +#define MAX_SIZE_OF_PROC 128 +#define MAX_SIZE_OF_THREAD (128 * MAX_SIZE_OF_PROC) +#define PF_IDLE 0x00000002 /* IDLE thread */ +#define PF_KTHREAD 0x00200000 /* kernel thread */ typedef struct { u32 pid; @@ -117,37 +117,37 @@ static __always_inline void emit_event(trace_event_data_t *event, void *ctx) return; } switch (event->rank) { - case 0: - bpf_ringbuf_output(&osprobe_map_0, event, sizeof(*event), 0); - break; - case 1: - bpf_ringbuf_output(&osprobe_map_1, event, sizeof(*event), 0); - break; - case 2: - bpf_ringbuf_output(&osprobe_map_2, event, sizeof(*event), 0); - break; - case 3: - bpf_ringbuf_output(&osprobe_map_3, event, sizeof(*event), 0); - break; - case 4: - bpf_ringbuf_output(&osprobe_map_4, event, sizeof(*event), 0); - break; - case 5: - bpf_ringbuf_output(&osprobe_map_5, event, sizeof(*event), 0); - break; - case 6: - bpf_ringbuf_output(&osprobe_map_6, event, sizeof(*event), 0); - break; - case 7: - bpf_ringbuf_output(&osprobe_map_7, event, sizeof(*event), 0); - break; - default: - break; + case 0: + bpf_ringbuf_output(&osprobe_map_0, event, sizeof(*event), 0); + break; + case 1: + bpf_ringbuf_output(&osprobe_map_1, event, sizeof(*event), 0); + break; + case 2: + bpf_ringbuf_output(&osprobe_map_2, event, sizeof(*event), 0); + break; + case 3: + bpf_ringbuf_output(&osprobe_map_3, event, sizeof(*event), 0); + break; + case 4: + bpf_ringbuf_output(&osprobe_map_4, event, sizeof(*event), 0); + break; + case 5: + bpf_ringbuf_output(&osprobe_map_5, event, sizeof(*event), 0); + break; + case 6: + bpf_ringbuf_output(&osprobe_map_6, event, sizeof(*event), 0); + break; + case 7: + bpf_ringbuf_output(&osprobe_map_7, event, sizeof(*event), 0); + break; + default: + break; } } -static __always_inline void create_cur_event(trace_event_data_t *cur_event, int key, - u64 start_time, u64 end_time, int rank, event_type_e type) +static __always_inline void create_cur_event(trace_event_data_t *cur_event, int key, u64 start_time, u64 end_time, + int rank, event_type_e type) { if (cur_event == NULL) { return; @@ -207,7 +207,6 @@ static __always_inline int get_npu_id(struct task_struct *task) // 全都不匹配返回-1 return -1; - } #endif diff --git a/systrace/src/os/common.h b/systrace/src/os/common.h index 1d4fd93..d33189d 100644 --- a/systrace/src/os/common.h +++ b/systrace/src/os/common.h @@ -17,18 +17,18 @@ #pragma once -#define THOUSAND 1000 -#define PATH_NUM 20 +#define THOUSAND 1000 +#define PATH_NUM 20 -#define __maybe_unused __attribute__((unused)) +#define __maybe_unused __attribute__((unused)) -#define MSEC_PER_SEC 1000L -#define USEC_PER_MSEC 1000L -#define NSEC_PER_USEC 1000L -#define NSEC_PER_MSEC 1000000L -#define USEC_PER_SEC 1000000L -#define NSEC_PER_SEC 1000000000L -#define FSEC_PER_SEC 1000000000000000LL +#define MSEC_PER_SEC 1000L +#define USEC_PER_MSEC 1000L +#define NSEC_PER_USEC 1000L +#define NSEC_PER_MSEC 1000000L +#define USEC_PER_SEC 1000000L +#define NSEC_PER_SEC 1000000000L +#define FSEC_PER_SEC 1000000000000000LL #ifndef __u8 typedef unsigned char __u8; diff --git a/systrace/src/os/os_cpu.bpf.c b/systrace/src/os/os_cpu.bpf.c index d6f2490..61a816f 100644 --- a/systrace/src/os/os_cpu.bpf.c +++ b/systrace/src/os/os_cpu.bpf.c @@ -33,9 +33,9 @@ struct { static __always_inline task_cpu_s *get_offcpu_enter(struct task_struct *task) { int rank = 0; - u32 pid = BPF_CORE_READ(task, pid); // 获取 TGID - u32 tgid = BPF_CORE_READ(task, tgid); // 获取 PID - offcpu_task_key_s task_offcpu_key = {0}; + u32 pid = BPF_CORE_READ(task, pid); // 获取 TGID + u32 tgid = BPF_CORE_READ(task, tgid); // 获取 PID + offcpu_task_key_s task_offcpu_key = { 0 }; task_offcpu_key.pid = pid; task_offcpu_key.tgid = tgid; task_cpu_s *offcpu_enter; @@ -56,7 +56,8 @@ static __always_inline task_cpu_s *get_offcpu_enter(struct task_struct *task) return offcpu_enter; } -static __inline int str_eq(const char *s1, const char *s2, int len) { +static __inline int str_eq(const char *s1, const char *s2, int len) +{ for (int i = 0; i < len; i++) { if (s1[i] != s2[i]) return 1; @@ -68,23 +69,24 @@ static __inline int str_eq(const char *s1, const char *s2, int len) { static __always_inline void process_oncpu(struct task_struct *task, void *ctx) { - u32 pid = BPF_CORE_READ(task, pid); // 获取 TGID - u32 tgid = BPF_CORE_READ(task, tgid); // 获取 PID - offcpu_task_key_s task_offcpu_key = {0}; + u32 pid = BPF_CORE_READ(task, pid); // 获取 TGID + u32 tgid = BPF_CORE_READ(task, tgid); // 获取 PID + offcpu_task_key_s task_offcpu_key = { 0 }; task_offcpu_key.pid = pid; task_offcpu_key.tgid = tgid; task_cpu_s *offcpu_enter = (task_cpu_s *)bpf_map_lookup_elem(&task_cpu_map, &task_offcpu_key); if (offcpu_enter == (void *)0) { return; } - + offcpu_enter->end_time = bpf_ktime_get_ns(); // i.e. offcpu's start_time if (offcpu_enter->start_time == 0) { bpf_map_delete_elem(&task_cpu_map, &task_offcpu_key); return; } trace_event_data_t cur_event; - create_cur_event(&cur_event, pid, offcpu_enter->start_time, offcpu_enter->end_time, offcpu_enter->rank, EVENT_TYPE_OFFCPU); + create_cur_event(&cur_event, pid, offcpu_enter->start_time, offcpu_enter->end_time, offcpu_enter->rank, + EVENT_TYPE_OFFCPU); cur_event.delay = offcpu_enter->delay; cur_event.next_pid = offcpu_enter->next_pid; bpf_probe_read_kernel(cur_event.next_comm, sizeof(cur_event.next_comm), &offcpu_enter->next_comm); diff --git a/systrace/src/os/os_mem.bpf.c b/systrace/src/os/os_mem.bpf.c index 71aa9e2..f8397ae 100644 --- a/systrace/src/os/os_mem.bpf.c +++ b/systrace/src/os/os_mem.bpf.c @@ -22,8 +22,8 @@ char g_license[] SEC("license") = "GPL"; -#define BPF_F_INDEX_MASK 0xffffffffULL -#define BPF_F_ALL_CPU BPF_F_INDEX_MASK +#define BPF_F_INDEX_MASK 0xffffffffULL +#define BPF_F_ALL_CPU BPF_F_INDEX_MASK #ifndef __PERF_OUT_MAX #define __PERF_OUT_MAX (64) @@ -48,8 +48,8 @@ struct { static __always_inline int fault_event_start(struct task_struct *task, event_type_e event) { - u32 pid = BPF_CORE_READ(task, pid); // 获取 TGID - u32 tgid = BPF_CORE_READ(task, tgid); // 获取 PID + u32 pid = BPF_CORE_READ(task, pid); // 获取 TGID + u32 tgid = BPF_CORE_READ(task, tgid); // 获取 PID int rank = 0; rank = get_npu_id(task); if (rank < 0) { @@ -57,36 +57,37 @@ static __always_inline int fault_event_start(struct task_struct *task, event_typ } pid = BPF_CORE_READ(task, pid); - fault_task_key_s fault_task_key = {0}; + fault_task_key_s fault_task_key = { 0 }; fault_task_key.event = event; fault_task_key.pid = pid; fault_task_key.tgid = tgid; - task_mem_s task_mem_event = {0}; + task_mem_s task_mem_event = { 0 }; task_mem_event.start_ts = bpf_ktime_get_ns(); task_mem_event.event = event; task_mem_event.key = pid; task_mem_event.rank = rank; bpf_map_update_elem(&fault_task_map, &fault_task_key, &task_mem_event, BPF_ANY); - + return 0; } static __always_inline int fault_event_end(struct task_struct *task, void *ctx, event_type_e event) { - u32 pid = BPF_CORE_READ(task, pid); // 获取 TGID - u32 tgid = BPF_CORE_READ(task, tgid); // 获取 PID - fault_task_key_s fault_task_key = {0}; + u32 pid = BPF_CORE_READ(task, pid); // 获取 TGID + u32 tgid = BPF_CORE_READ(task, tgid); // 获取 PID + fault_task_key_s fault_task_key = { 0 }; fault_task_key.event = event; fault_task_key.pid = pid; fault_task_key.tgid = tgid; - task_mem_s* task_mem_event = bpf_map_lookup_elem(&fault_task_map, &fault_task_key); + task_mem_s *task_mem_event = bpf_map_lookup_elem(&fault_task_map, &fault_task_key); if (task_mem_event) { u64 now = bpf_ktime_get_ns(); if (now > task_mem_event->start_ts) { trace_event_data_t cur_event; - create_cur_event(&cur_event, task_mem_event->key, task_mem_event->start_ts, now, task_mem_event->rank, event); + create_cur_event(&cur_event, task_mem_event->key, task_mem_event->start_ts, now, task_mem_event->rank, + event); // bpf_get_current_comm(&cur_event.comm, sizeof(cur_event.comm)); bpf_core_read_str(cur_event.comm, sizeof(cur_event.comm), &task->comm); emit_event(&cur_event, ctx); @@ -100,28 +101,28 @@ static __always_inline int fault_event_end(struct task_struct *task, void *ctx, static __always_inline int common_event_start(struct task_struct *task, event_type_e event) { int cpu = bpf_get_smp_processor_id(); - comm_mem_task_key_s comm_mem_task_key = {0}; - comm_mem_task_key.event = event; - comm_mem_task_key.key = cpu; + comm_mem_task_key_s comm_mem_task_key = { 0 }; + comm_mem_task_key.event = event; + comm_mem_task_key.key = cpu; - task_mem_s task_mem_event = {0}; + task_mem_s task_mem_event = { 0 }; task_mem_event.start_ts = bpf_ktime_get_ns(); task_mem_event.event = event; task_mem_event.key = cpu; bpf_map_update_elem(&comm_mem_task_map, &comm_mem_task_key, &task_mem_event, BPF_ANY); - + return 0; } static __always_inline int common_event_end(struct task_struct *task, void *ctx, event_type_e event) { int cpu = bpf_get_smp_processor_id(); - comm_mem_task_key_s comm_mem_task_key = {0}; + comm_mem_task_key_s comm_mem_task_key = { 0 }; comm_mem_task_key.event = event; comm_mem_task_key.key = cpu; - task_mem_s* task_mem_event = bpf_map_lookup_elem(&comm_mem_task_map, & comm_mem_task_key); + task_mem_s *task_mem_event = bpf_map_lookup_elem(&comm_mem_task_map, &comm_mem_task_key); if (task_mem_event) { u64 now = bpf_ktime_get_ns(); if (now > task_mem_event->start_ts) { diff --git a/systrace/src/os/os_probe.c b/systrace/src/os/os_probe.c index 67d492d..4aa759a 100644 --- a/systrace/src/os/os_probe.c +++ b/systrace/src/os/os_probe.c @@ -38,35 +38,35 @@ #include "os_mem.skel.h" #include "os_cpu.skel.h" -#define MAX_PATH_LEN 512 -#define LOG_INTERVAL_SEC 120 -#define RM_MAP_PATH "/usr/bin/rm -rf /sys/fs/bpf/sysTrace*" -#define PROC_FILTER_MAP_PATH "/sys/fs/bpf/sysTrace/__osprobe_proc_filter" -#define KERNEL_FILTER_MAP_PATH "/sys/fs/bpf/sysTrace/__osprobe_kernel_filter" +#define MAX_PATH_LEN 512 +#define LOG_INTERVAL_SEC 120 +#define RM_MAP_PATH "/usr/bin/rm -rf /sys/fs/bpf/sysTrace*" +#define PROC_FILTER_MAP_PATH "/sys/fs/bpf/sysTrace/__osprobe_proc_filter" +#define KERNEL_FILTER_MAP_PATH "/sys/fs/bpf/sysTrace/__osprobe_kernel_filter" #define LOG_ITEMS_MIN 10 -#define MAP_SET_COMMON_PIN_PATHS(probe_name, end, load) \ - INIT_OPEN_OPTS(probe_name); \ - OPEN_OPTS(probe_name, end, load); \ - MAP_SET_PIN_PATH(probe_name, osprobe_map_0, "/sys/fs/bpf/sysTrace/__osprobe_map_0" , load); \ - MAP_SET_PIN_PATH(probe_name, osprobe_map_1, "/sys/fs/bpf/sysTrace/__osprobe_map_1" , load); \ - MAP_SET_PIN_PATH(probe_name, osprobe_map_2, "/sys/fs/bpf/sysTrace/__osprobe_map_2" , load); \ - MAP_SET_PIN_PATH(probe_name, osprobe_map_3, "/sys/fs/bpf/sysTrace/__osprobe_map_3" , load); \ - MAP_SET_PIN_PATH(probe_name, osprobe_map_4, "/sys/fs/bpf/sysTrace/__osprobe_map_4" , load); \ - MAP_SET_PIN_PATH(probe_name, osprobe_map_5, "/sys/fs/bpf/sysTrace/__osprobe_map_5" , load); \ - MAP_SET_PIN_PATH(probe_name, osprobe_map_6, "/sys/fs/bpf/sysTrace/__osprobe_map_6" , load); \ - MAP_SET_PIN_PATH(probe_name, osprobe_map_7, "/sys/fs/bpf/sysTrace/__osprobe_map_7" , load); \ - MAP_SET_PIN_PATH(probe_name, proc_filter_map, PROC_FILTER_MAP_PATH, load); \ - MAP_SET_PIN_PATH(probe_name, kernel_filter_map, KERNEL_FILTER_MAP_PATH, load); \ - -#define OPEN_OSPROBE(probe_name, end, load, buffer) \ +#define MAP_SET_COMMON_PIN_PATHS(probe_name, end, load) \ + INIT_OPEN_OPTS(probe_name); \ + OPEN_OPTS(probe_name, end, load); \ + MAP_SET_PIN_PATH(probe_name, osprobe_map_0, "/sys/fs/bpf/sysTrace/__osprobe_map_0", load); \ + MAP_SET_PIN_PATH(probe_name, osprobe_map_1, "/sys/fs/bpf/sysTrace/__osprobe_map_1", load); \ + MAP_SET_PIN_PATH(probe_name, osprobe_map_2, "/sys/fs/bpf/sysTrace/__osprobe_map_2", load); \ + MAP_SET_PIN_PATH(probe_name, osprobe_map_3, "/sys/fs/bpf/sysTrace/__osprobe_map_3", load); \ + MAP_SET_PIN_PATH(probe_name, osprobe_map_4, "/sys/fs/bpf/sysTrace/__osprobe_map_4", load); \ + MAP_SET_PIN_PATH(probe_name, osprobe_map_5, "/sys/fs/bpf/sysTrace/__osprobe_map_5", load); \ + MAP_SET_PIN_PATH(probe_name, osprobe_map_6, "/sys/fs/bpf/sysTrace/__osprobe_map_6", load); \ + MAP_SET_PIN_PATH(probe_name, osprobe_map_7, "/sys/fs/bpf/sysTrace/__osprobe_map_7", load); \ + MAP_SET_PIN_PATH(probe_name, proc_filter_map, PROC_FILTER_MAP_PATH, load); \ + MAP_SET_PIN_PATH(probe_name, kernel_filter_map, KERNEL_FILTER_MAP_PATH, load); + +#define OPEN_OSPROBE(probe_name, end, load, buffer) \ MAP_SET_COMMON_PIN_PATHS(probe_name, end, load); \ - MAP_INIT_BPF_BUFFER_SHARED(probe_name, osprobe_map_0, &buffer, load); \ + MAP_INIT_BPF_BUFFER_SHARED(probe_name, osprobe_map_0, &buffer, load); #define MAP_SET_PIN_SINGLE(probe_name, osprobe_map, osprobe_map_path, end, load, buffer) \ - MAP_SET_PIN_PATH(probe_name, osprobe_map, osprobe_map_path , load); \ - MAP_SET_PIN_PATH(probe_name, proc_filter_map, PROC_FILTER_MAP_PATH, load); \ - MAP_INIT_BPF_BUFFER_SHARED(probe_name, osprobe_map, &buffer, load); \ + MAP_SET_PIN_PATH(probe_name, osprobe_map, osprobe_map_path, load); \ + MAP_SET_PIN_PATH(probe_name, proc_filter_map, PROC_FILTER_MAP_PATH, load); \ + MAP_INIT_BPF_BUFFER_SHARED(probe_name, osprobe_map, &buffer, load); static pthread_mutex_t file_mutex = PTHREAD_MUTEX_INITIALIZER; int g_stop = 0; @@ -77,8 +77,7 @@ static int rank; static int local_rank; static u64 sysBootTime; -typedef struct -{ +typedef struct { OSprobe *osprobe; time_t last_log_time; } OSprobe_ThreadData; @@ -88,19 +87,13 @@ void sig_int() g_stop = 1; }; -char *event_name[] = { - "mem_fault", - "swap_page", - "compaction", - "vmscan", - "offcpu" -}; +char *event_name[] = { "mem_fault", "swap_page", "compaction", "vmscan", "offcpu" }; // system boot time = current time - uptime since system boot. static int get_sys_boot_time() { - struct timespec ts_cur_time = {0}; - struct timespec ts_uptime = {0}; + struct timespec ts_cur_time = { 0 }; + struct timespec ts_uptime = { 0 }; __u64 cur_time = 0; __u64 uptime = 0; @@ -126,11 +119,12 @@ static __u64 get_unix_time_from_uptime(__u64 uptime) return sysBootTime + uptime; } -void initialize_osprobe() { +void initialize_osprobe() +{ const char *rank_str = getenv("RANK"); const char *local_rank_str = getenv("LOCAL_RANK"); rank = rank_str ? atoi(rank_str) : 0; - local_rank = local_rank_str? atoi(local_rank_str) : 0; + local_rank = local_rank_str ? atoi(local_rank_str) : 0; get_sys_boot_time(); } @@ -140,8 +134,7 @@ static void free_osprobe(OSprobe *osprobe) return; // 释放分配记录 - for (size_t i = 0; i < osprobe->n_osprobe_entries; i++) - { + for (size_t i = 0; i < osprobe->n_osprobe_entries; i++) { OSprobeEntry *entry = osprobe->osprobe_entries[i]; free(entry); } @@ -153,8 +146,7 @@ static void free_osprobe(OSprobe *osprobe) static void free_thread_data(void *data) { OSprobe_ThreadData *td = (OSprobe_ThreadData *)data; - if (td && td->osprobe) - { + if (td && td->osprobe) { free_osprobe(td->osprobe); free(td->osprobe); } @@ -173,8 +165,7 @@ static OSprobe_ThreadData *get_thread_data() pthread_once(&key_once, make_key); td = pthread_getspecific(thread_data_key); - if (!td) - { + if (!td) { td = calloc(1, sizeof(OSprobe_ThreadData)); td->osprobe = calloc(1, sizeof(OSprobe)); osprobe__init(td->osprobe); @@ -203,7 +194,6 @@ static void add_osprobe_entry(trace_event_data_t *evt_data) entry->rank = rank; entry->comm = strdup(evt_data->comm); - if (entry->os_event_type == EVENT_TYPE_OFFCPU && evt_data->next_comm) { entry->nxt_comm = strdup(evt_data->next_comm); entry->nxt_pid = evt_data->next_pid; @@ -211,49 +201,38 @@ static void add_osprobe_entry(trace_event_data_t *evt_data) td->osprobe->n_osprobe_entries++; td->osprobe->osprobe_entries = - realloc(td->osprobe->osprobe_entries, - td->osprobe->n_osprobe_entries * sizeof(OSprobeEntry *)); + realloc(td->osprobe->osprobe_entries, td->osprobe->n_osprobe_entries * sizeof(OSprobeEntry *)); - td->osprobe->osprobe_entries[td->osprobe->n_osprobe_entries - 1] = - entry; + td->osprobe->osprobe_entries[td->osprobe->n_osprobe_entries - 1] = entry; } -static void get_log_filename(time_t current, char *buf, - size_t buf_size) +static void get_log_filename(time_t current, char *buf, size_t buf_size) { struct tm *tm = localtime(¤t); const char *dir_path = SYS_TRACE_ROOT_DIR "osprobe"; - if (access(dir_path, F_OK) != 0) - { - if (mkdir(dir_path, 0755) != 0 && errno != EEXIST) - { + if (access(dir_path, F_OK) != 0) { + if (mkdir(dir_path, 0755) != 0 && errno != EEXIST) { perror("Failed to create directory"); - snprintf(buf, buf_size, "os_trace_%04d%02d%02d_%02d_rank_%d.pb", - tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, - tm->tm_hour, rank); + snprintf(buf, buf_size, "os_trace_%04d%02d%02d_%02d_rank_%d.pb", tm->tm_year + 1900, tm->tm_mon + 1, + tm->tm_mday, tm->tm_hour, rank); return; } } - snprintf(buf, buf_size, "%s/os_trace_%04d%02d%02d_%02d_rank_%d.pb", - dir_path, tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, - tm->tm_hour, rank); + snprintf(buf, buf_size, "%s/os_trace_%04d%02d%02d_%02d_rank_%d.pb", dir_path, tm->tm_year + 1900, tm->tm_mon + 1, + tm->tm_mday, tm->tm_hour, rank); } static char is_ready_to_write(OSprobe_ThreadData *td, time_t *current) { OSprobe *osprobe = td->osprobe; - if (!osprobe || - (osprobe->n_osprobe_entries == 0)) - { + if (!osprobe || (osprobe->n_osprobe_entries == 0)) { return 0; } *current = time(NULL); - if (osprobe->n_osprobe_entries < LOG_ITEMS_MIN) - { - if (*current - td->last_log_time < LOG_INTERVAL_SEC) - { + if (osprobe->n_osprobe_entries < LOG_ITEMS_MIN) { + if (*current - td->last_log_time < LOG_INTERVAL_SEC) { return 0; } } @@ -266,40 +245,32 @@ static void write_protobuf_to_file() time_t current; uint8_t *buf; OSprobe_ThreadData *td = get_thread_data(); - if (!td) - { + if (!td) { return; } - if (!is_ready_to_write(td, ¤t)) - { + if (!is_ready_to_write(td, ¤t)) { return; } - if (pthread_mutex_trylock(&file_mutex) == 0) - { // pthread_mutex_trylock or pthread_mutex_lock + if (pthread_mutex_trylock(&file_mutex) == 0) { // pthread_mutex_trylock or pthread_mutex_lock char filename[256]; - get_log_filename(current, filename, - sizeof(filename)); + get_log_filename(current, filename, sizeof(filename)); size_t len = osprobe__get_packed_size(td->osprobe); buf = malloc(len); osprobe__pack(td->osprobe, buf); FILE *fp = fopen(filename, "ab"); - if (fp) - { + if (fp) { fwrite(buf, len, 1, fp); fclose(fp); } pthread_mutex_unlock(&file_mutex); - } - else - { + } else { return; } - if (buf) - { + if (buf) { free(buf); } @@ -329,7 +300,7 @@ static int recv_bpf_msg(void *ctx, void *data, __u32 size) } static int load_mem_probe(struct bpf_prog_s *prog, struct bpf_buffer *buffer) -{ +{ INIT_BPF_APP(os_probe, EBPF_RLIM_LIMITED); OPEN_OSPROBE(os_mem, err, 1, buffer); prog->skels[prog->num].skel = os_mem_skel; @@ -376,7 +347,8 @@ err: return -1; } -int update_filter_map(){ +int update_filter_map() +{ int proc_filter_map_fd, kernel_filter_map_fd; int ret = 0; proc_filter_map_fd = bpf_obj_get(PROC_FILTER_MAP_PATH); @@ -392,8 +364,8 @@ int update_filter_map(){ return -1; } for (int dev_id = 0; dev_id < 8; ++dev_id) { - char send_key[16] = {0}; - char task_key[16] = {0}; + char send_key[16] = { 0 }; + char task_key[16] = { 0 }; snprintf(send_key, sizeof(send_key), "dev%d_sq_send_wq", dev_id); snprintf(task_key, sizeof(task_key), "dev%d_sq_task", dev_id); @@ -424,9 +396,11 @@ int update_filter_map(){ start_parsing = 1; continue; } - if (!start_parsing) continue; + if (!start_parsing) + continue; // 空行表示表格结束 - if (strstr(line, "====") || strlen(line) < 10) continue; + if (strstr(line, "====") || strlen(line) < 10) + continue; unsigned int npu, pid; @@ -445,8 +419,7 @@ int update_filter_map(){ return 0; } -int bpf_buffer_init_from_pin(struct bpf_buffer **buffer_ptr, const char *map_path, - bpf_buffer_sample_fn fn, void *ctx) +int bpf_buffer_init_from_pin(struct bpf_buffer **buffer_ptr, const char *map_path, bpf_buffer_sample_fn fn, void *ctx) { struct bpf_buffer *buffer; if (!map_path || !fn) { @@ -473,29 +446,30 @@ int bpf_buffer_init_from_pin(struct bpf_buffer **buffer_ptr, const char *map_pat buffer->fn = fn; buffer->ctx = ctx; switch (info.type) { - case BPF_MAP_TYPE_RINGBUF: - buffer->inner = ring_buffer__new(map_fd, (ring_buffer_sample_fn) fn, ctx, NULL); - if (!buffer->inner) { - fprintf(stderr, "ring_buffer__new failed for map: %s\n", map_path); - close(map_fd); - return -1; - } - break; + case BPF_MAP_TYPE_RINGBUF: + buffer->inner = ring_buffer__new(map_fd, (ring_buffer_sample_fn)fn, ctx, NULL); + if (!buffer->inner) { + fprintf(stderr, "ring_buffer__new failed for map: %s\n", map_path); + close(map_fd); + return -1; + } + break; - case BPF_MAP_TYPE_PERF_EVENT_ARRAY: - return -1; + case BPF_MAP_TYPE_PERF_EVENT_ARRAY: + return -1; - default: - fprintf(stderr, "Unsupported map type (%d) for map: %s\n", info.type, map_path); - close(map_fd); - return -1; + default: + fprintf(stderr, "Unsupported map type (%d) for map: %s\n", info.type, map_path); + close(map_fd); + return -1; } *buffer_ptr = buffer; close(map_fd); // 不再需要,buffer 内部已经引用 fd 或 dup return 0; } -int run_osprobe() { +int run_osprobe() +{ FILE *fp; int ret = 0; struct bpf_prog_s *prog = NULL; @@ -503,7 +477,6 @@ int run_osprobe() { initialize_osprobe(); if (local_rank == 0) { - fp = popen(RM_MAP_PATH, "r"); if (fp != NULL) { (void)pclose(fp); @@ -531,9 +504,7 @@ int run_osprobe() { while (!g_stop) { sleep(1); for (int i = 0; i < prog->num; i++) { - if (prog->buffers[i] - && ((ret = bpf_buffer__poll(prog->buffers[i], THOUSAND)) < 0) - && ret != -EINTR) { + if (prog->buffers[i] && ((ret = bpf_buffer__poll(prog->buffers[i], THOUSAND)) < 0) && ret != -EINTR) { fprintf(stderr, "[OS_PROBE] perf poll prog_%d failed.\n", i); break; } @@ -542,30 +513,24 @@ int run_osprobe() { return ret; - } - else - { + } else { char osprobe_map_path[MAX_PATH_LEN]; - snprintf(osprobe_map_path, sizeof(osprobe_map_path), - "/sys/fs/bpf/sysTrace/__osprobe_map_%d", local_rank); + snprintf(osprobe_map_path, sizeof(osprobe_map_path), "/sys/fs/bpf/sysTrace/__osprobe_map_%d", local_rank); while (access(osprobe_map_path, F_OK) != 0) { continue; } - ret = bpf_buffer_init_from_pin(&buffer, - osprobe_map_path, - recv_bpf_msg, NULL); + ret = bpf_buffer_init_from_pin(&buffer, osprobe_map_path, recv_bpf_msg, NULL); if (ret < 0) { fprintf(stderr, "[OS_PROBE RANK_%d] Failed to init buffer\n", local_rank); goto err; } while (!g_stop) { - if (((ret = bpf_buffer__poll(buffer, THOUSAND)) < 0) - && ret != -EINTR) { + if (((ret = bpf_buffer__poll(buffer, THOUSAND)) < 0) && ret != -EINTR) { fprintf(stderr, "[OS_PROBE RANK_%d] perf poll prog failed:%s.\n", local_rank, strerror(errno)); break; } } - } + } fprintf(stderr, "[OS_PROBE RANK_%d] sysTrace ebpf trace finished\n", local_rank); err: diff --git a/systrace/src/os/os_probe.h b/systrace/src/os/os_probe.h index 8fdbb1f..470bf4b 100644 --- a/systrace/src/os/os_probe.h +++ b/systrace/src/os/os_probe.h @@ -17,7 +17,7 @@ #pragma once -#define THREAD_COMM_LEN 16 +#define THREAD_COMM_LEN 16 typedef enum { EVENT_TYPE_MM_FAULT = 0, @@ -33,7 +33,7 @@ typedef struct { int rank; long long unsigned int start_time; long long unsigned int end_time; - long long unsigned int duration; // 若为多个事件聚合,则表示累计的执行时间 + long long unsigned int duration; // 若为多个事件聚合,则表示累计的执行时间 event_type_e type; long long unsigned int delay; char comm[THREAD_COMM_LEN]; diff --git a/systrace/src/trace/library_loader.cc b/systrace/src/trace/library_loader.cc index a74bb37..6c00629 100644 --- a/systrace/src/trace/library_loader.cc +++ b/systrace/src/trace/library_loader.cc @@ -6,15 +6,16 @@ namespace systrace { DynamicLibraryLoader::DynamicLibraryLoader(const std::string &library_path) - : library_handle_(nullptr), is_usable_(false), library_path_(library_path) + : library_handle_(nullptr) + , is_usable_(false) + , library_path_(library_path) { LoadDynamicLibrary(); } DynamicLibraryLoader::~DynamicLibraryLoader() { - if (library_handle_) - { + if (library_handle_) { dlclose(library_handle_); library_handle_ = nullptr; } @@ -22,8 +23,7 @@ DynamicLibraryLoader::~DynamicLibraryLoader() void DynamicLibraryLoader::LoadDynamicLibrary() { - if (library_handle_) - { + if (library_handle_) { STLOG(WARNING) << "Library already loaded: " << library_path_; return; } @@ -31,11 +31,9 @@ void DynamicLibraryLoader::LoadDynamicLibrary() dlerror(); library_handle_ = dlopen(library_path_.c_str(), RTLD_LAZY); - if (!library_handle_) - { + if (!library_handle_) { const char *error_message = dlerror(); - STLOG(WARNING) << "Failed to load library: " - << (error_message ? error_message : "Unknown error"); + STLOG(WARNING) << "Failed to load library: " << (error_message ? error_message : "Unknown error"); is_usable_ = false; return; } diff --git a/systrace/src/trace/library_loader.h b/systrace/src/trace/library_loader.h index abae8d7..bb0ebda 100644 --- a/systrace/src/trace/library_loader.h +++ b/systrace/src/trace/library_loader.h @@ -9,16 +9,15 @@ namespace systrace { -class DynamicLibraryLoader -{ - protected: +class DynamicLibraryLoader { +protected: void *library_handle_; bool is_usable_; const std::string library_path_; void LoadDynamicLibrary(); - public: +public: explicit DynamicLibraryLoader(const std::string &library_path); virtual ~DynamicLibraryLoader(); @@ -26,7 +25,10 @@ class DynamicLibraryLoader { return library_handle_ != nullptr && is_usable_; } - void *GetLibraryHandle() const { return library_handle_; } + void *GetLibraryHandle() const + { + return library_handle_; + } }; } // namespace systrace \ No newline at end of file diff --git a/systrace/src/trace/systrace_manager.cc b/systrace/src/trace/systrace_manager.cc index 856bbb8..47929b3 100644 --- a/systrace/src/trace/systrace_manager.cc +++ b/systrace/src/trace/systrace_manager.cc @@ -14,29 +14,25 @@ namespace systrace namespace { -constexpr uint64_t TRACE_INTERVAL = 100; -constexpr std::chrono::milliseconds POLL_INTERVAL(10); + constexpr uint64_t TRACE_INTERVAL = 100; + constexpr std::chrono::milliseconds POLL_INTERVAL(10); } // namespace PyTorchTrace &PyTorchTrace::getInstance() { - std::call_once(init_flag_, - []() - { - instance_ = new PyTorchTrace(); - instance_->initialize(); - }); + std::call_once(init_flag_, []() { + instance_ = new PyTorchTrace(); + instance_->initialize(); + }); return *instance_; } void PyTorchTrace::initialize() { pytorch_trace_.set_rank(config::GlobalConfig::Instance().rank); - STLOG(INFO) << "[PyTorchTrace] Rank set to: " - << config::GlobalConfig::Instance().rank; + STLOG(INFO) << "[PyTorchTrace] Rank set to: " << config::GlobalConfig::Instance().rank; - pytorch_tracing_library_ = - new pytorch_tracing::PyTorchTracingLibrary("libsysTrace.so"); + pytorch_tracing_library_ = new pytorch_tracing::PyTorchTracingLibrary("libsysTrace.so"); STLOG(INFO) << "[PyTorchTrace] Tracing library loaded"; registerTracingFunctions(); @@ -46,46 +42,39 @@ void PyTorchTrace::registerTracingFunctions() { std::ifstream funcListFile(PyFuncListPath_); std::string line; - if (!funcListFile.is_open()) - { + if (!funcListFile.is_open()) { STLOG(ERROR) << "Failed to open PyFuncList file"; return; } - while (std::getline(funcListFile, line)) - { - if (!line.empty() && line[0] != '#') - { + while (std::getline(funcListFile, line)) { + if (!line.empty() && line[0] != '#') { pytorch_tracing_functions_.push_back(line); } } funcListFile.close(); - auto errors = - pytorch_tracing_library_->Register(pytorch_tracing_functions_); - for (size_t i = 0; i < pytorch_tracing_functions_.size(); ++i) - { - STLOG(INFO) << "Registered function: " << pytorch_tracing_functions_[i] - << ", status: " << errors[i] << std::endl; + auto errors = pytorch_tracing_library_->Register(pytorch_tracing_functions_); + for (size_t i = 0; i < pytorch_tracing_functions_.size(); ++i) { + STLOG(INFO) + << "Registered function: " << pytorch_tracing_functions_[i] << ", status: " << errors[i] << std::endl; } } -bool PyTorchTrace::triggerTrace() +bool PyTorchTrace::triggerTrace() { - SharedData* shared_data = get_shared_data(); + SharedData *shared_data = get_shared_data(); if (!shared_data) { return false; } - return has_trigger_trace_.exchange(true) && shared_data->g_dump_L0; + return has_trigger_trace_.exchange(true) && shared_data->g_dump_L0; } void PyTorchTrace::dumpPyTorchTracing() { - const std::string &dump_path = - std::string(constant::TorchTraceConstant::DEFAULT_TRACE_DUMP_PATH); + const std::string &dump_path = std::string(constant::TorchTraceConstant::DEFAULT_TRACE_DUMP_PATH); - if (util::fs_utils::CreateDirectoryIfNotExists(dump_path)) - { + if (util::fs_utils::CreateDirectoryIfNotExists(dump_path)) { STLOG(ERROR) << "[PyTorchTrace] Failed to create dump directory"; return; } @@ -95,8 +84,7 @@ void PyTorchTrace::dumpPyTorchTracing() pytorch_trace_.set_rank(config::GlobalConfig::Instance().local_rank); pytorch_trace_.set_comm(config::GlobalConfig::Instance().job_name); - for (size_t i = 0; i < pytorch_tracing_functions_.size(); ++i) - { + for (size_t i = 0; i < pytorch_tracing_functions_.size(); ++i) { processFunctionTracingData(i); } @@ -107,22 +95,16 @@ void PyTorchTrace::processFunctionTracingData(size_t function_index) { std::vector data_holders; - if (auto data = pytorch_tracing_library_->RetrievePartialTracingData( - function_index)) - { + if (auto data = pytorch_tracing_library_->RetrievePartialTracingData(function_index)) { data_holders.push_back(data); } - while (auto data = - pytorch_tracing_library_->RetrieveAllTracingData(function_index)) - { + while (auto data = pytorch_tracing_library_->RetrieveAllTracingData(function_index)) { data_holders.push_back(data); } - for (auto data : data_holders) - { - for (uint32_t i = 0; i < data->cur; ++i) - { + for (auto data : data_holders) { + for (uint32_t i = 0; i < data->cur; ++i) { if (data->data[i].start == 0) continue; @@ -132,21 +114,16 @@ void PyTorchTrace::processFunctionTracingData(size_t function_index) trace->set_stage_id(data->data[i].count); trace->set_stage_type(pytorch_tracing_functions_[function_index]); - if (data->data[i].stack_depth > 0) - { - trace->mutable_stack_frames()->Reserve( - data->data[i].stack_depth); - for (int j = 0; j < data->data[i].stack_depth; ++j) - { - if (data->data[i].stack_info[j][0] != '\0') - { + if (data->data[i].stack_depth > 0) { + trace->mutable_stack_frames()->Reserve(data->data[i].stack_depth); + for (int j = 0; j < data->data[i].stack_depth; ++j) { + if (data->data[i].stack_info[j][0] != '\0') { trace->add_stack_frames(data->data[i].stack_info[j]); } } } - if (data->data[i].type == PAYLOAD_GC) - { + if (data->data[i].type == PAYLOAD_GC) { auto gc_debug = trace->mutable_gc_debug(); gc_debug->set_collected(data->data[i].payload.gc_debug[0]); gc_debug->set_uncollectable(data->data[i].payload.gc_debug[1]); @@ -154,31 +131,24 @@ void PyTorchTrace::processFunctionTracingData(size_t function_index) } } - for (auto data : data_holders) - { - pytorch_tracing_library_->ReleaseTracingData( - data, PY_TRACING_EMPTY_POOL, function_index); + for (auto data : data_holders) { + pytorch_tracing_library_->ReleaseTracingData(data, PY_TRACING_EMPTY_POOL, function_index); } } void PyTorchTrace::writeTraceToFile() { - const std::string &dump_path = - std::string(constant::TorchTraceConstant::DEFAULT_TRACE_DUMP_PATH); - std::string file_path = - dump_path + "/" + - util::fs_utils::GenerateClusterUniqueFilename(".timeline"); + const std::string &dump_path = std::string(constant::TorchTraceConstant::DEFAULT_TRACE_DUMP_PATH); + std::string file_path = dump_path + "/" + util::fs_utils::GenerateClusterUniqueFilename(".timeline"); std::ofstream file(file_path, std::ios::binary | std::ios::out); - if (!file) - { + if (!file) { STLOG(ERROR) << "[PyTorchTrace] Failed to open file: " << file_path; return; } std::string binary_data; - if (!pytorch_trace_.SerializeToString(&binary_data)) - { + if (!pytorch_trace_.SerializeToString(&binary_data)) { STLOG(ERROR) << "[PyTorchTrace] Failed to serialize trace data"; return; } @@ -188,16 +158,17 @@ void PyTorchTrace::writeTraceToFile() SysTrace &SysTrace::getInstance() { - std::call_once(init_flag_, - []() - { - instance_ = new SysTrace(); - instance_->initializeSystem(); - }); + std::call_once(init_flag_, []() { + instance_ = new SysTrace(); + instance_->initializeSystem(); + }); return *instance_; } -SysTrace::~SysTrace() { stopEventPoller(); } +SysTrace::~SysTrace() +{ + stopEventPoller(); +} void SysTrace::initializeSystem() { @@ -225,28 +196,23 @@ void SysTrace::startEventPoller() void SysTrace::stopEventPoller() { should_run_ = false; - if (event_poller_.joinable()) - { + if (event_poller_.joinable()) { event_poller_.join(); } } void SysTrace::eventPollerMain() { - while (should_run_) - { - if (loop_count_++ % TRACE_INTERVAL == 0) - { - if (PyTorchTrace::getInstance().triggerTrace()) - { + while (should_run_) { + if (loop_count_++ % TRACE_INTERVAL == 0) { + if (PyTorchTrace::getInstance().triggerTrace()) { PyTorchTrace::getInstance().dumpPyTorchTracing(); } } std::this_thread::sleep_for(POLL_INTERVAL); } - if (PyTorchTrace::getInstance().triggerTrace()) - { + if (PyTorchTrace::getInstance().triggerTrace()) { PyTorchTrace::getInstance().dumpPyTorchTracing(); } } diff --git a/systrace/src/trace/systrace_manager.h b/systrace/src/trace/systrace_manager.h index 85e43d5..37f1c02 100644 --- a/systrace/src/trace/systrace_manager.h +++ b/systrace/src/trace/systrace_manager.h @@ -18,9 +18,8 @@ namespace systrace { using namespace util; -class PyTorchTrace -{ - public: +class PyTorchTrace { +public: static PyTorchTrace &getInstance(); void dumpPyTorchTracing(); @@ -30,7 +29,7 @@ class PyTorchTrace PyTorchTrace(const PyTorchTrace &) = delete; PyTorchTrace &operator=(const PyTorchTrace &) = delete; - private: +private: PyTorchTrace() = default; ~PyTorchTrace() = default; @@ -43,7 +42,7 @@ class PyTorchTrace inline static std::once_flag init_flag_; Pytorch pytorch_trace_; - std::atomic has_trigger_trace_{false}; + std::atomic has_trigger_trace_ { false }; std::mutex trace_mutex_; std::vector pytorch_tracing_functions_; @@ -51,15 +50,14 @@ class PyTorchTrace pytorch_tracing::PyTorchTracingLibrary *pytorch_tracing_library_; }; -class SysTrace -{ - public: +class SysTrace { +public: static SysTrace &getInstance(); SysTrace(const SysTrace &) = delete; SysTrace &operator=(const SysTrace &) = delete; - private: +private: SysTrace() = default; ~SysTrace(); @@ -71,8 +69,8 @@ class SysTrace inline static SysTrace *instance_ = nullptr; inline static std::once_flag init_flag_; - std::atomic should_run_{true}; - std::atomic loop_count_{0}; + std::atomic should_run_ { true }; + std::atomic loop_count_ { 0 }; std::thread event_poller_; }; diff --git a/systrace/thirdparty/uthash.h b/systrace/thirdparty/uthash.h index 6d89200..5d0267e 100644 --- a/systrace/thirdparty/uthash.h +++ b/systrace/thirdparty/uthash.h @@ -42,7 +42,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. when compiling c++ source) this code uses whatever method is needed or, for VS2008 where neither is available, uses casting workarounds. */ #if !defined(DECLTYPE) && !defined(NO_DECLTYPE) -#if defined(_MSC_VER) /* MS compiler */ +#if defined(_MSC_VER) /* MS compiler */ #if _MSC_VER >= 1600 && defined(__cplusplus) /* VS2010 or newer in C++ mode */ #define DECLTYPE(x) (decltype(x)) #else /* VS2008 or older (or VS2010 in C mode) */ @@ -50,8 +50,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endif #elif defined(__MCST__) /* Elbrus C Compiler */ #define DECLTYPE(x) (__typeof(x)) -#elif defined(__BORLANDC__) || defined(__ICCARM__) || defined(__LCC__) || \ - defined(__WATCOMC__) +#elif defined(__BORLANDC__) || defined(__ICCARM__) || defined(__LCC__) || defined(__WATCOMC__) #define NO_DECLTYPE #else /* GNU, Sun and other compilers */ #define DECLTYPE(x) (__typeof(x)) @@ -60,17 +59,15 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifdef NO_DECLTYPE #define DECLTYPE(x) -#define DECLTYPE_ASSIGN(dst, src) \ - do \ - { \ - char **_da_dst = (char **)(&(dst)); \ - *_da_dst = (char *)(src); \ +#define DECLTYPE_ASSIGN(dst, src) \ + do { \ + char **_da_dst = (char **)(&(dst)); \ + *_da_dst = (char *)(src); \ } while (0) #else -#define DECLTYPE_ASSIGN(dst, src) \ - do \ - { \ - (dst) = DECLTYPE(dst)(src); \ +#define DECLTYPE_ASSIGN(dst, src) \ + do { \ + (dst) = DECLTYPE(dst)(src); \ } while (0) #endif @@ -110,16 +107,14 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. /* malloc failures can be recovered from */ #ifndef uthash_nonfatal_oom -#define uthash_nonfatal_oom(obj) \ - do \ - { \ +#define uthash_nonfatal_oom(obj) \ + do { \ } while (0) /* non-fatal OOM error */ #endif -#define HASH_RECORD_OOM(oomed) \ - do \ - { \ - (oomed) = 1; \ +#define HASH_RECORD_OOM(oomed) \ + do { \ + (oomed) = 1; \ } while (0) #define IF_HASH_NONFATAL_OOM(x) x @@ -137,20 +132,18 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. /* initial number of buckets */ #define HASH_INITIAL_NUM_BUCKETS 32U /* initial number of buckets */ -#define HASH_INITIAL_NUM_BUCKETS_LOG2 \ - 5U /* lg2 of initial number of buckets \ +#define HASH_INITIAL_NUM_BUCKETS_LOG2 \ + 5U /* lg2 of initial number of buckets \ */ #define HASH_BKT_CAPACITY_THRESH 10U /* expand when bucket count reaches */ /* calculate the element whose hash handle address is hhp */ #define ELMT_FROM_HH(tbl, hhp) ((void *)(((char *)(hhp)) - ((tbl)->hho))) /* calculate the hash handle from element address elp */ -#define HH_FROM_ELMT(tbl, elp) \ - ((UT_hash_handle *)(void *)(((char *)(elp)) + ((tbl)->hho))) +#define HH_FROM_ELMT(tbl, elp) ((UT_hash_handle *)(void *)(((char *)(elp)) + ((tbl)->hho))) #define HASH_ROLLBACK_BKT(hh, head, itemptrhh) \ - do \ - { \ + do { \ struct UT_hash_handle *_hd_hh_item = (itemptrhh); \ unsigned _hd_bkt; \ HASH_TO_BKT(_hd_hh_item->hashv, (head)->hh.tbl->num_buckets, _hd_bkt); \ @@ -159,80 +152,61 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. _hd_hh_item->hh_prev = NULL; \ } while (0) -#define HASH_VALUE(keyptr, keylen, hashv) \ - do \ - { \ - HASH_FUNCTION(keyptr, keylen, hashv); \ +#define HASH_VALUE(keyptr, keylen, hashv) \ + do { \ + HASH_FUNCTION(keyptr, keylen, hashv); \ } while (0) -#define HASH_FIND_BYHASHVALUE(hh, head, keyptr, keylen, hashval, out) \ - do \ - { \ - (out) = NULL; \ - if (head) \ - { \ - unsigned _hf_bkt; \ - HASH_TO_BKT(hashval, (head)->hh.tbl->num_buckets, _hf_bkt); \ - if (HASH_BLOOM_TEST((head)->hh.tbl, hashval)) \ - { \ - HASH_FIND_IN_BKT((head)->hh.tbl, hh, \ - (head)->hh.tbl->buckets[_hf_bkt], keyptr, \ - keylen, hashval, out); \ - } \ - } \ +#define HASH_FIND_BYHASHVALUE(hh, head, keyptr, keylen, hashval, out) \ + do { \ + (out) = NULL; \ + if (head) { \ + unsigned _hf_bkt; \ + HASH_TO_BKT(hashval, (head)->hh.tbl->num_buckets, _hf_bkt); \ + if (HASH_BLOOM_TEST((head)->hh.tbl, hashval)) { \ + HASH_FIND_IN_BKT((head)->hh.tbl, hh, (head)->hh.tbl->buckets[_hf_bkt], keyptr, keylen, hashval, out); \ + } \ + } \ } while (0) -#define HASH_FIND(hh, head, keyptr, keylen, out) \ - do \ - { \ - (out) = NULL; \ - if (head) \ - { \ - unsigned _hf_hashv; \ - HASH_VALUE(keyptr, keylen, _hf_hashv); \ - HASH_FIND_BYHASHVALUE(hh, head, keyptr, keylen, _hf_hashv, out); \ - } \ +#define HASH_FIND(hh, head, keyptr, keylen, out) \ + do { \ + (out) = NULL; \ + if (head) { \ + unsigned _hf_hashv; \ + HASH_VALUE(keyptr, keylen, _hf_hashv); \ + HASH_FIND_BYHASHVALUE(hh, head, keyptr, keylen, _hf_hashv, out); \ + } \ } while (0) #ifdef HASH_BLOOM #define HASH_BLOOM_BITLEN (1UL << HASH_BLOOM) -#define HASH_BLOOM_BYTELEN \ - (HASH_BLOOM_BITLEN / 8UL) + (((HASH_BLOOM_BITLEN % 8UL) != 0UL) ? 1UL : 0UL) -#define HASH_BLOOM_MAKE(tbl, oomed) \ - do \ - { \ - (tbl)->bloom_nbits = HASH_BLOOM; \ - (tbl)->bloom_bv = (uint8_t *)uthash_malloc(HASH_BLOOM_BYTELEN); \ - if (!(tbl)->bloom_bv) \ - { \ - HASH_RECORD_OOM(oomed); \ - } \ - else \ - { \ - uthash_bzero((tbl)->bloom_bv, HASH_BLOOM_BYTELEN); \ - (tbl)->bloom_sig = HASH_BLOOM_SIGNATURE; \ - } \ +#define HASH_BLOOM_BYTELEN (HASH_BLOOM_BITLEN / 8UL) + (((HASH_BLOOM_BITLEN % 8UL) != 0UL) ? 1UL : 0UL) +#define HASH_BLOOM_MAKE(tbl, oomed) \ + do { \ + (tbl)->bloom_nbits = HASH_BLOOM; \ + (tbl)->bloom_bv = (uint8_t *)uthash_malloc(HASH_BLOOM_BYTELEN); \ + if (!(tbl)->bloom_bv) { \ + HASH_RECORD_OOM(oomed); \ + } else { \ + uthash_bzero((tbl)->bloom_bv, HASH_BLOOM_BYTELEN); \ + (tbl)->bloom_sig = HASH_BLOOM_SIGNATURE; \ + } \ } while (0) -#define HASH_BLOOM_FREE(tbl) \ - do \ - { \ - uthash_free((tbl)->bloom_bv, HASH_BLOOM_BYTELEN); \ +#define HASH_BLOOM_FREE(tbl) \ + do { \ + uthash_free((tbl)->bloom_bv, HASH_BLOOM_BYTELEN); \ } while (0) #define HASH_BLOOM_BITSET(bv, idx) (bv[(idx) / 8U] |= (1U << ((idx) % 8U))) -#define HASH_BLOOM_BITTEST(bv, idx) \ - ((bv[(idx) / 8U] & (1U << ((idx) % 8U))) != 0) +#define HASH_BLOOM_BITTEST(bv, idx) ((bv[(idx) / 8U] & (1U << ((idx) % 8U))) != 0) -#define HASH_BLOOM_ADD(tbl, hashv) \ - HASH_BLOOM_BITSET( \ - (tbl)->bloom_bv, \ - ((hashv) & (uint32_t)((1UL << (tbl)->bloom_nbits) - 1U))) +#define HASH_BLOOM_ADD(tbl, hashv) \ + HASH_BLOOM_BITSET((tbl)->bloom_bv, ((hashv) & (uint32_t)((1UL << (tbl)->bloom_nbits) - 1U))) -#define HASH_BLOOM_TEST(tbl, hashv) \ - HASH_BLOOM_BITTEST( \ - (tbl)->bloom_bv, \ - ((hashv) & (uint32_t)((1UL << (tbl)->bloom_nbits) - 1U))) +#define HASH_BLOOM_TEST(tbl, hashv) \ + HASH_BLOOM_BITTEST((tbl)->bloom_bv, ((hashv) & (uint32_t)((1UL << (tbl)->bloom_nbits) - 1U))) #else #define HASH_BLOOM_MAKE(tbl, oomed) @@ -242,296 +216,223 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define HASH_BLOOM_BYTELEN 0U #endif -#define HASH_MAKE_TABLE(hh, head, oomed) \ - do \ - { \ - (head)->hh.tbl = \ - (UT_hash_table *)uthash_malloc(sizeof(UT_hash_table)); \ - if (!(head)->hh.tbl) \ - { \ - HASH_RECORD_OOM(oomed); \ - } \ - else \ - { \ - uthash_bzero((head)->hh.tbl, sizeof(UT_hash_table)); \ - (head)->hh.tbl->tail = &((head)->hh); \ - (head)->hh.tbl->num_buckets = HASH_INITIAL_NUM_BUCKETS; \ - (head)->hh.tbl->log2_num_buckets = HASH_INITIAL_NUM_BUCKETS_LOG2; \ - (head)->hh.tbl->hho = (char *)(&(head)->hh) - (char *)(head); \ - (head)->hh.tbl->buckets = (UT_hash_bucket *)uthash_malloc( \ - HASH_INITIAL_NUM_BUCKETS * sizeof(struct UT_hash_bucket)); \ - (head)->hh.tbl->signature = HASH_SIGNATURE; \ - if (!(head)->hh.tbl->buckets) \ - { \ - HASH_RECORD_OOM(oomed); \ - uthash_free((head)->hh.tbl, sizeof(UT_hash_table)); \ - } \ - else \ - { \ - uthash_bzero((head)->hh.tbl->buckets, \ - HASH_INITIAL_NUM_BUCKETS * \ - sizeof(struct UT_hash_bucket)); \ - HASH_BLOOM_MAKE((head)->hh.tbl, oomed); \ - IF_HASH_NONFATAL_OOM(if (oomed) { \ - uthash_free((head)->hh.tbl->buckets, \ - HASH_INITIAL_NUM_BUCKETS * \ - sizeof(struct UT_hash_bucket)); \ - uthash_free((head)->hh.tbl, sizeof(UT_hash_table)); \ - }) \ - } \ - } \ +#define HASH_MAKE_TABLE(hh, head, oomed) \ + do { \ + (head)->hh.tbl = (UT_hash_table *)uthash_malloc(sizeof(UT_hash_table)); \ + if (!(head)->hh.tbl) { \ + HASH_RECORD_OOM(oomed); \ + } else { \ + uthash_bzero((head)->hh.tbl, sizeof(UT_hash_table)); \ + (head)->hh.tbl->tail = &((head)->hh); \ + (head)->hh.tbl->num_buckets = HASH_INITIAL_NUM_BUCKETS; \ + (head)->hh.tbl->log2_num_buckets = HASH_INITIAL_NUM_BUCKETS_LOG2; \ + (head)->hh.tbl->hho = (char *)(&(head)->hh) - (char *)(head); \ + (head)->hh.tbl->buckets = \ + (UT_hash_bucket *)uthash_malloc(HASH_INITIAL_NUM_BUCKETS * sizeof(struct UT_hash_bucket)); \ + (head)->hh.tbl->signature = HASH_SIGNATURE; \ + if (!(head)->hh.tbl->buckets) { \ + HASH_RECORD_OOM(oomed); \ + uthash_free((head)->hh.tbl, sizeof(UT_hash_table)); \ + } else { \ + uthash_bzero((head)->hh.tbl->buckets, HASH_INITIAL_NUM_BUCKETS * sizeof(struct UT_hash_bucket)); \ + HASH_BLOOM_MAKE((head)->hh.tbl, oomed); \ + IF_HASH_NONFATAL_OOM(if (oomed) { \ + uthash_free((head)->hh.tbl->buckets, HASH_INITIAL_NUM_BUCKETS * sizeof(struct UT_hash_bucket)); \ + uthash_free((head)->hh.tbl, sizeof(UT_hash_table)); \ + }) \ + } \ + } \ } while (0) -#define HASH_REPLACE_BYHASHVALUE_INORDER(hh, head, fieldname, keylen_in, \ - hashval, add, replaced, cmpfcn) \ - do \ - { \ - (replaced) = NULL; \ - HASH_FIND_BYHASHVALUE(hh, head, &((add)->fieldname), keylen_in, \ - hashval, replaced); \ - if (replaced) \ - { \ - HASH_DELETE(hh, head, replaced); \ - } \ - HASH_ADD_KEYPTR_BYHASHVALUE_INORDER(hh, head, &((add)->fieldname), \ - keylen_in, hashval, add, cmpfcn); \ +#define HASH_REPLACE_BYHASHVALUE_INORDER(hh, head, fieldname, keylen_in, hashval, add, replaced, cmpfcn) \ + do { \ + (replaced) = NULL; \ + HASH_FIND_BYHASHVALUE(hh, head, &((add)->fieldname), keylen_in, hashval, replaced); \ + if (replaced) { \ + HASH_DELETE(hh, head, replaced); \ + } \ + HASH_ADD_KEYPTR_BYHASHVALUE_INORDER(hh, head, &((add)->fieldname), keylen_in, hashval, add, cmpfcn); \ } while (0) -#define HASH_REPLACE_BYHASHVALUE(hh, head, fieldname, keylen_in, hashval, add, \ - replaced) \ - do \ - { \ - (replaced) = NULL; \ - HASH_FIND_BYHASHVALUE(hh, head, &((add)->fieldname), keylen_in, \ - hashval, replaced); \ - if (replaced) \ - { \ - HASH_DELETE(hh, head, replaced); \ - } \ - HASH_ADD_KEYPTR_BYHASHVALUE(hh, head, &((add)->fieldname), keylen_in, \ - hashval, add); \ +#define HASH_REPLACE_BYHASHVALUE(hh, head, fieldname, keylen_in, hashval, add, replaced) \ + do { \ + (replaced) = NULL; \ + HASH_FIND_BYHASHVALUE(hh, head, &((add)->fieldname), keylen_in, hashval, replaced); \ + if (replaced) { \ + HASH_DELETE(hh, head, replaced); \ + } \ + HASH_ADD_KEYPTR_BYHASHVALUE(hh, head, &((add)->fieldname), keylen_in, hashval, add); \ } while (0) -#define HASH_REPLACE(hh, head, fieldname, keylen_in, add, replaced) \ - do \ - { \ - unsigned _hr_hashv; \ - HASH_VALUE(&((add)->fieldname), keylen_in, _hr_hashv); \ - HASH_REPLACE_BYHASHVALUE(hh, head, fieldname, keylen_in, _hr_hashv, \ - add, replaced); \ +#define HASH_REPLACE(hh, head, fieldname, keylen_in, add, replaced) \ + do { \ + unsigned _hr_hashv; \ + HASH_VALUE(&((add)->fieldname), keylen_in, _hr_hashv); \ + HASH_REPLACE_BYHASHVALUE(hh, head, fieldname, keylen_in, _hr_hashv, add, replaced); \ } while (0) -#define HASH_REPLACE_INORDER(hh, head, fieldname, keylen_in, add, replaced, \ - cmpfcn) \ - do \ - { \ - unsigned _hr_hashv; \ - HASH_VALUE(&((add)->fieldname), keylen_in, _hr_hashv); \ - HASH_REPLACE_BYHASHVALUE_INORDER(hh, head, fieldname, keylen_in, \ - _hr_hashv, add, replaced, cmpfcn); \ +#define HASH_REPLACE_INORDER(hh, head, fieldname, keylen_in, add, replaced, cmpfcn) \ + do { \ + unsigned _hr_hashv; \ + HASH_VALUE(&((add)->fieldname), keylen_in, _hr_hashv); \ + HASH_REPLACE_BYHASHVALUE_INORDER(hh, head, fieldname, keylen_in, _hr_hashv, add, replaced, cmpfcn); \ } while (0) -#define HASH_APPEND_LIST(hh, head, add) \ - do \ - { \ - (add)->hh.next = NULL; \ - (add)->hh.prev = ELMT_FROM_HH((head)->hh.tbl, (head)->hh.tbl->tail); \ - (head)->hh.tbl->tail->next = (add); \ - (head)->hh.tbl->tail = &((add)->hh); \ +#define HASH_APPEND_LIST(hh, head, add) \ + do { \ + (add)->hh.next = NULL; \ + (add)->hh.prev = ELMT_FROM_HH((head)->hh.tbl, (head)->hh.tbl->tail); \ + (head)->hh.tbl->tail->next = (add); \ + (head)->hh.tbl->tail = &((add)->hh); \ } while (0) -#define HASH_AKBI_INNER_LOOP(hh, head, add, cmpfcn) \ - do \ - { \ - do \ - { \ - if (cmpfcn(DECLTYPE(head)(_hs_iter), add) > 0) \ - { \ - break; \ - } \ - } while ((_hs_iter = HH_FROM_ELMT((head)->hh.tbl, _hs_iter)->next)); \ +#define HASH_AKBI_INNER_LOOP(hh, head, add, cmpfcn) \ + do { \ + do { \ + if (cmpfcn(DECLTYPE(head)(_hs_iter), add) > 0) { \ + break; \ + } \ + } while ((_hs_iter = HH_FROM_ELMT((head)->hh.tbl, _hs_iter)->next)); \ } while (0) #ifdef NO_DECLTYPE #undef HASH_AKBI_INNER_LOOP -#define HASH_AKBI_INNER_LOOP(hh, head, add, cmpfcn) \ - do \ - { \ - char *_hs_saved_head = (char *)(head); \ - do \ - { \ - DECLTYPE_ASSIGN(head, _hs_iter); \ - if (cmpfcn(head, add) > 0) \ - { \ - DECLTYPE_ASSIGN(head, _hs_saved_head); \ - break; \ - } \ - DECLTYPE_ASSIGN(head, _hs_saved_head); \ - } while ((_hs_iter = HH_FROM_ELMT((head)->hh.tbl, _hs_iter)->next)); \ +#define HASH_AKBI_INNER_LOOP(hh, head, add, cmpfcn) \ + do { \ + char *_hs_saved_head = (char *)(head); \ + do { \ + DECLTYPE_ASSIGN(head, _hs_iter); \ + if (cmpfcn(head, add) > 0) { \ + DECLTYPE_ASSIGN(head, _hs_saved_head); \ + break; \ + } \ + DECLTYPE_ASSIGN(head, _hs_saved_head); \ + } while ((_hs_iter = HH_FROM_ELMT((head)->hh.tbl, _hs_iter)->next)); \ } while (0) #endif #if HASH_NONFATAL_OOM -#define HASH_ADD_TO_TABLE(hh, head, keyptr, keylen_in, hashval, add, oomed) \ - do \ - { \ - if (!(oomed)) \ - { \ - unsigned _ha_bkt; \ - (head)->hh.tbl->num_items++; \ - HASH_TO_BKT(hashval, (head)->hh.tbl->num_buckets, _ha_bkt); \ - HASH_ADD_TO_BKT((head)->hh.tbl->buckets[_ha_bkt], hh, &(add)->hh, \ - oomed); \ - if (oomed) \ - { \ - HASH_ROLLBACK_BKT(hh, head, &(add)->hh); \ - HASH_DELETE_HH(hh, head, &(add)->hh); \ - (add)->hh.tbl = NULL; \ - uthash_nonfatal_oom(add); \ - } \ - else \ - { \ - HASH_BLOOM_ADD((head)->hh.tbl, hashval); \ - HASH_EMIT_KEY(hh, head, keyptr, keylen_in); \ - } \ - } \ - else \ - { \ - (add)->hh.tbl = NULL; \ - uthash_nonfatal_oom(add); \ - } \ +#define HASH_ADD_TO_TABLE(hh, head, keyptr, keylen_in, hashval, add, oomed) \ + do { \ + if (!(oomed)) { \ + unsigned _ha_bkt; \ + (head)->hh.tbl->num_items++; \ + HASH_TO_BKT(hashval, (head)->hh.tbl->num_buckets, _ha_bkt); \ + HASH_ADD_TO_BKT((head)->hh.tbl->buckets[_ha_bkt], hh, &(add)->hh, oomed); \ + if (oomed) { \ + HASH_ROLLBACK_BKT(hh, head, &(add)->hh); \ + HASH_DELETE_HH(hh, head, &(add)->hh); \ + (add)->hh.tbl = NULL; \ + uthash_nonfatal_oom(add); \ + } else { \ + HASH_BLOOM_ADD((head)->hh.tbl, hashval); \ + HASH_EMIT_KEY(hh, head, keyptr, keylen_in); \ + } \ + } else { \ + (add)->hh.tbl = NULL; \ + uthash_nonfatal_oom(add); \ + } \ } while (0) #else -#define HASH_ADD_TO_TABLE(hh, head, keyptr, keylen_in, hashval, add, oomed) \ - do \ - { \ - unsigned _ha_bkt; \ - (head)->hh.tbl->num_items++; \ - HASH_TO_BKT(hashval, (head)->hh.tbl->num_buckets, _ha_bkt); \ - HASH_ADD_TO_BKT((head)->hh.tbl->buckets[_ha_bkt], hh, &(add)->hh, \ - oomed); \ - HASH_BLOOM_ADD((head)->hh.tbl, hashval); \ - HASH_EMIT_KEY(hh, head, keyptr, keylen_in); \ +#define HASH_ADD_TO_TABLE(hh, head, keyptr, keylen_in, hashval, add, oomed) \ + do { \ + unsigned _ha_bkt; \ + (head)->hh.tbl->num_items++; \ + HASH_TO_BKT(hashval, (head)->hh.tbl->num_buckets, _ha_bkt); \ + HASH_ADD_TO_BKT((head)->hh.tbl->buckets[_ha_bkt], hh, &(add)->hh, oomed); \ + HASH_BLOOM_ADD((head)->hh.tbl, hashval); \ + HASH_EMIT_KEY(hh, head, keyptr, keylen_in); \ } while (0) #endif -#define HASH_ADD_KEYPTR_BYHASHVALUE_INORDER(hh, head, keyptr, keylen_in, \ - hashval, add, cmpfcn) \ - do \ - { \ - IF_HASH_NONFATAL_OOM(int _ha_oomed = 0;) \ - (add)->hh.hashv = (hashval); \ - (add)->hh.key = (char *)(keyptr); \ - (add)->hh.keylen = (unsigned)(keylen_in); \ - if (!(head)) \ - { \ - (add)->hh.next = NULL; \ - (add)->hh.prev = NULL; \ - HASH_MAKE_TABLE(hh, add, _ha_oomed); \ +#define HASH_ADD_KEYPTR_BYHASHVALUE_INORDER(hh, head, keyptr, keylen_in, hashval, add, cmpfcn) \ + do { \ + IF_HASH_NONFATAL_OOM(int _ha_oomed = 0;) \ + (add)->hh.hashv = (hashval); \ + (add)->hh.key = (char *)(keyptr); \ + (add)->hh.keylen = (unsigned)(keylen_in); \ + if (!(head)) { \ + (add)->hh.next = NULL; \ + (add)->hh.prev = NULL; \ + HASH_MAKE_TABLE(hh, add, _ha_oomed); \ IF_HASH_NONFATAL_OOM(if (!_ha_oomed) { ) \ - (head) = (add); \ - IF_HASH_NONFATAL_OOM( \ - }) \ - } \ - else \ - { \ - void *_hs_iter = (head); \ - (add)->hh.tbl = (head)->hh.tbl; \ - HASH_AKBI_INNER_LOOP(hh, head, add, cmpfcn); \ - if (_hs_iter) \ - { \ - (add)->hh.next = _hs_iter; \ - if (((add)->hh.prev = \ - HH_FROM_ELMT((head)->hh.tbl, _hs_iter)->prev)) \ - { \ - HH_FROM_ELMT((head)->hh.tbl, (add)->hh.prev)->next = \ - (add); \ - } \ - else \ - { \ - (head) = (add); \ - } \ - HH_FROM_ELMT((head)->hh.tbl, _hs_iter)->prev = (add); \ - } \ - else \ - { \ - HASH_APPEND_LIST(hh, head, add); \ - } \ - } \ - HASH_ADD_TO_TABLE(hh, head, keyptr, keylen_in, hashval, add, \ - _ha_oomed); \ - HASH_FSCK(hh, head, "HASH_ADD_KEYPTR_BYHASHVALUE_INORDER"); \ + (head) = (add); \ + IF_HASH_NONFATAL_OOM( \ + }) \ + } else { \ + void *_hs_iter = (head); \ + (add)->hh.tbl = (head)->hh.tbl; \ + HASH_AKBI_INNER_LOOP(hh, head, add, cmpfcn); \ + if (_hs_iter) { \ + (add)->hh.next = _hs_iter; \ + if (((add)->hh.prev = HH_FROM_ELMT((head)->hh.tbl, _hs_iter)->prev)) { \ + HH_FROM_ELMT((head)->hh.tbl, (add)->hh.prev)->next = (add); \ + } else { \ + (head) = (add); \ + } \ + HH_FROM_ELMT((head)->hh.tbl, _hs_iter)->prev = (add); \ + } else { \ + HASH_APPEND_LIST(hh, head, add); \ + } \ + } \ + HASH_ADD_TO_TABLE(hh, head, keyptr, keylen_in, hashval, add, _ha_oomed); \ + HASH_FSCK(hh, head, "HASH_ADD_KEYPTR_BYHASHVALUE_INORDER"); \ } while (0) -#define HASH_ADD_KEYPTR_INORDER(hh, head, keyptr, keylen_in, add, cmpfcn) \ - do \ - { \ - unsigned _hs_hashv; \ - HASH_VALUE(keyptr, keylen_in, _hs_hashv); \ - HASH_ADD_KEYPTR_BYHASHVALUE_INORDER(hh, head, keyptr, keylen_in, \ - _hs_hashv, add, cmpfcn); \ +#define HASH_ADD_KEYPTR_INORDER(hh, head, keyptr, keylen_in, add, cmpfcn) \ + do { \ + unsigned _hs_hashv; \ + HASH_VALUE(keyptr, keylen_in, _hs_hashv); \ + HASH_ADD_KEYPTR_BYHASHVALUE_INORDER(hh, head, keyptr, keylen_in, _hs_hashv, add, cmpfcn); \ } while (0) -#define HASH_ADD_BYHASHVALUE_INORDER(hh, head, fieldname, keylen_in, hashval, \ - add, cmpfcn) \ - HASH_ADD_KEYPTR_BYHASHVALUE_INORDER(hh, head, &((add)->fieldname), \ - keylen_in, hashval, add, cmpfcn) - -#define HASH_ADD_INORDER(hh, head, fieldname, keylen_in, add, cmpfcn) \ - HASH_ADD_KEYPTR_INORDER(hh, head, &((add)->fieldname), keylen_in, add, \ - cmpfcn) - -#define HASH_ADD_KEYPTR_BYHASHVALUE(hh, head, keyptr, keylen_in, hashval, add) \ - do \ - { \ - IF_HASH_NONFATAL_OOM(int _ha_oomed = 0;) \ - (add)->hh.hashv = (hashval); \ - (add)->hh.key = (const void *)(keyptr); \ - (add)->hh.keylen = (unsigned)(keylen_in); \ - if (!(head)) \ - { \ - (add)->hh.next = NULL; \ - (add)->hh.prev = NULL; \ - HASH_MAKE_TABLE(hh, add, _ha_oomed); \ +#define HASH_ADD_BYHASHVALUE_INORDER(hh, head, fieldname, keylen_in, hashval, add, cmpfcn) \ + HASH_ADD_KEYPTR_BYHASHVALUE_INORDER(hh, head, &((add)->fieldname), keylen_in, hashval, add, cmpfcn) + +#define HASH_ADD_INORDER(hh, head, fieldname, keylen_in, add, cmpfcn) \ + HASH_ADD_KEYPTR_INORDER(hh, head, &((add)->fieldname), keylen_in, add, cmpfcn) + +#define HASH_ADD_KEYPTR_BYHASHVALUE(hh, head, keyptr, keylen_in, hashval, add) \ + do { \ + IF_HASH_NONFATAL_OOM(int _ha_oomed = 0;) \ + (add)->hh.hashv = (hashval); \ + (add)->hh.key = (const void *)(keyptr); \ + (add)->hh.keylen = (unsigned)(keylen_in); \ + if (!(head)) { \ + (add)->hh.next = NULL; \ + (add)->hh.prev = NULL; \ + HASH_MAKE_TABLE(hh, add, _ha_oomed); \ IF_HASH_NONFATAL_OOM(if (!_ha_oomed) { ) \ - (head) = (add); \ - IF_HASH_NONFATAL_OOM( \ - }) \ - } \ - else \ - { \ - (add)->hh.tbl = (head)->hh.tbl; \ - HASH_APPEND_LIST(hh, head, add); \ - } \ - HASH_ADD_TO_TABLE(hh, head, keyptr, keylen_in, hashval, add, \ - _ha_oomed); \ - HASH_FSCK(hh, head, "HASH_ADD_KEYPTR_BYHASHVALUE"); \ + (head) = (add); \ + IF_HASH_NONFATAL_OOM( \ + }) \ + } else { \ + (add)->hh.tbl = (head)->hh.tbl; \ + HASH_APPEND_LIST(hh, head, add); \ + } \ + HASH_ADD_TO_TABLE(hh, head, keyptr, keylen_in, hashval, add, _ha_oomed); \ + HASH_FSCK(hh, head, "HASH_ADD_KEYPTR_BYHASHVALUE"); \ } while (0) -#define HASH_ADD_KEYPTR(hh, head, keyptr, keylen_in, add) \ - do \ - { \ - unsigned _ha_hashv; \ - HASH_VALUE(keyptr, keylen_in, _ha_hashv); \ - HASH_ADD_KEYPTR_BYHASHVALUE(hh, head, keyptr, keylen_in, _ha_hashv, \ - add); \ +#define HASH_ADD_KEYPTR(hh, head, keyptr, keylen_in, add) \ + do { \ + unsigned _ha_hashv; \ + HASH_VALUE(keyptr, keylen_in, _ha_hashv); \ + HASH_ADD_KEYPTR_BYHASHVALUE(hh, head, keyptr, keylen_in, _ha_hashv, add); \ } while (0) -#define HASH_ADD_BYHASHVALUE(hh, head, fieldname, keylen_in, hashval, add) \ - HASH_ADD_KEYPTR_BYHASHVALUE(hh, head, &((add)->fieldname), keylen_in, \ - hashval, add) +#define HASH_ADD_BYHASHVALUE(hh, head, fieldname, keylen_in, hashval, add) \ + HASH_ADD_KEYPTR_BYHASHVALUE(hh, head, &((add)->fieldname), keylen_in, hashval, add) -#define HASH_ADD(hh, head, fieldname, keylen_in, add) \ - HASH_ADD_KEYPTR(hh, head, &((add)->fieldname), keylen_in, add) +#define HASH_ADD(hh, head, fieldname, keylen_in, add) HASH_ADD_KEYPTR(hh, head, &((add)->fieldname), keylen_in, add) -#define HASH_TO_BKT(hashv, num_bkts, bkt) \ - do \ - { \ - bkt = ((hashv) & ((num_bkts) - 1U)); \ +#define HASH_TO_BKT(hashv, num_bkts, bkt) \ + do { \ + bkt = ((hashv) & ((num_bkts) - 1U)); \ } while (0) /* delete "delptr" from the hash table. @@ -548,83 +449,56 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #define HASH_DELETE(hh, head, delptr) HASH_DELETE_HH(hh, head, &(delptr)->hh) -#define HASH_DELETE_HH(hh, head, delptrhh) \ - do \ - { \ - const struct UT_hash_handle *_hd_hh_del = (delptrhh); \ - if ((_hd_hh_del->prev == NULL) && (_hd_hh_del->next == NULL)) \ - { \ - HASH_BLOOM_FREE((head)->hh.tbl); \ - uthash_free((head)->hh.tbl->buckets, \ - (head)->hh.tbl->num_buckets * \ - sizeof(struct UT_hash_bucket)); \ - uthash_free((head)->hh.tbl, sizeof(UT_hash_table)); \ - (head) = NULL; \ - } \ - else \ - { \ - unsigned _hd_bkt; \ - if (_hd_hh_del == (head)->hh.tbl->tail) \ - { \ - (head)->hh.tbl->tail = \ - HH_FROM_ELMT((head)->hh.tbl, _hd_hh_del->prev); \ - } \ - if (_hd_hh_del->prev != NULL) \ - { \ - HH_FROM_ELMT((head)->hh.tbl, _hd_hh_del->prev)->next = \ - _hd_hh_del->next; \ - } \ - else \ - { \ - DECLTYPE_ASSIGN(head, _hd_hh_del->next); \ - } \ - if (_hd_hh_del->next != NULL) \ - { \ - HH_FROM_ELMT((head)->hh.tbl, _hd_hh_del->next)->prev = \ - _hd_hh_del->prev; \ - } \ - HASH_TO_BKT(_hd_hh_del->hashv, (head)->hh.tbl->num_buckets, \ - _hd_bkt); \ - HASH_DEL_IN_BKT((head)->hh.tbl->buckets[_hd_bkt], _hd_hh_del); \ - (head)->hh.tbl->num_items--; \ - } \ - HASH_FSCK(hh, head, "HASH_DELETE_HH"); \ +#define HASH_DELETE_HH(hh, head, delptrhh) \ + do { \ + const struct UT_hash_handle *_hd_hh_del = (delptrhh); \ + if ((_hd_hh_del->prev == NULL) && (_hd_hh_del->next == NULL)) { \ + HASH_BLOOM_FREE((head)->hh.tbl); \ + uthash_free((head)->hh.tbl->buckets, (head)->hh.tbl->num_buckets * sizeof(struct UT_hash_bucket)); \ + uthash_free((head)->hh.tbl, sizeof(UT_hash_table)); \ + (head) = NULL; \ + } else { \ + unsigned _hd_bkt; \ + if (_hd_hh_del == (head)->hh.tbl->tail) { \ + (head)->hh.tbl->tail = HH_FROM_ELMT((head)->hh.tbl, _hd_hh_del->prev); \ + } \ + if (_hd_hh_del->prev != NULL) { \ + HH_FROM_ELMT((head)->hh.tbl, _hd_hh_del->prev)->next = _hd_hh_del->next; \ + } else { \ + DECLTYPE_ASSIGN(head, _hd_hh_del->next); \ + } \ + if (_hd_hh_del->next != NULL) { \ + HH_FROM_ELMT((head)->hh.tbl, _hd_hh_del->next)->prev = _hd_hh_del->prev; \ + } \ + HASH_TO_BKT(_hd_hh_del->hashv, (head)->hh.tbl->num_buckets, _hd_bkt); \ + HASH_DEL_IN_BKT((head)->hh.tbl->buckets[_hd_bkt], _hd_hh_del); \ + (head)->hh.tbl->num_items--; \ + } \ + HASH_FSCK(hh, head, "HASH_DELETE_HH"); \ } while (0) /* convenience forms of HASH_FIND/HASH_ADD/HASH_DEL */ -#define HASH_FIND_STR(head, findstr, out) \ - do \ - { \ - unsigned _uthash_hfstr_keylen = (unsigned)uthash_strlen(findstr); \ - HASH_FIND(hh, head, findstr, _uthash_hfstr_keylen, out); \ +#define HASH_FIND_STR(head, findstr, out) \ + do { \ + unsigned _uthash_hfstr_keylen = (unsigned)uthash_strlen(findstr); \ + HASH_FIND(hh, head, findstr, _uthash_hfstr_keylen, out); \ } while (0) -#define HASH_ADD_STR(head, strfield, add) \ - do \ - { \ - unsigned _uthash_hastr_keylen = \ - (unsigned)uthash_strlen((add)->strfield); \ - HASH_ADD(hh, head, strfield[0], _uthash_hastr_keylen, add); \ +#define HASH_ADD_STR(head, strfield, add) \ + do { \ + unsigned _uthash_hastr_keylen = (unsigned)uthash_strlen((add)->strfield); \ + HASH_ADD(hh, head, strfield[0], _uthash_hastr_keylen, add); \ } while (0) -#define HASH_REPLACE_STR(head, strfield, add, replaced) \ - do \ - { \ - unsigned _uthash_hrstr_keylen = \ - (unsigned)uthash_strlen((add)->strfield); \ - HASH_REPLACE(hh, head, strfield[0], _uthash_hrstr_keylen, add, \ - replaced); \ +#define HASH_REPLACE_STR(head, strfield, add, replaced) \ + do { \ + unsigned _uthash_hrstr_keylen = (unsigned)uthash_strlen((add)->strfield); \ + HASH_REPLACE(hh, head, strfield[0], _uthash_hrstr_keylen, add, replaced); \ } while (0) -#define HASH_FIND_INT(head, findint, out) \ - HASH_FIND(hh, head, findint, sizeof(int), out) -#define HASH_ADD_INT(head, intfield, add) \ - HASH_ADD(hh, head, intfield, sizeof(int), add) -#define HASH_REPLACE_INT(head, intfield, add, replaced) \ - HASH_REPLACE(hh, head, intfield, sizeof(int), add, replaced) -#define HASH_FIND_PTR(head, findptr, out) \ - HASH_FIND(hh, head, findptr, sizeof(void *), out) -#define HASH_ADD_PTR(head, ptrfield, add) \ - HASH_ADD(hh, head, ptrfield, sizeof(void *), add) -#define HASH_REPLACE_PTR(head, ptrfield, add, replaced) \ - HASH_REPLACE(hh, head, ptrfield, sizeof(void *), add, replaced) +#define HASH_FIND_INT(head, findint, out) HASH_FIND(hh, head, findint, sizeof(int), out) +#define HASH_ADD_INT(head, intfield, add) HASH_ADD(hh, head, intfield, sizeof(int), add) +#define HASH_REPLACE_INT(head, intfield, add, replaced) HASH_REPLACE(hh, head, intfield, sizeof(int), add, replaced) +#define HASH_FIND_PTR(head, findptr, out) HASH_FIND(hh, head, findptr, sizeof(void *), out) +#define HASH_ADD_PTR(head, ptrfield, add) HASH_ADD(hh, head, ptrfield, sizeof(void *), add) +#define HASH_REPLACE_PTR(head, ptrfield, add, replaced) HASH_REPLACE(hh, head, ptrfield, sizeof(void *), add, replaced) #define HASH_DEL(head, delptr) HASH_DELETE(hh, head, delptr) /* HASH_FSCK checks hash integrity on every add/delete when HASH_DEBUG is @@ -633,72 +507,55 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifdef HASH_DEBUG #include /* fprintf, stderr */ -#define HASH_OOPS(...) \ - do \ - { \ - fprintf(stderr, __VA_ARGS__); \ - exit(-1); \ +#define HASH_OOPS(...) \ + do { \ + fprintf(stderr, __VA_ARGS__); \ + exit(-1); \ } while (0) -#define HASH_FSCK(hh, head, where) \ - do \ - { \ - struct UT_hash_handle *_thh; \ - if (head) \ - { \ - unsigned _bkt_i; \ - unsigned _count = 0; \ - char *_prev; \ - for (_bkt_i = 0; _bkt_i < (head)->hh.tbl->num_buckets; ++_bkt_i) \ - { \ - unsigned _bkt_count = 0; \ - _thh = (head)->hh.tbl->buckets[_bkt_i].hh_head; \ - _prev = NULL; \ - while (_thh) \ - { \ - if (_prev != (char *)(_thh->hh_prev)) \ - { \ - HASH_OOPS("%s: invalid hh_prev %p, actual %p\n", \ - (where), (void *)_thh->hh_prev, \ - (void *)_prev); \ - } \ - _bkt_count++; \ - _prev = (char *)(_thh); \ - _thh = _thh->hh_next; \ - } \ - _count += _bkt_count; \ - if ((head)->hh.tbl->buckets[_bkt_i].count != _bkt_count) \ - { \ - HASH_OOPS("%s: invalid bucket count %u, actual %u\n", \ - (where), (head)->hh.tbl->buckets[_bkt_i].count, \ - _bkt_count); \ - } \ - } \ - if (_count != (head)->hh.tbl->num_items) \ - { \ - HASH_OOPS("%s: invalid hh item count %u, actual %u\n", \ - (where), (head)->hh.tbl->num_items, _count); \ - } \ - _count = 0; \ - _prev = NULL; \ - _thh = &(head)->hh; \ - while (_thh) \ - { \ - _count++; \ - if (_prev != (char *)_thh->prev) \ - { \ - HASH_OOPS("%s: invalid prev %p, actual %p\n", (where), \ - (void *)_thh->prev, (void *)_prev); \ - } \ - _prev = (char *)ELMT_FROM_HH((head)->hh.tbl, _thh); \ - _thh = (_thh->next ? HH_FROM_ELMT((head)->hh.tbl, _thh->next) \ - : NULL); \ - } \ - if (_count != (head)->hh.tbl->num_items) \ - { \ - HASH_OOPS("%s: invalid app item count %u, actual %u\n", \ - (where), (head)->hh.tbl->num_items, _count); \ - } \ - } \ +#define HASH_FSCK(hh, head, where) \ + do { \ + struct UT_hash_handle *_thh; \ + if (head) { \ + unsigned _bkt_i; \ + unsigned _count = 0; \ + char *_prev; \ + for (_bkt_i = 0; _bkt_i < (head)->hh.tbl->num_buckets; ++_bkt_i) { \ + unsigned _bkt_count = 0; \ + _thh = (head)->hh.tbl->buckets[_bkt_i].hh_head; \ + _prev = NULL; \ + while (_thh) { \ + if (_prev != (char *)(_thh->hh_prev)) { \ + HASH_OOPS("%s: invalid hh_prev %p, actual %p\n", (where), (void *)_thh->hh_prev, \ + (void *)_prev); \ + } \ + _bkt_count++; \ + _prev = (char *)(_thh); \ + _thh = _thh->hh_next; \ + } \ + _count += _bkt_count; \ + if ((head)->hh.tbl->buckets[_bkt_i].count != _bkt_count) { \ + HASH_OOPS("%s: invalid bucket count %u, actual %u\n", (where), \ + (head)->hh.tbl->buckets[_bkt_i].count, _bkt_count); \ + } \ + } \ + if (_count != (head)->hh.tbl->num_items) { \ + HASH_OOPS("%s: invalid hh item count %u, actual %u\n", (where), (head)->hh.tbl->num_items, _count); \ + } \ + _count = 0; \ + _prev = NULL; \ + _thh = &(head)->hh; \ + while (_thh) { \ + _count++; \ + if (_prev != (char *)_thh->prev) { \ + HASH_OOPS("%s: invalid prev %p, actual %p\n", (where), (void *)_thh->prev, (void *)_prev); \ + } \ + _prev = (char *)ELMT_FROM_HH((head)->hh.tbl, _thh); \ + _thh = (_thh->next ? HH_FROM_ELMT((head)->hh.tbl, _thh->next) : NULL); \ + } \ + if (_count != (head)->hh.tbl->num_items) { \ + HASH_OOPS("%s: invalid app item count %u, actual %u\n", (where), (head)->hh.tbl->num_items, _count); \ + } \ + } \ } while (0) #else #define HASH_FSCK(hh, head, where) @@ -708,12 +565,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * the descriptor to which this macro is defined for tuning the hash function. * The app can #include to get the prototype for write(2). */ #ifdef HASH_EMIT_KEYS -#define HASH_EMIT_KEY(hh, head, keyptr, fieldlen) \ - do \ - { \ - unsigned _klen = fieldlen; \ - write(HASH_EMIT_KEYS, &_klen, sizeof(_klen)); \ - write(HASH_EMIT_KEYS, keyptr, (unsigned long)fieldlen); \ +#define HASH_EMIT_KEY(hh, head, keyptr, fieldlen) \ + do { \ + unsigned _klen = fieldlen; \ + write(HASH_EMIT_KEYS, &_klen, sizeof(_klen)); \ + write(HASH_EMIT_KEYS, keyptr, (unsigned long)fieldlen); \ } while (0) #else #define HASH_EMIT_KEY(hh, head, keyptr, fieldlen) @@ -721,287 +577,248 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. /* The Bernstein hash function, used in Perl prior to v5.6. Note (x<<5+x)=x*33. */ -#define HASH_BER(key, keylen, hashv) \ - do \ - { \ - unsigned _hb_keylen = (unsigned)keylen; \ - const unsigned char *_hb_key = (const unsigned char *)(key); \ - (hashv) = 0; \ - while (_hb_keylen-- != 0U) \ - { \ - (hashv) = (((hashv) << 5) + (hashv)) + *_hb_key++; \ - } \ +#define HASH_BER(key, keylen, hashv) \ + do { \ + unsigned _hb_keylen = (unsigned)keylen; \ + const unsigned char *_hb_key = (const unsigned char *)(key); \ + (hashv) = 0; \ + while (_hb_keylen-- != 0U) { \ + (hashv) = (((hashv) << 5) + (hashv)) + *_hb_key++; \ + } \ } while (0) /* SAX/FNV/OAT/JEN hash functions are macro variants of those listed at * http://eternallyconfuzzled.com/tuts/algorithms/jsw_tut_hashing.aspx * (archive link: https://archive.is/Ivcan ) */ -#define HASH_SAX(key, keylen, hashv) \ - do \ - { \ - unsigned _sx_i; \ - const unsigned char *_hs_key = (const unsigned char *)(key); \ - hashv = 0; \ - for (_sx_i = 0; _sx_i < keylen; _sx_i++) \ - { \ - hashv ^= (hashv << 5) + (hashv >> 2) + _hs_key[_sx_i]; \ - } \ +#define HASH_SAX(key, keylen, hashv) \ + do { \ + unsigned _sx_i; \ + const unsigned char *_hs_key = (const unsigned char *)(key); \ + hashv = 0; \ + for (_sx_i = 0; _sx_i < keylen; _sx_i++) { \ + hashv ^= (hashv << 5) + (hashv >> 2) + _hs_key[_sx_i]; \ + } \ } while (0) /* FNV-1a variation */ -#define HASH_FNV(key, keylen, hashv) \ - do \ - { \ - unsigned _fn_i; \ - const unsigned char *_hf_key = (const unsigned char *)(key); \ - (hashv) = 2166136261U; \ - for (_fn_i = 0; _fn_i < keylen; _fn_i++) \ - { \ - hashv = hashv ^ _hf_key[_fn_i]; \ - hashv = hashv * 16777619U; \ - } \ +#define HASH_FNV(key, keylen, hashv) \ + do { \ + unsigned _fn_i; \ + const unsigned char *_hf_key = (const unsigned char *)(key); \ + (hashv) = 2166136261U; \ + for (_fn_i = 0; _fn_i < keylen; _fn_i++) { \ + hashv = hashv ^ _hf_key[_fn_i]; \ + hashv = hashv * 16777619U; \ + } \ } while (0) -#define HASH_OAT(key, keylen, hashv) \ - do \ - { \ - unsigned _ho_i; \ - const unsigned char *_ho_key = (const unsigned char *)(key); \ - hashv = 0; \ - for (_ho_i = 0; _ho_i < keylen; _ho_i++) \ - { \ - hashv += _ho_key[_ho_i]; \ - hashv += (hashv << 10); \ - hashv ^= (hashv >> 6); \ - } \ - hashv += (hashv << 3); \ - hashv ^= (hashv >> 11); \ - hashv += (hashv << 15); \ +#define HASH_OAT(key, keylen, hashv) \ + do { \ + unsigned _ho_i; \ + const unsigned char *_ho_key = (const unsigned char *)(key); \ + hashv = 0; \ + for (_ho_i = 0; _ho_i < keylen; _ho_i++) { \ + hashv += _ho_key[_ho_i]; \ + hashv += (hashv << 10); \ + hashv ^= (hashv >> 6); \ + } \ + hashv += (hashv << 3); \ + hashv ^= (hashv >> 11); \ + hashv += (hashv << 15); \ } while (0) -#define HASH_JEN_MIX(a, b, c) \ - do \ - { \ - a -= b; \ - a -= c; \ - a ^= (c >> 13); \ - b -= c; \ - b -= a; \ - b ^= (a << 8); \ - c -= a; \ - c -= b; \ - c ^= (b >> 13); \ - a -= b; \ - a -= c; \ - a ^= (c >> 12); \ - b -= c; \ - b -= a; \ - b ^= (a << 16); \ - c -= a; \ - c -= b; \ - c ^= (b >> 5); \ - a -= b; \ - a -= c; \ - a ^= (c >> 3); \ - b -= c; \ - b -= a; \ - b ^= (a << 10); \ - c -= a; \ - c -= b; \ - c ^= (b >> 15); \ +#define HASH_JEN_MIX(a, b, c) \ + do { \ + a -= b; \ + a -= c; \ + a ^= (c >> 13); \ + b -= c; \ + b -= a; \ + b ^= (a << 8); \ + c -= a; \ + c -= b; \ + c ^= (b >> 13); \ + a -= b; \ + a -= c; \ + a ^= (c >> 12); \ + b -= c; \ + b -= a; \ + b ^= (a << 16); \ + c -= a; \ + c -= b; \ + c ^= (b >> 5); \ + a -= b; \ + a -= c; \ + a ^= (c >> 3); \ + b -= c; \ + b -= a; \ + b ^= (a << 10); \ + c -= a; \ + c -= b; \ + c ^= (b >> 15); \ } while (0) -#define HASH_JEN(key, keylen, hashv) \ - do \ - { \ - unsigned _hj_i, _hj_j, _hj_k; \ - unsigned const char *_hj_key = (unsigned const char *)(key); \ - hashv = 0xfeedbeefu; \ - _hj_i = _hj_j = 0x9e3779b9u; \ - _hj_k = (unsigned)(keylen); \ - while (_hj_k >= 12U) \ - { \ - _hj_i += \ - (_hj_key[0] + ((unsigned)_hj_key[1] << 8) + \ - ((unsigned)_hj_key[2] << 16) + ((unsigned)_hj_key[3] << 24)); \ - _hj_j += \ - (_hj_key[4] + ((unsigned)_hj_key[5] << 8) + \ - ((unsigned)_hj_key[6] << 16) + ((unsigned)_hj_key[7] << 24)); \ - hashv += (_hj_key[8] + ((unsigned)_hj_key[9] << 8) + \ - ((unsigned)_hj_key[10] << 16) + \ - ((unsigned)_hj_key[11] << 24)); \ - \ - HASH_JEN_MIX(_hj_i, _hj_j, hashv); \ - \ - _hj_key += 12; \ - _hj_k -= 12U; \ - } \ - hashv += (unsigned)(keylen); \ - switch (_hj_k) \ - { \ - case 11: \ - hashv += ((unsigned)_hj_key[10] << 24); /* FALLTHROUGH */ \ - case 10: \ - hashv += ((unsigned)_hj_key[9] << 16); /* FALLTHROUGH */ \ - case 9: \ - hashv += ((unsigned)_hj_key[8] << 8); /* FALLTHROUGH */ \ - case 8: \ - _hj_j += ((unsigned)_hj_key[7] << 24); /* FALLTHROUGH */ \ - case 7: \ - _hj_j += ((unsigned)_hj_key[6] << 16); /* FALLTHROUGH */ \ - case 6: \ - _hj_j += ((unsigned)_hj_key[5] << 8); /* FALLTHROUGH */ \ - case 5: \ - _hj_j += _hj_key[4]; /* FALLTHROUGH */ \ - case 4: \ - _hj_i += ((unsigned)_hj_key[3] << 24); /* FALLTHROUGH */ \ - case 3: \ - _hj_i += ((unsigned)_hj_key[2] << 16); /* FALLTHROUGH */ \ - case 2: \ - _hj_i += ((unsigned)_hj_key[1] << 8); /* FALLTHROUGH */ \ - case 1: \ - _hj_i += _hj_key[0]; /* FALLTHROUGH */ \ - default:; \ - } \ - HASH_JEN_MIX(_hj_i, _hj_j, hashv); \ +#define HASH_JEN(key, keylen, hashv) \ + do { \ + unsigned _hj_i, _hj_j, _hj_k; \ + unsigned const char *_hj_key = (unsigned const char *)(key); \ + hashv = 0xfeedbeefu; \ + _hj_i = _hj_j = 0x9e3779b9u; \ + _hj_k = (unsigned)(keylen); \ + while (_hj_k >= 12U) { \ + _hj_i += (_hj_key[0] + ((unsigned)_hj_key[1] << 8) + ((unsigned)_hj_key[2] << 16) + \ + ((unsigned)_hj_key[3] << 24)); \ + _hj_j += (_hj_key[4] + ((unsigned)_hj_key[5] << 8) + ((unsigned)_hj_key[6] << 16) + \ + ((unsigned)_hj_key[7] << 24)); \ + hashv += (_hj_key[8] + ((unsigned)_hj_key[9] << 8) + ((unsigned)_hj_key[10] << 16) + \ + ((unsigned)_hj_key[11] << 24)); \ + \ + HASH_JEN_MIX(_hj_i, _hj_j, hashv); \ + \ + _hj_key += 12; \ + _hj_k -= 12U; \ + } \ + hashv += (unsigned)(keylen); \ + switch (_hj_k) { \ + case 11: \ + hashv += ((unsigned)_hj_key[10] << 24); /* FALLTHROUGH */ \ + case 10: \ + hashv += ((unsigned)_hj_key[9] << 16); /* FALLTHROUGH */ \ + case 9: \ + hashv += ((unsigned)_hj_key[8] << 8); /* FALLTHROUGH */ \ + case 8: \ + _hj_j += ((unsigned)_hj_key[7] << 24); /* FALLTHROUGH */ \ + case 7: \ + _hj_j += ((unsigned)_hj_key[6] << 16); /* FALLTHROUGH */ \ + case 6: \ + _hj_j += ((unsigned)_hj_key[5] << 8); /* FALLTHROUGH */ \ + case 5: \ + _hj_j += _hj_key[4]; /* FALLTHROUGH */ \ + case 4: \ + _hj_i += ((unsigned)_hj_key[3] << 24); /* FALLTHROUGH */ \ + case 3: \ + _hj_i += ((unsigned)_hj_key[2] << 16); /* FALLTHROUGH */ \ + case 2: \ + _hj_i += ((unsigned)_hj_key[1] << 8); /* FALLTHROUGH */ \ + case 1: \ + _hj_i += _hj_key[0]; /* FALLTHROUGH */ \ + default:; \ + } \ + HASH_JEN_MIX(_hj_i, _hj_j, hashv); \ } while (0) /* The Paul Hsieh hash function */ #undef get16bits -#if (defined(__GNUC__) && defined(__i386__)) || defined(__WATCOMC__) || \ - defined(_MSC_VER) || defined(__BORLANDC__) || defined(__TURBOC__) +#if (defined(__GNUC__) && defined(__i386__)) || defined(__WATCOMC__) || defined(_MSC_VER) || defined(__BORLANDC__) || \ + defined(__TURBOC__) #define get16bits(d) (*((const uint16_t *)(d))) #endif #if !defined(get16bits) -#define get16bits(d) \ - ((((uint32_t)(((const uint8_t *)(d))[1])) << 8) + \ - (uint32_t)(((const uint8_t *)(d))[0])) +#define get16bits(d) ((((uint32_t)(((const uint8_t *)(d))[1])) << 8) + (uint32_t)(((const uint8_t *)(d))[0])) #endif -#define HASH_SFH(key, keylen, hashv) \ - do \ - { \ - unsigned const char *_sfh_key = (unsigned const char *)(key); \ - uint32_t _sfh_tmp, _sfh_len = (uint32_t)keylen; \ - \ - unsigned _sfh_rem = _sfh_len & 3U; \ - _sfh_len >>= 2; \ - hashv = 0xcafebabeu; \ - \ - /* Main loop */ \ - for (; _sfh_len > 0U; _sfh_len--) \ - { \ - hashv += get16bits(_sfh_key); \ - _sfh_tmp = ((uint32_t)(get16bits(_sfh_key + 2)) << 11) ^ hashv; \ - hashv = (hashv << 16) ^ _sfh_tmp; \ - _sfh_key += 2U * sizeof(uint16_t); \ - hashv += hashv >> 11; \ - } \ - \ - /* Handle end cases */ \ - switch (_sfh_rem) \ - { \ - case 3: \ - hashv += get16bits(_sfh_key); \ - hashv ^= hashv << 16; \ - hashv ^= (uint32_t)(_sfh_key[sizeof(uint16_t)]) << 18; \ - hashv += hashv >> 11; \ - break; \ - case 2: \ - hashv += get16bits(_sfh_key); \ - hashv ^= hashv << 11; \ - hashv += hashv >> 17; \ - break; \ - case 1: \ - hashv += *_sfh_key; \ - hashv ^= hashv << 10; \ - hashv += hashv >> 1; \ - break; \ - default:; \ - } \ - \ - /* Force "avalanching" of final 127 bits */ \ - hashv ^= hashv << 3; \ - hashv += hashv >> 5; \ - hashv ^= hashv << 4; \ - hashv += hashv >> 17; \ - hashv ^= hashv << 25; \ - hashv += hashv >> 6; \ +#define HASH_SFH(key, keylen, hashv) \ + do { \ + unsigned const char *_sfh_key = (unsigned const char *)(key); \ + uint32_t _sfh_tmp, _sfh_len = (uint32_t)keylen; \ + \ + unsigned _sfh_rem = _sfh_len & 3U; \ + _sfh_len >>= 2; \ + hashv = 0xcafebabeu; \ + \ + /* Main loop */ \ + for (; _sfh_len > 0U; _sfh_len--) { \ + hashv += get16bits(_sfh_key); \ + _sfh_tmp = ((uint32_t)(get16bits(_sfh_key + 2)) << 11) ^ hashv; \ + hashv = (hashv << 16) ^ _sfh_tmp; \ + _sfh_key += 2U * sizeof(uint16_t); \ + hashv += hashv >> 11; \ + } \ + \ + /* Handle end cases */ \ + switch (_sfh_rem) { \ + case 3: \ + hashv += get16bits(_sfh_key); \ + hashv ^= hashv << 16; \ + hashv ^= (uint32_t)(_sfh_key[sizeof(uint16_t)]) << 18; \ + hashv += hashv >> 11; \ + break; \ + case 2: \ + hashv += get16bits(_sfh_key); \ + hashv ^= hashv << 11; \ + hashv += hashv >> 17; \ + break; \ + case 1: \ + hashv += *_sfh_key; \ + hashv ^= hashv << 10; \ + hashv += hashv >> 1; \ + break; \ + default:; \ + } \ + \ + /* Force "avalanching" of final 127 bits */ \ + hashv ^= hashv << 3; \ + hashv += hashv >> 5; \ + hashv ^= hashv << 4; \ + hashv += hashv >> 17; \ + hashv ^= hashv << 25; \ + hashv += hashv >> 6; \ } while (0) /* iterate over items in a known bucket to find desired item */ -#define HASH_FIND_IN_BKT(tbl, hh, head, keyptr, keylen_in, hashval, out) \ - do \ - { \ - if ((head).hh_head != NULL) \ - { \ - DECLTYPE_ASSIGN(out, ELMT_FROM_HH(tbl, (head).hh_head)); \ - } \ - else \ - { \ - (out) = NULL; \ - } \ - while ((out) != NULL) \ - { \ - if ((out)->hh.hashv == (hashval) && \ - (out)->hh.keylen == (keylen_in)) \ - { \ - if (HASH_KEYCMP((out)->hh.key, keyptr, keylen_in) == 0) \ - { \ - break; \ - } \ - } \ - if ((out)->hh.hh_next != NULL) \ - { \ - DECLTYPE_ASSIGN(out, ELMT_FROM_HH(tbl, (out)->hh.hh_next)); \ - } \ - else \ - { \ - (out) = NULL; \ - } \ - } \ +#define HASH_FIND_IN_BKT(tbl, hh, head, keyptr, keylen_in, hashval, out) \ + do { \ + if ((head).hh_head != NULL) { \ + DECLTYPE_ASSIGN(out, ELMT_FROM_HH(tbl, (head).hh_head)); \ + } else { \ + (out) = NULL; \ + } \ + while ((out) != NULL) { \ + if ((out)->hh.hashv == (hashval) && (out)->hh.keylen == (keylen_in)) { \ + if (HASH_KEYCMP((out)->hh.key, keyptr, keylen_in) == 0) { \ + break; \ + } \ + } \ + if ((out)->hh.hh_next != NULL) { \ + DECLTYPE_ASSIGN(out, ELMT_FROM_HH(tbl, (out)->hh.hh_next)); \ + } else { \ + (out) = NULL; \ + } \ + } \ } while (0) /* add an item to a bucket */ -#define HASH_ADD_TO_BKT(head, hh, addhh, oomed) \ - do \ - { \ - UT_hash_bucket *_ha_head = &(head); \ - _ha_head->count++; \ - (addhh)->hh_next = _ha_head->hh_head; \ - (addhh)->hh_prev = NULL; \ - if (_ha_head->hh_head != NULL) \ - { \ - _ha_head->hh_head->hh_prev = (addhh); \ - } \ - _ha_head->hh_head = (addhh); \ - if ((_ha_head->count >= \ - ((_ha_head->expand_mult + 1U) * HASH_BKT_CAPACITY_THRESH)) && \ - !(addhh)->tbl->noexpand) \ - { \ - HASH_EXPAND_BUCKETS(addhh, (addhh)->tbl, oomed); \ - IF_HASH_NONFATAL_OOM(if (oomed) { HASH_DEL_IN_BKT(head, addhh); }) \ - } \ +#define HASH_ADD_TO_BKT(head, hh, addhh, oomed) \ + do { \ + UT_hash_bucket *_ha_head = &(head); \ + _ha_head->count++; \ + (addhh)->hh_next = _ha_head->hh_head; \ + (addhh)->hh_prev = NULL; \ + if (_ha_head->hh_head != NULL) { \ + _ha_head->hh_head->hh_prev = (addhh); \ + } \ + _ha_head->hh_head = (addhh); \ + if ((_ha_head->count >= ((_ha_head->expand_mult + 1U) * HASH_BKT_CAPACITY_THRESH)) && \ + !(addhh)->tbl->noexpand) { \ + HASH_EXPAND_BUCKETS(addhh, (addhh)->tbl, oomed); \ + IF_HASH_NONFATAL_OOM(if (oomed) { HASH_DEL_IN_BKT(head, addhh); }) \ + } \ } while (0) /* remove an item from a given bucket */ -#define HASH_DEL_IN_BKT(head, delhh) \ - do \ - { \ - UT_hash_bucket *_hd_head = &(head); \ - _hd_head->count--; \ - if (_hd_head->hh_head == (delhh)) \ - { \ - _hd_head->hh_head = (delhh)->hh_next; \ - } \ - if ((delhh)->hh_prev) \ - { \ - (delhh)->hh_prev->hh_next = (delhh)->hh_next; \ - } \ - if ((delhh)->hh_next) \ - { \ - (delhh)->hh_next->hh_prev = (delhh)->hh_prev; \ - } \ +#define HASH_DEL_IN_BKT(head, delhh) \ + do { \ + UT_hash_bucket *_hd_head = &(head); \ + _hd_head->count--; \ + if (_hd_head->hh_head == (delhh)) { \ + _hd_head->hh_head = (delhh)->hh_next; \ + } \ + if ((delhh)->hh_prev) { \ + (delhh)->hh_prev->hh_next = (delhh)->hh_next; \ + } \ + if ((delhh)->hh_next) { \ + (delhh)->hh_next->hh_prev = (delhh)->hh_prev; \ + } \ } while (0) /* Bucket expansion has the effect of doubling the number of buckets @@ -1033,199 +850,132 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ceil(n/b) = (n>>lb) + ( (n & (b-1)) ? 1:0) * */ -#define HASH_EXPAND_BUCKETS(hh, tbl, oomed) \ - do \ - { \ - unsigned _he_bkt; \ - unsigned _he_bkt_i; \ - struct UT_hash_handle *_he_thh, *_he_hh_nxt; \ - UT_hash_bucket *_he_new_buckets, *_he_newbkt; \ - _he_new_buckets = (UT_hash_bucket *)uthash_malloc( \ - sizeof(struct UT_hash_bucket) * (tbl)->num_buckets * 2U); \ - if (!_he_new_buckets) \ - { \ - HASH_RECORD_OOM(oomed); \ - } \ - else \ - { \ - uthash_bzero(_he_new_buckets, sizeof(struct UT_hash_bucket) * \ - (tbl)->num_buckets * 2U); \ - (tbl)->ideal_chain_maxlen = \ - ((tbl)->num_items >> ((tbl)->log2_num_buckets + 1U)) + \ - ((((tbl)->num_items & (((tbl)->num_buckets * 2U) - 1U)) != 0U) \ - ? 1U \ - : 0U); \ - (tbl)->nonideal_items = 0; \ - for (_he_bkt_i = 0; _he_bkt_i < (tbl)->num_buckets; _he_bkt_i++) \ - { \ - _he_thh = (tbl)->buckets[_he_bkt_i].hh_head; \ - while (_he_thh != NULL) \ - { \ - _he_hh_nxt = _he_thh->hh_next; \ - HASH_TO_BKT(_he_thh->hashv, (tbl)->num_buckets * 2U, \ - _he_bkt); \ - _he_newbkt = &(_he_new_buckets[_he_bkt]); \ - if (++(_he_newbkt->count) > (tbl)->ideal_chain_maxlen) \ - { \ - (tbl)->nonideal_items++; \ - if (_he_newbkt->count > _he_newbkt->expand_mult * \ - (tbl)->ideal_chain_maxlen) \ - { \ - _he_newbkt->expand_mult++; \ - } \ - } \ - _he_thh->hh_prev = NULL; \ - _he_thh->hh_next = _he_newbkt->hh_head; \ - if (_he_newbkt->hh_head != NULL) \ - { \ - _he_newbkt->hh_head->hh_prev = _he_thh; \ - } \ - _he_newbkt->hh_head = _he_thh; \ - _he_thh = _he_hh_nxt; \ - } \ - } \ - uthash_free((tbl)->buckets, \ - (tbl)->num_buckets * sizeof(struct UT_hash_bucket)); \ - (tbl)->num_buckets *= 2U; \ - (tbl)->log2_num_buckets++; \ - (tbl)->buckets = _he_new_buckets; \ - (tbl)->ineff_expands = \ - ((tbl)->nonideal_items > ((tbl)->num_items >> 1)) \ - ? ((tbl)->ineff_expands + 1U) \ - : 0U; \ - if ((tbl)->ineff_expands > 1U) \ - { \ - (tbl)->noexpand = 1; \ - uthash_noexpand_fyi(tbl); \ - } \ - uthash_expand_fyi(tbl); \ - } \ +#define HASH_EXPAND_BUCKETS(hh, tbl, oomed) \ + do { \ + unsigned _he_bkt; \ + unsigned _he_bkt_i; \ + struct UT_hash_handle *_he_thh, *_he_hh_nxt; \ + UT_hash_bucket *_he_new_buckets, *_he_newbkt; \ + _he_new_buckets = (UT_hash_bucket *)uthash_malloc(sizeof(struct UT_hash_bucket) * (tbl)->num_buckets * 2U); \ + if (!_he_new_buckets) { \ + HASH_RECORD_OOM(oomed); \ + } else { \ + uthash_bzero(_he_new_buckets, sizeof(struct UT_hash_bucket) * (tbl)->num_buckets * 2U); \ + (tbl)->ideal_chain_maxlen = ((tbl)->num_items >> ((tbl)->log2_num_buckets + 1U)) + \ + ((((tbl)->num_items & (((tbl)->num_buckets * 2U) - 1U)) != 0U) ? 1U : 0U); \ + (tbl)->nonideal_items = 0; \ + for (_he_bkt_i = 0; _he_bkt_i < (tbl)->num_buckets; _he_bkt_i++) { \ + _he_thh = (tbl)->buckets[_he_bkt_i].hh_head; \ + while (_he_thh != NULL) { \ + _he_hh_nxt = _he_thh->hh_next; \ + HASH_TO_BKT(_he_thh->hashv, (tbl)->num_buckets * 2U, _he_bkt); \ + _he_newbkt = &(_he_new_buckets[_he_bkt]); \ + if (++(_he_newbkt->count) > (tbl)->ideal_chain_maxlen) { \ + (tbl)->nonideal_items++; \ + if (_he_newbkt->count > _he_newbkt->expand_mult * (tbl)->ideal_chain_maxlen) { \ + _he_newbkt->expand_mult++; \ + } \ + } \ + _he_thh->hh_prev = NULL; \ + _he_thh->hh_next = _he_newbkt->hh_head; \ + if (_he_newbkt->hh_head != NULL) { \ + _he_newbkt->hh_head->hh_prev = _he_thh; \ + } \ + _he_newbkt->hh_head = _he_thh; \ + _he_thh = _he_hh_nxt; \ + } \ + } \ + uthash_free((tbl)->buckets, (tbl)->num_buckets * sizeof(struct UT_hash_bucket)); \ + (tbl)->num_buckets *= 2U; \ + (tbl)->log2_num_buckets++; \ + (tbl)->buckets = _he_new_buckets; \ + (tbl)->ineff_expands = ((tbl)->nonideal_items > ((tbl)->num_items >> 1)) ? ((tbl)->ineff_expands + 1U) : \ + 0U; \ + if ((tbl)->ineff_expands > 1U) { \ + (tbl)->noexpand = 1; \ + uthash_noexpand_fyi(tbl); \ + } \ + uthash_expand_fyi(tbl); \ + } \ } while (0) /* This is an adaptation of Simon Tatham's O(n log(n)) mergesort */ /* Note that HASH_SORT assumes the hash handle name to be hh. * HASH_SRT was added to allow the hash handle name to be passed in. */ #define HASH_SORT(head, cmpfcn) HASH_SRT(hh, head, cmpfcn) -#define HASH_SRT(hh, head, cmpfcn) \ - do \ - { \ - unsigned _hs_i; \ - unsigned _hs_looping, _hs_nmerges, _hs_insize, _hs_psize, _hs_qsize; \ - struct UT_hash_handle *_hs_p, *_hs_q, *_hs_e, *_hs_list, *_hs_tail; \ - if (head != NULL) \ - { \ - _hs_insize = 1; \ - _hs_looping = 1; \ - _hs_list = &((head)->hh); \ - while (_hs_looping != 0U) \ - { \ - _hs_p = _hs_list; \ - _hs_list = NULL; \ - _hs_tail = NULL; \ - _hs_nmerges = 0; \ - while (_hs_p != NULL) \ - { \ - _hs_nmerges++; \ - _hs_q = _hs_p; \ - _hs_psize = 0; \ - for (_hs_i = 0; _hs_i < _hs_insize; ++_hs_i) \ - { \ - _hs_psize++; \ - _hs_q = \ - ((_hs_q->next != NULL) \ - ? HH_FROM_ELMT((head)->hh.tbl, _hs_q->next) \ - : NULL); \ - if (_hs_q == NULL) \ - { \ - break; \ - } \ - } \ - _hs_qsize = _hs_insize; \ - while ((_hs_psize != 0U) || \ - ((_hs_qsize != 0U) && (_hs_q != NULL))) \ - { \ - if (_hs_psize == 0U) \ - { \ - _hs_e = _hs_q; \ - _hs_q = ((_hs_q->next != NULL) \ - ? HH_FROM_ELMT((head)->hh.tbl, \ - _hs_q->next) \ - : NULL); \ - _hs_qsize--; \ - } \ - else if ((_hs_qsize == 0U) || (_hs_q == NULL)) \ - { \ - _hs_e = _hs_p; \ - if (_hs_p != NULL) \ - { \ - _hs_p = ((_hs_p->next != NULL) \ - ? HH_FROM_ELMT((head)->hh.tbl, \ - _hs_p->next) \ - : NULL); \ - } \ - _hs_psize--; \ - } \ - else if ((cmpfcn(DECLTYPE(head)(ELMT_FROM_HH( \ - (head)->hh.tbl, _hs_p)), \ - DECLTYPE(head)(ELMT_FROM_HH( \ - (head)->hh.tbl, _hs_q)))) <= 0) \ - { \ - _hs_e = _hs_p; \ - if (_hs_p != NULL) \ - { \ - _hs_p = ((_hs_p->next != NULL) \ - ? HH_FROM_ELMT((head)->hh.tbl, \ - _hs_p->next) \ - : NULL); \ - } \ - _hs_psize--; \ - } \ - else \ - { \ - _hs_e = _hs_q; \ - _hs_q = ((_hs_q->next != NULL) \ - ? HH_FROM_ELMT((head)->hh.tbl, \ - _hs_q->next) \ - : NULL); \ - _hs_qsize--; \ - } \ - if (_hs_tail != NULL) \ - { \ - _hs_tail->next = \ - ((_hs_e != NULL) \ - ? ELMT_FROM_HH((head)->hh.tbl, _hs_e) \ - : NULL); \ - } \ - else \ - { \ - _hs_list = _hs_e; \ - } \ - if (_hs_e != NULL) \ - { \ - _hs_e->prev = \ - ((_hs_tail != NULL) \ - ? ELMT_FROM_HH((head)->hh.tbl, _hs_tail) \ - : NULL); \ - } \ - _hs_tail = _hs_e; \ - } \ - _hs_p = _hs_q; \ - } \ - if (_hs_tail != NULL) \ - { \ - _hs_tail->next = NULL; \ - } \ - if (_hs_nmerges <= 1U) \ - { \ - _hs_looping = 0; \ - (head)->hh.tbl->tail = _hs_tail; \ - DECLTYPE_ASSIGN(head, \ - ELMT_FROM_HH((head)->hh.tbl, _hs_list)); \ - } \ - _hs_insize *= 2U; \ - } \ - HASH_FSCK(hh, head, "HASH_SRT"); \ - } \ +#define HASH_SRT(hh, head, cmpfcn) \ + do { \ + unsigned _hs_i; \ + unsigned _hs_looping, _hs_nmerges, _hs_insize, _hs_psize, _hs_qsize; \ + struct UT_hash_handle *_hs_p, *_hs_q, *_hs_e, *_hs_list, *_hs_tail; \ + if (head != NULL) { \ + _hs_insize = 1; \ + _hs_looping = 1; \ + _hs_list = &((head)->hh); \ + while (_hs_looping != 0U) { \ + _hs_p = _hs_list; \ + _hs_list = NULL; \ + _hs_tail = NULL; \ + _hs_nmerges = 0; \ + while (_hs_p != NULL) { \ + _hs_nmerges++; \ + _hs_q = _hs_p; \ + _hs_psize = 0; \ + for (_hs_i = 0; _hs_i < _hs_insize; ++_hs_i) { \ + _hs_psize++; \ + _hs_q = ((_hs_q->next != NULL) ? HH_FROM_ELMT((head)->hh.tbl, _hs_q->next) : NULL); \ + if (_hs_q == NULL) { \ + break; \ + } \ + } \ + _hs_qsize = _hs_insize; \ + while ((_hs_psize != 0U) || ((_hs_qsize != 0U) && (_hs_q != NULL))) { \ + if (_hs_psize == 0U) { \ + _hs_e = _hs_q; \ + _hs_q = ((_hs_q->next != NULL) ? HH_FROM_ELMT((head)->hh.tbl, _hs_q->next) : NULL); \ + _hs_qsize--; \ + } else if ((_hs_qsize == 0U) || (_hs_q == NULL)) { \ + _hs_e = _hs_p; \ + if (_hs_p != NULL) { \ + _hs_p = ((_hs_p->next != NULL) ? HH_FROM_ELMT((head)->hh.tbl, _hs_p->next) : NULL); \ + } \ + _hs_psize--; \ + } else if ((cmpfcn(DECLTYPE(head)(ELMT_FROM_HH((head)->hh.tbl, _hs_p)), \ + DECLTYPE(head)(ELMT_FROM_HH((head)->hh.tbl, _hs_q)))) <= 0) { \ + _hs_e = _hs_p; \ + if (_hs_p != NULL) { \ + _hs_p = ((_hs_p->next != NULL) ? HH_FROM_ELMT((head)->hh.tbl, _hs_p->next) : NULL); \ + } \ + _hs_psize--; \ + } else { \ + _hs_e = _hs_q; \ + _hs_q = ((_hs_q->next != NULL) ? HH_FROM_ELMT((head)->hh.tbl, _hs_q->next) : NULL); \ + _hs_qsize--; \ + } \ + if (_hs_tail != NULL) { \ + _hs_tail->next = ((_hs_e != NULL) ? ELMT_FROM_HH((head)->hh.tbl, _hs_e) : NULL); \ + } else { \ + _hs_list = _hs_e; \ + } \ + if (_hs_e != NULL) { \ + _hs_e->prev = ((_hs_tail != NULL) ? ELMT_FROM_HH((head)->hh.tbl, _hs_tail) : NULL); \ + } \ + _hs_tail = _hs_e; \ + } \ + _hs_p = _hs_q; \ + } \ + if (_hs_tail != NULL) { \ + _hs_tail->next = NULL; \ + } \ + if (_hs_nmerges <= 1U) { \ + _hs_looping = 0; \ + (head)->hh.tbl->tail = _hs_tail; \ + DECLTYPE_ASSIGN(head, ELMT_FROM_HH((head)->hh.tbl, _hs_list)); \ + } \ + _hs_insize *= 2U; \ + } \ + HASH_FSCK(hh, head, "HASH_SRT"); \ + } \ } while (0) /* This function selects items from one hash into another hash. @@ -1233,116 +983,90 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * in both hashes. There is no copy of the items made; rather * they are added into the new hash through a secondary hash * hash handle that must be present in the structure. */ -#define HASH_SELECT(hh_dst, dst, hh_src, src, cond) \ - do \ - { \ - unsigned _src_bkt, _dst_bkt; \ - void *_last_elt = NULL, *_elt; \ - UT_hash_handle *_src_hh, *_dst_hh, *_last_elt_hh = NULL; \ - ptrdiff_t _dst_hho = ((char *)(&(dst)->hh_dst) - (char *)(dst)); \ - if ((src) != NULL) \ - { \ - for (_src_bkt = 0; _src_bkt < (src)->hh_src.tbl->num_buckets; \ - _src_bkt++) \ - { \ - for (_src_hh = (src)->hh_src.tbl->buckets[_src_bkt].hh_head; \ - _src_hh != NULL; _src_hh = _src_hh->hh_next) \ - { \ - _elt = ELMT_FROM_HH((src)->hh_src.tbl, _src_hh); \ - if (cond(_elt)) \ - { \ - IF_HASH_NONFATAL_OOM(int _hs_oomed = 0;) \ - _dst_hh = (UT_hash_handle *)(void *)(((char *)_elt) + \ - _dst_hho); \ - _dst_hh->key = _src_hh->key; \ - _dst_hh->keylen = _src_hh->keylen; \ - _dst_hh->hashv = _src_hh->hashv; \ - _dst_hh->prev = _last_elt; \ - _dst_hh->next = NULL; \ - if (_last_elt_hh != NULL) \ - { \ - _last_elt_hh->next = _elt; \ - } \ - if ((dst) == NULL) \ - { \ - DECLTYPE_ASSIGN(dst, _elt); \ - HASH_MAKE_TABLE(hh_dst, dst, _hs_oomed); \ - IF_HASH_NONFATAL_OOM(if (_hs_oomed) { \ - uthash_nonfatal_oom(_elt); \ - (dst) = NULL; \ - continue; \ - }) \ - } \ - else \ - { \ - _dst_hh->tbl = (dst)->hh_dst.tbl; \ - } \ - HASH_TO_BKT(_dst_hh->hashv, _dst_hh->tbl->num_buckets, \ - _dst_bkt); \ - HASH_ADD_TO_BKT(_dst_hh->tbl->buckets[_dst_bkt], \ - hh_dst, _dst_hh, _hs_oomed); \ - (dst)->hh_dst.tbl->num_items++; \ - IF_HASH_NONFATAL_OOM(if (_hs_oomed) { \ - HASH_ROLLBACK_BKT(hh_dst, dst, _dst_hh); \ - HASH_DELETE_HH(hh_dst, dst, _dst_hh); \ - _dst_hh->tbl = NULL; \ - uthash_nonfatal_oom(_elt); \ - continue; \ - }) \ - HASH_BLOOM_ADD(_dst_hh->tbl, _dst_hh->hashv); \ - _last_elt = _elt; \ - _last_elt_hh = _dst_hh; \ - } \ - } \ - } \ - } \ - HASH_FSCK(hh_dst, dst, "HASH_SELECT"); \ +#define HASH_SELECT(hh_dst, dst, hh_src, src, cond) \ + do { \ + unsigned _src_bkt, _dst_bkt; \ + void *_last_elt = NULL, *_elt; \ + UT_hash_handle *_src_hh, *_dst_hh, *_last_elt_hh = NULL; \ + ptrdiff_t _dst_hho = ((char *)(&(dst)->hh_dst) - (char *)(dst)); \ + if ((src) != NULL) { \ + for (_src_bkt = 0; _src_bkt < (src)->hh_src.tbl->num_buckets; _src_bkt++) { \ + for (_src_hh = (src)->hh_src.tbl->buckets[_src_bkt].hh_head; _src_hh != NULL; \ + _src_hh = _src_hh->hh_next) { \ + _elt = ELMT_FROM_HH((src)->hh_src.tbl, _src_hh); \ + if (cond(_elt)) { \ + IF_HASH_NONFATAL_OOM(int _hs_oomed = 0;) \ + _dst_hh = (UT_hash_handle *)(void *)(((char *)_elt) + _dst_hho); \ + _dst_hh->key = _src_hh->key; \ + _dst_hh->keylen = _src_hh->keylen; \ + _dst_hh->hashv = _src_hh->hashv; \ + _dst_hh->prev = _last_elt; \ + _dst_hh->next = NULL; \ + if (_last_elt_hh != NULL) { \ + _last_elt_hh->next = _elt; \ + } \ + if ((dst) == NULL) { \ + DECLTYPE_ASSIGN(dst, _elt); \ + HASH_MAKE_TABLE(hh_dst, dst, _hs_oomed); \ + IF_HASH_NONFATAL_OOM(if (_hs_oomed) { \ + uthash_nonfatal_oom(_elt); \ + (dst) = NULL; \ + continue; \ + }) \ + } else { \ + _dst_hh->tbl = (dst)->hh_dst.tbl; \ + } \ + HASH_TO_BKT(_dst_hh->hashv, _dst_hh->tbl->num_buckets, _dst_bkt); \ + HASH_ADD_TO_BKT(_dst_hh->tbl->buckets[_dst_bkt], hh_dst, _dst_hh, _hs_oomed); \ + (dst)->hh_dst.tbl->num_items++; \ + IF_HASH_NONFATAL_OOM(if (_hs_oomed) { \ + HASH_ROLLBACK_BKT(hh_dst, dst, _dst_hh); \ + HASH_DELETE_HH(hh_dst, dst, _dst_hh); \ + _dst_hh->tbl = NULL; \ + uthash_nonfatal_oom(_elt); \ + continue; \ + }) \ + HASH_BLOOM_ADD(_dst_hh->tbl, _dst_hh->hashv); \ + _last_elt = _elt; \ + _last_elt_hh = _dst_hh; \ + } \ + } \ + } \ + } \ + HASH_FSCK(hh_dst, dst, "HASH_SELECT"); \ } while (0) -#define HASH_CLEAR(hh, head) \ - do \ - { \ - if ((head) != NULL) \ - { \ - HASH_BLOOM_FREE((head)->hh.tbl); \ - uthash_free((head)->hh.tbl->buckets, \ - (head)->hh.tbl->num_buckets * \ - sizeof(struct UT_hash_bucket)); \ - uthash_free((head)->hh.tbl, sizeof(UT_hash_table)); \ - (head) = NULL; \ - } \ +#define HASH_CLEAR(hh, head) \ + do { \ + if ((head) != NULL) { \ + HASH_BLOOM_FREE((head)->hh.tbl); \ + uthash_free((head)->hh.tbl->buckets, (head)->hh.tbl->num_buckets * sizeof(struct UT_hash_bucket)); \ + uthash_free((head)->hh.tbl, sizeof(UT_hash_table)); \ + (head) = NULL; \ + } \ } while (0) -#define HASH_OVERHEAD(hh, head) \ - (((head) != NULL) \ - ? ((size_t)(((head)->hh.tbl->num_items * sizeof(UT_hash_handle)) + \ - ((head)->hh.tbl->num_buckets * sizeof(UT_hash_bucket)) + \ - sizeof(UT_hash_table) + (HASH_BLOOM_BYTELEN))) \ - : 0U) +#define HASH_OVERHEAD(hh, head) \ + (((head) != NULL) ? ((size_t)(((head)->hh.tbl->num_items * sizeof(UT_hash_handle)) + \ + ((head)->hh.tbl->num_buckets * sizeof(UT_hash_bucket)) + sizeof(UT_hash_table) + \ + (HASH_BLOOM_BYTELEN))) : \ + 0U) #ifdef NO_DECLTYPE -#define HASH_ITER(hh, head, el, tmp) \ - for (((el) = (head)), \ - ((*(char **)(&(tmp))) = \ - (char *)((head != NULL) ? (head)->hh.next : NULL)); \ - (el) != NULL; ((el) = (tmp)), \ - ((*(char **)(&(tmp))) = \ - (char *)((tmp != NULL) ? (tmp)->hh.next : NULL))) +#define HASH_ITER(hh, head, el, tmp) \ + for (((el) = (head)), ((*(char **)(&(tmp))) = (char *)((head != NULL) ? (head)->hh.next : NULL)); (el) != NULL; \ + ((el) = (tmp)), ((*(char **)(&(tmp))) = (char *)((tmp != NULL) ? (tmp)->hh.next : NULL))) #else -#define HASH_ITER(hh, head, el, tmp) \ - for (((el) = (head)), \ - ((tmp) = DECLTYPE(el)((head != NULL) ? (head)->hh.next : NULL)); \ - (el) != NULL; \ - ((el) = (tmp)), \ - ((tmp) = DECLTYPE(el)((tmp != NULL) ? (tmp)->hh.next : NULL))) +#define HASH_ITER(hh, head, el, tmp) \ + for (((el) = (head)), ((tmp) = DECLTYPE(el)((head != NULL) ? (head)->hh.next : NULL)); (el) != NULL; \ + ((el) = (tmp)), ((tmp) = DECLTYPE(el)((tmp != NULL) ? (tmp)->hh.next : NULL))) #endif /* obtain a count of items in the hash */ #define HASH_COUNT(head) HASH_CNT(hh, head) #define HASH_CNT(hh, head) ((head != NULL) ? ((head)->hh.tbl->num_items) : 0U) -typedef struct UT_hash_bucket -{ +typedef struct UT_hash_bucket { struct UT_hash_handle *hh_head; unsigned count; @@ -1366,8 +1090,7 @@ typedef struct UT_hash_bucket #define HASH_SIGNATURE 0xa0111fe1u #define HASH_BLOOM_SIGNATURE 0xb12220f2u -typedef struct UT_hash_table -{ +typedef struct UT_hash_table { UT_hash_bucket *buckets; unsigned num_buckets, log2_num_buckets; unsigned num_items; @@ -1394,24 +1117,22 @@ typedef struct UT_hash_table uint32_t signature; /* used only to find hash tables in external analysis */ #ifdef HASH_BLOOM - uint32_t - bloom_sig; /* used only to test bloom exists in external analysis */ + uint32_t bloom_sig; /* used only to test bloom exists in external analysis */ uint8_t *bloom_bv; uint8_t bloom_nbits; #endif } UT_hash_table; -typedef struct UT_hash_handle -{ +typedef struct UT_hash_handle { struct UT_hash_table *tbl; - void *prev; /* prev element in app order */ - void *next; /* next element in app order */ + void *prev; /* prev element in app order */ + void *next; /* next element in app order */ struct UT_hash_handle *hh_prev; /* previous hh in bucket order */ struct UT_hash_handle *hh_next; /* next hh in bucket order */ - const void *key; /* ptr to enclosing struct's key */ - unsigned keylen; /* enclosing struct's key len */ - unsigned hashv; /* result of hash-fcn(key) */ + const void *key; /* ptr to enclosing struct's key */ + unsigned keylen; /* enclosing struct's key len */ + unsigned hashv; /* result of hash-fcn(key) */ } UT_hash_handle; #endif /* UTHASH_H */ \ No newline at end of file -- Gitee