• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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