summaryrefslogtreecommitdiff
path: root/lib/event.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/event.c')
-rw-r--r--lib/event.c74
1 files changed, 68 insertions, 6 deletions
diff --git a/lib/event.c b/lib/event.c
index 6c5c8b14..5031f314 100644
--- a/lib/event.c
+++ b/lib/event.c
@@ -114,17 +114,42 @@ ev_send(event_list *l, event *e)
e->list = l;
- LOCK_DOMAIN(event, l->lock);
- if (enlisted(&e->n))
+ struct event_cork *ec = e->cork;
+
+ uint ping = 0;
+
+ if (ec)
{
+ LOCK_DOMAIN(cork, ec->lock);
+ LOCK_DOMAIN(event, l->lock);
+
+ if (!enlisted(&e->n))
+ if (ec->count)
+ add_tail(&ec->events, &e->n);
+ else
+ {
+ add_tail(&l->events, &e->n);
+ ping = 1;
+ }
+
UNLOCK_DOMAIN(event, l->lock);
- return;
+ UNLOCK_DOMAIN(cork, ec->lock);
}
+ else
+ {
+ LOCK_DOMAIN(event, l->lock);
- add_tail(&l->events, &e->n);
- UNLOCK_DOMAIN(event, l->lock);
+ if (!enlisted(&e->n))
+ {
+ add_tail(&l->events, &e->n);
+ ping = 1;
+ }
- birdloop_ping(l->loop);
+ UNLOCK_DOMAIN(event, l->lock);
+ }
+
+ if (ping)
+ birdloop_ping(l->loop);
}
void io_log_event(void *hook, void *data);
@@ -224,3 +249,40 @@ ev_run_list_limited(event_list *l, uint limit)
return repeat;
}
+
+void ev_cork(struct event_cork *ec)
+{
+ LOCK_DOMAIN(cork, ec->lock);
+ ec->count++;
+ UNLOCK_DOMAIN(cork, ec->lock);
+}
+
+void ev_uncork(struct event_cork *ec)
+{
+ LOCK_DOMAIN(cork, ec->lock);
+
+ if (--ec->count)
+ {
+ UNLOCK_DOMAIN(cork, ec->lock);
+ return;
+ }
+
+ node *n;
+ WALK_LIST_FIRST(n, ec->events)
+ {
+ event *e = SKIP_BACK(event, n, n);
+ event_list *el = e->list;
+
+ rem_node(&e->n);
+
+ LOCK_DOMAIN(event, el->lock);
+ add_tail(&el->events, &e->n);
+ UNLOCK_DOMAIN(event, el->lock);
+
+ birdloop_ping(el->loop);
+ }
+
+ UNLOCK_DOMAIN(cork, ec->lock);
+
+ birdloop_ping(&main_birdloop);
+}