25RCSID(
"$Id: 269d1650ac99193ad2bad75cfcb8d47c268cfab1 $")
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>
134 char worker_name[32];
144 PERROR(
"%s - Failed creating worker", worker_name);
151 if (
sc->worker_thread_instantiate) {
153 char section_name[32];
161 PERROR(
"%s - Worker thread instantiation failed", worker_name);
171 PERROR(
"%s - Failed adding worker to network %u", worker_name, sn->thread.id);
194 if (
sc->worker_thread_detach)
sc->worker_thread_detach(NULL);
221 char network_name[32];
229 PERROR(
"%s - Failed creating network", network_name);
276 bool single_threaded,
299 sc->config->max_networks = 1;
300 sc->config->max_workers = 4;
304 if (
sc->config->max_networks < 1)
sc->config->max_networks = 1;
305 if (
sc->config->max_networks > 64)
sc->config->max_networks = 64;
306 if (
sc->config->max_workers < 1)
sc->config->max_workers = 1;
307 if (
sc->config->max_workers > 64)
sc->config->max_workers = 64;
311 sc->single_threaded = single_threaded;
314 sc->cs =
sc->config->cs;
316 sc->worker_thread_instantiate = worker_thread_instantiate;
317 sc->worker_thread_detach = worker_thread_detach;
323 if (single_threaded) {
325 if (!
sc->single_network) {
326 PERROR(
"Failed creating network");
327 pre_instantiate_st_fail:
333 PERROR(
"Failed creating coordinators");
335 PERROR(
"Failed destroying network");
337 goto pre_instantiate_st_fail;
342 if (!
sc->single_worker) {
343 PERROR(
"Failed creating worker");
345 PERROR(
"Failed destroying network");
347 goto pre_instantiate_st_fail;
353 if (
sc->worker_thread_instantiate) {
359 if (
sc->worker_thread_instantiate(
sc->single_worker,
el, subcs) < 0) {
360 PERROR(
"Worker thread instantiation failed");
363 PERROR(
"Failed destroying network");
366 goto pre_instantiate_st_fail;
371 PERROR(
"Failed adding worker commands");
373 if (
sc->worker_thread_detach)
sc->worker_thread_detach(NULL);
378 PERROR(
"Failed adding network commands");
387 DEBUG(
"Scheduler created in single-threaded mode");
422 if (!
sc->network_sem) {
432 if (!
sc->worker_sem)
goto sem_fail;
435 if (!
sc->coord_sem)
goto sem_fail;
440 for (i = 0; i <
sc->config->max_networks; i++) {
441 DEBUG3(
"Creating %u/%u networks", i + 1,
sc->config->max_networks);
448 ERROR(
"Network %u - Failed allocating memory", i);
458 PERROR(
"Failed creating network %u", i);
486 for (i = 0; i <
sc->config->max_workers; i++) {
487 DEBUG3(
"Creating %u/%u workers", i + 1,
sc->config->max_workers);
494 ERROR(
"Worker %u - Failed allocating memory", i);
504 PERROR(
"Failed creating worker %u", i);
530 PERROR(
"Failed adding worker commands");
546 PERROR(
"Failed adding network commands");
551 if (
sc)
INFO(
"Scheduler created successfully with %u networks and %u workers",
560 if (
sc->worker_thread_instantiate &&
562 PERROR(
"Main thread instantiation failed");
597 if (
sc->single_threaded) {
603 ERROR(
"Failed destroying network");
616 if (
sc->worker_thread_detach)
sc->worker_thread_detach(NULL);
624 PERROR(
"Failed signaling network %i to exit", sne->thread.id);
636 DEBUG2(
"Scheduler - Waiting for semaphore indicating network exit %u/%u", i + 1,
640 DEBUG2(
"Scheduler - All networks indicated exit complete");
664 DEBUG2(
"Scheduler - Waiting for semaphore indicating worker exit %u/%u", i + 1,
668 DEBUG2(
"Scheduler - All workers indicated exit complete");
718 if (
sc->single_threaded) {
719 nr =
sc->single_network;
750 if (
sc->single_threaded) {
751 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?
void fr_schedule_worker_id_set(int id)
Explicitly set the worker id for the current thread.
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.