source: benchmark/io/io_uring.h@ f03209d3

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 f03209d3 was 1c49dc5, checked in by Thierry Delisle <tdelisle@…>, 5 years ago

Updated batch benchmark to factor io_uring setup

  • Property mode set to 100644
File size: 5.2 KB
Line 
1extern "C" {
2 #ifndef _GNU_SOURCE /* See feature_test_macros(7) */
3 #define _GNU_SOURCE /* See feature_test_macros(7) */
4 #endif
5 #include <errno.h>
6 #include <stdio.h>
7 #include <stdint.h>
8 #include <stdlib.h>
9 #include <string.h>
10 #include <unistd.h>
11 #include <sys/mman.h>
12 #include <sys/syscall.h>
13 #include <sys/uio.h>
14 #include <fcntl.h>
15
16 #include <linux/io_uring.h>
17}
18
19# ifndef __NR_io_uring_setup
20# define __NR_io_uring_setup 425
21# endif
22# ifndef __NR_io_uring_enter
23# define __NR_io_uring_enter 426
24# endif
25# ifndef __NR_io_uring_register
26# define __NR_io_uring_register 427
27# endif
28
29struct io_uring_sq {
30 // Head and tail of the ring (associated with array)
31 volatile uint32_t * head;
32 volatile uint32_t * tail;
33
34 // The actual kernel ring which uses head/tail
35 // indexes into the sqes arrays
36 uint32_t * array;
37
38 // number of entries and mask to go with it
39 const uint32_t * num;
40 const uint32_t * mask;
41
42 // Submission flags (Not sure what for)
43 uint32_t * flags;
44
45 // number of sqes not submitted (whatever that means)
46 uint32_t * dropped;
47
48 // Like head/tail but not seen by the kernel
49 volatile uint32_t alloc;
50
51 // A buffer of sqes (not the actual ring)
52 struct io_uring_sqe * sqes;
53
54 // The location and size of the mmaped area
55 void * ring_ptr;
56 size_t ring_sz;
57};
58
59struct io_uring_cq {
60 // Head and tail of the ring
61 volatile uint32_t * head;
62 volatile uint32_t * tail;
63
64 // number of entries and mask to go with it
65 const uint32_t * mask;
66 const uint32_t * num;
67
68 // number of cqes not submitted (whatever that means)
69 uint32_t * overflow;
70
71 // the kernel ring
72 struct io_uring_cqe * cqes;
73
74 // The location and size of the mmaped area
75 void * ring_ptr;
76 size_t ring_sz;
77};
78
79struct io_ring {
80 struct io_uring_sq submit_q;
81 struct io_uring_cq completion_q;
82 uint32_t flags;
83 int fd;
84};
85
86struct IO_singleton {
87 io_ring io;
88};
89
90IO_singleton self;
91
92void init_uring(uint32_t nentries) {
93 // Step 1 : call to setup
94 struct io_uring_params params;
95 memset(&params, 0, sizeof(params));
96 // params.flags = IORING_SETUP_SQPOLL;
97
98 int fd = syscall(__NR_io_uring_setup, nentries, &params );
99 if(fd < 0) {
100 fprintf(stderr, "KERNEL ERROR: IO_URING SETUP - %s\n", strerror(errno));
101 abort();
102 }
103
104 // Step 2 : mmap result
105 memset(&self.io, 0, sizeof(struct io_ring));
106 struct io_uring_sq & sq = self.io.submit_q;
107 struct io_uring_cq & cq = self.io.completion_q;
108
109 // calculate the right ring size
110 sq.ring_sz = params.sq_off.array + (params.sq_entries * sizeof(unsigned) );
111 cq.ring_sz = params.cq_off.cqes + (params.cq_entries * sizeof(struct io_uring_cqe));
112
113 // Requires features
114 // // adjust the size according to the parameters
115 // if ((params.features & IORING_FEAT_SINGLE_MMAP) != 0) {
116 // cq->ring_sz = sq->ring_sz = max(cq->ring_sz, sq->ring_sz);
117 // }
118
119 // mmap the Submit Queue into existence
120 sq.ring_ptr = mmap(0, sq.ring_sz, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_POPULATE, fd, IORING_OFF_SQ_RING);
121 if (sq.ring_ptr == (void*)MAP_FAILED) {
122 fprintf(stderr, "KERNEL ERROR: IO_URING MMAP1 - %s\n", strerror(errno));
123 abort();
124 }
125
126 // mmap the Completion Queue into existence (may or may not be needed)
127 // Requires features
128 // if ((params.features & IORING_FEAT_SINGLE_MMAP) != 0) {
129 // cq->ring_ptr = sq->ring_ptr;
130 // }
131 // else {
132 // We need multiple call to MMAP
133 cq.ring_ptr = mmap(0, cq.ring_sz, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_POPULATE, fd, IORING_OFF_CQ_RING);
134 if (cq.ring_ptr == (void*)MAP_FAILED) {
135 munmap(sq.ring_ptr, sq.ring_sz);
136 fprintf(stderr, "KERNEL ERROR: IO_URING MMAP2 - %s\n", strerror(errno));
137 abort();
138 }
139 // }
140
141 // mmap the submit queue entries
142 size_t size = params.sq_entries * sizeof(struct io_uring_sqe);
143 sq.sqes = (struct io_uring_sqe *)mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_POPULATE, fd, IORING_OFF_SQES);
144 if (sq.sqes == (struct io_uring_sqe *)MAP_FAILED) {
145 munmap(sq.ring_ptr, sq.ring_sz);
146 if (cq.ring_ptr != sq.ring_ptr) munmap(cq.ring_ptr, cq.ring_sz);
147 fprintf(stderr, "KERNEL ERROR: IO_URING MMAP3 - %s\n", strerror(errno));
148 abort();
149 }
150
151 // Get the pointers from the kernel to fill the structure
152 // submit queue
153 sq.head = (volatile uint32_t *)(((intptr_t)sq.ring_ptr) + params.sq_off.head);
154 sq.tail = (volatile uint32_t *)(((intptr_t)sq.ring_ptr) + params.sq_off.tail);
155 sq.mask = ( const uint32_t *)(((intptr_t)sq.ring_ptr) + params.sq_off.ring_mask);
156 sq.num = ( const uint32_t *)(((intptr_t)sq.ring_ptr) + params.sq_off.ring_entries);
157 sq.flags = ( uint32_t *)(((intptr_t)sq.ring_ptr) + params.sq_off.flags);
158 sq.dropped = ( uint32_t *)(((intptr_t)sq.ring_ptr) + params.sq_off.dropped);
159 sq.array = ( uint32_t *)(((intptr_t)sq.ring_ptr) + params.sq_off.array);
160 sq.alloc = *sq.tail;
161
162 // completion queue
163 cq.head = (volatile uint32_t *)(((intptr_t)cq.ring_ptr) + params.cq_off.head);
164 cq.tail = (volatile uint32_t *)(((intptr_t)cq.ring_ptr) + params.cq_off.tail);
165 cq.mask = ( const uint32_t *)(((intptr_t)cq.ring_ptr) + params.cq_off.ring_mask);
166 cq.num = ( const uint32_t *)(((intptr_t)cq.ring_ptr) + params.cq_off.ring_entries);
167 cq.overflow = ( uint32_t *)(((intptr_t)cq.ring_ptr) + params.cq_off.overflow);
168 cq.cqes = (struct io_uring_cqe *)(((intptr_t)cq.ring_ptr) + params.cq_off.cqes);
169
170 self.io.fd = fd;
171}
Note: See TracBrowser for help on using the repository browser.