]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - gdb/testsuite/lib/rocm.exp
gdb/testsuite: allow "require" callbacks to provide a reason
[thirdparty/binutils-gdb.git] / gdb / testsuite / lib / rocm.exp
1 # Copyright (C) 2019-2023 Free Software Foundation, Inc.
2 #
3 # This program is free software; you can redistribute it and/or modify
4 # it under the terms of the GNU General Public License as published by
5 # the Free Software Foundation; either version 3 of the License, or
6 # (at your option) any later version.
7 #
8 # This program is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # GNU General Public License for more details.
12 #
13 # You should have received a copy of the GNU General Public License
14 # along with this program. If not, see <http://www.gnu.org/licenses/>.
15 #
16 # Support library for testing ROCm (AMD GPU) GDB features.
17
18 # Get the list of gpu targets to compile for.
19 #
20 # If HCC_AMDGPU_TARGET is set in the environment, use it. Otherwise,
21 # try reading it from the system using the rocm_agent_enumerator
22 # utility.
23
24 proc hcc_amdgpu_targets {} {
25 # Look for HCC_AMDGPU_TARGET (same env var hipcc uses). If
26 # that fails, try using rocm_agent_enumerator (again, same as
27 # hipcc does).
28 if {[info exists ::env(HCC_AMDGPU_TARGET)]} {
29 return [split $::env(HCC_AMDGPU_TARGET) ","]
30 }
31
32 set rocm_agent_enumerator "rocm_agent_enumerator"
33
34 # If available, use ROCM_PATH to locate rocm_agent_enumerator.
35 if { [info exists ::env(ROCM_PATH)] } {
36 set rocm_agent_enumerator \
37 "$::env(ROCM_PATH)/bin/rocm_agent_enumerator"
38 }
39
40 # If we fail to locate the rocm_agent_enumerator, just return an empty
41 # list of targets and let the caller decide if this should be an error.
42 if { [which $rocm_agent_enumerator] == 0 } {
43 return [list]
44 }
45
46 set result [remote_exec host $rocm_agent_enumerator]
47 if { [lindex $result 0] != 0 } {
48 error "rocm_agent_enumerator failed"
49 }
50
51 set targets [list]
52 foreach target [lindex $result 1] {
53 # Ignore gfx000 which is the host CPU.
54 if { $target ne "gfx000" } {
55 lappend targets $target
56 }
57 }
58
59 return $targets
60 }
61
62 gdb_caching_proc allow_hipcc_tests {} {
63 # Only the native target supports ROCm debugging. E.g., when
64 # testing against GDBserver, there's no point in running the ROCm
65 # tests.
66 if {[target_info gdb_protocol] != ""} {
67 return {0 "remote debugging"}
68 }
69
70 # Ensure that GDB is built with amd-dbgapi support.
71 set output [remote_exec host $::GDB "$::INTERNAL_GDBFLAGS --configuration"]
72 if { [string first "--with-amd-dbgapi" $output] == -1 } {
73 return {0 "amd-dbgapi not supported"}
74 }
75
76 # Check we have a working hipcc compiler available.
77 set targets [hcc_amdgpu_targets]
78 if { [llength $targets] == 0} {
79 return {0 "no suitable amdgpu targets found"}
80 }
81
82 set flags [list hip additional_flags=--offload-arch=[join $targets ","]]
83 if {![gdb_simple_compile hipprobe {
84 #include <hip/hip_runtime.h>
85 __global__ void
86 kern () {}
87
88 int
89 main ()
90 {
91 kern<<<1, 1>>> ();
92 hipDeviceSynchronize ();
93 return 0;
94 }
95 } executable $flags]} {
96 return {0 "failed to compile hip program"}
97 }
98
99 return 1
100 }
101
102 # The lock file used to ensure that only one GDB has access to the GPU
103 # at a time.
104 set gpu_lock_filename $objdir/gpu-parallel.lock
105
106 # Acquire lock file LOCKFILE. Tries forever until the lock file is
107 # successfully created.
108
109 proc lock_file_acquire {lockfile} {
110 verbose -log "acquiring lock file: $::subdir/${::gdb_test_file_name}.exp"
111 while {true} {
112 if {![catch {open $lockfile {WRONLY CREAT EXCL}} rc]} {
113 set msg "locked by $::subdir/${::gdb_test_file_name}.exp"
114 verbose -log "lock file: $msg"
115 # For debugging, put info in the lockfile about who owns
116 # it.
117 puts $rc $msg
118 flush $rc
119 return [list $rc $lockfile]
120 }
121 after 10
122 }
123 }
124
125 # Release a lock file.
126
127 proc lock_file_release {info} {
128 verbose -log "releasing lock file: $::subdir/${::gdb_test_file_name}.exp"
129
130 if {![catch {fconfigure [lindex $info 0]}]} {
131 if {![catch {
132 close [lindex $info 0]
133 file delete -force [lindex $info 1]
134 } rc]} {
135 return ""
136 } else {
137 return -code error "Error releasing lockfile: '$rc'"
138 }
139 } else {
140 error "invalid lock"
141 }
142 }
143
144 # Run body under the GPU lock. Also calls gdb_exit before releasing
145 # the GPU lock.
146
147 proc with_rocm_gpu_lock { body } {
148 if {[info exists ::GDB_PARALLEL]} {
149 set lock_rc [lock_file_acquire $::gpu_lock_filename]
150 }
151
152 set code [catch {uplevel 1 $body} result]
153
154 # In case BODY returned early due to some testcase failing, and
155 # left GDB running, debugging the GPU.
156 gdb_exit
157
158 if {[info exists ::GDB_PARALLEL]} {
159 lock_file_release $lock_rc
160 }
161
162 if {$code == 1} {
163 global errorInfo errorCode
164 return -code $code -errorinfo $errorInfo -errorcode $errorCode $result
165 } else {
166 return -code $code $result
167 }
168 }