Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.openwrt.org/project/libubox.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--uloop.c53
-rw-r--r--uloop.h7
2 files changed, 58 insertions, 2 deletions
diff --git a/uloop.c b/uloop.c
index bf13199..54ebe8d 100644
--- a/uloop.c
+++ b/uloop.c
@@ -43,6 +43,14 @@ struct uloop_fd_event {
unsigned int events;
};
+struct uloop_fd_stack {
+ struct uloop_fd_stack *next;
+ struct uloop_fd *fd;
+ unsigned int events;
+};
+
+static struct uloop_fd_stack *fd_stack = NULL;
+
#define ULOOP_MAX_EVENTS 10
static struct list_head timeouts = LIST_HEAD_INIT(timeouts);
@@ -285,6 +293,32 @@ static int uloop_fetch_events(int timeout)
#endif
+static bool uloop_fd_stack_event(struct uloop_fd *fd, int events)
+{
+ struct uloop_fd_stack *cur;
+
+ /*
+ * Do not buffer events for level-triggered fds, they will keep firing.
+ * Caller needs to take care of recursion issues.
+ */
+ if (!(fd->flags & ULOOP_EDGE_TRIGGER))
+ return false;
+
+ for (cur = fd_stack; cur; cur = cur->next) {
+ if (cur->fd != fd)
+ continue;
+
+ if (events < 0)
+ cur->fd = NULL;
+ else
+ cur->events |= events | ULOOP_EVENT_BUFFERED;
+
+ return true;
+ }
+
+ return false;
+}
+
static void uloop_run_events(int timeout)
{
struct uloop_fd_event *cur;
@@ -298,17 +332,33 @@ static void uloop_run_events(int timeout)
}
while (cur_nfds > 0) {
+ struct uloop_fd_stack stack_cur;
+ unsigned int events;
+
cur = &cur_fds[cur_fd++];
cur_nfds--;
fd = cur->fd;
+ events = cur->events;
if (!fd)
continue;
if (!fd->cb)
continue;
- fd->cb(fd, cur->events);
+ if (uloop_fd_stack_event(fd, cur->events))
+ continue;
+
+ stack_cur.next = fd_stack;
+ stack_cur.fd = fd;
+ fd_stack = &stack_cur;
+ do {
+ stack_cur.events = 0;
+ fd->cb(fd, events);
+ events = stack_cur.events & ULOOP_EVENT_MASK;
+ } while (stack_cur.fd && events);
+ fd_stack = stack_cur.next;
+
return;
}
}
@@ -352,6 +402,7 @@ int uloop_fd_delete(struct uloop_fd *fd)
cur_fds[cur_fd + i].fd = NULL;
}
fd->registered = false;
+ uloop_fd_stack_event(fd, -1);
return __uloop_fd_delete(fd);
}
diff --git a/uloop.h b/uloop.h
index 39b9b58..98dd818 100644
--- a/uloop.h
+++ b/uloop.h
@@ -44,8 +44,13 @@ typedef void (*uloop_process_handler)(struct uloop_process *c, int ret);
#define ULOOP_WRITE (1 << 1)
#define ULOOP_EDGE_TRIGGER (1 << 2)
#define ULOOP_BLOCKING (1 << 3)
+
+#define ULOOP_EVENT_MASK (ULOOP_READ | ULOOP_WRITE)
+
+/* internal flags */
+#define ULOOP_EVENT_BUFFERED (1 << 4)
#ifdef USE_KQUEUE
-#define ULOOP_EDGE_DEFER (1 << 4)
+#define ULOOP_EDGE_DEFER (1 << 5)
#endif
struct uloop_fd