[llvm-branch-commits] [compiler-rt] [compiler-rt] Add more common HSA utilities for memory and symbolization (PR #228297)

via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Thu Oct 1 18:12:54 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-compiler-rt-sanitizer

Author: Joseph Huber (jhuber6)

<details>
<summary>Changes</summary>

Summary:
Adds memory pool management for different kinds of allocation. Intended
to be used for the in-progress concurrency sanitizer.

RFC: discourse.llvm.org/t/rfc-a-thread-concurrency-sanitizer-for-gpus-in-compiler-rt/91113

---

<sub>Stack created with <a href="https://github.com/github/gh-stack">GitHub Stacks CLI</a> • <a href="https://gh.io/stacks-feedback">Give Feedback 💬</a></sub>

---
Full diff: https://github.com/llvm/llvm-project/pull/228297.diff


6 Files Affected:

- (modified) compiler-rt/lib/sanitizer_common/sanitizer_offload.cpp (+46-3) 
- (modified) compiler-rt/lib/sanitizer_common/sanitizer_offload.h (+3) 
- (modified) compiler-rt/lib/sanitizer_common/sanitizer_offload_hsa.h (+2) 
- (modified) compiler-rt/lib/sanitizer_common/sanitizer_offload_image.cpp (+21) 
- (modified) compiler-rt/lib/sanitizer_common/sanitizer_symbolizer.h (+4) 
- (modified) compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_libcdep.cpp (+15) 


``````````diff
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_offload.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_offload.cpp
index 57255546ea888..adb515e38b848 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_offload.cpp
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_offload.cpp
@@ -102,7 +102,7 @@ bool Offload::Discover() {
                                   Out) == HSA_STATUS_SUCCESS;
   };
   auto Pool = [&](hsa_agent_t Agent) {
-    hsa_amd_memory_pool_t Found{};
+    hsa_amd_memory_pool_t Fine{};
     Iterate<hsa_amd_memory_pool_t>(
         Api.hsa_amd_agent_iterate_memory_pools, Agent,
         [&](hsa_amd_memory_pool_t Mem) {
@@ -118,10 +118,10 @@ bool Offload::Discover() {
               HSA_STATUS_SUCCESS)
             return HSA_STATUS_SUCCESS;
           if (Flags & HSA_AMD_MEMORY_POOL_GLOBAL_FLAG_FINE_GRAINED)
-            Found = Mem;
+            Fine = Mem;
           return HSA_STATUS_SUCCESS;
         });
-    return Found;
+    return Fine;
   };
 
   CheckHsa(Iterate<hsa_agent_t>(Api.hsa_iterate_agents, [&](hsa_agent_t Agent) {
@@ -296,6 +296,49 @@ bool Offload::Alloc(const Device& D, uptr Bytes, void** Out) {
   return true;
 }
 
+bool Offload::GetMemoryPool(hsa_agent_t Agent, hsa_amd_memory_pool_t* Pool) {
+  Lock L(&OffloadMtx);
+  if (!Ready() || !Pool)
+    return false;
+  *Pool = {};
+  hsa_status_t Status = Iterate<hsa_amd_memory_pool_t>(
+      Api.hsa_amd_agent_iterate_memory_pools, Agent,
+      [&](hsa_amd_memory_pool_t Mem) {
+        hsa_amd_segment_t Segment;
+        u32 Flags = 0;
+        bool Allowed = false;
+        if (Api.hsa_amd_memory_pool_get_info(Mem,
+                                             HSA_AMD_MEMORY_POOL_INFO_SEGMENT,
+                                             &Segment) != HSA_STATUS_SUCCESS ||
+            Segment != HSA_AMD_SEGMENT_GLOBAL ||
+            Api.hsa_amd_memory_pool_get_info(
+                Mem, HSA_AMD_MEMORY_POOL_INFO_GLOBAL_FLAGS, &Flags) !=
+                HSA_STATUS_SUCCESS ||
+            !(Flags & HSA_AMD_MEMORY_POOL_GLOBAL_FLAG_COARSE_GRAINED) ||
+            Api.hsa_amd_memory_pool_get_info(
+                Mem, HSA_AMD_MEMORY_POOL_INFO_RUNTIME_ALLOC_ALLOWED,
+                &Allowed) != HSA_STATUS_SUCCESS ||
+            !Allowed)
+          return HSA_STATUS_SUCCESS;
+        *Pool = Mem;
+        return HSA_STATUS_SUCCESS;
+      });
+  return Status == HSA_STATUS_SUCCESS && Pool->handle;
+}
+
+bool Offload::Allocate(hsa_amd_memory_pool_t Pool, uptr Bytes, void** Out) {
+  Lock L(&OffloadMtx);
+  if (!Ready() || !Pool.handle || !Bytes || !Out)
+    return false;
+  void* P = nullptr;
+  if (Api.hsa_amd_memory_pool_allocate(Pool, Bytes, 0, &P) !=
+          HSA_STATUS_SUCCESS ||
+      !P)
+    return false;
+  *Out = P;
+  return true;
+}
+
 void Offload::Free(void* P) { Api.hsa_amd_memory_pool_free(P); }
 
 bool Offload::Copy(void* Dst, const void* Src, uptr N) {
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_offload.h b/compiler-rt/lib/sanitizer_common/sanitizer_offload.h
index 4df2a2ca11f05..5a39e4103546c 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_offload.h
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_offload.h
@@ -40,7 +40,10 @@ class Offload {
   void TrackExecutable(hsa_executable_t Exec);
   void UntrackExecutable(hsa_executable_t Exec);
   void UntrackImages();
+  bool GetMemoryPool(hsa_agent_t Agent, hsa_amd_memory_pool_t* Pool);
+  bool Allocate(hsa_amd_memory_pool_t Pool, uptr Bytes, void** Out);
   SymbolizedStack* Symbolize(uptr PC);
+  bool SymbolizeData(uptr Addr, DataInfo* Info);
 
  private:
   friend struct OffloadRpc;
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_offload_hsa.h b/compiler-rt/lib/sanitizer_common/sanitizer_offload_hsa.h
index 2300f9fa2bfab..d2a92832539f2 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_offload_hsa.h
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_offload_hsa.h
@@ -78,10 +78,12 @@ typedef enum { HSA_AMD_SEGMENT_GLOBAL = 0 } hsa_amd_segment_t;
 typedef enum {
   HSA_AMD_MEMORY_POOL_INFO_SEGMENT = 0,
   HSA_AMD_MEMORY_POOL_INFO_GLOBAL_FLAGS = 1,
+  HSA_AMD_MEMORY_POOL_INFO_RUNTIME_ALLOC_ALLOWED = 5,
 } hsa_amd_memory_pool_info_t;
 
 typedef enum {
   HSA_AMD_MEMORY_POOL_GLOBAL_FLAG_FINE_GRAINED = 2,
+  HSA_AMD_MEMORY_POOL_GLOBAL_FLAG_COARSE_GRAINED = 4,
 } hsa_amd_memory_pool_global_flag_t;
 
 typedef enum {
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_offload_image.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_offload_image.cpp
index eb0c5a468c5f2..09c54f7ea5c06 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_offload_image.cpp
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_offload_image.cpp
@@ -145,4 +145,25 @@ SymbolizedStack* Offload::Symbolize(uptr PC) {
   return Frames;
 }
 
+bool Offload::SymbolizeData(uptr Addr, DataInfo* Info) {
+  if (!Addr || !Info)
+    return false;
+
+  char* Path = nullptr;
+  uptr Offset = 0;
+  if (!SnapshotImage(Addr, &Path, &Offset) || !Path)
+    return false;
+
+  bool Symbolized =
+      Symbolizer::GetOrInit()->SymbolizeModuleData(Path, Offset, Info);
+  InternalFree(Path);
+  if (!Symbolized)
+    return false;
+  if (!Info->name || !Info->name[0] || Info->name[0] == '?') {
+    Info->Clear();
+    return false;
+  }
+  return true;
+}
+
 }  // namespace __sanitizer
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer.h b/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer.h
index d2aa2288f483c..d40df017bdda6 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer.h
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer.h
@@ -143,6 +143,10 @@ class Symbolizer final {
   // current executing process, such as an offloading device.
   SymbolizedStack* SymbolizeModuleOffset(const char* module_name,
                                          uptr module_offset);
+  // Like SymbolizeData, but the module is not mapped in this process
+  // (offload device images).
+  bool SymbolizeModuleData(const char* module_name, uptr module_offset,
+                           DataInfo* info);
   bool SymbolizeData(uptr address, DataInfo *info);
   bool SymbolizeFrame(uptr address, FrameInfo *info);
 
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_libcdep.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_libcdep.cpp
index b5a85c05efde7..8ba6a14b420cb 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_libcdep.cpp
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_symbolizer_libcdep.cpp
@@ -114,6 +114,21 @@ SymbolizedStack* Symbolizer::SymbolizeModuleOffset(const char* module_name,
   return res;
 }
 
+bool Symbolizer::SymbolizeModuleData(const char* module_name,
+                                     uptr module_offset, DataInfo* info) {
+  Lock l(&mu_);
+  info->Clear();
+  info->module = internal_strdup(module_name);
+  info->module_offset = module_offset;
+  info->module_arch = kModuleArchUnknown;
+  for (auto& tool : tools_) {
+    SymbolizerScope sym_scope(this);
+    if (tool.SymbolizeData(module_offset, info))
+      return true;
+  }
+  return false;
+}
+
 bool Symbolizer::SymbolizeData(uptr addr, DataInfo *info) {
   Lock l(&mu_);
   const char *module_name = nullptr;

``````````

</details>


https://github.com/llvm/llvm-project/pull/228297


More information about the llvm-branch-commits mailing list