Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
labs
BIRD Internet Routing Daemon
Commits
16cff36a
Commit
16cff36a
authored
Nov 16, 2022
by
Maria Matejka
Browse files
Threads and loops hopefully finished
parent
2deb9de0
Pipeline
#106526
failed with stages
in 54 minutes and 16 seconds
Changes
9
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
doc/reply_codes
View file @
16cff36a
...
...
@@ -61,6 +61,7 @@ Reply codes of BIRD command-line interface
1023 Show Babel interfaces
1024 Show Babel neighbors
1025 Show Babel entries
1026 Show threads
8000 Reply too long
8001 Route not found
...
...
lib/event.c
View file @
16cff36a
...
...
@@ -261,7 +261,7 @@ ev_send(event_list *l, event *e)
memory_order_acq_rel
,
memory_order_acquire
));
edlog
(
l
,
e
,
next
,
4
,
EDL_SEND
);
birdloop_ping
(
l
->
loop
);
if
(
l
->
loop
)
birdloop_ping
(
l
->
loop
);
}
void
io_log_event
(
void
*
hook
,
void
*
data
);
...
...
lib/locking.h
View file @
16cff36a
...
...
@@ -14,6 +14,7 @@ struct domain_generic;
/* Here define the global lock order; first to last. */
struct
lock_order
{
struct
domain_generic
*
the_bird
;
struct
domain_generic
*
control
;
struct
domain_generic
*
proto
;
struct
domain_generic
*
service
;
struct
domain_generic
*
rtable
;
...
...
@@ -34,6 +35,9 @@ struct domain_generic *domain_new(const char *name, uint order);
#define DOMAIN_FREE(type, d) domain_free((d).type)
void
domain_free
(
struct
domain_generic
*
);
#define DOMAIN_NAME(type, d) domain_name((d).type)
const
char
*
domain_name
(
struct
domain_generic
*
);
#define DOMAIN_NULL(type) (DOMAIN(type)) {}
#define LOCK_DOMAIN(type, d) do_lock(((d).type), &(locking_stack.type))
...
...
nest/rt-table.c
View file @
16cff36a
...
...
@@ -2856,7 +2856,7 @@ rt_setup(pool *pp, struct rtable_config *cf)
}
/* Start the service thread */
t
->
loop
=
birdloop_new
(
p
,
DOMAIN_ORDER
(
service
),
mb_sprintf
(
p
,
"Routing ta
h
le %s"
,
t
->
name
));
t
->
loop
=
birdloop_new
(
p
,
DOMAIN_ORDER
(
service
),
mb_sprintf
(
p
,
"Routing ta
b
le %s"
,
t
->
name
));
birdloop_enter
(
t
->
loop
);
birdloop_flag_set_handler
(
t
->
loop
,
&
t
->
fh
);
birdloop_leave
(
t
->
loop
);
...
...
sysdep/unix/config.Y
View file @
16cff36a
...
...
@@ -145,6 +145,11 @@ CF_CLI_HELP(GRACEFUL, restart, [[Shut the daemon down for graceful restart]])
CF_CLI(GRACEFUL RESTART,,, [[Shut the daemon down for graceful restart]])
{ cmd_graceful_restart(); } ;
CF_CLI(SHOW THREADS,,, [[Write out thread information]])
{ cmd_show_threads(0); } ;
CF_CLI(SHOW THREADS ALL,,, [[Write out thread and IO loop information]])
{ cmd_show_threads(1); } ;
cfg_name:
/* empty */ { $$ = NULL; }
...
...
sysdep/unix/domain.c
View file @
16cff36a
...
...
@@ -70,6 +70,12 @@ domain_free(struct domain_generic *dg)
xfree
(
dg
);
}
const
char
*
domain_name
(
struct
domain_generic
*
dg
)
{
return
dg
->
name
;
}
uint
dg_order
(
struct
domain_generic
*
dg
)
{
return
dg
->
order
;
...
...
sysdep/unix/io-loop.c
View file @
16cff36a
...
...
@@ -18,6 +18,7 @@
#include
"lib/buffer.h"
#include
"lib/lists.h"
#include
"lib/locking.h"
#include
"lib/resource.h"
#include
"lib/event.h"
#include
"lib/timer.h"
...
...
@@ -26,9 +27,36 @@
#include
"lib/io-loop.h"
#include
"sysdep/unix/io-loop.h"
#include
"conf/conf.h"
#include
"nest/cli.h"
#define THREAD_STACK_SIZE 65536
/* To be lowered in near future */
/*
* Nanosecond time for accounting purposes
*
* A fixed point on startup is set as zero, all other values are relative to that.
* Caution: this overflows after like 500 years or so. If you plan to run
* BIRD for such a long time, please implement some means of overflow prevention.
*/
static
struct
timespec
ns_begin
;
static
void
ns_init
(
void
)
{
if
(
clock_gettime
(
CLOCK_MONOTONIC
,
&
ns_begin
))
bug
(
"clock_gettime: %m"
);
}
static
u64
ns_now
(
void
)
{
struct
timespec
ts
;
if
(
clock_gettime
(
CLOCK_MONOTONIC
,
&
ts
))
bug
(
"clock_gettime: %m"
);
return
(
u64
)
(
ts
.
tv_sec
-
ns_begin
.
tv_sec
)
*
1000000000
+
ts
.
tv_nsec
-
ns_begin
.
tv_nsec
;
}
/*
* Current thread context
*/
...
...
@@ -90,21 +118,6 @@ birdloop_process_flags(struct birdloop *loop)
return
!!
flags
;
}
static
int
birdloop_run_events
(
struct
birdloop
*
loop
)
{
btime
begin
=
current_time
();
while
(
current_time
()
-
begin
<
5
MS
)
{
if
(
!
ev_run_list
(
&
loop
->
event_list
))
return
0
;
times_update
();
}
return
1
;
}
/*
* Wakeup code for birdloop
*/
...
...
@@ -242,7 +255,8 @@ sockets_add(struct birdloop *loop, sock *s)
loop
->
sock_num
++
;
s
->
index
=
-
1
;
loop
->
poll_changed
=
1
;
if
(
loop
->
thread
)
atomic_store_explicit
(
&
loop
->
thread
->
poll_changed
,
1
,
memory_order_release
);
birdloop_ping
(
loop
);
}
...
...
@@ -263,7 +277,9 @@ sockets_remove(struct birdloop *loop, sock *s)
/* Decouple the socket from the loop at all. */
rem_node
(
&
s
->
n
);
loop
->
sock_num
--
;
loop
->
poll_changed
=
1
;
if
(
loop
->
thread
)
atomic_store_explicit
(
&
loop
->
thread
->
poll_changed
,
1
,
memory_order_release
);
s
->
index
=
-
1
;
/* Close the filedescriptor. If it ever gets into the poll(), it just returns
...
...
@@ -306,7 +322,6 @@ sockets_prepare(struct birdloop *loop, struct pollfd *pfd, struct pollfd *end)
pfd
++
;
}
loop
->
poll_changed
=
0
;
return
pfd
;
}
...
...
@@ -342,7 +357,7 @@ sockets_fire(struct birdloop *loop)
if
(
rev
&
POLLOUT
)
{
loop
->
poll_changed
=
1
;
atomic_store_explicit
(
&
loop
->
thread
->
poll_changed
,
1
,
memory_order_release
)
;
while
(
e
=
sk_write
(
s
))
;
}
...
...
@@ -358,10 +373,12 @@ static DOMAIN(resource) birdloop_domain;
static
list
birdloop_pickup
;
static
list
bird_thread_pickup
;
static
_Thread_local
struct
bird_thread
*
this_thread
;
static
void
*
bird_thread_main
(
void
*
arg
)
{
struct
bird_thread
*
thr
=
arg
;
struct
bird_thread
*
thr
=
this_thread
=
arg
;
rcu_thread_start
(
&
thr
->
rcu
);
synchronize_rcu
();
...
...
@@ -369,7 +386,7 @@ bird_thread_main(void *arg)
tmp_init
(
thr
->
pool
);
init_list
(
&
thr
->
loops
);
int
refresh_sockets
=
1
;
u32
refresh_sockets
=
1
;
struct
pollfd
*
pfd
,
*
end
;
...
...
@@ -387,10 +404,11 @@ bird_thread_main(void *arg)
UNLOCK_DOMAIN
(
resource
,
birdloop_domain
);
add_tail
(
&
thr
->
loops
,
&
loop
->
n
);
refresh_sockets
=
1
;
birdloop_enter
(
loop
);
loop
->
thread
=
thr
;
if
(
!
EMPTY_LIST
(
loop
->
sock_list
))
refresh_sockets
=
1
;
birdloop_leave
(
loop
);
/* If there are more loops to be picked up, wakeup the next thread */
...
...
@@ -407,21 +425,33 @@ bird_thread_main(void *arg)
WALK_LIST2
(
loop
,
nn
,
thr
->
loops
,
n
)
{
birdloop_enter
(
loop
);
u64
after_enter
=
ns_now
();
timer
*
t
;
times_update
();
timers_fire
(
&
loop
->
time
,
0
);
if
(
birdloop_process_flags
(
loop
)
+
birdloop_run_events
(
loop
))
int
again
=
birdloop_process_flags
(
loop
)
+
ev_run_list
(
&
loop
->
event_list
);
#if 0
if (loop->n.next->next)
__builtin_prefetch(SKIP_BACK(struct birdloop, n, loop->n.next)->time.domain);
#endif
if
(
again
)
timeout
=
MIN
(
0
,
timeout
);
else
if
(
t
=
timers_first
(
&
loop
->
time
))
timeout
=
MIN
(((
tm_remains
(
t
)
TO_MS
)
+
1
),
timeout
);
if
(
loop
->
poll_changed
)
refresh_sockets
=
1
;
u64
before_leave
=
ns_now
();
loop
->
total_time_spent_ns
+=
(
before_leave
-
after_enter
);
birdloop_leave
(
loop
);
ev_run_list
(
&
thr
->
priority_events
);
}
refresh_sockets
+=
atomic_exchange_explicit
(
&
thr
->
poll_changed
,
0
,
memory_order_acq_rel
);
if
(
!
refresh_sockets
&&
((
timeout
<
0
)
||
(
timeout
>
5000
)))
flush_local_pages
();
...
...
@@ -462,19 +492,23 @@ poll_retry:;
/* Drain wakeup fd */
if
(
thr
->
pfd
[
0
].
revents
&
POLLIN
)
{
ASSERT_DIE
(
rv
>
0
);
rv
--
;
wakeup_drain
(
thr
);
}
atomic_exchange_explicit
(
&
thr
->
ping_sent
,
0
,
memory_order_acq_rel
);
if
(
!
rv
&&
!
atomic_exchange_explicit
(
&
thr
->
run_cleanup
,
0
,
memory_order_acq_rel
))
continue
;
/* Process stops and regular sockets */
node
*
nxt
;
WALK_LIST2_DELSAFE
(
loop
,
nn
,
nxt
,
thr
->
loops
,
n
)
{
birdloop_enter
(
loop
);
if
(
loop
->
poll_changed
)
refresh_sockets
=
1
;
if
(
loop
->
stopped
)
{
/* Flush remaining events */
...
...
@@ -509,13 +543,14 @@ bird_thread_start(pool *pp)
{
pool
*
p
=
rp_new
(
pp
,
"Thread"
);
struct
bird_thread
*
thr
=
mb_alloc
(
p
,
sizeof
(
*
thr
));
struct
bird_thread
*
thr
=
mb_alloc
z
(
p
,
sizeof
(
*
thr
));
thr
->
pool
=
p
;
thr
->
pfd
=
mb_alloc
(
p
,
sizeof
(
struct
pollfd
)
*
(
thr
->
pfd_max
=
16
));
atomic_store_explicit
(
&
thr
->
ping_sent
,
0
,
memory_order_relaxed
);
wakeup_init
(
thr
);
ev_init_list
(
&
thr
->
priority_events
,
NULL
,
"Thread direct event list"
);
LOCK_DOMAIN
(
resource
,
birdloop_domain
);
add_tail
(
&
bird_thread_pickup
,
&
thr
->
n
);
...
...
@@ -547,6 +582,102 @@ bird_thread_stop(struct bird_thread *thr)
rfree
(
thr
->
pool
);
}
DEFINE_DOMAIN
(
control
);
struct
bird_thread_show_data
{
cli
*
cli
;
pool
*
pool
;
DOMAIN
(
control
)
lock
;
uint
total
;
uint
done
;
u8
show_loops
;
};
static
void
bird_thread_show_cli_cont
(
struct
cli
*
c
UNUSED
)
{
/* Explicitly do nothing to prevent CLI from trying to parse another command. */
}
static
int
bird_thread_show_cli_cleanup
(
struct
cli
*
c
UNUSED
)
{
return
1
;
/* Defer the cleanup until the writeout is finished. */
}
static
void
bird_thread_show
(
void
*
data
)
{
struct
bird_thread_show_data
*
tsd
=
data
;
LOCK_DOMAIN
(
control
,
tsd
->
lock
);
if
(
tsd
->
show_loops
)
cli_printf
(
tsd
->
cli
,
-
1026
,
"Thread %p"
,
this_thread
);
u64
total_time_ns
=
0
;
struct
birdloop
*
loop
;
WALK_LIST
(
loop
,
this_thread
->
loops
)
{
if
(
tsd
->
show_loops
)
cli_printf
(
tsd
->
cli
,
-
1026
,
" Loop %s time: %t"
,
domain_name
(
loop
->
time
.
domain
),
loop
->
total_time_spent_ns
NS
);
total_time_ns
+=
loop
->
total_time_spent_ns
;
}
tsd
->
done
++
;
int
last
=
(
tsd
->
done
==
tsd
->
total
);
if
(
last
)
{
tsd
->
cli
->
cont
=
NULL
;
tsd
->
cli
->
cleanup
=
NULL
;
}
if
(
tsd
->
show_loops
)
cli_printf
(
tsd
->
cli
,
(
last
?
1
:
-
1
)
*
1026
,
" Total time: %t"
,
total_time_ns
NS
);
else
cli_printf
(
tsd
->
cli
,
(
last
?
1
:
-
1
)
*
1026
,
"Thread %p time %t"
,
this_thread
,
total_time_ns
NS
);
UNLOCK_DOMAIN
(
control
,
tsd
->
lock
);
if
(
last
)
{
the_bird_lock
();
cli_write_trigger
(
tsd
->
cli
);
DOMAIN_FREE
(
control
,
tsd
->
lock
);
rfree
(
tsd
->
pool
);
the_bird_unlock
();
}
}
void
cmd_show_threads
(
int
show_loops
)
{
pool
*
p
=
rp_new
(
&
root_pool
,
"Show Threads"
);
struct
bird_thread_show_data
*
tsd
=
mb_allocz
(
p
,
sizeof
(
struct
bird_thread_show_data
));
tsd
->
lock
=
DOMAIN_NEW
(
control
,
"Show Threads"
);
tsd
->
cli
=
this_cli
;
tsd
->
pool
=
p
;
tsd
->
show_loops
=
show_loops
;
this_cli
->
cont
=
bird_thread_show_cli_cont
;
this_cli
->
cleanup
=
bird_thread_show_cli_cleanup
;
LOCK_DOMAIN
(
control
,
tsd
->
lock
);
LOCK_DOMAIN
(
resource
,
birdloop_domain
);
struct
bird_thread
*
thr
;
WALK_LIST
(
thr
,
bird_thread_pickup
)
{
tsd
->
total
++
;
ev_send
(
&
thr
->
priority_events
,
ev_new_init
(
p
,
bird_thread_show
,
tsd
));
wakeup_do_kick
(
thr
);
}
UNLOCK_DOMAIN
(
resource
,
birdloop_domain
);
UNLOCK_DOMAIN
(
control
,
tsd
->
lock
);
}
/*
* Birdloop
...
...
@@ -560,11 +691,13 @@ static void birdloop_enter_locked(struct birdloop *loop);
void
birdloop_init
(
void
)
{
ns_init
();
birdloop_domain
=
DOMAIN_NEW
(
resource
,
"Loop Pickup"
);
init_list
(
&
birdloop_pickup
);
init_list
(
&
bird_thread_pickup
);
#define THREAD_PREFORK_COUNT
1
#define THREAD_PREFORK_COUNT
6
for
(
int
i
=
0
;
i
<
THREAD_PREFORK_COUNT
;
i
++
)
bird_thread_start
(
&
root_pool
);
...
...
@@ -613,7 +746,10 @@ birdloop_do_stop(struct birdloop *loop, void (*stopped)(void *data), void *data)
loop
->
stopped
=
stopped
;
loop
->
stop_data
=
data
;
if
(
loop
->
thread
)
{
atomic_store_explicit
(
&
loop
->
thread
->
run_cleanup
,
1
,
memory_order_release
);
wakeup_do_kick
(
loop
->
thread
);
}
}
void
...
...
sysdep/unix/io-loop.h
View file @
16cff36a
...
...
@@ -31,7 +31,6 @@ struct birdloop
int
sock_num
;
uint
ping_pending
;
uint
poll_changed
;
uint
links
;
...
...
@@ -45,6 +44,8 @@ struct birdloop
struct
bird_thread
*
thread
;
struct
pollfd
*
pfd
;
u64
total_time_spent_ns
;
};
struct
bird_thread
...
...
@@ -55,7 +56,11 @@ struct bird_thread
uint
pfd_max
;
_Atomic
u32
ping_sent
;
_Atomic
u32
run_cleanup
;
_Atomic
u32
poll_changed
;
struct
pipe
wakeup
;
event_list
priority_events
;
pthread_t
thread_id
;
pthread_attr_t
thread_attr
;
...
...
@@ -66,5 +71,4 @@ struct bird_thread
pool
*
pool
;
};
#endif
sysdep/unix/unix.h
View file @
16cff36a
...
...
@@ -32,6 +32,7 @@ void cmd_reconfig_undo(void);
void
cmd_reconfig_status
(
void
);
void
cmd_shutdown
(
void
);
void
cmd_graceful_restart
(
void
);
void
cmd_show_threads
(
int
);
#define UNIX_DEFAULT_CONFIGURE_TIMEOUT 300
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment