mirror of
https://gitlab.nic.cz/labs/bird.git
synced 2024-12-22 09:41:54 +00:00
Refactored the deferring framework into a separate structure
This commit is contained in:
parent
2b38a833cd
commit
29cd2c0170
@ -1,4 +1,4 @@
|
||||
src := a-path.c a-set.c bitmap.c bitops.c blake2s.c blake2b.c checksum.c event.c flowspec.c idm.c ip.c lists.c lockfree.c mac.c md5.c mempool.c net.c netindex.c patmatch.c printf.c rcu.c resource.c sha1.c sha256.c sha512.c slab.c slists.c strtoul.c tbf.c timer.c xmalloc.c
|
||||
src := a-path.c a-set.c bitmap.c bitops.c blake2s.c blake2b.c checksum.c defer.c event.c flowspec.c idm.c ip.c lists.c lockfree.c mac.c md5.c mempool.c net.c netindex.c patmatch.c printf.c rcu.c resource.c sha1.c sha256.c sha512.c slab.c slists.c strtoul.c tbf.c timer.c xmalloc.c
|
||||
obj := $(src-o-files)
|
||||
$(all-daemon)
|
||||
|
||||
|
40
lib/defer.c
Normal file
40
lib/defer.c
Normal file
@ -0,0 +1,40 @@
|
||||
/*
|
||||
* BIRD -- Deferring calls to the end of the task
|
||||
*
|
||||
* (c) 2024 Maria Matejka <mq@jmq.cz>
|
||||
*
|
||||
* Can be freely distributed and used under the terms of the GNU GPL.
|
||||
*/
|
||||
|
||||
#include "lib/defer.h"
|
||||
|
||||
_Thread_local struct deferred local_deferred = {};
|
||||
|
||||
static void
|
||||
defer_execute(void *_ld)
|
||||
{
|
||||
ASSERT_DIE(_ld == &local_deferred);
|
||||
|
||||
/* Run */
|
||||
for (struct deferred_call *call = local_deferred.first; call; call = call->next)
|
||||
call->hook(call);
|
||||
|
||||
/* Cleanup */
|
||||
local_deferred.first = NULL;
|
||||
local_deferred.last = &local_deferred.first;
|
||||
|
||||
lp_flush(local_deferred.lp);
|
||||
}
|
||||
|
||||
void
|
||||
defer_init(linpool *lp)
|
||||
{
|
||||
local_deferred = (struct deferred) {
|
||||
.e = {
|
||||
.hook = defer_execute,
|
||||
.data = &local_deferred,
|
||||
},
|
||||
.lp = lp,
|
||||
.last = &local_deferred.first,
|
||||
};
|
||||
}
|
48
lib/defer.h
Normal file
48
lib/defer.h
Normal file
@ -0,0 +1,48 @@
|
||||
/*
|
||||
* BIRD -- Deferring calls to the end of the task
|
||||
*
|
||||
* (c) 2024 Maria Matejka <mq@jmq.cz>
|
||||
*
|
||||
* Can be freely distributed and used under the terms of the GNU GPL.
|
||||
*/
|
||||
|
||||
/**
|
||||
* There are cases when we need to just run something multiple times after the
|
||||
* current task ends, mostly for cleanup reasons, and it doesn't need the
|
||||
* full-blown event list overhead. Therefore, one just can use this tool
|
||||
* instead. */
|
||||
|
||||
#include "lib/birdlib.h"
|
||||
#include "lib/event.h"
|
||||
#include "lib/resource.h"
|
||||
#include "lib/io-loop.h"
|
||||
|
||||
struct deferred_call {
|
||||
struct deferred_call *next;
|
||||
void (*hook)(struct deferred_call *);
|
||||
};
|
||||
|
||||
struct deferred {
|
||||
event e;
|
||||
linpool *lp;
|
||||
struct deferred_call *first, **last;
|
||||
};
|
||||
|
||||
extern _Thread_local struct deferred local_deferred;
|
||||
void defer_init(linpool *lp);
|
||||
|
||||
static inline void defer_call(struct deferred_call *call, size_t actual_size) {
|
||||
/* Reallocate the call to the appropriate linpool */
|
||||
ASSERT_DIE(actual_size < 128);
|
||||
struct deferred_call *a = lp_alloc(local_deferred.lp, actual_size);
|
||||
memcpy(a, call, actual_size);
|
||||
|
||||
/* If first, send the actual event to the local thread */
|
||||
if (local_deferred.last == &local_deferred.first)
|
||||
ev_send_this_thread(&local_deferred.e);
|
||||
|
||||
/* Add to list */
|
||||
a->next = NULL;
|
||||
*local_deferred.last = a;
|
||||
local_deferred.last = &a->next;
|
||||
}
|
@ -12,16 +12,10 @@
|
||||
|
||||
#define LOCAL_DEBUG
|
||||
|
||||
_Thread_local struct lfuc_unlock_queue *lfuc_unlock_queue;
|
||||
|
||||
void lfuc_unlock_deferred(void *_q)
|
||||
void lfuc_unlock_deferred(struct deferred_call *dc)
|
||||
{
|
||||
struct lfuc_unlock_queue *q = _q;
|
||||
for (u32 i = 0; i < q->pos; i++)
|
||||
lfuc_unlock_immediately(q->block[i].c, q->block[i].el, q->block[i].ev);
|
||||
|
||||
free_page(q);
|
||||
lfuc_unlock_queue = NULL;
|
||||
struct lfuc_unlock_queue_item *luqi = SKIP_BACK(struct lfuc_unlock_queue_item, dc, dc);
|
||||
lfuc_unlock_immediately(luqi->c, luqi->el, luqi->ev);
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
@ -10,6 +10,7 @@
|
||||
#ifndef _BIRD_LOCKFREE_H_
|
||||
#define _BIRD_LOCKFREE_H_
|
||||
|
||||
#include "lib/defer.h"
|
||||
#include "lib/event.h"
|
||||
#include "lib/rcu.h"
|
||||
#include "lib/settle.h"
|
||||
@ -108,46 +109,25 @@ static inline void lfuc_unlock_immediately(struct lfuc *c, event_list *el, event
|
||||
// return uc - LFUC_IN_PROGRESS - 1;
|
||||
}
|
||||
|
||||
extern _Thread_local struct lfuc_unlock_queue {
|
||||
event e;
|
||||
u32 pos;
|
||||
struct lfuc_unlock_queue_block {
|
||||
struct lfuc *c;
|
||||
event_list *el;
|
||||
event *ev;
|
||||
} block[0];
|
||||
} *lfuc_unlock_queue;
|
||||
struct lfuc_unlock_queue_item {
|
||||
struct deferred_call dc;
|
||||
struct lfuc *c;
|
||||
event_list *el;
|
||||
event *ev;
|
||||
};
|
||||
|
||||
void lfuc_unlock_deferred(void *queue);
|
||||
void lfuc_unlock_deferred(struct deferred_call *dc);
|
||||
|
||||
static inline void lfuc_unlock(struct lfuc *c, event_list *el, event *ev)
|
||||
{
|
||||
static u32 queue_items = 0;
|
||||
if (queue_items == 0)
|
||||
{
|
||||
ASSERT_DIE((u64) page_size > sizeof(struct lfuc_unlock_queue) + sizeof(struct lfuc_unlock_queue_block));
|
||||
queue_items = (page_size - OFFSETOF(struct lfuc_unlock_queue, block))
|
||||
/ sizeof lfuc_unlock_queue->block[0];
|
||||
}
|
||||
|
||||
if (!lfuc_unlock_queue || (lfuc_unlock_queue->pos >= queue_items))
|
||||
{
|
||||
lfuc_unlock_queue = alloc_page();
|
||||
*lfuc_unlock_queue = (struct lfuc_unlock_queue) {
|
||||
.e = {
|
||||
.hook = lfuc_unlock_deferred,
|
||||
.data = lfuc_unlock_queue,
|
||||
},
|
||||
};
|
||||
|
||||
ev_send_this_thread(&lfuc_unlock_queue->e);
|
||||
}
|
||||
|
||||
lfuc_unlock_queue->block[lfuc_unlock_queue->pos++] = (struct lfuc_unlock_queue_block) {
|
||||
struct lfuc_unlock_queue_item luqi = {
|
||||
.dc.hook = lfuc_unlock_deferred,
|
||||
.c = c,
|
||||
.el = el,
|
||||
.ev = ev,
|
||||
};
|
||||
|
||||
defer_call(&luqi.dc, sizeof luqi);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include "nest/bird.h"
|
||||
|
||||
#include "lib/buffer.h"
|
||||
#include "lib/defer.h"
|
||||
#include "lib/lists.h"
|
||||
#include "lib/locking.h"
|
||||
#include "lib/resource.h"
|
||||
@ -794,6 +795,8 @@ bird_thread_main(void *arg)
|
||||
tmp_init(thr->pool, birdloop_domain(thr->meta));
|
||||
init_list(&thr->loops);
|
||||
|
||||
defer_init(lp_new(thr->pool));
|
||||
|
||||
thr->sock_changed = 1;
|
||||
|
||||
struct pfd pfd;
|
||||
@ -1377,6 +1380,8 @@ birdloop_init(void)
|
||||
birdloop_enter_locked(&main_birdloop);
|
||||
this_birdloop = &main_birdloop;
|
||||
this_thread = &main_thread;
|
||||
|
||||
defer_init(lp_new(&root_pool));
|
||||
}
|
||||
|
||||
static void
|
||||
|
Loading…
Reference in New Issue
Block a user