1111#define __has_builtin (x ) 0
1212#endif
1313
14- // Make sure these are included first so they don't conflict with the system.
15- #include < limits.h>
16-
1714#include " shared/rpc.h"
1815#include " shared/rpc_opcodes.h"
1916
17+ #include " src/__support/CPP/type_traits.h"
2018#include " src/__support/arg_list.h"
2119#include " src/stdio/printf_core/converter.h"
2220#include " src/stdio/printf_core/parser.h"
2321#include " src/stdio/printf_core/writer.h"
2422
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; }
3457
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+ };
3776
38- namespace {
3977struct TempStorage {
4078 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]);
4386 }
4487
45- std::vector<std::unique_ptr< char []> > storage;
88+ TempVector< char * > storage;
4689};
47- } // namespace
4890
4991enum Stream {
5092 File = 0 ,
@@ -71,15 +113,18 @@ static void handle_printf(rpc::Server::Port &port, TempStorage &temp_storage) {
71113 FILE *files[num_lanes] = {nullptr };
72114 // Get the appropriate output stream to use.
73115 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) {
75117 port.recv ([&](rpc::Buffer *buffer, uint32_t id) {
76118 files[id] = reinterpret_cast <FILE *>(buffer->data [0 ]);
77119 });
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+ }
83128
84129 uint64_t format_sizes[num_lanes] = {0 };
85130 void *format[num_lanes] = {nullptr };
@@ -96,14 +141,16 @@ static void handle_printf(rpc::Server::Port &port, TempStorage &temp_storage) {
96141 if (!format[lane])
97142 continue ;
98143
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);
101148
102149 internal::DummyArgList<packed> printf_args;
103- Parser<internal::DummyArgList<packed> &> parser (
150+ printf_core:: Parser<internal::DummyArgList<packed> &> parser (
104151 reinterpret_cast <const char *>(format[lane]), printf_args);
105152
106- for (FormatSection cur_section = parser.get_next_section ();
153+ for (printf_core:: FormatSection cur_section = parser.get_next_section ();
107154 !cur_section.raw_string .empty ();
108155 cur_section = parser.get_next_section ())
109156 ;
@@ -117,25 +164,27 @@ static void handle_printf(rpc::Server::Port &port, TempStorage &temp_storage) {
117164
118165 // Identify any arguments that are actually pointers to strings on the client.
119166 // 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];
121168 int buffer_size[num_lanes] = {0 };
122169 for (uint32_t lane = 0 ; lane < num_lanes; ++lane) {
123170 if (!format[lane])
124171 continue ;
125172
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);
128177
129178 internal::StructArgList<packed> printf_args (args[lane], args_sizes[lane]);
130- Parser<internal::StructArgList<packed>> parser (
179+ printf_core:: Parser<internal::StructArgList<packed>> parser (
131180 reinterpret_cast <const char *>(format[lane]), printf_args);
132181
133- for (FormatSection cur_section = parser.get_next_section ();
182+ for (printf_core:: FormatSection cur_section = parser.get_next_section ();
134183 !cur_section.raw_string .empty ();
135184 cur_section = parser.get_next_section ()) {
136185 if (cur_section.has_conv && cur_section.conv_name == ' s' &&
137186 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 );
139188 // Get the minimum size of the string in the case of padding.
140189 char c = ' \0 ' ;
141190 cur_section.conv_val_ptr = &c;
@@ -151,9 +200,14 @@ static void handle_printf(rpc::Server::Port &port, TempStorage &temp_storage) {
151200 }
152201
153202 // 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)) {
157211 port.send ([&](rpc::Buffer *buffer, uint32_t id) {
158212 void *ptr = !strs_to_copy[id].empty () ? strs_to_copy[id].back () : nullptr ;
159213 buffer->data [1 ] = reinterpret_cast <uintptr_t >(ptr);
@@ -168,7 +222,7 @@ static void handle_printf(rpc::Server::Port &port, TempStorage &temp_storage) {
168222 if (!strs[lane])
169223 continue ;
170224
171- copied_strs[lane].emplace_back (strs[lane]);
225+ copied_strs[lane].push_back (strs[lane]);
172226 buffer_size[lane] += str_sizes[lane];
173227 }
174228 }
@@ -180,18 +234,19 @@ static void handle_printf(rpc::Server::Port &port, TempStorage &temp_storage) {
180234 continue ;
181235
182236 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);
186241
187242 internal::StructArgList<packed> printf_args (args[lane], args_sizes[lane]);
188- Parser<internal::StructArgList<packed>> parser (
243+ printf_core:: Parser<internal::StructArgList<packed>> parser (
189244 reinterpret_cast <const char *>(format[lane]), printf_args);
190245
191246 // Parse and print the format string using the arguments we copied from
192247 // the client.
193248 int ret = 0 ;
194- for (FormatSection cur_section = parser.get_next_section ();
249+ for (printf_core:: FormatSection cur_section = parser.get_next_section ();
195250 !cur_section.raw_string .empty ();
196251 cur_section = parser.get_next_section ()) {
197252 // 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) {
242297 port.recv ([&](rpc::Buffer *buffer, uint32_t id) {
243298 files[id] = reinterpret_cast <FILE *>(buffer->data [0 ]);
244299 });
245- } else if (port.get_opcode () == LIBC_WRITE_TO_STDERR) {
246- std::fill (files, files + num_lanes, stderr);
247300 } 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;
249303 }
250304
251305 port.recv_n (strs, sizes,
@@ -270,7 +324,7 @@ rpc::Status handle_port_impl(rpc::Server::Port &port) {
270324 });
271325 port.send_n (data, sizes);
272326 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 ));
274328 });
275329 break ;
276330 }
@@ -281,7 +335,7 @@ rpc::Status handle_port_impl(rpc::Server::Port &port) {
281335 data[id] = temp_storage.alloc (buffer->data [0 ]);
282336 const char *str = fgets (reinterpret_cast <char *>(data[id]),
283337 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 ;
285339 });
286340 port.send_n (data, sizes);
287341 break ;
@@ -310,7 +364,7 @@ rpc::Status handle_port_impl(rpc::Server::Port &port) {
310364 port.recv_and_send ([](rpc::Buffer *, uint32_t ) {});
311365 port.recv ([](rpc::Buffer *buffer, uint32_t ) {
312366 int status = 0 ;
313- std::memcpy (&status, buffer->data , sizeof (int ));
367+ __builtin_memcpy (&status, buffer->data , sizeof (int ));
314368 exit (status);
315369 });
316370 break ;
@@ -444,17 +498,19 @@ rpc::Status handle_port_impl(rpc::Server::Port &port) {
444498 return rpc::RPC_SUCCESS;
445499}
446500
501+ } // namespace LIBC_NAMESPACE
502+
447503namespace rpc {
448504// The implementation of this function currently lives in the utility directory
449505// at 'utils/gpu/server/rpc_server.cpp'.
450506rpc::Status handle_libc_opcodes (rpc::Server::Port &port, uint32_t num_lanes) {
451507 switch (num_lanes) {
452508 case 1 :
453- return handle_port_impl<1 >(port);
509+ return LIBC_NAMESPACE:: handle_port_impl<1 >(port);
454510 case 32 :
455- return handle_port_impl<32 >(port);
511+ return LIBC_NAMESPACE:: handle_port_impl<32 >(port);
456512 case 64 :
457- return handle_port_impl<64 >(port);
513+ return LIBC_NAMESPACE:: handle_port_impl<64 >(port);
458514 default :
459515 return rpc::RPC_ERROR;
460516 }
0 commit comments