/* SPDX-License-Identifier: MIT */ #ifndef LIBURING_PROXY_H #define LIBURING_PROXY_H #include /* * Generic opcode agnostic encoding to sqe/cqe->user_data */ struct userdata { union { struct { uint16_t op_tid; /* 4 bits op, 12 bits tid */ uint16_t bid; uint16_t fd; }; uint64_t val; }; }; #define OP_SHIFT (12) #define TID_MASK ((1U << 12) - 1) /* * Packs the information that we will need at completion time into the * sqe->user_data field, which is passed back in the completion in * cqe->user_data. Some apps would need more space than this, and in fact * I'd love to pack the requested IO size in here, and it's not uncommon to * see apps use this field as just a cookie to either index a data structure * at completion time, or even just put the pointer to the associated * structure into this field. */ static inline void __encode_userdata(struct io_uring_sqe *sqe, int tid, int op, int bid, int fd) { struct userdata ud = { .op_tid = (op << OP_SHIFT) | tid, .bid = bid, .fd = fd }; io_uring_sqe_set_data64(sqe, ud.val); } static inline uint64_t __raw_encode(int tid, int op, int bid, int fd) { struct userdata ud = { .op_tid = (op << OP_SHIFT) | tid, .bid = bid, .fd = fd }; return ud.val; } static inline int cqe_to_op(struct io_uring_cqe *cqe) { struct userdata ud = { .val = cqe->user_data }; return ud.op_tid >> OP_SHIFT; } static inline int cqe_to_bid(struct io_uring_cqe *cqe) { struct userdata ud = { .val = cqe->user_data }; return ud.bid; } static inline int cqe_to_fd(struct io_uring_cqe *cqe) { struct userdata ud = { .val = cqe->user_data }; return ud.fd; } static unsigned long long mtime_since(const struct timeval *s, const struct timeval *e) { long long sec, usec; sec = e->tv_sec - s->tv_sec; usec = (e->tv_usec - s->tv_usec); if (sec > 0 && usec < 0) { sec--; usec += 1000000; } sec *= 1000; usec /= 1000; return sec + usec; } static unsigned long long mtime_since_now(struct timeval *tv) { struct timeval end; gettimeofday(&end, NULL); return mtime_since(tv, &end); } #endif