libubox
C utility functions for OpenWrt.
udebug.c
Go to the documentation of this file.
1 /*
2  * udebug - debug ring buffer library
3  *
4  * Copyright (C) 2023 Felix Fietkau <nbd@nbd.name>
5  *
6  * Permission to use, copy, modify, and/or distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  */
18 #define _GNU_SOURCE
19 #include <sys/types.h>
20 #include <sys/mman.h>
21 #include <sys/socket.h>
22 #include <unistd.h>
23 #include <string.h>
24 #include <stdio.h>
25 #include <fcntl.h>
26 #include <errno.h>
27 #include <poll.h>
28 #include <time.h>
29 #include "udebug-priv.h"
30 #include "usock.h"
31 
32 #define ALIGN(i, sz) (((i) + (sz) - 1) & ~((sz) - 1))
33 
34 #ifndef MAP_ANONYMOUS
35 #define MAP_ANONYMOUS MAP_ANON
36 #endif
37 
38 #define UDEBUG_MIN_ALLOC_LEN 128
39 static struct blob_buf b;
40 static unsigned int page_size;
41 
42 static void __randname(char *template)
43 {
44  int i;
45  struct timespec ts;
46  unsigned long r;
47 
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;
52 }
53 
54 int udebug_id_cmp(const void *k1, const void *k2, void *ptr)
55 {
56  uint32_t id1 = (uint32_t)(uintptr_t)k1, id2 = (uint32_t)(uintptr_t)k2;
57  if (id1 < id2)
58  return -1;
59  else if (id1 > id2)
60  return 1;
61  return 0;
62 }
63 
64 static inline int
66 {
67  char *template = name + strlen(name) - 6;
68  int fd;
69 
70  if (template < name || memcmp(template, "XXXXXX", 6) != 0)
71  return -1;
72 
73  for (int i = 0; i < 100; i++) {
74  __randname(template);
75  fd = shm_open(name, O_RDWR | O_CREAT | O_EXCL, 0600);
76  if (fd >= 0) {
77  if (shm_unlink(name) < 0) {
78  close(fd);
79  continue;
80  }
81  return fd;
82  }
83 
84  if (fd < 0 && errno != EEXIST)
85  return -1;
86  }
87 
88  return -1;
89 }
90 
91 static void __udebug_disconnect(struct udebug *ctx, bool reconnect)
92 {
93  uloop_fd_delete(&ctx->fd);
94  close(ctx->fd.fd);
95  ctx->fd.fd = -1;
96  ctx->poll_handle = -1;
97  if (ctx->reconnect.cb && reconnect)
98  uloop_timeout_set(&ctx->reconnect, 1);
99 }
100 
101 uint64_t udebug_timestamp(void)
102 {
103  struct timespec ts;
104  uint64_t val;
105 
106  clock_gettime(CLOCK_REALTIME, &ts);
107 
108  val = ts.tv_sec;
109  val *= UDEBUG_TS_SEC;
110  val += ts.tv_nsec / 1000;
111 
112  return val;
113 }
114 
115 static int
116 __udebug_buf_map(struct udebug_buf *buf, int fd)
117 {
118  unsigned int pad = 0;
119  void *ptr, *ptr2;
120 
121 #ifdef mips
122  pad = page_size;
123 #endif
124  ptr = mmap(NULL, buf->head_size + 2 * buf->data_size + pad, PROT_NONE,
125  MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
126  if (ptr == MAP_FAILED)
127  return -1;
128 
129 #ifdef mips
130  ptr = (void *)ALIGN((unsigned long)ptr, page_size);
131 #endif
132 
133  ptr2 = mmap(ptr, buf->head_size + buf->data_size,
134  PROT_READ | PROT_WRITE, MAP_FIXED | MAP_SHARED, fd, 0);
135  if (ptr2 != ptr)
136  goto err_unmap;
137 
138  ptr2 = mmap(ptr + buf->head_size + buf->data_size, buf->data_size,
139  PROT_READ | PROT_WRITE, MAP_FIXED | MAP_SHARED, fd,
140  buf->head_size);
141  if (ptr2 != ptr + buf->head_size + buf->data_size)
142  goto err_unmap;
143 
144  buf->hdr = ptr;
145  buf->data = ptr + buf->head_size;
146  return 0;
147 
148 err_unmap:
149  munmap(ptr, buf->head_size + 2 * buf->data_size);
150  return -1;
151 }
152 
153 static int
154 writev_retry(int fd, struct iovec *iov, int iov_len, int sock_fd)
155 {
156  uint8_t fd_buf[CMSG_SPACE(sizeof(int))] = { 0 };
157  struct msghdr msghdr = { 0 };
158  struct cmsghdr *cmsg;
159  int len = 0;
160  int *pfd;
161 
162  msghdr.msg_iov = iov,
163  msghdr.msg_iovlen = iov_len,
164  msghdr.msg_control = fd_buf;
165  msghdr.msg_controllen = sizeof(fd_buf);
166 
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));
171 
172  pfd = (int *) CMSG_DATA(cmsg);
173  msghdr.msg_controllen = cmsg->cmsg_len;
174 
175  do {
176  ssize_t cur_len;
177 
178  if (sock_fd < 0) {
179  msghdr.msg_control = NULL;
180  msghdr.msg_controllen = 0;
181  } else {
182  *pfd = sock_fd;
183  }
184 
185  cur_len = sendmsg(fd, &msghdr, 0);
186  if (cur_len < 0) {
187  struct pollfd pfd = {
188  .fd = fd,
189  .events = POLLOUT
190  };
191 
192  switch(errno) {
193  case EAGAIN:
194  poll(&pfd, 1, -1);
195  break;
196  case EINTR:
197  break;
198  default:
199  return -1;
200  }
201  continue;
202  }
203 
204  if (len > 0)
205  sock_fd = -1;
206 
207  len += cur_len;
208  while (cur_len >= (ssize_t) iov->iov_len) {
209  cur_len -= iov->iov_len;
210  iov_len--;
211  iov++;
212  if (!iov_len)
213  return len;
214  }
215  iov->iov_base += cur_len;
216  iov->iov_len -= cur_len;
217  msghdr.msg_iov = iov;
218  msghdr.msg_iovlen = iov_len;
219  } while (1);
220 
221  /* Should never reach here */
222  return -1;
223 }
224 
225 static int
226 recv_retry(int fd, struct iovec *iov, bool wait, int *recv_fd)
227 {
228  uint8_t fd_buf[CMSG_SPACE(sizeof(int))] = { 0 };
229  struct msghdr msghdr = { 0 };
230  struct cmsghdr *cmsg;
231  int total = 0;
232  int bytes;
233  int *pfd;
234 
235  msghdr.msg_iov = iov,
236  msghdr.msg_iovlen = 1,
237  msghdr.msg_control = fd_buf;
238  msghdr.msg_controllen = sizeof(fd_buf);
239 
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));
244 
245  pfd = (int *) CMSG_DATA(cmsg);
246 
247  while (iov->iov_len > 0) {
248  if (recv_fd) {
249  msghdr.msg_control = fd_buf;
250  msghdr.msg_controllen = cmsg->cmsg_len;
251  } else {
252  msghdr.msg_control = NULL;
253  msghdr.msg_controllen = 0;
254  }
255 
256  *pfd = -1;
257  bytes = recvmsg(fd, &msghdr, 0);
258  if (!bytes)
259  return -2;
260  if (bytes < 0) {
261  bytes = 0;
262  if (errno == EINTR)
263  continue;
264 
265  if (errno != EAGAIN)
266  return -2;
267  }
268  if (!wait && !bytes)
269  return 0;
270 
271  if (recv_fd)
272  *recv_fd = *pfd;
273  else if (*pfd >= 0)
274  close(*pfd);
275 
276  if (bytes > 0)
277  recv_fd = NULL;
278 
279  wait = true;
280  iov->iov_len -= bytes;
281  iov->iov_base += bytes;
282  total += bytes;
283 
284  if (iov->iov_len > 0) {
285  struct pollfd pfd = {
286  .fd = fd,
287  .events = POLLIN
288  };
289  int ret;
290  do {
291  ret = poll(&pfd, 1, UDEBUG_TIMEOUT);
292  } while (ret < 0 && errno == EINTR);
293 
294  if (!(pfd.revents & POLLIN))
295  return -1;
296  }
297  }
298 
299  return total;
300 }
301 
302 static void
304  struct blob_attr *meta, int fd)
305 {
306  struct iovec iov[2] = {
307  { .iov_base = msg, .iov_len = sizeof(*msg) },
308  {}
309  };
310 
311  if (!meta) {
312  blob_buf_init(&b, 0);
313  meta = b.head;
314  }
315 
316  iov[1].iov_base = meta;
317  iov[1].iov_len = blob_pad_len(meta);
318  writev_retry(ctx->fd.fd, iov, ARRAY_SIZE(iov), fd);
319 }
320 
321 static bool
322 udebug_recv_msg(struct udebug *ctx, struct udebug_client_msg *msg, int *fd,
323  bool wait)
324 {
325  struct iovec iov = {
326  .iov_base = msg,
327  .iov_len = sizeof(*msg)
328  };
329  int ret;
330 
331  ret = recv_retry(ctx->fd.fd, &iov, wait, fd);
332  if (ret == -2)
333  __udebug_disconnect(ctx, true);
334 
335  return ret == sizeof(*msg);
336 }
337 
338 static struct udebug_client_msg *
339 __udebug_poll(struct udebug *ctx, int *fd, bool wait)
340 {
341  static struct udebug_client_msg msg = {};
342 
343  while (udebug_recv_msg(ctx, &msg, fd, wait)) {
344  struct udebug_remote_buf *rb;
345  void *key;
346 
347  if (msg.type != CL_MSG_RING_NOTIFY)
348  return &msg;
349 
350  if (fd && *fd >= 0)
351  close(*fd);
352 
353  if (!ctx->notify_cb)
354  continue;
355 
356  key = (void *)(uintptr_t)msg.id;
357  rb = avl_find_element(&ctx->remote_rings, key, rb, node);
358  if (!rb || !rb->poll)
359  continue;
360 
361  if (ctx->poll_handle >= 0)
362  __atomic_fetch_or(&rb->buf.hdr->notify,
363  1UL << ctx->poll_handle,
364  __ATOMIC_RELAXED);
365  ctx->notify_cb(ctx, rb);
366  }
367 
368  return NULL;
369 }
370 
371 static struct udebug_client_msg *
373 {
374  int type = msg->type;
375  int fd = -1;
376 
377  do {
378  if (fd >= 0)
379  close(fd);
380  fd = -1;
381  msg = __udebug_poll(ctx, &fd, true);
382  } while (msg && msg->type != type);
383  if (!msg)
384  return NULL;
385 
386  if (rfd)
387  *rfd = fd;
388  else if (fd >= 0)
389  close(fd);
390 
391  return msg;
392 }
393 
394 static void
396 {
397  struct udebug_client_msg msg = {
398  .type = type,
399  .id = buf->id,
400  };
401 
402  udebug_send_msg(buf->ctx, &msg, NULL, -1);
403  udebug_wait_for_response(buf->ctx, &msg, NULL);
404 }
405 
406 static size_t __udebug_headsize(unsigned int ring_size)
407 {
408  ring_size *= sizeof(struct udebug_ptr);
409  return ALIGN(sizeof(struct udebug_hdr) + ring_size, page_size);
410 }
411 
412 static void udebug_init_page_size(void)
413 {
414  if (page_size)
415  return;
416  page_size = sysconf(_SC_PAGESIZE);
417 #ifdef mips
418  /* leave extra alignment room to account for data cache aliases */
419  if (page_size < 32 * 1024)
420  page_size = 32 * 1024;
421 #endif
422 }
423 
424 int udebug_buf_open(struct udebug_buf *buf, int fd, uint32_t ring_size, uint32_t data_size)
425 {
427  INIT_LIST_HEAD(&buf->list);
428  buf->ring_size = ring_size;
430  buf->data_size = data_size;
431 
432  if (buf->ring_size > (1U << 24) || buf->data_size > (1U << 29))
433  return -1;
434 
435  if (__udebug_buf_map(buf, fd))
436  return -1;
437 
438  if (buf->ring_size != buf->hdr->ring_size ||
439  buf->data_size != buf->hdr->data_size) {
440  munmap(buf->hdr, buf->head_size + 2 * buf->data_size);
441  buf->hdr = NULL;
442  return -1;
443  }
444 
445  buf->fd = fd;
446 
447  return 0;
448 }
449 
450 int udebug_buf_init(struct udebug_buf *buf, size_t entries, size_t size)
451 {
452  char filename[] = "/udebug.XXXXXX";
453  unsigned int order = 12;
454  uint8_t ring_order = 5;
455  size_t head_size;
456  int fd;
457 
459  INIT_LIST_HEAD(&buf->list);
460  if (size < page_size)
461  size = page_size;
462  while(size > 1U << order)
463  order++;
464  size = 1 << order;
465  while (entries > 1U << ring_order)
466  ring_order++;
467  entries = 1 << ring_order;
468 
469  if (size > (1U << 29) || entries > (1U << 24))
470  return -1;
471 
472  head_size = __udebug_headsize(entries);
473  while (ALIGN(sizeof(*buf->hdr) + (entries * 2) * sizeof(struct udebug_ptr), page_size) == head_size)
474  entries *= 2;
475 
476  fd = shm_open_anon(filename);
477  if (fd < 0)
478  return -1;
479 
480  if (ftruncate(fd, head_size + size) < 0)
481  goto err_close;
482 
483  buf->head_size = head_size;
484  buf->data_size = size;
485  buf->ring_size = entries;
486 
487  if (__udebug_buf_map(buf, fd))
488  goto err_close;
489 
490  buf->fd = fd;
491  buf->hdr->ring_size = entries;
492  buf->hdr->data_size = size;
493 
494  /* ensure hdr changes are visible */
495  __sync_synchronize();
496 
497  return 0;
498 
499 err_close:
500  close(fd);
501  return -1;
502 }
503 
504 static void *udebug_buf_alloc(struct udebug_buf *buf, uint32_t ofs, uint32_t len)
505 {
506  struct udebug_hdr *hdr = buf->hdr;
507 
508  hdr->data_used = u32_max(hdr->data_used, ofs + len + 1);
509 
510  /* ensure that data_used update is visible before clobbering data */
511  __sync_synchronize();
512 
513  return udebug_buf_ptr(buf, ofs);
514 }
515 
516 uint64_t udebug_buf_flags(struct udebug_buf *buf)
517 {
518  struct udebug_hdr *hdr = buf->hdr;
519  uint64_t flags;
520 
521  if (!hdr)
522  return 0;
523 
524  flags = hdr->flags[0];
525  if (sizeof(flags) != sizeof(uintptr_t))
526  flags |= ((uint64_t)hdr->flags[1]) << 32;
527 
528  return flags;
529 }
530 
531 void udebug_entry_init_ts(struct udebug_buf *buf, uint64_t timestamp)
532 {
533  struct udebug_hdr *hdr = buf->hdr;
534  struct udebug_ptr *ptr;
535 
536  if (!hdr)
537  return;
538 
539  ptr = udebug_ring_ptr(hdr, hdr->head);
540  ptr->start = hdr->data_head;
541  ptr->len = 0;
542  ptr->timestamp = timestamp;
543 }
544 
545 void *udebug_entry_append(struct udebug_buf *buf, const void *data, uint32_t len)
546 {
547  struct udebug_hdr *hdr = buf->hdr;
548  struct udebug_ptr *ptr;
549  uint32_t ofs;
550  void *ret;
551 
552  if (!hdr)
553  return NULL;
554 
555  ptr = udebug_ring_ptr(hdr, hdr->head);
556  ofs = ptr->start + ptr->len;
557  if (ptr->len + len > buf->data_size / 2)
558  return NULL;
559 
560  ret = udebug_buf_alloc(buf, ofs, len);
561  if (data)
562  memcpy(ret, data, len);
563  ptr->len += len;
564 
565  return ret;
566 }
567 
568 uint16_t udebug_entry_trim(struct udebug_buf *buf, uint16_t len)
569 {
570  struct udebug_hdr *hdr = buf->hdr;
571  struct udebug_ptr *ptr;
572 
573  if (!hdr)
574  return 0;
575 
576  ptr = udebug_ring_ptr(hdr, hdr->head);
577  if (len)
578  ptr->len -= len;
579 
580  return ptr->len;
581 }
582 
583 void udebug_entry_set_length(struct udebug_buf *buf, uint16_t len)
584 {
585  struct udebug_hdr *hdr = buf->hdr;
586  struct udebug_ptr *ptr;
587 
588  if (!hdr)
589  return;
590 
591  ptr = udebug_ring_ptr(hdr, hdr->head);
592  ptr->len = len;
593 }
594 
595 int udebug_entry_printf(struct udebug_buf *buf, const char *fmt, ...)
596 {
597  va_list ap;
598  size_t ret;
599 
600  va_start(ap, fmt);
601  ret = udebug_entry_vprintf(buf, fmt, ap);
602  va_end(ap);
603 
604  return ret;
605 }
606 
607 int udebug_entry_vprintf(struct udebug_buf *buf, const char *fmt, va_list ap)
608 {
609  struct udebug_hdr *hdr = buf->hdr;
610  struct udebug_ptr *ptr;
611  uint32_t ofs;
612  uint32_t len;
613  va_list ap2;
614  char *str;
615 
616  if (!hdr)
617  return -1;
618 
619  ptr = udebug_ring_ptr(hdr, hdr->head);
620  ofs = ptr->start + ptr->len;
621  if (ptr->len > buf->data_size / 2)
622  return -1;
623 
624  str = udebug_buf_alloc(buf, ofs, UDEBUG_MIN_ALLOC_LEN);
625  va_copy(ap2, ap);
626  len = vsnprintf(str, UDEBUG_MIN_ALLOC_LEN, fmt, ap2);
627  va_end(ap2);
628  if (len <= UDEBUG_MIN_ALLOC_LEN)
629  goto out;
630 
631  if (ptr->len + len > buf->data_size / 2)
632  return -1;
633 
634  udebug_buf_alloc(buf, ofs, len + 1);
635  len = vsnprintf(str, len, fmt, ap);
636 
637 out:
638  ptr->len += len;
639  return 0;
640 }
641 
642 void udebug_entry_add(struct udebug_buf *buf)
643 {
644  struct udebug_hdr *hdr = buf->hdr;
645  struct udebug_ptr *ptr;
646  uint32_t notify;
647  uint8_t *data;
648 
649  if (!hdr)
650  return;
651 
652  ptr = udebug_ring_ptr(hdr, hdr->head);
653 
654  /* ensure strings are always 0-terminated */
655  data = udebug_buf_ptr(buf, ptr->start + ptr->len);
656  *data = 0;
657  hdr->data_head = ptr->start + ptr->len + 1;
658 
659  /* ensure that all data changes are visible before advancing head */
660  __sync_synchronize();
661 
662  u32_set(&hdr->head, u32_get(&hdr->head) + 1);
663  if (!u32_get(&hdr->head))
664  u32_set(&hdr->head_hi, u32_get(&hdr->head_hi) + 1);
665 
666  /* ensure that head change is visible */
667  __sync_synchronize();
668 
669  notify = __atomic_exchange_n(&hdr->notify, 0, __ATOMIC_RELAXED);
670  if (notify) {
671  struct udebug_client_msg msg = {
673  .id = buf->id,
674  .notify_mask = notify,
675  };
676  blob_buf_init(&b, 0);
677 
678  udebug_send_msg(buf->ctx, &msg, b.head, -1);
679  }
680 }
681 void udebug_buf_free(struct udebug_buf *buf)
682 {
683  struct udebug *ctx = buf->ctx;
684 
685  if (!list_empty(&buf->list) && buf->list.prev)
686  list_del(&buf->list);
687 
688  if (ctx && ctx->fd.fd >= 0)
690 
691  munmap(buf->hdr, buf->head_size + 2 * buf->data_size);
692  close(buf->fd);
693  memset(buf, 0, sizeof(*buf));
694 }
695 
696 static void
697 __udebug_buf_add(struct udebug *ctx, struct udebug_buf *buf)
698 {
699  struct udebug_client_msg msg = {
701  .id = buf->id,
702  .ring_size = buf->hdr->ring_size,
703  .data_size = buf->hdr->data_size,
704  };
705  const struct udebug_buf_meta *meta = buf->meta;
706  void *c;
707 
708  blob_buf_init(&b, 0);
709  blobmsg_add_string(&b, "name", meta->name);
710  c = blobmsg_open_array(&b, "flags");
711  for (size_t i = 0; i < meta->n_flags; i++) {
712  const struct udebug_buf_flag *flag = &meta->flags[i];
713  void *e = blobmsg_open_array(&b, NULL);
714  blobmsg_add_string(&b, NULL, flag->name);
715  blobmsg_add_u64(&b, NULL, flag->mask);
716  blobmsg_close_array(&b, e);
717  }
718  blobmsg_close_array(&b, c);
719 
720  udebug_send_msg(ctx, &msg, b.head, buf->fd);
721  udebug_wait_for_response(ctx, &msg, NULL);
722 }
723 
724 int udebug_buf_add(struct udebug *ctx, struct udebug_buf *buf,
725  const struct udebug_buf_meta *meta)
726 {
727  if (!buf->hdr)
728  return -1;
729 
730  list_add_tail(&buf->list, &ctx->local_rings);
731  buf->ctx = ctx;
732  buf->meta = meta;
733  buf->id = ctx->next_id++;
734  buf->hdr->format = meta->format;
735  buf->hdr->sub_format = meta->sub_format;
736 
737  if (ctx->fd.fd >= 0)
738  __udebug_buf_add(ctx, buf);
739 
740  return 0;
741 }
742 
743 void udebug_init(struct udebug *ctx)
744 {
746  avl_init(&ctx->remote_rings, udebug_id_cmp, true, NULL);
747  ctx->fd.fd = -1;
748  ctx->poll_handle = -1;
749 }
750 
751 static void udebug_reconnect_cb(struct uloop_timeout *t)
752 {
753  struct udebug *ctx = container_of(t, struct udebug, reconnect);
754 
755  if (udebug_connect(ctx, ctx->socket_path) < 0) {
756  uloop_timeout_set(&ctx->reconnect, 1000);
757  return;
758  }
759 
760  udebug_add_uloop(ctx);
761 }
762 
763 void udebug_auto_connect(struct udebug *ctx, const char *path)
764 {
765  free(ctx->socket_path);
767  ctx->socket_path = path ? strdup(path) : NULL;
768  if (ctx->fd.fd >= 0)
769  return;
770 
772 }
773 
774 int udebug_connect(struct udebug *ctx, const char *path)
775 {
776  struct udebug_remote_buf *rb;
777  struct udebug_buf *buf;
778 
779  if (ctx->fd.fd >= 0)
780  close(ctx->fd.fd);
781  ctx->fd.fd = -1;
782 
783  if (!path)
784  path = UDEBUG_SOCK_NAME;
785 
786  ctx->fd.fd = usock(USOCK_UNIX, path, NULL);
787  if (ctx->fd.fd < 0)
788  return -1;
789 
790  list_for_each_entry(buf, &ctx->local_rings, list)
791  __udebug_buf_add(ctx, buf);
792 
794  if (!rb->poll)
795  continue;
796 
797  rb->poll = false;
798  udebug_remote_buf_set_poll(ctx, rb, true);
799  }
800 
801  return 0;
802 }
803 
804 void udebug_poll(struct udebug *ctx)
805 {
806  while (__udebug_poll(ctx, NULL, false));
807 }
808 
809 struct udebug_client_msg *
811 {
812  udebug_send_msg(ctx, msg, NULL, -1);
813 
814  return udebug_wait_for_response(ctx, msg, rfd);
815 }
816 
817 static void udebug_fd_cb(struct uloop_fd *fd, unsigned int events)
818 {
819  struct udebug *ctx = container_of(fd, struct udebug, fd);
820 
821  if (fd->eof)
822  __udebug_disconnect(ctx, true);
823 
824  udebug_poll(ctx);
825 }
826 
827 void udebug_add_uloop(struct udebug *ctx)
828 {
829  if (ctx->fd.registered)
830  return;
831 
832  ctx->fd.cb = udebug_fd_cb;
833  uloop_fd_add(&ctx->fd, ULOOP_READ);
834 }
835 
836 void udebug_free(struct udebug *ctx)
837 {
838  struct udebug_remote_buf *rb, *tmp;
839  struct udebug_buf *buf;
840 
841  free(ctx->socket_path);
842  ctx->socket_path = NULL;
843 
844  __udebug_disconnect(ctx, false);
846 
847  while (!list_empty(&ctx->local_rings)) {
848  buf = list_first_entry(&ctx->local_rings, struct udebug_buf, list);
849  udebug_buf_free(buf);
850  }
851 
853  udebug_remote_buf_unmap(ctx, rb);
854 }
void avl_init(struct avl_tree *tree, avl_tree_comp comp, bool allow_dups, void *ptr)
Definition: avl.c:92
#define avl_find_element(tree, key, element, node_element)
Definition: avl.h:240
#define avl_for_each_element(tree, element, node_member)
Definition: avl.h:366
#define avl_for_each_element_safe(tree, element, node_member, ptr)
Definition: avl.h:503
int blob_buf_init(struct blob_buf *buf, int id)
Definition: blob.c:91
static size_t blob_pad_len(const struct blob_attr *attr)
Definition: blob.h:118
char data[]
Definition: blob.h:1
static int blobmsg_add_u64(struct blob_buf *buf, const char *name, uint64_t val)
Definition: blobmsg.h:228
static int blobmsg_add_string(struct blob_buf *buf, const char *name, const char *string)
Definition: blobmsg.h:235
static void blobmsg_close_array(struct blob_buf *buf, void *cookie)
Definition: blobmsg.h:262
uint8_t name[]
Definition: blobmsg.h:1
static void * blobmsg_open_array(struct blob_buf *buf, const char *name)
Definition: blobmsg.h:250
static void list_add_tail(struct list_head *_new, struct list_head *head)
Definition: list.h:165
#define list_for_each_entry(p, h, field)
Definition: list.h:132
static bool list_empty(const struct list_head *head)
Definition: list.h:69
static void list_del(struct list_head *entry)
Definition: list.h:96
#define list_first_entry(ptr, type, field)
Definition: list.h:121
static void INIT_LIST_HEAD(struct list_head *list)
Definition: list.h:63
#define container_of(ptr, type, member)
Definition: list.h:38
Definition: blob.h:52
Definition: blob.h:64
struct blob_attr * head
Definition: blob.h:65
struct list_head * prev
Definition: list.h:55
Definition: test-avl.c:13
const char * name
Definition: udebug.h:59
uint64_t mask
Definition: udebug.h:60
const char * name
Definition: udebug.h:64
const struct udebug_buf_flag * flags
Definition: udebug.h:67
uint32_t sub_format
Definition: udebug.h:66
enum udebug_format format
Definition: udebug.h:65
unsigned int n_flags
Definition: udebug.h:68
void * data
Definition: udebug.h:79
size_t head_size
Definition: udebug.h:81
struct udebug_hdr * hdr
Definition: udebug.h:78
struct list_head list
Definition: udebug.h:76
uint32_t id
Definition: udebug.h:74
struct udebug * ctx
Definition: udebug.h:72
int fd
Definition: udebug.h:83
const struct udebug_buf_meta * meta
Definition: udebug.h:73
size_t data_size
Definition: udebug.h:80
size_t ring_size
Definition: udebug.h:82
uintptr_t notify
Definition: udebug-proto.h:31
uint32_t head_hi
Definition: udebug-proto.h:33
uint32_t ring_size
Definition: udebug-proto.h:24
uintptr_t flags[8/sizeof(uintptr_t)]
Definition: udebug-proto.h:30
uint32_t data_head
Definition: udebug-proto.h:35
uint32_t data_used
Definition: udebug-proto.h:36
uint32_t sub_format
Definition: udebug-proto.h:28
uint32_t format
Definition: udebug-proto.h:27
uint32_t data_size
Definition: udebug-proto.h:25
uint32_t head
Definition: udebug-proto.h:34
uint64_t timestamp
Definition: udebug.h:118
uint32_t len
Definition: udebug.h:117
uint32_t start
Definition: udebug.h:116
struct udebug_buf buf
Definition: udebug.h:92
Definition: udebug.h:102
char * socket_path
Definition: udebug.h:108
uint32_t next_id
Definition: udebug.h:105
struct uloop_timeout reconnect
Definition: udebug.h:109
void(* notify_cb)(struct udebug *ctx, struct udebug_remote_buf *rb)
Definition: udebug.h:112
int poll_handle
Definition: udebug.h:107
struct uloop_fd fd
Definition: udebug.h:106
struct avl_tree remote_rings
Definition: udebug.h:104
struct list_head local_rings
Definition: udebug.h:103
Definition: uloop.h:63
bool registered
Definition: uloop.h:68
int fd
Definition: uloop.h:65
uloop_fd_handler cb
Definition: uloop.h:64
uloop_timeout_handler cb
Definition: uloop.h:77
#define ARRAY_SIZE(x)
#define UDEBUG_TIMEOUT
Definition: udebug-priv.h:25
int uint32_t ring_size
Definition: udebug-priv.h:27
int uint32_t uint32_t data_size
Definition: udebug-priv.h:27
struct udebug_client_msg int * rfd
Definition: udebug-priv.h:29
static uint32_t u32_get(void *ptr)
Definition: udebug-priv.h:47
int fd
Definition: udebug-priv.h:27
struct udebug_client_msg * msg
Definition: udebug-priv.h:29
static int32_t u32_max(uint32_t a, uint32_t b)
Definition: udebug-priv.h:36
static void u32_set(void *ptr, uint32_t val)
Definition: udebug-priv.h:41
uint8_t type
Definition: udebug-proto.h:0
udebug_client_msg_type
Definition: udebug-proto.h:39
@ CL_MSG_RING_ADD
Definition: udebug-proto.h:40
@ CL_MSG_RING_REMOVE
Definition: udebug-proto.h:41
@ CL_MSG_RING_NOTIFY
Definition: udebug-proto.h:42
static struct udebug_ptr * udebug_ring_ptr(struct udebug_hdr *hdr, uint32_t idx)
Definition: udebug-proto.h:61
static void * udebug_buf_ptr(struct udebug_buf *buf, uint32_t ofs)
Definition: udebug-proto.h:67
int udebug_remote_buf_set_poll(struct udebug *ctx, struct udebug_remote_buf *rb, bool val)
Definition: udebug-remote.c:89
void udebug_remote_buf_unmap(struct udebug *ctx, struct udebug_remote_buf *rb)
Definition: udebug-remote.c:77
static void udebug_buf_msg(struct udebug_buf *buf, enum udebug_client_msg_type type)
Definition: udebug.c:395
void udebug_add_uloop(struct udebug *ctx)
Definition: udebug.c:827
static void * udebug_buf_alloc(struct udebug_buf *buf, uint32_t ofs, uint32_t len)
Definition: udebug.c:504
static unsigned int page_size
Definition: udebug.c:40
static void udebug_reconnect_cb(struct uloop_timeout *t)
Definition: udebug.c:751
static void udebug_init_page_size(void)
Definition: udebug.c:412
void udebug_entry_add(struct udebug_buf *buf)
Definition: udebug.c:642
static int shm_open_anon(char *name)
Definition: udebug.c:65
void * udebug_entry_append(struct udebug_buf *buf, const void *data, uint32_t len)
Definition: udebug.c:545
static size_t __udebug_headsize(unsigned int ring_size)
Definition: udebug.c:406
uint16_t udebug_entry_trim(struct udebug_buf *buf, uint16_t len)
Definition: udebug.c:568
int udebug_connect(struct udebug *ctx, const char *path)
Definition: udebug.c:774
static void __randname(char *template)
Definition: udebug.c:42
int udebug_entry_vprintf(struct udebug_buf *buf, const char *fmt, va_list ap)
Definition: udebug.c:607
int udebug_buf_add(struct udebug *ctx, struct udebug_buf *buf, const struct udebug_buf_meta *meta)
Definition: udebug.c:724
int udebug_entry_printf(struct udebug_buf *buf, const char *fmt,...)
Definition: udebug.c:595
static int __udebug_buf_map(struct udebug_buf *buf, int fd)
Definition: udebug.c:116
uint64_t udebug_buf_flags(struct udebug_buf *buf)
Definition: udebug.c:516
void udebug_free(struct udebug *ctx)
Definition: udebug.c:836
static struct udebug_client_msg * udebug_wait_for_response(struct udebug *ctx, struct udebug_client_msg *msg, int *rfd)
Definition: udebug.c:372
static int recv_retry(int fd, struct iovec *iov, bool wait, int *recv_fd)
Definition: udebug.c:226
static void udebug_fd_cb(struct uloop_fd *fd, unsigned int events)
Definition: udebug.c:817
static struct udebug_client_msg * __udebug_poll(struct udebug *ctx, int *fd, bool wait)
Definition: udebug.c:339
static struct blob_buf b
Definition: udebug.c:39
void udebug_buf_free(struct udebug_buf *buf)
Definition: udebug.c:681
static int writev_retry(int fd, struct iovec *iov, int iov_len, int sock_fd)
Definition: udebug.c:154
uint64_t udebug_timestamp(void)
Definition: udebug.c:101
static void udebug_send_msg(struct udebug *ctx, struct udebug_client_msg *msg, struct blob_attr *meta, int fd)
Definition: udebug.c:303
#define UDEBUG_MIN_ALLOC_LEN
Definition: udebug.c:38
static void __udebug_disconnect(struct udebug *ctx, bool reconnect)
Definition: udebug.c:91
struct udebug_client_msg * udebug_send_and_wait(struct udebug *ctx, struct udebug_client_msg *msg, int *rfd)
Definition: udebug.c:810
int udebug_buf_init(struct udebug_buf *buf, size_t entries, size_t size)
Definition: udebug.c:450
static bool udebug_recv_msg(struct udebug *ctx, struct udebug_client_msg *msg, int *fd, bool wait)
Definition: udebug.c:322
void udebug_auto_connect(struct udebug *ctx, const char *path)
Definition: udebug.c:763
void udebug_poll(struct udebug *ctx)
Definition: udebug.c:804
void udebug_entry_set_length(struct udebug_buf *buf, uint16_t len)
Definition: udebug.c:583
void udebug_init(struct udebug *ctx)
Definition: udebug.c:743
#define MAP_ANONYMOUS
Definition: udebug.c:35
static void __udebug_buf_add(struct udebug *ctx, struct udebug_buf *buf)
Definition: udebug.c:697
int udebug_buf_open(struct udebug_buf *buf, int fd, uint32_t ring_size, uint32_t data_size)
Definition: udebug.c:424
#define ALIGN(i, sz)
Definition: udebug.c:32
void udebug_entry_init_ts(struct udebug_buf *buf, uint64_t timestamp)
Definition: udebug.c:531
int udebug_id_cmp(const void *k1, const void *k2, void *ptr)
Definition: udebug.c:54
#define UDEBUG_TS_SEC
Definition: udebug.h:53
#define UDEBUG_SOCK_NAME
Definition: udebug.h:29
static struct epoll_event events[ULOOP_MAX_EVENTS]
Definition: uloop-epoll.c:60
int uloop_fd_add(struct uloop_fd *sock, unsigned int flags)
Definition: uloop.c:235
int uloop_timeout_cancel(struct uloop_timeout *timeout)
Definition: uloop.c:348
int uloop_fd_delete(struct uloop_fd *fd)
Definition: uloop.c:265
int uloop_timeout_set(struct uloop_timeout *timeout, int msecs)
Definition: uloop.c:328
#define ULOOP_READ
Definition: uloop.h:47
int usock(int type, const char *host, const char *service)
Definition: usock.c:252
#define USOCK_UNIX
Definition: usock.h:31