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)
|
obj := $(src-o-files)
|
||||||
$(all-daemon)
|
$(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
|
#define LOCAL_DEBUG
|
||||||
|
|
||||||
_Thread_local struct lfuc_unlock_queue *lfuc_unlock_queue;
|
void lfuc_unlock_deferred(struct deferred_call *dc)
|
||||||
|
|
||||||
void lfuc_unlock_deferred(void *_q)
|
|
||||||
{
|
{
|
||||||
struct lfuc_unlock_queue *q = _q;
|
struct lfuc_unlock_queue_item *luqi = SKIP_BACK(struct lfuc_unlock_queue_item, dc, dc);
|
||||||
for (u32 i = 0; i < q->pos; i++)
|
lfuc_unlock_immediately(luqi->c, luqi->el, luqi->ev);
|
||||||
lfuc_unlock_immediately(q->block[i].c, q->block[i].el, q->block[i].ev);
|
|
||||||
|
|
||||||
free_page(q);
|
|
||||||
lfuc_unlock_queue = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
#ifndef _BIRD_LOCKFREE_H_
|
#ifndef _BIRD_LOCKFREE_H_
|
||||||
#define _BIRD_LOCKFREE_H_
|
#define _BIRD_LOCKFREE_H_
|
||||||
|
|
||||||
|
#include "lib/defer.h"
|
||||||
#include "lib/event.h"
|
#include "lib/event.h"
|
||||||
#include "lib/rcu.h"
|
#include "lib/rcu.h"
|
||||||
#include "lib/settle.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;
|
// return uc - LFUC_IN_PROGRESS - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
extern _Thread_local struct lfuc_unlock_queue {
|
struct lfuc_unlock_queue_item {
|
||||||
event e;
|
struct deferred_call dc;
|
||||||
u32 pos;
|
struct lfuc *c;
|
||||||
struct lfuc_unlock_queue_block {
|
event_list *el;
|
||||||
struct lfuc *c;
|
event *ev;
|
||||||
event_list *el;
|
};
|
||||||
event *ev;
|
|
||||||
} block[0];
|
|
||||||
} *lfuc_unlock_queue;
|
|
||||||
|
|
||||||
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 inline void lfuc_unlock(struct lfuc *c, event_list *el, event *ev)
|
||||||
{
|
{
|
||||||
static u32 queue_items = 0;
|
struct lfuc_unlock_queue_item luqi = {
|
||||||
if (queue_items == 0)
|
.dc.hook = lfuc_unlock_deferred,
|
||||||
{
|
|
||||||
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) {
|
|
||||||
.c = c,
|
.c = c,
|
||||||
.el = el,
|
.el = el,
|
||||||
.ev = ev,
|
.ev = ev,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
defer_call(&luqi.dc, sizeof luqi);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
#include "nest/bird.h"
|
#include "nest/bird.h"
|
||||||
|
|
||||||
#include "lib/buffer.h"
|
#include "lib/buffer.h"
|
||||||
|
#include "lib/defer.h"
|
||||||
#include "lib/lists.h"
|
#include "lib/lists.h"
|
||||||
#include "lib/locking.h"
|
#include "lib/locking.h"
|
||||||
#include "lib/resource.h"
|
#include "lib/resource.h"
|
||||||
@ -794,6 +795,8 @@ bird_thread_main(void *arg)
|
|||||||
tmp_init(thr->pool, birdloop_domain(thr->meta));
|
tmp_init(thr->pool, birdloop_domain(thr->meta));
|
||||||
init_list(&thr->loops);
|
init_list(&thr->loops);
|
||||||
|
|
||||||
|
defer_init(lp_new(thr->pool));
|
||||||
|
|
||||||
thr->sock_changed = 1;
|
thr->sock_changed = 1;
|
||||||
|
|
||||||
struct pfd pfd;
|
struct pfd pfd;
|
||||||
@ -1377,6 +1380,8 @@ birdloop_init(void)
|
|||||||
birdloop_enter_locked(&main_birdloop);
|
birdloop_enter_locked(&main_birdloop);
|
||||||
this_birdloop = &main_birdloop;
|
this_birdloop = &main_birdloop;
|
||||||
this_thread = &main_thread;
|
this_thread = &main_thread;
|
||||||
|
|
||||||
|
defer_init(lp_new(&root_pool));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
Loading…
Reference in New Issue
Block a user