1 /* SPDX-License-Identifier: MIT */
2 #ifndef LIBURING_PROXY_H
3 #define LIBURING_PROXY_H
4
5 #include <sys/time.h>
6
7 /*
8 * Generic opcode agnostic encoding to sqe/cqe->user_data
9 */
10 struct userdata {
11 union {
12 struct {
13 uint16_t op_tid; /* 4 bits op, 12 bits tid */
14 uint16_t bid;
15 uint16_t fd;
16 };
17 uint64_t val;
18 };
19 };
20
21 #define OP_SHIFT (12)
22 #define TID_MASK ((1U << 12) - 1)
23
24 /*
25 * Packs the information that we will need at completion time into the
26 * sqe->user_data field, which is passed back in the completion in
27 * cqe->user_data. Some apps would need more space than this, and in fact
28 * I'd love to pack the requested IO size in here, and it's not uncommon to
29 * see apps use this field as just a cookie to either index a data structure
30 * at completion time, or even just put the pointer to the associated
31 * structure into this field.
32 */
__encode_userdata(struct io_uring_sqe * sqe,int tid,int op,int bid,int fd)33 static inline void __encode_userdata(struct io_uring_sqe *sqe, int tid, int op,
34 int bid, int fd)
35 {
36 struct userdata ud = {
37 .op_tid = (op << OP_SHIFT) | tid,
38 .bid = bid,
39 .fd = fd
40 };
41
42 io_uring_sqe_set_data64(sqe, ud.val);
43 }
44
__raw_encode(int tid,int op,int bid,int fd)45 static inline uint64_t __raw_encode(int tid, int op, int bid, int fd)
46 {
47 struct userdata ud = {
48 .op_tid = (op << OP_SHIFT) | tid,
49 .bid = bid,
50 .fd = fd
51 };
52
53 return ud.val;
54 }
55
cqe_to_op(struct io_uring_cqe * cqe)56 static inline int cqe_to_op(struct io_uring_cqe *cqe)
57 {
58 struct userdata ud = { .val = cqe->user_data };
59
60 return ud.op_tid >> OP_SHIFT;
61 }
62
cqe_to_bid(struct io_uring_cqe * cqe)63 static inline int cqe_to_bid(struct io_uring_cqe *cqe)
64 {
65 struct userdata ud = { .val = cqe->user_data };
66
67 return ud.bid;
68 }
69
cqe_to_fd(struct io_uring_cqe * cqe)70 static inline int cqe_to_fd(struct io_uring_cqe *cqe)
71 {
72 struct userdata ud = { .val = cqe->user_data };
73
74 return ud.fd;
75 }
76
mtime_since(const struct timeval * s,const struct timeval * e)77 static unsigned long long mtime_since(const struct timeval *s,
78 const struct timeval *e)
79 {
80 long long sec, usec;
81
82 sec = e->tv_sec - s->tv_sec;
83 usec = (e->tv_usec - s->tv_usec);
84 if (sec > 0 && usec < 0) {
85 sec--;
86 usec += 1000000;
87 }
88
89 sec *= 1000;
90 usec /= 1000;
91 return sec + usec;
92 }
93
mtime_since_now(struct timeval * tv)94 static unsigned long long mtime_since_now(struct timeval *tv)
95 {
96 struct timeval end;
97
98 gettimeofday(&end, NULL);
99 return mtime_since(tv, &end);
100 }
101
102 #endif
103