25RCSID(
"$Id: 9e8cc03f39e4e22a305416a4f6e47cc343631c06 $")
27#define LOG_DST sc->log
29#include <freeradius-devel/autoconf.h>
31#include <freeradius-devel/io/schedule.h>
32#include <freeradius-devel/io/thread.h>
33#include <freeradius-devel/util/dlist.h>
34#include <freeradius-devel/util/rb.h>
35#include <freeradius-devel/util/syserror.h>
36#include <freeradius-devel/server/trigger.h>
37#include <freeradius-devel/util/semaphore.h>
125 char worker_name[32];
135 PERROR(
"%s - Failed creating worker", worker_name);
142 if (
sc->worker_thread_instantiate) {
144 char section_name[32];
152 PERROR(
"%s - Worker thread instantiation failed", worker_name);
162 PERROR(
"%s - Failed adding worker to network %u", worker_name, sn->thread.id);
185 if (
sc->worker_thread_detach)
sc->worker_thread_detach(NULL);
212 char network_name[32];
220 PERROR(
"%s - Failed creating network", network_name);
267 bool single_threaded,
290 sc->config->max_networks = 1;
291 sc->config->max_workers = 4;
295 if (
sc->config->max_networks < 1)
sc->config->max_networks = 1;
296 if (
sc->config->max_networks > 64)
sc->config->max_networks = 64;
297 if (
sc->config->max_workers < 1)
sc->config->max_workers = 1;
298 if (
sc->config->max_workers > 64)
sc->config->max_workers = 64;
302 sc->single_threaded = single_threaded;
305 sc->cs =
sc->config->cs;
307 sc->worker_thread_instantiate = worker_thread_instantiate;
308 sc->worker_thread_detach = worker_thread_detach;
314 if (single_threaded) {
316 if (!
sc->single_network) {
317 PERROR(
"Failed creating network");
318 pre_instantiate_st_fail:
324 PERROR(
"Failed creating coordinators");
326 PERROR(
"Failed destroying network");
328 goto pre_instantiate_st_fail;
333 if (!
sc->single_worker) {
334 PERROR(
"Failed creating worker");
336 PERROR(
"Failed destroying network");
338 goto pre_instantiate_st_fail;
344 if (
sc->worker_thread_instantiate) {
350 if (
sc->worker_thread_instantiate(
sc->single_worker,
el, subcs) < 0) {
351 PERROR(
"Worker thread instantiation failed");
354 PERROR(
"Failed destroying network");
357 goto pre_instantiate_st_fail;
362 PERROR(
"Failed adding worker commands");
364 if (
sc->worker_thread_detach)
sc->worker_thread_detach(NULL);
369 PERROR(
"Failed adding network commands");
378 DEBUG(
"Scheduler created in single-threaded mode");
413 if (!
sc->network_sem) {
423 if (!
sc->worker_sem)
goto sem_fail;
426 if (!
sc->coord_sem)
goto sem_fail;
431 for (i = 0; i <
sc->config->max_networks; i++) {
432 DEBUG3(
"Creating %u/%u networks", i + 1,
sc->config->max_networks);
439 ERROR(
"Network %u - Failed allocating memory", i);
449 PERROR(
"Failed creating network %u", i);
477 for (i = 0; i <
sc->config->max_workers; i++) {
478 DEBUG3(
"Creating %u/%u workers", i + 1,
sc->config->max_workers);
485 ERROR(
"Worker %u - Failed allocating memory", i);
495 PERROR(
"Failed creating worker %u", i);
521 PERROR(
"Failed adding worker commands");
537 PERROR(
"Failed adding network commands");
542 if (
sc)
INFO(
"Scheduler created successfully with %u networks and %u workers",
551 if (
sc->worker_thread_instantiate &&
553 PERROR(
"Main thread instantiation failed");
588 if (
sc->single_threaded) {
594 ERROR(
"Failed destroying network");
607 if (
sc->worker_thread_detach)
sc->worker_thread_detach(NULL);
615 PERROR(
"Failed signaling network %i to exit", sne->thread.id);
627 DEBUG2(
"Scheduler - Waiting for semaphore indicating network exit %u/%u", i + 1,
631 DEBUG2(
"Scheduler - All networks indicated exit complete");
655 DEBUG2(
"Scheduler - Waiting for semaphore indicating worker exit %u/%u", i + 1,
659 DEBUG2(
"Scheduler - All workers indicated exit complete");
709 if (
sc->single_threaded) {
710 nr =
sc->single_network;
741 if (
sc->single_threaded) {
742 nr =
sc->single_network;
static int const char char buffer[256]
A section grouping multiple CONF_PAIR.
CONF_SECTION * cf_section_find(CONF_SECTION const *cs, char const *name1, char const *name2)
Find a CONF_SECTION with name1 and optionally name2.
fr_command_register_hook_t fr_command_register_hook
int fr_coords_create(TALLOC_CTX *ctx, fr_event_list_t *el)
Start coordinators in single threaded mode.
void fr_coords_destroy(void)
Clean up coordinators in single threaded mode.
int fr_coord_post_event_insert(fr_event_list_t *el)
Insert instance specific post-event callbacks.
int fr_coord_pre_event_insert(fr_event_list_t *el)
Insert instance specific pre-event callbacks.
int fr_coord_start(uint32_t num_workers, fr_sem_t *sem)
Start all registered coordinator threads in multi-threaded mode.
#define fr_dlist_init(_head, _type, _field)
Initialise the head structure of a doubly linked list.
static void * fr_dlist_head(fr_dlist_head_t const *list_head)
Return the HEAD item of a list or NULL if the list is empty.
#define fr_dlist_foreach(_list_head, _type, _iter)
Iterate over the contents of a list.
static unsigned int fr_dlist_num_elements(fr_dlist_head_t const *head)
Return the number of elements in the dlist.
static void * fr_dlist_pop_head(fr_dlist_head_t *list_head)
Remove the head item in a list.
static int fr_dlist_insert_head(fr_dlist_head_t *list_head, void *ptr)
Insert an item into the head of a list.
static void * fr_dlist_next(fr_dlist_head_t const *list_head, void const *ptr)
Get the next item in a list.
Head of a doubly linked list.
fr_cmd_table_t cmd_network_table[]
int fr_network_listen_add(fr_network_t *nr, fr_listen_t *li)
Add a fr_listen_t to a network.
int fr_network_worker_add(fr_network_t *nr, fr_worker_t *worker)
Add a worker to a network in a different thread.
int fr_network_destroy(fr_network_t *nr)
Stop a network thread in an orderly way.
int fr_network_directory_add(fr_network_t *nr, fr_listen_t *li)
Add a "watch directory" call to a network.
void fr_network(fr_network_t *nr)
The main network worker function.
void fr_network_worker_add_self(fr_network_t *nr, fr_worker_t *worker)
Add a worker to a network in the same thread.
int fr_network_exit(fr_network_t *nr)
Signal a network thread to exit.
void fr_network_stats_log(fr_network_t const *nr, fr_log_t const *log)
fr_network_t * fr_network_create(TALLOC_CTX *ctx, fr_event_list_t *el, char const *name, fr_log_t const *logger, fr_log_lvl_t lvl, fr_network_config_t const *config)
Create a network.
int fr_event_pre_insert(fr_event_list_t *el, fr_event_status_cb_t callback, void *uctx)
Add a pre-event callback to the event list.
int fr_event_post_insert(fr_event_list_t *el, fr_event_post_cb_t callback, void *uctx)
Add a post-event callback to the event list.
Stores all information relating to an event list.
static const conf_parser_t config[]
CONF_SECTION * cs
thread pool configuration section
fr_thread_t thread
common thread structure - must be first!
fr_timer_t * ev
timer for stats_interval
static _Thread_local int worker_id
Internal ID of the current worker thread.
fr_sem_t * coord_sem
for inter-thread signaling
fr_schedule_t * fr_schedule_create(TALLOC_CTX *ctx, bool single_threaded, fr_event_list_t *el, fr_log_t *logger, fr_log_lvl_t lvl, fr_schedule_thread_instantiate_t worker_thread_instantiate, fr_schedule_thread_detach_t worker_thread_detach, fr_schedule_config_t *config)
Create a scheduler and spawn the child threads.
fr_event_list_t * el
event list for single-threaded mode.
fr_schedule_t * sc
the scheduler we are running under
fr_sem_t * worker_sem
for inter-thread signaling
fr_worker_t * single_worker
for single-threaded mode
fr_log_lvl_t lvl
log level
static void stats_timer(fr_timer_list_t *tl, fr_time_t now, void *uctx)
fr_network_t * fr_schedule_directory_add(fr_schedule_t *sc, fr_listen_t *li)
Add a directory NOTE_EXTEND to a scheduler.
fr_schedule_config_t * config
configuration
fr_network_t * single_network
for single-threaded mode
fr_schedule_thread_instantiate_t worker_thread_instantiate
thread instantiation callback
fr_network_t * fr_schedule_listen_add(fr_schedule_t *sc, fr_listen_t *li)
Add a fr_listen_t to a scheduler.
fr_network_t * nr
the receive data structure
fr_schedule_thread_detach_t worker_thread_detach
bool running
is the scheduler running?
int fr_schedule_worker_id(void)
Return the worker id for the current thread.
static void * fr_schedule_worker_thread(void *arg)
Entry point for worker threads.
fr_sem_t * network_sem
for inter-thread signaling
unsigned int num_workers_exited
number of exited workers
int fr_schedule_destroy(fr_schedule_t **sc_to_free)
Destroy a scheduler, and tell its child threads to exit.
bool single_threaded
true if running in single-threaded mode.
fr_dlist_head_t networks
list of networks
fr_log_t * log
log destination
fr_dlist_head_t workers
list of workers
static void * fr_schedule_network_thread(void *arg)
Initialize and run the network thread.
Scheduler specific information for network threads.
int(* fr_schedule_thread_instantiate_t)(TALLOC_CTX *ctx, fr_event_list_t *el, void *uctx)
Setup a new thread.
void(* fr_schedule_thread_detach_t)(void *uctx)
Explicitly free resources allocated by fr_schedule_thread_instantiate_t.
fr_time_delta_t stats_interval
print channel statistics
void fr_sem_free(fr_sem_t *sem)
fr_sem_t * fr_sem_alloc(void)
#define SEM_WAIT_INTR(_x)
static const uchar sc[16]
PUBLIC int snprintf(char *string, size_t length, char *format, va_alist)
char const * fr_syserror(int num)
Guaranteed to be thread-safe version of strerror.
void fr_thread_start(fr_thread_t *thread, fr_sem_t *sem)
Signal the parent that we're done.
int fr_thread_wait_list(fr_sem_t *sem, fr_dlist_head_t *head)
Wait for multiple threads to signal readiness via a semaphore.
int fr_thread_create(pthread_t *thread, fr_thread_entry_t func, void *arg)
Create a joinable thread.
int fr_thread_setup(fr_thread_t *out, char const *name)
Common setup for child threads: block signals, allocate a talloc context, and create an event list.
void fr_thread_exit(fr_thread_t *thread, fr_thread_status_t status, fr_sem_t *sem)
Signal the parent that we're done.
fr_thread_status_t status
running, etc.
fr_event_list_t * el
our event list
int id
unique ID for this thread
fr_thread_status_t
Track the child thread status.
@ FR_THREAD_INITIALIZING
initialized, but not running
@ FR_THREAD_EXITED
exited, and in the exited queue
@ FR_THREAD_FAIL
failed, and in the exited queue
TALLOC_CTX * ctx
our allocation ctx
pthread_t pthread_id
of this thread
#define fr_time_delta_ispos(_a)
#define fr_time_add(_a, _b)
Add a time/time delta together.
static fr_event_list_t * el
#define fr_strerror_const(_msg)
int fr_worker_pre_event(UNUSED fr_time_t now, UNUSED fr_time_delta_t wake, void *uctx)
Pre-event handler.
fr_worker_t * fr_worker_alloc(TALLOC_CTX *ctx, fr_event_list_t *el, char const *name, fr_log_t const *logger, fr_log_lvl_t lvl, fr_worker_config_t *config)
Create a worker.
fr_cmd_table_t cmd_worker_table[]
void fr_worker_destroy(fr_worker_t *worker)
Destroy a worker.
void fr_worker_post_event(UNUSED fr_event_list_t *el, UNUSED fr_time_t now, void *uctx)
Post-event handler.
void fr_worker(fr_worker_t *worker)
The main loop and entry point of the stand-alone worker thread.
A worker which takes packets from a master, and processes them.
int uses
how many network threads are using it
fr_schedule_t * sc
the scheduler we are running under
fr_thread_t thread
common thread structure - must be first!
fr_time_t cpu_time
how much CPU time this worker has used
fr_worker_t * worker
the worker data structure
Scheduler specific information for worker threads.