ustream: prevent recursive calls to the read callback
[project/libubox.git] / udebug.c
index 0d8d0d42474ac5acad8d560d8578a2fc87a43617..e39a32cb165f687325c7465d78b64c02a55e2713 100644 (file)
--- a/udebug.c
+++ b/udebug.c
@@ -37,6 +37,7 @@
 
 #define UDEBUG_MIN_ALLOC_LEN   128
 static struct blob_buf b;
+static unsigned int page_size;
 
 static void __randname(char *template)
 {
@@ -112,22 +113,30 @@ uint64_t udebug_timestamp(void)
 }
 
 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;
@@ -394,24 +403,36 @@ udebug_buf_msg(struct udebug_buf *buf, enum udebug_client_msg_type type)
        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 ||
@@ -421,21 +442,23 @@ int udebug_buf_open(struct udebug_buf *buf, int fd, uint32_t ring_size, uint32_t
                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;
@@ -446,8 +469,8 @@ int udebug_buf_init(struct udebug_buf *buf, size_t entries, size_t size)
        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);
@@ -461,7 +484,7 @@ int udebug_buf_init(struct udebug_buf *buf, size_t entries, size_t size)
        buf->data_size = size;
        buf->ring_size = entries;
 
-       if (__udebug_buf_map(buf))
+       if (__udebug_buf_map(buf, fd))
                goto err_close;
 
        buf->fd = fd;
@@ -587,6 +610,7 @@ int udebug_entry_vprintf(struct udebug_buf *buf, const char *fmt, va_list ap)
        struct udebug_ptr *ptr;
        uint32_t ofs;
        uint32_t len;
+       va_list ap2;
        char *str;
 
        if (!hdr)
@@ -598,7 +622,9 @@ int udebug_entry_vprintf(struct udebug_buf *buf, const char *fmt, va_list ap)
                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;