11
11
#define __has_builtin (x ) 0
12
12
#endif
13
13
14
- // Make sure these are included first so they don't conflict with the system.
15
- #include < limits.h>
16
-
17
14
#include " shared/rpc.h"
18
15
#include " shared/rpc_opcodes.h"
19
16
17
+ #include " src/__support/CPP/type_traits.h"
20
18
#include " src/__support/arg_list.h"
21
19
#include " src/stdio/printf_core/converter.h"
22
20
#include " src/stdio/printf_core/parser.h"
23
21
#include " src/stdio/printf_core/writer.h"
24
22
25
- #include < algorithm>
26
- #include < atomic>
27
- #include < cstdio>
28
- #include < cstring>
29
- #include < memory>
30
- #include < mutex>
31
- #include < unordered_map>
32
- #include < variant>
33
- #include < vector>
23
+ #include < stdio.h>
24
+ #include < stdlib.h>
25
+
26
+ namespace LIBC_NAMESPACE {
27
+
28
+ // Minimal replacement for 'std::vector' that works for trivial types.
29
+ template <typename T> class TempVector {
30
+ static_assert (cpp::is_trivially_constructible<T>::value &&
31
+ cpp::is_trivially_destructible<T>::value,
32
+ " Not a trivial type." );
33
+ T *data;
34
+ size_t current;
35
+ size_t capacity;
36
+
37
+ public:
38
+ TempVector () : data(nullptr ), current(0 ), capacity(0 ) {}
39
+
40
+ ~TempVector () { free (data); }
41
+
42
+ void push_back (const T &value) {
43
+ if (current == capacity)
44
+ grow ();
45
+ data[current] = T (value);
46
+ ++current;
47
+ }
48
+
49
+ void push_back (T &&value) {
50
+ if (current == capacity)
51
+ grow ();
52
+ data[current] = T (static_cast <T &&>(value));
53
+ ++current;
54
+ }
55
+
56
+ void pop_back () { --current; }
34
57
35
- using namespace LIBC_NAMESPACE ;
36
- using namespace LIBC_NAMESPACE ::printf_core;
58
+ bool empty () { return current == 0 ; }
59
+
60
+ size_t size () { return current; }
61
+
62
+ T &operator [](size_t index) { return data[index]; }
63
+
64
+ T &back () { return data[current - 1 ]; }
65
+
66
+ private:
67
+ void grow () {
68
+ size_t new_capacity = capacity ? capacity * 2 : 1 ;
69
+ void *new_data = realloc (data, new_capacity * sizeof (T));
70
+ if (!new_data)
71
+ abort ();
72
+ data = static_cast <T *>(new_data);
73
+ capacity = new_capacity;
74
+ }
75
+ };
37
76
38
- namespace {
39
77
struct TempStorage {
40
78
char *alloc (size_t size) {
41
- storage.emplace_back (std::make_unique<char []>(size));
42
- return storage.back ().get ();
79
+ storage.push_back (reinterpret_cast <char *>(malloc (size)));
80
+ return storage.back ();
81
+ }
82
+
83
+ ~TempStorage () {
84
+ for (size_t i = 0 ; i < storage.size (); ++i)
85
+ free (storage[i]);
43
86
}
44
87
45
- std::vector<std::unique_ptr< char []> > storage;
88
+ TempVector< char * > storage;
46
89
};
47
- } // namespace
48
90
49
91
enum Stream {
50
92
File = 0 ,
@@ -71,15 +113,18 @@ static void handle_printf(rpc::Server::Port &port, TempStorage &temp_storage) {
71
113
FILE *files[num_lanes] = {nullptr };
72
114
// Get the appropriate output stream to use.
73
115
if (port.get_opcode () == LIBC_PRINTF_TO_STREAM ||
74
- port.get_opcode () == LIBC_PRINTF_TO_STREAM_PACKED)
116
+ port.get_opcode () == LIBC_PRINTF_TO_STREAM_PACKED) {
75
117
port.recv ([&](rpc::Buffer *buffer, uint32_t id) {
76
118
files[id] = reinterpret_cast <FILE *>(buffer->data [0 ]);
77
119
});
78
- else if (port.get_opcode () == LIBC_PRINTF_TO_STDOUT ||
79
- port.get_opcode () == LIBC_PRINTF_TO_STDOUT_PACKED)
80
- std::fill (files, files + num_lanes, stdout);
81
- else
82
- std::fill (files, files + num_lanes, stderr);
120
+ } else if (port.get_opcode () == LIBC_PRINTF_TO_STDOUT ||
121
+ port.get_opcode () == LIBC_PRINTF_TO_STDOUT_PACKED) {
122
+ for (uint32_t i = 0 ; i < num_lanes; ++i)
123
+ files[i] = stdout;
124
+ } else {
125
+ for (uint32_t i = 0 ; i < num_lanes; ++i)
126
+ files[i] = stderr;
127
+ }
83
128
84
129
uint64_t format_sizes[num_lanes] = {0 };
85
130
void *format[num_lanes] = {nullptr };
@@ -96,14 +141,16 @@ static void handle_printf(rpc::Server::Port &port, TempStorage &temp_storage) {
96
141
if (!format[lane])
97
142
continue ;
98
143
99
- WriteBuffer<WriteMode::FILL_BUFF_AND_DROP_OVERFLOW> wb (nullptr , 0 );
100
- Writer writer (wb);
144
+ printf_core::WriteBuffer<
145
+ printf_core::WriteMode::FILL_BUFF_AND_DROP_OVERFLOW>
146
+ wb (nullptr , 0 );
147
+ printf_core::Writer writer (wb);
101
148
102
149
internal::DummyArgList<packed> printf_args;
103
- Parser<internal::DummyArgList<packed> &> parser (
150
+ printf_core:: Parser<internal::DummyArgList<packed> &> parser (
104
151
reinterpret_cast <const char *>(format[lane]), printf_args);
105
152
106
- for (FormatSection cur_section = parser.get_next_section ();
153
+ for (printf_core:: FormatSection cur_section = parser.get_next_section ();
107
154
!cur_section.raw_string .empty ();
108
155
cur_section = parser.get_next_section ())
109
156
;
@@ -117,25 +164,27 @@ static void handle_printf(rpc::Server::Port &port, TempStorage &temp_storage) {
117
164
118
165
// Identify any arguments that are actually pointers to strings on the client.
119
166
// Additionally we want to determine how much buffer space we need to print.
120
- std::vector <void *> strs_to_copy[num_lanes];
167
+ TempVector <void *> strs_to_copy[num_lanes];
121
168
int buffer_size[num_lanes] = {0 };
122
169
for (uint32_t lane = 0 ; lane < num_lanes; ++lane) {
123
170
if (!format[lane])
124
171
continue ;
125
172
126
- WriteBuffer<WriteMode::FILL_BUFF_AND_DROP_OVERFLOW> wb (nullptr , 0 );
127
- Writer writer (wb);
173
+ printf_core::WriteBuffer<
174
+ printf_core::WriteMode::FILL_BUFF_AND_DROP_OVERFLOW>
175
+ wb (nullptr , 0 );
176
+ printf_core::Writer writer (wb);
128
177
129
178
internal::StructArgList<packed> printf_args (args[lane], args_sizes[lane]);
130
- Parser<internal::StructArgList<packed>> parser (
179
+ printf_core:: Parser<internal::StructArgList<packed>> parser (
131
180
reinterpret_cast <const char *>(format[lane]), printf_args);
132
181
133
- for (FormatSection cur_section = parser.get_next_section ();
182
+ for (printf_core:: FormatSection cur_section = parser.get_next_section ();
134
183
!cur_section.raw_string .empty ();
135
184
cur_section = parser.get_next_section ()) {
136
185
if (cur_section.has_conv && cur_section.conv_name == ' s' &&
137
186
cur_section.conv_val_ptr ) {
138
- strs_to_copy[lane].emplace_back (cur_section.conv_val_ptr );
187
+ strs_to_copy[lane].push_back (cur_section.conv_val_ptr );
139
188
// Get the minimum size of the string in the case of padding.
140
189
char c = ' \0 ' ;
141
190
cur_section.conv_val_ptr = &c;
@@ -151,9 +200,14 @@ static void handle_printf(rpc::Server::Port &port, TempStorage &temp_storage) {
151
200
}
152
201
153
202
// Recieve any strings from the client and push them into a buffer.
154
- std::vector<void *> copied_strs[num_lanes];
155
- while (std::any_of (std::begin (strs_to_copy), std::end (strs_to_copy),
156
- [](const auto &v) { return !v.empty () && v.back (); })) {
203
+ TempVector<void *> copied_strs[num_lanes];
204
+ auto HasPendingCopies = [](TempVector<void *> v[num_lanes]) {
205
+ for (uint32_t i = 0 ; i < num_lanes; ++i)
206
+ if (!v[i].empty () && v[i].back ())
207
+ return true ;
208
+ return false ;
209
+ };
210
+ while (HasPendingCopies (strs_to_copy)) {
157
211
port.send ([&](rpc::Buffer *buffer, uint32_t id) {
158
212
void *ptr = !strs_to_copy[id].empty () ? strs_to_copy[id].back () : nullptr ;
159
213
buffer->data [1 ] = reinterpret_cast <uintptr_t >(ptr);
@@ -168,7 +222,7 @@ static void handle_printf(rpc::Server::Port &port, TempStorage &temp_storage) {
168
222
if (!strs[lane])
169
223
continue ;
170
224
171
- copied_strs[lane].emplace_back (strs[lane]);
225
+ copied_strs[lane].push_back (strs[lane]);
172
226
buffer_size[lane] += str_sizes[lane];
173
227
}
174
228
}
@@ -180,18 +234,19 @@ static void handle_printf(rpc::Server::Port &port, TempStorage &temp_storage) {
180
234
continue ;
181
235
182
236
char *buffer = temp_storage.alloc (buffer_size[lane]);
183
- WriteBuffer<WriteMode::FILL_BUFF_AND_DROP_OVERFLOW> wb (buffer,
184
- buffer_size[lane]);
185
- Writer writer (wb);
237
+ printf_core::WriteBuffer<
238
+ printf_core::WriteMode::FILL_BUFF_AND_DROP_OVERFLOW>
239
+ wb (buffer, buffer_size[lane]);
240
+ printf_core::Writer writer (wb);
186
241
187
242
internal::StructArgList<packed> printf_args (args[lane], args_sizes[lane]);
188
- Parser<internal::StructArgList<packed>> parser (
243
+ printf_core:: Parser<internal::StructArgList<packed>> parser (
189
244
reinterpret_cast <const char *>(format[lane]), printf_args);
190
245
191
246
// Parse and print the format string using the arguments we copied from
192
247
// the client.
193
248
int ret = 0 ;
194
- for (FormatSection cur_section = parser.get_next_section ();
249
+ for (printf_core:: FormatSection cur_section = parser.get_next_section ();
195
250
!cur_section.raw_string .empty ();
196
251
cur_section = parser.get_next_section ()) {
197
252
// If this argument was a string we use the memory buffer we copied from
@@ -242,10 +297,9 @@ rpc::Status handle_port_impl(rpc::Server::Port &port) {
242
297
port.recv ([&](rpc::Buffer *buffer, uint32_t id) {
243
298
files[id] = reinterpret_cast <FILE *>(buffer->data [0 ]);
244
299
});
245
- } else if (port.get_opcode () == LIBC_WRITE_TO_STDERR) {
246
- std::fill (files, files + num_lanes, stderr);
247
300
} else {
248
- std::fill (files, files + num_lanes, stdout);
301
+ for (uint32_t i = 0 ; i < num_lanes; ++i)
302
+ files[i] = port.get_opcode () == LIBC_WRITE_TO_STDERR ? stderr : stdout;
249
303
}
250
304
251
305
port.recv_n (strs, sizes,
@@ -270,7 +324,7 @@ rpc::Status handle_port_impl(rpc::Server::Port &port) {
270
324
});
271
325
port.send_n (data, sizes);
272
326
port.send ([&](rpc::Buffer *buffer, uint32_t id) {
273
- std::memcpy (buffer->data , &sizes[id], sizeof (uint64_t ));
327
+ __builtin_memcpy (buffer->data , &sizes[id], sizeof (uint64_t ));
274
328
});
275
329
break ;
276
330
}
@@ -281,7 +335,7 @@ rpc::Status handle_port_impl(rpc::Server::Port &port) {
281
335
data[id] = temp_storage.alloc (buffer->data [0 ]);
282
336
const char *str = fgets (reinterpret_cast <char *>(data[id]),
283
337
buffer->data [0 ], to_stream (buffer->data [1 ]));
284
- sizes[id] = !str ? 0 : std::strlen (str) + 1 ;
338
+ sizes[id] = !str ? 0 : __builtin_strlen (str) + 1 ;
285
339
});
286
340
port.send_n (data, sizes);
287
341
break ;
@@ -310,7 +364,7 @@ rpc::Status handle_port_impl(rpc::Server::Port &port) {
310
364
port.recv_and_send ([](rpc::Buffer *, uint32_t ) {});
311
365
port.recv ([](rpc::Buffer *buffer, uint32_t ) {
312
366
int status = 0 ;
313
- std::memcpy (&status, buffer->data , sizeof (int ));
367
+ __builtin_memcpy (&status, buffer->data , sizeof (int ));
314
368
exit (status);
315
369
});
316
370
break ;
@@ -444,17 +498,19 @@ rpc::Status handle_port_impl(rpc::Server::Port &port) {
444
498
return rpc::RPC_SUCCESS;
445
499
}
446
500
501
+ } // namespace LIBC_NAMESPACE
502
+
447
503
namespace rpc {
448
504
// The implementation of this function currently lives in the utility directory
449
505
// at 'utils/gpu/server/rpc_server.cpp'.
450
506
rpc::Status handle_libc_opcodes (rpc::Server::Port &port, uint32_t num_lanes) {
451
507
switch (num_lanes) {
452
508
case 1 :
453
- return handle_port_impl<1 >(port);
509
+ return LIBC_NAMESPACE:: handle_port_impl<1 >(port);
454
510
case 32 :
455
- return handle_port_impl<32 >(port);
511
+ return LIBC_NAMESPACE:: handle_port_impl<32 >(port);
456
512
case 64 :
457
- return handle_port_impl<64 >(port);
513
+ return LIBC_NAMESPACE:: handle_port_impl<64 >(port);
458
514
default :
459
515
return rpc::RPC_ERROR;
460
516
}
0 commit comments