source: libcfa/src/concurrency/iocall.cfa @ 4ec028d

ADTarm-ehast-experimentalenumforall-pointer-decayjacob/cs343-translationnew-astnew-ast-unique-exprpthread-emulationqualifiedEnum
Last change on this file since 4ec028d was 31bb2e1, checked in by Thierry Delisle <tdelisle@…>, 4 years ago

Moved implementations of cfa_[io call] to iocall.cfa

  • Property mode set to 100644
File size: 11.7 KB
Line 
1//
2// Cforall Version 1.0.0 Copyright (C) 2020 University of Waterloo
3//
4// The contents of this file are covered under the licence agreement in the
5// file "LICENCE" distributed with Cforall.
6//
7// iocall.cfa --
8//
9// Author           : Thierry Delisle
10// Created On       : Wed Jul  1 14:51:00 2020
11// Last Modified By :
12// Last Modified On :
13// Update Count     :
14//
15
16#if defined(HAVE_LINUX_IO_URING_H)
17        #include <stdint.h>
18        #include <linux/io_uring.h>
19
20        #include "kernel_private.hfa"
21
22        extern [* struct io_uring_sqe, uint32_t] __submit_alloc( struct __io_data & ring, uint64_t data );
23        extern void __submit( struct __io_data & ring, uint32_t idx );
24
25//=============================================================================================
26// I/O Interface
27//=============================================================================================
28
29        #define __submit_prelude \
30                __io_user_data_t data = { 0, active_thread() }; \
31                struct __io_data & ring = *data.thrd->curr_cluster->io; \
32                struct io_uring_sqe * sqe; \
33                uint32_t idx; \
34                [sqe, idx] = __submit_alloc( ring, (uint64_t)(uintptr_t)&data );
35
36        #define __submit_wait \
37                /*__cfaabi_bits_print_safe( STDERR_FILENO, "Preparing user data %p for %p\n", &data, data.thrd );*/ \
38                verify( sqe->user_data == (uint64_t)(uintptr_t)&data ); \
39                __submit( ring, idx ); \
40                park( __cfaabi_dbg_ctx ); \
41                return data.result;
42        #endif
43
44        // Some forward declarations
45        #include <unistd.h>
46
47        extern "C" {
48                #include <sys/types.h>
49                #include <sys/socket.h>
50                #include <sys/syscall.h>
51
52        #if defined(HAVE_PREADV2)
53                struct iovec;
54                extern ssize_t preadv2 (int fd, const struct iovec *iov, int iovcnt, off_t offset, int flags);
55        #endif
56        #if defined(HAVE_PWRITEV2)
57                struct iovec;
58                extern ssize_t pwritev2(int fd, const struct iovec *iov, int iovcnt, off_t offset, int flags);
59        #endif
60
61                extern int fsync(int fd);
62                extern int sync_file_range(int fd, int64_t offset, int64_t nbytes, unsigned int flags);
63
64                struct msghdr;
65                struct sockaddr;
66                extern ssize_t sendmsg(int sockfd, const struct msghdr *msg, int flags);
67                extern ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags);
68                extern ssize_t send(int sockfd, const void *buf, size_t len, int flags);
69                extern ssize_t recv(int sockfd, void *buf, size_t len, int flags);
70                extern int accept4(int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags);
71                extern int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
72
73                extern int fallocate(int fd, int mode, uint64_t offset, uint64_t len);
74                extern int posix_fadvise(int fd, uint64_t offset, uint64_t len, int advice);
75                extern int madvise(void *addr, size_t length, int advice);
76
77                extern int openat(int dirfd, const char *pathname, int flags, mode_t mode);
78                extern int close(int fd);
79
80                extern ssize_t read (int fd, void *buf, size_t count);
81        }
82
83        //-----------------------------------------------------------------------------
84        // Asynchronous operations
85        #if defined(HAVE_PREADV2)
86                ssize_t cfa_preadv2(int fd, const struct iovec *iov, int iovcnt, off_t offset, int flags) {
87                        #if !defined(HAVE_LINUX_IO_URING_H) || !defined(IORING_OP_READV)
88                                return preadv2(fd, iov, iovcnt, offset, flags);
89                        #else
90                                __submit_prelude
91
92                                (*sqe){ IORING_OP_READV, fd, iov, iovcnt, offset };
93
94                                __submit_wait
95                        #endif
96                }
97        #endif
98
99        #if defined(HAVE_PWRITEV2)
100                ssize_t cfa_pwritev2(int fd, const struct iovec *iov, int iovcnt, off_t offset, int flags) {
101                        #if !defined(HAVE_LINUX_IO_URING_H) || !defined(IORING_OP_WRITEV)
102                                return pwritev2(fd, iov, iovcnt, offset, flags);
103                        #else
104                                __submit_prelude
105
106                                (*sqe){ IORING_OP_WRITEV, fd, iov, iovcnt, offset };
107
108                                __submit_wait
109                        #endif
110                }
111        #endif
112
113        int cfa_fsync(int fd) {
114                #if !defined(HAVE_LINUX_IO_URING_H) || !defined(IORING_OP_FSYNC)
115                        return fsync(fd);
116                #else
117                        __submit_prelude
118
119                        (*sqe){ IORING_OP_FSYNC, fd };
120
121                        __submit_wait
122                #endif
123        }
124
125        int cfa_sync_file_range(int fd, int64_t offset, int64_t nbytes, unsigned int flags) {
126                #if !defined(HAVE_LINUX_IO_URING_H) || !defined(IORING_OP_SYNC_FILE_RANGE)
127                        return sync_file_range(fd, offset, nbytes, flags);
128                #else
129                        __submit_prelude
130
131                        (*sqe){ IORING_OP_SYNC_FILE_RANGE, fd };
132                        sqe->off = offset;
133                        sqe->len = nbytes;
134                        sqe->sync_range_flags = flags;
135
136                        __submit_wait
137                #endif
138        }
139
140
141        ssize_t cfa_sendmsg(int sockfd, const struct msghdr *msg, int flags) {
142                #if !defined(HAVE_LINUX_IO_URING_H) || !defined(IORING_OP_SENDMSG)
143                        return sendmsg(sockfd, msg, flags);
144                #else
145                        __submit_prelude
146
147                        (*sqe){ IORING_OP_SENDMSG, sockfd, msg, 1, 0 };
148                        sqe->msg_flags = flags;
149
150                        __submit_wait
151                #endif
152        }
153
154        ssize_t cfa_recvmsg(int sockfd, struct msghdr *msg, int flags) {
155                #if !defined(HAVE_LINUX_IO_URING_H) || !defined(IORING_OP_RECVMSG)
156                        return recvmsg(sockfd, msg, flags);
157                #else
158                        __submit_prelude
159
160                        (*sqe){ IORING_OP_RECVMSG, sockfd, msg, 1, 0 };
161                        sqe->msg_flags = flags;
162
163                        __submit_wait
164                #endif
165        }
166
167        ssize_t cfa_send(int sockfd, const void *buf, size_t len, int flags) {
168                #if !defined(HAVE_LINUX_IO_URING_H) || !defined(IORING_OP_SEND)
169                        return send( sockfd, buf, len, flags );
170                #else
171                        __submit_prelude
172
173                        (*sqe){ IORING_OP_SEND, sockfd };
174                        sqe->addr = (uint64_t)buf;
175                        sqe->len = len;
176                        sqe->msg_flags = flags;
177
178                        __submit_wait
179                #endif
180        }
181
182        ssize_t cfa_recv(int sockfd, void *buf, size_t len, int flags) {
183                #if !defined(HAVE_LINUX_IO_URING_H) || !defined(IORING_OP_RECV)
184                        return recv( sockfd, buf, len, flags );
185                #else
186                        __submit_prelude
187
188                        (*sqe){ IORING_OP_RECV, sockfd };
189                        sqe->addr = (uint64_t)buf;
190                        sqe->len = len;
191                        sqe->msg_flags = flags;
192
193                        __submit_wait
194                #endif
195        }
196
197        int cfa_accept4(int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags) {
198                #if !defined(HAVE_LINUX_IO_URING_H) || !defined(IORING_OP_ACCEPT)
199                        return accept4( sockfd, addr, addrlen, flags );
200                #else
201                        __submit_prelude
202
203                        (*sqe){ IORING_OP_ACCEPT, sockfd };
204                        sqe->addr = addr;
205                        sqe->addr2 = addrlen;
206                        sqe->accept_flags = flags;
207
208                        __submit_wait
209                #endif
210        }
211
212        int cfa_connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen) {
213                #if !defined(HAVE_LINUX_IO_URING_H) || !defined(IORING_OP_CONNECT)
214                        return connect( sockfd, addr, addrlen );
215                #else
216                        __submit_prelude
217
218                        (*sqe){ IORING_OP_CONNECT, sockfd };
219                        sqe->addr = (uint64_t)addr;
220                        sqe->off = addrlen;
221
222                        __submit_wait
223                #endif
224        }
225
226        int cfa_fallocate(int fd, int mode, uint64_t offset, uint64_t len) {
227                #if !defined(HAVE_LINUX_IO_URING_H) || !defined(IORING_OP_FALLOCATE)
228                        return fallocate( fd, mode, offset, len );
229                #else
230                        __submit_prelude
231
232                        (*sqe){ IORING_OP_FALLOCATE, fd };
233                        sqe->off = offset;
234                        sqe->len = length;
235                        sqe->mode = mode;
236
237                        __submit_wait
238                #endif
239        }
240
241        int cfa_fadvise(int fd, uint64_t offset, uint64_t len, int advice) {
242                #if !defined(HAVE_LINUX_IO_URING_H) || !defined(IORING_OP_FADVISE)
243                        return posix_fadvise( fd, offset, len, advice );
244                #else
245                        __submit_prelude
246
247                        (*sqe){ IORING_OP_FADVISE, fd };
248                        sqe->off = (uint64_t)offset;
249                        sqe->len = length;
250                        sqe->fadvise_advice = advice;
251
252                        __submit_wait
253                #endif
254        }
255
256        int cfa_madvise(void *addr, size_t length, int advice) {
257                #if !defined(HAVE_LINUX_IO_URING_H) || !defined(IORING_OP_MADVISE)
258                        return madvise( addr, length, advice );
259                #else
260                        __submit_prelude
261
262                        (*sqe){ IORING_OP_MADVISE, 0 };
263                        sqe->addr = (uint64_t)addr;
264                        sqe->len = length;
265                        sqe->fadvise_advice = advice;
266
267                        __submit_wait
268                #endif
269        }
270
271        int cfa_openat(int dirfd, const char *pathname, int flags, mode_t mode) {
272                #if !defined(HAVE_LINUX_IO_URING_H) || !defined(IORING_OP_OPENAT)
273                        return openat( dirfd, pathname, flags, mode );
274                #else
275                        __submit_prelude
276
277                        (*sqe){ IORING_OP_OPENAT, dirfd };
278                        sqe->addr = (uint64_t)pathname;
279                        sqe->open_flags = flags;
280                        sqe->mode = mode;
281
282                        __submit_wait
283                #endif
284        }
285
286        int cfa_close(int fd) {
287                #if !defined(HAVE_LINUX_IO_URING_H) || !defined(IORING_OP_CLOSE)
288                        return close( fd );
289                #else
290                        __submit_prelude
291
292                        (*sqe){ IORING_OP_CLOSE, fd };
293
294                        __submit_wait
295                #endif
296        }
297
298
299        ssize_t cfa_read(int fd, void *buf, size_t count) {
300                #if !defined(HAVE_LINUX_IO_URING_H) || !defined(IORING_OP_READ)
301                        return read( fd, buf, count );
302                #else
303                        __submit_prelude
304
305                        (*sqe){ IORING_OP_READ, fd, buf, count, 0 };
306
307                        __submit_wait
308                #endif
309        }
310
311        ssize_t cfa_write(int fd, void *buf, size_t count) {
312                #if !defined(HAVE_LINUX_IO_URING_H) || !defined(IORING_OP_WRITE)
313                        return read( fd, buf, count );
314                #else
315                        __submit_prelude
316
317                        (*sqe){ IORING_OP_WRITE, fd, buf, count, 0 };
318
319                        __submit_wait
320                #endif
321        }
322
323        //-----------------------------------------------------------------------------
324        // Check if a function is asynchronous
325
326        // Macro magic to reduce the size of the following switch case
327        #define IS_DEFINED_APPLY(f, ...) f(__VA_ARGS__)
328        #define IS_DEFINED_SECOND(first, second, ...) second
329        #define IS_DEFINED_TEST(expansion) _CFA_IO_FEATURE_##expansion
330        #define IS_DEFINED(macro) IS_DEFINED_APPLY( IS_DEFINED_SECOND,IS_DEFINED_TEST(macro) false, true)
331
332        bool has_user_level_blocking( fptr_t func ) {
333                #if defined(HAVE_LINUX_IO_URING_H)
334                        #if defined(HAVE_PREADV2)
335                                if( /*func == (fptr_t)preadv2 || */
336                                        func == (fptr_t)cfa_preadv2 )
337                                        #define _CFA_IO_FEATURE_IORING_OP_READV ,
338                                        return IS_DEFINED(IORING_OP_READV);
339                        #endif
340
341                        #if defined(HAVE_PWRITEV2)
342                                if( /*func == (fptr_t)pwritev2 || */
343                                        func == (fptr_t)cfa_pwritev2 )
344                                        #define _CFA_IO_FEATURE_IORING_OP_WRITEV ,
345                                        return IS_DEFINED(IORING_OP_WRITEV);
346                        #endif
347
348                        if( /*func == (fptr_t)fsync || */
349                                func == (fptr_t)cfa_fsync )
350                                #define _CFA_IO_FEATURE_IORING_OP_FSYNC ,
351                                return IS_DEFINED(IORING_OP_FSYNC);
352
353                        if( /*func == (fptr_t)ync_file_range || */
354                                func == (fptr_t)cfa_sync_file_range )
355                                #define _CFA_IO_FEATURE_IORING_OP_SYNC_FILE_RANGE ,
356                                return IS_DEFINED(IORING_OP_SYNC_FILE_RANGE);
357
358                        if( /*func == (fptr_t)sendmsg || */
359                                func == (fptr_t)cfa_sendmsg )
360                                #define _CFA_IO_FEATURE_IORING_OP_SENDMSG ,
361                                return IS_DEFINED(IORING_OP_SENDMSG);
362
363                        if( /*func == (fptr_t)recvmsg || */
364                                func == (fptr_t)cfa_recvmsg )
365                                #define _CFA_IO_FEATURE_IORING_OP_RECVMSG ,
366                                return IS_DEFINED(IORING_OP_RECVMSG);
367
368                        if( /*func == (fptr_t)send || */
369                                func == (fptr_t)cfa_send )
370                                #define _CFA_IO_FEATURE_IORING_OP_SEND ,
371                                return IS_DEFINED(IORING_OP_SEND);
372
373                        if( /*func == (fptr_t)recv || */
374                                func == (fptr_t)cfa_recv )
375                                #define _CFA_IO_FEATURE_IORING_OP_RECV ,
376                                return IS_DEFINED(IORING_OP_RECV);
377
378                        if( /*func == (fptr_t)accept4 || */
379                                func == (fptr_t)cfa_accept4 )
380                                #define _CFA_IO_FEATURE_IORING_OP_ACCEPT ,
381                                return IS_DEFINED(IORING_OP_ACCEPT);
382
383                        if( /*func == (fptr_t)connect || */
384                                func == (fptr_t)cfa_connect )
385                                #define _CFA_IO_FEATURE_IORING_OP_CONNECT ,
386                                return IS_DEFINED(IORING_OP_CONNECT);
387
388                        if( /*func == (fptr_t)fallocate || */
389                                func == (fptr_t)cfa_fallocate )
390                                #define _CFA_IO_FEATURE_IORING_OP_FALLOCATE ,
391                                return IS_DEFINED(IORING_OP_FALLOCATE);
392
393                        if( /*func == (fptr_t)posix_fadvise || */
394                                func == (fptr_t)cfa_fadvise )
395                                #define _CFA_IO_FEATURE_IORING_OP_FADVISE ,
396                                return IS_DEFINED(IORING_OP_FADVISE);
397
398                        if( /*func == (fptr_t)madvise || */
399                                func == (fptr_t)cfa_madvise )
400                                #define _CFA_IO_FEATURE_IORING_OP_MADVISE ,
401                                return IS_DEFINED(IORING_OP_MADVISE);
402
403                        if( /*func == (fptr_t)openat || */
404                                func == (fptr_t)cfa_openat )
405                                #define _CFA_IO_FEATURE_IORING_OP_OPENAT ,
406                                return IS_DEFINED(IORING_OP_OPENAT);
407
408                        if( /*func == (fptr_t)close || */
409                                func == (fptr_t)cfa_close )
410                                #define _CFA_IO_FEATURE_IORING_OP_CLOSE ,
411                                return IS_DEFINED(IORING_OP_CLOSE);
412
413                        if( /*func == (fptr_t)read || */
414                                func == (fptr_t)cfa_read )
415                                #define _CFA_IO_FEATURE_IORING_OP_READ ,
416                                return IS_DEFINED(IORING_OP_READ);
417
418                        if( /*func == (fptr_t)write || */
419                                func == (fptr_t)cfa_write )
420                                #define _CFA_IO_FEATURE_IORING_OP_WRITE ,
421                                return IS_DEFINED(IORING_OP_WRITE);
422                #endif
423
424                return false;
425        }
426#endif
Note: See TracBrowser for help on using the repository browser.