source: libcfa/src/concurrency/io/call.cfa.in@ d48b174

ADT arm-eh ast-experimental enum forall-pointer-decay jacob/cs343-translation new-ast-unique-expr pthread-emulation qualifiedEnum
Last change on this file since d48b174 was 426f60c, checked in by Thierry Delisle <tdelisle@…>, 5 years ago

Web server seems to work

  • Property mode set to 100644
File size: 15.2 KB
Line 
1#!python3
2#
3# Cforall Version 1.0.0 Copyright (C) 2020 University of Waterloo
4#
5# The contents of this file are covered under the licence agreement in the
6# file "LICENCE" distributed with Cforall.
7#
8# call.cfa.in -- Python script to generate io/call.cfa
9#
10# Author : Thierry Delisle
11# Created On : Fri Sep 11 12:41:16 2020
12# Last Modified By :
13# Last Modified On :
14# Update Count :
15#
16
17Header = """//
18// Cforall Version 1.0.0 Copyright (C) 2020 University of Waterloo
19//
20// The contents of this file are covered under the licence agreement in the
21// file "LICENCE" distributed with Cforall.
22//
23// call.cfa -- Api for cforall
24//
25// Author : Generated from call.cfa.in
26// Created On : {}
27//
28
29"""
30
31Prelude = """#define __cforall_thread__
32
33#include "bits/defs.hfa"
34#include "kernel.hfa"
35#include "io/types.hfa"
36
37//=============================================================================================
38// I/O uring backend
39//=============================================================================================
40
41#if defined(CFA_HAVE_LINUX_IO_URING_H)
42 #include <assert.h>
43 #include <stdint.h>
44 #include <errno.h>
45 #include <linux/io_uring.h>
46
47 #include "kernel/fwd.hfa"
48
49 static const __u8 REGULAR_FLAGS = 0
50 #if defined(CFA_HAVE_IOSQE_FIXED_FILE)
51 | IOSQE_FIXED_FILE
52 #endif
53 #if defined(CFA_HAVE_IOSQE_IO_DRAIN)
54 | IOSQE_IO_DRAIN
55 #endif
56 #if defined(CFA_HAVE_IOSQE_ASYNC)
57 | IOSQE_ASYNC
58 #endif
59 ;
60
61 static const __u32 LINK_FLAGS = 0
62 #if defined(CFA_HAVE_IOSQE_IO_LINK)
63 | IOSQE_IO_LINK
64 #endif
65 #if defined(CFA_HAVE_IOSQE_IO_HARDLINK)
66 | IOSQE_IO_HARDLINK
67 #endif
68 ;
69
70 static const __u32 SPLICE_FLAGS = 0
71 #if defined(CFA_HAVE_SPLICE_F_FD_IN_FIXED)
72 | SPLICE_F_FD_IN_FIXED
73 #endif
74 ;
75
76 extern [* volatile struct io_uring_sqe, __u32] __submit_alloc( struct __io_data & ring, __u64 data );
77 extern void __submit( struct io_context * ctx, __u32 idx ) __attribute__((nonnull (1)));
78
79 static inline io_context * __get_io_context( void ) {
80 cluster * cltr = active_cluster();
81
82 /* paranoid */ verifyf( cltr, "No active cluster for io operation\\n");
83 assertf( cltr->io.cnt > 0, "Cluster %p has no default io contexts and no context was specified\\n", cltr );
84
85 /* paranoid */ verifyf( cltr->io.ctxs, "default io contexts for cluster %p are missing\\n", cltr);
86 return &cltr->io.ctxs[ thread_rand() % cltr->io.cnt ];
87 }
88#endif
89
90//=============================================================================================
91// I/O Forwards
92//=============================================================================================
93#include <time.hfa>
94
95// Some forward declarations
96#include <errno.h>
97#include <unistd.h>
98
99extern "C" {
100 #include <sys/types.h>
101 #include <sys/socket.h>
102 #include <sys/syscall.h>
103
104#if defined(CFA_HAVE_PREADV2)
105 struct iovec;
106 extern ssize_t preadv2 (int fd, const struct iovec *iov, int iovcnt, off_t offset, int flags);
107#endif
108#if defined(CFA_HAVE_PWRITEV2)
109 struct iovec;
110 extern ssize_t pwritev2(int fd, const struct iovec *iov, int iovcnt, off_t offset, int flags);
111#endif
112
113 extern int fsync(int fd);
114
115 #if __OFF_T_MATCHES_OFF64_T
116 typedef __off64_t off_t;
117 #else
118 typedef __off_t off_t;
119 #endif
120 typedef __off64_t off64_t;
121 extern int sync_file_range(int fd, off64_t offset, off64_t nbytes, unsigned int flags);
122
123 struct msghdr;
124 struct sockaddr;
125 extern ssize_t sendmsg(int sockfd, const struct msghdr *msg, int flags);
126 extern ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags);
127 extern ssize_t send(int sockfd, const void *buf, size_t len, int flags);
128 extern ssize_t recv(int sockfd, void *buf, size_t len, int flags);
129 extern int accept4(int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags);
130 extern int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
131
132 extern int fallocate(int fd, int mode, off_t offset, off_t len);
133 extern int posix_fadvise(int fd, off_t offset, off_t len, int advice);
134 extern int madvise(void *addr, size_t length, int advice);
135
136 extern int openat(int dirfd, const char *pathname, int flags, mode_t mode);
137 extern int close(int fd);
138
139 extern ssize_t read (int fd, void *buf, size_t count);
140
141 struct epoll_event;
142 extern int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
143
144 extern ssize_t splice(int fd_in, loff_t *off_in, int fd_out, loff_t *off_out, size_t len, unsigned int flags);
145 extern ssize_t tee(int fd_in, int fd_out, size_t len, unsigned int flags);
146}
147
148//=============================================================================================
149// I/O Interface
150//=============================================================================================
151"""
152
153print(Header.format("A Date"))
154print(Prelude)
155
156import re
157import sys
158class Call:
159 def __init__(self, op, signature, body, define=None):
160 sig = re.search("(.*) (.*)\((.*)\)", signature)
161 if not sig:
162 print("OP '{}' has invalid signature {}".format(op, signature), file=sys.stderr)
163 sys.exit(1)
164
165 self.op = op
166 self.ret = sig.group(1)
167 self.name = sig.group(2)
168 self.params = sig.group(3)
169 self.define = define
170 self.body = ""
171
172 accepted_keys = [ 'ioprio', 'fd', 'off', 'addr2','addr', 'splice_off_in','len',
173 'rw_flags', 'fsync_flags', 'poll_events', 'poll32_events',
174 'sync_range_flags', 'msg_flags', 'timeout_flags', 'accept_flags',
175 'cancel_flags', 'open_flags', 'statx_flags', 'fadvise_advice',
176 'splice_flags', 'buf_index' ,'buf_group' 'personality',
177 'splice_fd_in' ]
178
179 for k, v in body.items():
180 if not k in accepted_keys:
181 print("OP '{}' has invalid body kew {}".format(op, k), file=sys.stderr)
182 sys.exit(1)
183
184 self.body += "\n sqe->{key} = {value};".format(key=k, value=v)
185
186
187 def args(self):
188 param_a = self.params.split(',')
189 args_a = [p.replace('*', ' ').split()[-1] for p in param_a]
190 for a in args_a:
191 if '*' in a:
192 print("OP '{}' has invalid * in argument {}".format(self.op, a), file=sys.stderr)
193 sys.exit(1)
194
195 return ', '.join(args_a)
196
197AsyncTemplate = """inline void async_{name}(io_future_t & future, {params}, int submit_flags, io_cancellation * cancellation, io_context * context) {{
198 #if !defined(CFA_HAVE_LINUX_IO_URING_H) || !defined(CFA_HAVE_IORING_OP_{op})
199 ssize_t res = {name}({args});
200 if (res >= 0) {{
201 fulfil(future, res);
202 }}
203 else {{
204 fulfil(future, -errno);
205 }}
206 #else
207 // we don't support LINK yet
208 if( 0 != (submit_flags & LINK_FLAGS) ) {{
209 errno = ENOTSUP; return -1;
210 }}
211
212 if( !context ) {{
213 context = __get_io_context();
214 }}
215 if(cancellation) {{
216 cancellation->target = (__u64)(uintptr_t)&future;
217 }}
218
219 __u8 sflags = REGULAR_FLAGS & submit_flags;
220 struct __io_data & ring = *context->thrd.ring;
221
222 __u32 idx;
223 volatile struct io_uring_sqe * sqe;
224 [sqe, idx] = __submit_alloc( ring, (__u64)(uintptr_t)&future );
225
226 sqe->__pad2[0] = sqe->__pad2[1] = sqe->__pad2[2] = 0;
227 sqe->opcode = IORING_OP_{op};
228 sqe->flags = sflags;{body}
229
230 verify( sqe->user_data == (__u64)(uintptr_t)&future );
231 __submit( context, idx );
232 #endif
233}}"""
234
235SyncTemplate = """{ret} cfa_{name}({params}, int submit_flags, Duration timeout, io_cancellation * cancellation, io_context * context) {{
236 if( timeout >= 0 ) {{
237 errno = ENOTSUP;
238 return -1;
239 }}
240 io_future_t future;
241
242 async_{name}( future, {args}, submit_flags, cancellation, context );
243
244 wait( future );
245 if( future.result < 0 ) {{
246 errno = -future.result;
247 return -1;
248 }}
249 return future.result;
250}}"""
251
252calls = [
253 # CFA_HAVE_IORING_OP_READV
254 Call('READV', 'ssize_t preadv2(int fd, const struct iovec *iov, int iovcnt, off_t offset, int flags)', {
255 'fd' : 'fd',
256 'off' : 'offset',
257 'addr': '(__u64)iov',
258 'len' : 'iovcnt',
259 }, define = 'CFA_HAVE_PREADV2'),
260 # CFA_HAVE_IORING_OP_WRITEV
261 Call('WRITEV', 'ssize_t pwritev2(int fd, const struct iovec *iov, int iovcnt, off_t offset, int flags)', {
262 'fd' : 'fd',
263 'off' : 'offset',
264 'addr': '(__u64)iov',
265 'len' : 'iovcnt'
266 }, define = 'CFA_HAVE_PWRITEV2'),
267 # CFA_HAVE_IORING_OP_FSYNC
268 Call('FSYNC', 'int fsync(int fd)', {
269 'fd': 'fd'
270 }),
271 # CFA_HAVE_IORING_OP_EPOLL_CTL
272 Call('EPOLL_CTL', 'int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event)', {
273 'fd': 'epfd',
274 'addr': 'fd',
275 'len': 'op',
276 'off': '(__u64)event'
277 }),
278 # CFA_HAVE_IORING_OP_SYNC_FILE_RANGE
279 Call('SYNC_FILE_RANGE', 'int sync_file_range(int fd, off64_t offset, off64_t nbytes, unsigned int flags)', {
280 'fd': 'fd',
281 'off': 'offset',
282 'len': 'nbytes',
283 'sync_range_flags': 'flags'
284 }),
285 # CFA_HAVE_IORING_OP_SENDMSG
286 Call('SENDMSG', 'ssize_t sendmsg(int sockfd, const struct msghdr *msg, int flags)', {
287 'fd': 'sockfd',
288 'addr': '(__u64)(struct msghdr *)msg',
289 'len': '1',
290 'msg_flags': 'flags'
291 }),
292 # CFA_HAVE_IORING_OP_RECVMSG
293 Call('RECVMSG', 'ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags)', {
294 'fd': 'sockfd',
295 'addr': '(__u64)(struct msghdr *)msg',
296 'len': '1',
297 'msg_flags': 'flags'
298 }),
299 # CFA_HAVE_IORING_OP_SEND
300 Call('SEND', 'ssize_t send(int sockfd, const void *buf, size_t len, int flags)', {
301 'fd': 'sockfd',
302 'addr': '(__u64)buf',
303 'len': 'len',
304 'msg_flags': 'flags'
305 }),
306 # CFA_HAVE_IORING_OP_RECV
307 Call('RECV', 'ssize_t recv(int sockfd, void *buf, size_t len, int flags)', {
308 'fd': 'sockfd',
309 'addr': '(__u64)buf',
310 'len': 'len',
311 'msg_flags': 'flags'
312 }),
313 # CFA_HAVE_IORING_OP_ACCEPT
314 Call('ACCEPT', 'int accept4(int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags)', {
315 'fd': 'sockfd',
316 'ioprio': '0',
317 'addr': '(__u64)addr',
318 'addr2': '(__u64)addrlen',
319 'accept_flags': 'flags'
320 }),
321 # CFA_HAVE_IORING_OP_CONNECT
322 Call('CONNECT', 'int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen)', {
323 'fd': 'sockfd',
324 'addr': '(__u64)addr',
325 'off': 'addrlen'
326 }),
327 # CFA_HAVE_IORING_OP_FALLOCATE
328 Call('FALLOCATE', 'int fallocate(int fd, int mode, off_t offset, off_t len)', {
329 'fd': 'fd',
330 'addr': '(__u64)len',
331 'len': 'mode',
332 'off': 'offset'
333 }),
334 # CFA_HAVE_IORING_OP_FADVISE
335 Call('FADVISE', 'int posix_fadvise(int fd, off_t offset, off_t len, int advice)', {
336 'fd': 'fd',
337 'off': 'offset',
338 'len': 'len',
339 'fadvise_advice': 'advice'
340 }),
341 # CFA_HAVE_IORING_OP_MADVISE
342 Call('MADVISE', 'int madvise(void *addr, size_t length, int advice)', {
343 'addr': '(__u64)addr',
344 'len': 'length',
345 'fadvise_advice': 'advice'
346 }),
347 # CFA_HAVE_IORING_OP_OPENAT
348 Call('OPENAT', 'int openat(int dirfd, const char *pathname, int flags, mode_t mode)', {
349 'fd': 'dirfd',
350 'addr': '(__u64)pathname',
351 'len': 'mode',
352 'open_flags': 'flags;'
353 }),
354 # CFA_HAVE_IORING_OP_OPENAT2
355 Call('OPENAT2', 'int openat2(int dirfd, const char *pathname, struct open_how * how, size_t size)', {
356 'fd': 'dirfd',
357 'addr': 'pathname',
358 'len': 'sizeof(*how)',
359 'off': '(__u64)how',
360 }, define = 'CFA_HAVE_OPENAT2'),
361 # CFA_HAVE_IORING_OP_CLOSE
362 Call('CLOSE', 'int close(int fd)', {
363 'fd': 'fd'
364 }),
365 # CFA_HAVE_IORING_OP_STATX
366 Call('STATX', 'int statx(int dirfd, const char *pathname, int flags, unsigned int mask, struct statx *statxbuf)', {
367 'fd': 'dirfd',
368 'off': '(__u64)statxbuf',
369 'addr': 'pathname',
370 'len': 'mask',
371 'statx_flags': 'flags'
372 }, define = 'CFA_HAVE_STATX'),
373 # CFA_HAVE_IORING_OP_READ
374 Call('READ', 'ssize_t read(int fd, void * buf, size_t count)', {
375 'fd': 'fd',
376 'off': '0',
377 'addr': '(__u64)buf',
378 'len': 'count'
379 }),
380 # CFA_HAVE_IORING_OP_WRITE
381 Call('WRITE', 'ssize_t write(int fd, void * buf, size_t count)', {
382 'fd': 'fd',
383 'off': '0',
384 'addr': '(__u64)buf',
385 'len': 'count'
386 }),
387 # CFA_HAVE_IORING_OP_SPLICE
388 Call('SPLICE', 'ssize_t splice(int fd_in, loff_t *off_in, int fd_out, loff_t *off_out, size_t len, unsigned int flags)', {
389 'splice_fd_in': 'fd_in',
390 'splice_off_in': 'off_in ? (__u64)*off_in : (__u64)-1',
391 'fd': 'fd_out',
392 'off': 'off_out ? (__u64)*off_out : (__u64)-1',
393 'len': 'len',
394 'splice_flags': 'flags'
395 }),
396 # CFA_HAVE_IORING_OP_TEE
397 Call('TEE', 'ssize_t tee(int fd_in, int fd_out, size_t len, unsigned int flags)', {
398 'splice_fd_in': 'fd_in',
399 'fd': 'fd_out',
400 'len': 'len',
401 'splice_flags': 'flags'
402 })
403]
404
405print("//----------")
406print("// synchronous calls")
407for c in calls:
408 if c.define:
409 print("""#if defined({define})
410 {ret} cfa_{name}({params}, int submit_flags, Duration timeout, io_cancellation * cancellation, io_context * context);
411#endif""".format(define=c.define,ret=c.ret, name=c.name, params=c.params))
412 else:
413 print("{ret} cfa_{name}({params}, int submit_flags, Duration timeout, io_cancellation * cancellation, io_context * context);"
414 .format(ret=c.ret, name=c.name, params=c.params))
415
416print("\n//----------")
417print("// asynchronous calls")
418for c in calls:
419 if c.define:
420 print("""#if defined({define})
421 void async_{name}(io_future_t & future, {params}, int submit_flags, io_cancellation * cancellation, io_context * context);
422#endif""".format(define=c.define,name=c.name, params=c.params))
423 else:
424 print("void async_{name}(io_future_t & future, {params}, int submit_flags, io_cancellation * cancellation, io_context * context);"
425 .format(name=c.name, params=c.params))
426print("\n")
427
428for c in calls:
429 print("//-----------------------------------------------------------------------------")
430 print("// {}".format(c.name))
431 Async = AsyncTemplate.format(
432 name = c.name,
433 ret = c.ret,
434 params = c.params,
435 args = c.args(),
436 op = c.op,
437 body = c.body
438
439 )
440 Sync = SyncTemplate.format(
441 name = c.name,
442 ret = c.ret,
443 params = c.params,
444 args = c.args()
445 )
446
447 if c.define:
448 print("""#if defined({})
449 //----------
450 // asynchronous call
451 {}
452
453 //----------
454 // synchronous call
455 {}
456#endif
457""".format(c.define, "\n\t".join( Async.splitlines() ), "\n\t".join( Sync.splitlines() )))
458 else :
459 print("""//----------
460// asynchronous call
461{}
462
463//----------
464// synchronous call
465{}
466""".format(Async, Sync))
467
468print("""
469//-----------------------------------------------------------------------------
470bool cancel(io_cancellation & this) {
471 #if !defined(CFA_HAVE_LINUX_IO_URING_H) || !defined(CFA_HAVE_IORING_OP_ASYNC_CANCEL)
472 return false;
473 #else
474 io_future_t future;
475
476 io_context * context = __get_io_context();
477
478 __u8 sflags = 0;
479 struct __io_data & ring = *context->thrd.ring;
480
481 __u32 idx;
482 volatile struct io_uring_sqe * sqe;
483 [sqe, idx] = __submit_alloc( ring, (__u64)(uintptr_t)&future );
484
485 sqe->__pad2[0] = sqe->__pad2[1] = sqe->__pad2[2] = 0;
486 sqe->opcode = IORING_OP_ASYNC_CANCEL;
487 sqe->flags = sflags;
488 sqe->addr = this.target;
489
490 verify( sqe->user_data == (__u64)(uintptr_t)&future );
491 __submit( context, idx );
492
493 wait(future);
494
495 if( future.result == 0 ) return true; // Entry found
496 if( future.result == -EALREADY) return true; // Entry found but in progress
497 if( future.result == -ENOENT ) return false; // Entry not found
498 return false;
499 #endif
500}
501
502//-----------------------------------------------------------------------------
503// Check if a function is has asynchronous
504bool has_user_level_blocking( fptr_t func ) {
505 #if defined(CFA_HAVE_LINUX_IO_URING_H)""")
506
507for c in calls:
508 if c.define:
509 print(""" #if defined({define})
510 if( /*func == (fptr_t)preadv2 || */
511 func == (fptr_t)cfa_{name} ||
512 func == (fptr_t)async_{name} ) {{
513 #if defined(CFA_HAVE_IORING_OP_{op})
514 return true;
515 #else
516 return false;
517 #endif
518 }}
519 #endif""".format(define=c.define, name=c.name, op=c.op))
520 else:
521 print(""" if( /*func == (fptr_t)preadv2 || */
522 func == (fptr_t)cfa_{name} ||
523 func == (fptr_t)async_{name} ) {{
524 #if defined(CFA_HAVE_IORING_OP_{op})
525 return true;
526 #else
527 return false;
528 #endif
529 }}""".format(name=c.name, op=c.op))
530
531print(""" #endif
532
533 return false;
534}""")
Note: See TracBrowser for help on using the repository browser.