#define UDEBUG_MIN_ALLOC_LEN 128
static struct blob_buf b;
+static unsigned int page_size;
static void __randname(char *template)
{
}
static int
-__udebug_buf_map(struct udebug_buf *buf)
+__udebug_buf_map(struct udebug_buf *buf, int fd)
{
+ unsigned int pad = 0;
void *ptr, *ptr2;
- ptr = mmap(NULL, buf->head_size + 2 * buf->data_size, PROT_NONE,
+#ifdef mips
+ pad = page_size;
+#endif
+ ptr = mmap(NULL, buf->head_size + 2 * buf->data_size + pad, PROT_NONE,
MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
if (ptr == MAP_FAILED)
return -1;
+#ifdef mips
+ ptr = (void *)ALIGN((unsigned long)ptr, page_size);
+#endif
+
ptr2 = mmap(ptr, buf->head_size + buf->data_size,
- PROT_READ | PROT_WRITE, MAP_FIXED | MAP_SHARED, buf->fd, 0);
+ PROT_READ | PROT_WRITE, MAP_FIXED | MAP_SHARED, fd, 0);
if (ptr2 != ptr)
goto err_unmap;
ptr2 = mmap(ptr + buf->head_size + buf->data_size, buf->data_size,
- PROT_READ | PROT_WRITE, MAP_FIXED | MAP_SHARED, buf->fd,
+ PROT_READ | PROT_WRITE, MAP_FIXED | MAP_SHARED, fd,
buf->head_size);
if (ptr2 != ptr + buf->head_size + buf->data_size)
goto err_unmap;
return total;
}
-void udebug_send_msg(struct udebug *ctx, struct udebug_client_msg *msg,
- struct blob_attr *meta, int fd)
+static void
+udebug_send_msg(struct udebug *ctx, struct udebug_client_msg *msg,
+ struct blob_attr *meta, int fd)
{
struct iovec iov[2] = {
{ .iov_base = msg, .iov_len = sizeof(*msg) },
writev_retry(ctx->fd.fd, iov, ARRAY_SIZE(iov), fd);
}
+static bool
+udebug_recv_msg(struct udebug *ctx, struct udebug_client_msg *msg, int *fd,
+ bool wait)
+{
+ struct iovec iov = {
+ .iov_base = msg,
+ .iov_len = sizeof(*msg)
+ };
+ int ret;
+
+ ret = recv_retry(ctx->fd.fd, &iov, wait, fd);
+ if (ret == -2)
+ __udebug_disconnect(ctx, true);
+
+ return ret == sizeof(*msg);
+}
+
+static struct udebug_client_msg *
+__udebug_poll(struct udebug *ctx, int *fd, bool wait)
+{
+ static struct udebug_client_msg msg = {};
+
+ while (udebug_recv_msg(ctx, &msg, fd, wait)) {
+ struct udebug_remote_buf *rb;
+ void *key;
+
+ if (msg.type != CL_MSG_RING_NOTIFY)
+ return &msg;
+
+ if (fd && *fd >= 0)
+ close(*fd);
+
+ if (!ctx->notify_cb)
+ continue;
+
+ key = (void *)(uintptr_t)msg.id;
+ rb = avl_find_element(&ctx->remote_rings, key, rb, node);
+ if (!rb || !rb->poll)
+ continue;
+
+ if (ctx->poll_handle >= 0)
+ __atomic_fetch_or(&rb->buf.hdr->notify,
+ 1UL << ctx->poll_handle,
+ __ATOMIC_RELAXED);
+ ctx->notify_cb(ctx, rb);
+ }
+
+ return NULL;
+}
+
+static struct udebug_client_msg *
+udebug_wait_for_response(struct udebug *ctx, struct udebug_client_msg *msg, int *rfd)
+{
+ int type = msg->type;
+ int fd = -1;
+
+ do {
+ if (fd >= 0)
+ close(fd);
+ fd = -1;
+ msg = __udebug_poll(ctx, &fd, true);
+ } while (msg && msg->type != type);
+ if (!msg)
+ return NULL;
+
+ if (rfd)
+ *rfd = fd;
+ else if (fd >= 0)
+ close(fd);
+
+ return msg;
+}
+
static void
udebug_buf_msg(struct udebug_buf *buf, enum udebug_client_msg_type type)
{
};
udebug_send_msg(buf->ctx, &msg, NULL, -1);
+ udebug_wait_for_response(buf->ctx, &msg, NULL);
}
-static size_t __udebug_headsize(unsigned int ring_size, unsigned int page_size)
+static size_t __udebug_headsize(unsigned int ring_size)
{
ring_size *= sizeof(struct udebug_ptr);
return ALIGN(sizeof(struct udebug_hdr) + ring_size, page_size);
}
+static void udebug_init_page_size(void)
+{
+ if (page_size)
+ return;
+ page_size = sysconf(_SC_PAGESIZE);
+#ifdef mips
+ /* leave extra alignment room to account for data cache aliases */
+ if (page_size < 32 * 1024)
+ page_size = 32 * 1024;
+#endif
+}
+
int udebug_buf_open(struct udebug_buf *buf, int fd, uint32_t ring_size, uint32_t data_size)
{
+ udebug_init_page_size();
INIT_LIST_HEAD(&buf->list);
- buf->fd = fd;
buf->ring_size = ring_size;
- buf->head_size = __udebug_headsize(ring_size, sysconf(_SC_PAGESIZE));
+ buf->head_size = __udebug_headsize(ring_size);
buf->data_size = data_size;
if (buf->ring_size > (1U << 24) || buf->data_size > (1U << 29))
return -1;
- if (__udebug_buf_map(buf))
+ if (__udebug_buf_map(buf, fd))
return -1;
if (buf->ring_size != buf->hdr->ring_size ||
return -1;
}
+ buf->fd = fd;
+
return 0;
}
int udebug_buf_init(struct udebug_buf *buf, size_t entries, size_t size)
{
- uint32_t pagesz = sysconf(_SC_PAGESIZE);
char filename[] = "/udebug.XXXXXX";
unsigned int order = 12;
uint8_t ring_order = 5;
size_t head_size;
int fd;
+ udebug_init_page_size();
INIT_LIST_HEAD(&buf->list);
- if (size < pagesz)
- size = pagesz;
+ if (size < page_size)
+ size = page_size;
while(size > 1U << order)
order++;
size = 1 << order;
if (size > (1U << 29) || entries > (1U << 24))
return -1;
- head_size = __udebug_headsize(entries, pagesz);
- while (ALIGN(sizeof(*buf->hdr) + (entries * 2) * sizeof(struct udebug_ptr), pagesz) == head_size)
+ head_size = __udebug_headsize(entries);
+ while (ALIGN(sizeof(*buf->hdr) + (entries * 2) * sizeof(struct udebug_ptr), page_size) == head_size)
entries *= 2;
fd = shm_open_anon(filename);
buf->head_size = head_size;
buf->data_size = size;
buf->ring_size = entries;
- buf->fd = fd;
- if (__udebug_buf_map(buf))
+ if (__udebug_buf_map(buf, fd))
goto err_close;
+ buf->fd = fd;
buf->hdr->ring_size = entries;
buf->hdr->data_size = size;
uint16_t udebug_entry_trim(struct udebug_buf *buf, uint16_t len)
{
struct udebug_hdr *hdr = buf->hdr;
- struct udebug_ptr *ptr = udebug_ring_ptr(hdr, hdr->head);
+ struct udebug_ptr *ptr;
+ if (!hdr)
+ return 0;
+
+ ptr = udebug_ring_ptr(hdr, hdr->head);
if (len)
ptr->len -= len;
void udebug_entry_set_length(struct udebug_buf *buf, uint16_t len)
{
struct udebug_hdr *hdr = buf->hdr;
- struct udebug_ptr *ptr = udebug_ring_ptr(hdr, hdr->head);
+ struct udebug_ptr *ptr;
+ if (!hdr)
+ return;
+
+ ptr = udebug_ring_ptr(hdr, hdr->head);
ptr->len = len;
}
struct udebug_ptr *ptr;
uint32_t ofs;
uint32_t len;
+ va_list ap2;
char *str;
if (!hdr)
return -1;
str = udebug_buf_alloc(buf, ofs, UDEBUG_MIN_ALLOC_LEN);
- len = vsnprintf(str, UDEBUG_MIN_ALLOC_LEN, fmt, ap);
+ va_copy(ap2, ap);
+ len = vsnprintf(str, UDEBUG_MIN_ALLOC_LEN, fmt, ap2);
+ va_end(ap2);
if (len <= UDEBUG_MIN_ALLOC_LEN)
goto out;
void udebug_entry_add(struct udebug_buf *buf)
{
struct udebug_hdr *hdr = buf->hdr;
- struct udebug_ptr *ptr = udebug_ring_ptr(hdr, hdr->head);
+ struct udebug_ptr *ptr;
uint32_t notify;
uint8_t *data;
+ if (!hdr)
+ return;
+
+ ptr = udebug_ring_ptr(hdr, hdr->head);
+
/* ensure strings are always 0-terminated */
data = udebug_buf_ptr(buf, ptr->start + ptr->len);
*data = 0;
blobmsg_close_array(&b, c);
udebug_send_msg(ctx, &msg, b.head, buf->fd);
+ udebug_wait_for_response(ctx, &msg, NULL);
}
int udebug_buf_add(struct udebug *ctx, struct udebug_buf *buf,
const struct udebug_buf_meta *meta)
{
+ if (!buf->hdr)
+ return -1;
+
list_add_tail(&buf->list, &ctx->local_rings);
buf->ctx = ctx;
buf->meta = meta;
return 0;
}
-static bool
-udebug_recv_msg(struct udebug *ctx, struct udebug_client_msg *msg, int *fd,
- bool wait)
+void udebug_poll(struct udebug *ctx)
{
- struct iovec iov = {
- .iov_base = msg,
- .iov_len = sizeof(*msg)
- };
- int ret;
-
- ret = recv_retry(ctx->fd.fd, &iov, wait, fd);
- if (ret == -2)
- __udebug_disconnect(ctx, true);
-
- return ret == sizeof(*msg);
+ while (__udebug_poll(ctx, NULL, false));
}
-struct udebug_client_msg *__udebug_poll(struct udebug *ctx, int *fd, bool wait)
+struct udebug_client_msg *
+udebug_send_and_wait(struct udebug *ctx, struct udebug_client_msg *msg, int *rfd)
{
- static struct udebug_client_msg msg = {};
-
- while (udebug_recv_msg(ctx, &msg, fd, wait)) {
- struct udebug_remote_buf *rb;
- void *key;
-
- if (msg.type != CL_MSG_RING_NOTIFY)
- return &msg;
-
- if (fd && *fd >= 0)
- close(*fd);
-
- if (!ctx->notify_cb)
- continue;
-
- key = (void *)(uintptr_t)msg.id;
- rb = avl_find_element(&ctx->remote_rings, key, rb, node);
- if (!rb || !rb->poll)
- continue;
+ udebug_send_msg(ctx, msg, NULL, -1);
- if (ctx->poll_handle >= 0)
- __atomic_fetch_or(&rb->buf.hdr->notify,
- 1UL << ctx->poll_handle,
- __ATOMIC_RELAXED);
- ctx->notify_cb(ctx, rb);
- }
-
- return NULL;
-}
-
-void udebug_poll(struct udebug *ctx)
-{
- while (__udebug_poll(ctx, NULL, false));
+ return udebug_wait_for_response(ctx, msg, rfd);
}
static void udebug_fd_cb(struct uloop_fd *fd, unsigned int events)