Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 533145c

Browse files
committed
[libc] Support 'assert.h' on the GPU
This patch adds the necessary support to provide `assert` functionality through the GPU `libc` implementation. This implementation creates a special-case GPU implementation rather than relying on the common version. This is because the GPU has special considerings for printing. The assertion is printed out in chunks with `write_to_stderr`, however when combined with the GPU execution model this causes 32+ threads to all execute in-lock step. Meaning that we'll get a horribly fragmented message. Furthermore, potentially thousands of threads could hit the assertion at once and try to print even if we had it all in one `printf`. This is solved by having a one-time lock that each thread group / wave / warp will attempt to claim. We only let one thread group pass through while the others simply stop executing. Finally only the first thread in that group will do the printing until we finally abort execution. Reviewed By: sivachandra Differential Revision: https://reviews.llvm.org/D159296
1 parent 4294bca commit 533145c

12 files changed

Lines changed: 149 additions & 21 deletions

File tree

libc/config/gpu/api.td

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,38 @@ include "config/public_api.td"
33
include "spec/stdc.td"
44
include "spec/posix.td"
55
include "spec/gpu_ext.td"
6+
include "spec/gnu_ext.td"
7+
include "spec/llvm_libc_ext.td"
8+
9+
def AssertMacro : MacroDef<"assert"> {
10+
let Defn = [{
11+
#undef assert
12+
13+
#ifdef NDEBUG
14+
#define assert(e) (void)0
15+
#else
16+
17+
#define assert(e) \
18+
((e) ? (void)0 : __assert_fail(#e, __FILE__, __LINE__, __PRETTY_FUNCTION__))
19+
#endif
20+
}];
21+
}
22+
23+
def StaticAssertMacro : MacroDef<"static_assert"> {
24+
let Defn = [{
25+
#ifndef __cplusplus
26+
#undef static_assert
27+
#define static_assert _Static_assert
28+
#endif
29+
}];
30+
}
31+
32+
def AssertAPI : PublicAPI<"assert.h"> {
33+
let Macros = [
34+
AssertMacro,
35+
StaticAssertMacro,
36+
];
37+
}
638

739
def StringAPI : PublicAPI<"string.h"> {
840
let Types = ["size_t"];

libc/config/gpu/entrypoints.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
set(TARGET_LIBC_ENTRYPOINTS
2+
# assert.h entrypoints
3+
libc.src.assert.__assert_fail
4+
25
# ctype.h entrypoints
36
libc.src.ctype.isalnum
47
libc.src.ctype.isalpha

libc/config/gpu/headers.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
set(TARGET_PUBLIC_HEADERS
2+
libc.include.assert
23
libc.include.ctype
34
libc.include.string
45
libc.include.inttypes

libc/docs/gpu/support.rst

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ fopen |check| |check|
130130
fread |check| |check|
131131
============= ========= ============
132132

133-
stdio.h
133+
time.h
134134
--------
135135

136136
============= ========= ============
@@ -139,3 +139,13 @@ Function Name Available RPC Required
139139
clock |check|
140140
nanosleep |check|
141141
============= ========= ============
142+
143+
assert.h
144+
--------
145+
146+
============= ========= ============
147+
Function Name Available RPC Required
148+
============= ========= ============
149+
assert |check| |check|
150+
__assert_fail |check| |check|
151+
============= ========= ============

libc/src/__support/GPU/utils.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,19 @@
1919
#include "generic/utils.h"
2020
#endif
2121

22+
namespace __llvm_libc {
23+
namespace gpu {
24+
/// Get the first active thread inside the lane.
25+
LIBC_INLINE uint64_t get_first_lane_id(uint64_t lane_mask) {
26+
return __builtin_ffsl(lane_mask) - 1;
27+
}
28+
29+
/// Conditional that is only true for a single thread in a lane.
30+
LIBC_INLINE bool is_first_lane(uint64_t lane_mask) {
31+
return gpu::get_lane_id() == get_first_lane_id(lane_mask);
32+
}
33+
34+
} // namespace gpu
35+
} // namespace __llvm_libc
36+
2237
#endif // LLVM_LIBC_SRC_SUPPORT_OSUTIL_IO_H

libc/src/__support/RPC/rpc.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,7 @@ template <bool Invert, typename Packet> struct Process {
214214
// restrict to a single thread to avoid one thread dropping the lock, then
215215
// an unrelated warp claiming the lock, then a second thread in this warp
216216
// dropping the lock again.
217-
clear_nth(lock, index, rpc::is_first_lane(lane_mask));
217+
clear_nth(lock, index, gpu::is_first_lane(lane_mask));
218218
gpu::sync_lane(lane_mask);
219219
}
220220

@@ -546,7 +546,7 @@ template <uint16_t opcode> LIBC_INLINE Client::Port Client::open() {
546546
continue;
547547
}
548548

549-
if (is_first_lane(lane_mask)) {
549+
if (gpu::is_first_lane(lane_mask)) {
550550
process.packet[index].header.opcode = opcode;
551551
process.packet[index].header.mask = lane_mask;
552552
}

libc/src/__support/RPC/rpc_util.h

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -30,16 +30,6 @@ LIBC_INLINE void sleep_briefly() {
3030
#endif
3131
}
3232

33-
/// Get the first active thread inside the lane.
34-
LIBC_INLINE uint64_t get_first_lane_id(uint64_t lane_mask) {
35-
return __builtin_ffsl(lane_mask) - 1;
36-
}
37-
38-
/// Conditional that is only true for a single thread in a lane.
39-
LIBC_INLINE bool is_first_lane(uint64_t lane_mask) {
40-
return gpu::get_lane_id() == get_first_lane_id(lane_mask);
41-
}
42-
4333
/// Conditional to indicate if this process is running on the GPU.
4434
LIBC_INLINE constexpr bool is_process_gpu() {
4535
#if defined(LIBC_TARGET_ARCH_IS_GPU)

libc/src/assert/CMakeLists.txt

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,18 @@
1+
if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${LIBC_TARGET_OS})
2+
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/${LIBC_TARGET_OS})
3+
else()
4+
add_subdirectory(generic)
5+
endif()
6+
7+
if(TARGET libc.src.assert.${LIBC_TARGET_OS}.__assert_fail)
8+
set(assert_fail_dep libc.src.assert.${LIBC_TARGET_OS}.__assert_fail)
9+
else()
10+
set(assert_fail_dep libc.src.assert.generic.__assert_fail)
11+
endif()
12+
113
add_entrypoint_object(
214
__assert_fail
3-
SRCS
4-
__assert_fail.cpp
5-
HDRS
6-
__assert_fail.h
7-
assert.h
15+
ALIAS
816
DEPENDS
9-
libc.include.assert
10-
libc.src.__support.OSUtil.osutil
11-
libc.src.stdlib.abort
17+
${assert_fail_dep}
1218
)
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
add_entrypoint_object(
2+
__assert_fail
3+
SRCS
4+
__assert_fail.cpp
5+
HDRS
6+
../__assert_fail.h
7+
../assert.h
8+
DEPENDS
9+
libc.include.assert
10+
libc.src.__support.OSUtil.osutil
11+
libc.src.stdlib.abort
12+
)

0 commit comments

Comments
 (0)