19 #include <sys/types.h>
21 #include <sys/socket.h>
32 #define ALIGN(i, sz) (((i) + (sz) - 1) & ~((sz) - 1))
35 #define MAP_ANONYMOUS MAP_ANON
38 #define UDEBUG_MIN_ALLOC_LEN 128
48 clock_gettime(CLOCK_REALTIME, &ts);
49 r = ts.tv_sec + ts.tv_nsec;
50 for (i=0; i<6; i++, r>>=5)
51 template[i] =
'A'+(r&15)+(r&16)*2;
56 uint32_t id1 = (uint32_t)(uintptr_t)k1, id2 = (uint32_t)(uintptr_t)k2;
67 char *
template =
name + strlen(
name) - 6;
70 if (
template <
name || memcmp(
template,
"XXXXXX", 6) != 0)
73 for (
int i = 0; i < 100; i++) {
75 fd = shm_open(
name, O_RDWR | O_CREAT | O_EXCL, 0600);
77 if (shm_unlink(
name) < 0) {
84 if (
fd < 0 && errno != EEXIST)
106 clock_gettime(CLOCK_REALTIME, &ts);
110 val += ts.tv_nsec / 1000;
118 unsigned int pad = 0;
126 if (ptr == MAP_FAILED)
134 PROT_READ | PROT_WRITE, MAP_FIXED | MAP_SHARED,
fd, 0);
139 PROT_READ | PROT_WRITE, MAP_FIXED | MAP_SHARED,
fd,
156 uint8_t fd_buf[CMSG_SPACE(
sizeof(
int))] = { 0 };
157 struct msghdr msghdr = { 0 };
158 struct cmsghdr *cmsg;
162 msghdr.msg_iov = iov,
163 msghdr.msg_iovlen = iov_len,
164 msghdr.msg_control = fd_buf;
165 msghdr.msg_controllen =
sizeof(fd_buf);
167 cmsg = CMSG_FIRSTHDR(&msghdr);
168 cmsg->cmsg_type = SCM_RIGHTS;
169 cmsg->cmsg_level = SOL_SOCKET;
170 cmsg->cmsg_len = CMSG_LEN(
sizeof(
int));
172 pfd = (
int *) CMSG_DATA(cmsg);
173 msghdr.msg_controllen = cmsg->cmsg_len;
179 msghdr.msg_control = NULL;
180 msghdr.msg_controllen = 0;
185 cur_len = sendmsg(
fd, &msghdr, 0);
187 struct pollfd pfd = {
208 while (cur_len >= (ssize_t) iov->iov_len) {
209 cur_len -= iov->iov_len;
215 iov->iov_base += cur_len;
216 iov->iov_len -= cur_len;
217 msghdr.msg_iov = iov;
218 msghdr.msg_iovlen = iov_len;
228 uint8_t fd_buf[CMSG_SPACE(
sizeof(
int))] = { 0 };
229 struct msghdr msghdr = { 0 };
230 struct cmsghdr *cmsg;
235 msghdr.msg_iov = iov,
236 msghdr.msg_iovlen = 1,
237 msghdr.msg_control = fd_buf;
238 msghdr.msg_controllen =
sizeof(fd_buf);
240 cmsg = CMSG_FIRSTHDR(&msghdr);
241 cmsg->cmsg_type = SCM_RIGHTS;
242 cmsg->cmsg_level = SOL_SOCKET;
243 cmsg->cmsg_len = CMSG_LEN(
sizeof(
int));
245 pfd = (
int *) CMSG_DATA(cmsg);
247 while (iov->iov_len > 0) {
249 msghdr.msg_control = fd_buf;
250 msghdr.msg_controllen = cmsg->cmsg_len;
252 msghdr.msg_control = NULL;
253 msghdr.msg_controllen = 0;
257 bytes = recvmsg(
fd, &msghdr, 0);
280 iov->iov_len -= bytes;
281 iov->iov_base += bytes;
284 if (iov->iov_len > 0) {
285 struct pollfd pfd = {
292 }
while (ret < 0 && errno == EINTR);
294 if (!(pfd.revents & POLLIN))
306 struct iovec iov[2] = {
307 { .iov_base =
msg, .iov_len =
sizeof(*msg) },
316 iov[1].iov_base = meta;
327 .iov_len =
sizeof(*msg)
335 return ret ==
sizeof(*msg);
356 key = (
void *)(uintptr_t)
msg.
id;
358 if (!rb || !rb->
poll)
452 char filename[] =
"/udebug.XXXXXX";
453 unsigned int order = 12;
454 uint8_t ring_order = 5;
462 while(size > 1U << order)
465 while (entries > 1U << ring_order)
467 entries = 1 << ring_order;
469 if (size > (1U << 29) || entries > (1U << 24))
480 if (ftruncate(
fd, head_size + size) < 0)
495 __sync_synchronize();
511 __sync_synchronize();
524 flags = hdr->
flags[0];
525 if (
sizeof(flags) !=
sizeof(uintptr_t))
526 flags |= ((uint64_t)hdr->
flags[1]) << 32;
562 memcpy(ret,
data, len);
635 len = vsnprintf(str, len, fmt, ap);
660 __sync_synchronize();
667 __sync_synchronize();
669 notify = __atomic_exchange_n(&hdr->
notify, 0, __ATOMIC_RELAXED);
674 .notify_mask = notify,
688 if (ctx && ctx->
fd.
fd >= 0)
693 memset(buf, 0,
sizeof(*buf));
711 for (
size_t i = 0; i < meta->
n_flags; i++) {
void avl_init(struct avl_tree *tree, avl_tree_comp comp, bool allow_dups, void *ptr)
#define avl_find_element(tree, key, element, node_element)
#define avl_for_each_element(tree, element, node_member)
#define avl_for_each_element_safe(tree, element, node_member, ptr)
int blob_buf_init(struct blob_buf *buf, int id)
static size_t blob_pad_len(const struct blob_attr *attr)
static int blobmsg_add_u64(struct blob_buf *buf, const char *name, uint64_t val)
static int blobmsg_add_string(struct blob_buf *buf, const char *name, const char *string)
static void blobmsg_close_array(struct blob_buf *buf, void *cookie)
static void * blobmsg_open_array(struct blob_buf *buf, const char *name)
static void list_add_tail(struct list_head *_new, struct list_head *head)
#define list_for_each_entry(p, h, field)
static bool list_empty(const struct list_head *head)
static void list_del(struct list_head *entry)
#define list_first_entry(ptr, type, field)
static void INIT_LIST_HEAD(struct list_head *list)
#define container_of(ptr, type, member)
const struct udebug_buf_meta * meta
uintptr_t flags[8/sizeof(uintptr_t)]
struct uloop_timeout reconnect
void(* notify_cb)(struct udebug *ctx, struct udebug_remote_buf *rb)
struct avl_tree remote_rings
struct list_head local_rings
int uint32_t uint32_t data_size
struct udebug_client_msg int * rfd
static uint32_t u32_get(void *ptr)
struct udebug_client_msg * msg
static int32_t u32_max(uint32_t a, uint32_t b)
static void u32_set(void *ptr, uint32_t val)
static struct udebug_ptr * udebug_ring_ptr(struct udebug_hdr *hdr, uint32_t idx)
static void * udebug_buf_ptr(struct udebug_buf *buf, uint32_t ofs)
int udebug_remote_buf_set_poll(struct udebug *ctx, struct udebug_remote_buf *rb, bool val)
void udebug_remote_buf_unmap(struct udebug *ctx, struct udebug_remote_buf *rb)
static void udebug_buf_msg(struct udebug_buf *buf, enum udebug_client_msg_type type)
void udebug_add_uloop(struct udebug *ctx)
static void * udebug_buf_alloc(struct udebug_buf *buf, uint32_t ofs, uint32_t len)
static unsigned int page_size
static void udebug_reconnect_cb(struct uloop_timeout *t)
static void udebug_init_page_size(void)
void udebug_entry_add(struct udebug_buf *buf)
static int shm_open_anon(char *name)
void * udebug_entry_append(struct udebug_buf *buf, const void *data, uint32_t len)
static size_t __udebug_headsize(unsigned int ring_size)
uint16_t udebug_entry_trim(struct udebug_buf *buf, uint16_t len)
int udebug_connect(struct udebug *ctx, const char *path)
static void __randname(char *template)
int udebug_entry_vprintf(struct udebug_buf *buf, const char *fmt, va_list ap)
int udebug_buf_add(struct udebug *ctx, struct udebug_buf *buf, const struct udebug_buf_meta *meta)
int udebug_entry_printf(struct udebug_buf *buf, const char *fmt,...)
static int __udebug_buf_map(struct udebug_buf *buf, int fd)
uint64_t udebug_buf_flags(struct udebug_buf *buf)
void udebug_free(struct udebug *ctx)
static struct udebug_client_msg * udebug_wait_for_response(struct udebug *ctx, struct udebug_client_msg *msg, int *rfd)
static int recv_retry(int fd, struct iovec *iov, bool wait, int *recv_fd)
static void udebug_fd_cb(struct uloop_fd *fd, unsigned int events)
static struct udebug_client_msg * __udebug_poll(struct udebug *ctx, int *fd, bool wait)
void udebug_buf_free(struct udebug_buf *buf)
static int writev_retry(int fd, struct iovec *iov, int iov_len, int sock_fd)
uint64_t udebug_timestamp(void)
static void udebug_send_msg(struct udebug *ctx, struct udebug_client_msg *msg, struct blob_attr *meta, int fd)
#define UDEBUG_MIN_ALLOC_LEN
static void __udebug_disconnect(struct udebug *ctx, bool reconnect)
struct udebug_client_msg * udebug_send_and_wait(struct udebug *ctx, struct udebug_client_msg *msg, int *rfd)
int udebug_buf_init(struct udebug_buf *buf, size_t entries, size_t size)
static bool udebug_recv_msg(struct udebug *ctx, struct udebug_client_msg *msg, int *fd, bool wait)
void udebug_auto_connect(struct udebug *ctx, const char *path)
void udebug_poll(struct udebug *ctx)
void udebug_entry_set_length(struct udebug_buf *buf, uint16_t len)
void udebug_init(struct udebug *ctx)
static void __udebug_buf_add(struct udebug *ctx, struct udebug_buf *buf)
int udebug_buf_open(struct udebug_buf *buf, int fd, uint32_t ring_size, uint32_t data_size)
void udebug_entry_init_ts(struct udebug_buf *buf, uint64_t timestamp)
int udebug_id_cmp(const void *k1, const void *k2, void *ptr)
static struct epoll_event events[ULOOP_MAX_EVENTS]
int uloop_fd_add(struct uloop_fd *sock, unsigned int flags)
int uloop_timeout_cancel(struct uloop_timeout *timeout)
int uloop_fd_delete(struct uloop_fd *fd)
int uloop_timeout_set(struct uloop_timeout *timeout, int msecs)
int usock(int type, const char *host, const char *service)