From: Alan T. DeKok Date: Thu, 12 Jul 2018 15:32:27 +0000 (-0400) Subject: fix up dlist functions. X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=3b655b420a6ce702ec3c581e3da40d033e0082bb;p=thirdparty%2Ffreeradius-server.git fix up dlist functions. Add a separate `fr_dlist_head_t`, which contains an offset of the encapsulating structure. And then fix up the various functions to take a head / ptr instead of "entry". That way the caller doesn't have to play dumb games with `fr_dlist_t *entry = ...` and various casts. --- diff --git a/src/lib/io/channel.h b/src/lib/io/channel.h index f7bc600d6a6..35d881db21d 100644 --- a/src/lib/io/channel.h +++ b/src/lib/io/channel.h @@ -96,7 +96,7 @@ typedef struct fr_channel_data_t { union { struct { fr_time_t *recv_time; //!< time original request was received (network -> worker) - fr_dlist_t list; //!< list of unprocessed packets for the worker + fr_dlist_t entry; //!< list of unprocessed packets for the worker bool is_dup; //!< dup, new, etc. } request; diff --git a/src/lib/io/network.c b/src/lib/io/network.c index 9d2c873ef96..6b8eb888d31 100644 --- a/src/lib/io/network.c +++ b/src/lib/io/network.c @@ -34,7 +34,6 @@ RCSID("$Id$") #include #include #include -#include /* * Define our own debugging. @@ -85,8 +84,6 @@ typedef struct fr_network_socket_t { fr_channel_data_t *pending; //!< the currently pending partial packet fr_heap_t *waiting; //!< packets waiting to be written - - fr_dlist_t entry; //!< for deleted sockets } fr_network_socket_t; /* @@ -741,7 +738,6 @@ static void fr_network_socket_callback(void *ctx, void const *data, size_t data_ memcpy(&s->listen, data, sizeof(s->listen)); MEM(s->waiting = fr_heap_create(s, waiting_cmp, fr_channel_data_t, channel.heap_id)); - FR_DLIST_INIT(s->entry); talloc_set_destructor(s, _network_socket_free); @@ -815,7 +811,6 @@ static void fr_network_directory_callback(void *ctx, void const *data, size_t da memcpy(&s->listen, data, sizeof(s->listen)); MEM(s->waiting = fr_heap_create(s, waiting_cmp, fr_channel_data_t, channel.heap_id)); - FR_DLIST_INIT(s->entry); talloc_set_destructor(s, _network_socket_free); diff --git a/src/lib/io/schedule.c b/src/lib/io/schedule.c index ff1b84bbbbc..55808bbb16b 100644 --- a/src/lib/io/schedule.c +++ b/src/lib/io/schedule.c @@ -132,7 +132,7 @@ struct fr_schedule_t { fr_schedule_thread_instantiate_t worker_thread_instantiate; //!< thread instantiation callback void *worker_instantiate_ctx; //!< thread instantiation context - fr_dlist_t workers; //!< list of workers + fr_dlist_head_t workers; //!< list of workers fr_network_t *single_network; //!< for single-threaded mode fr_worker_t *single_worker; //!< for single-threaded mode @@ -362,7 +362,7 @@ fr_schedule_t *fr_schedule_create(TALLOC_CTX *ctx, fr_event_list_t *el, { #ifdef HAVE_PTHREAD_H int i; - fr_dlist_t *entry, *next; + fr_schedule_worker_t *sw, *next; #endif fr_schedule_t *sc; @@ -439,7 +439,7 @@ fr_schedule_t *fr_schedule_create(TALLOC_CTX *ctx, fr_event_list_t *el, /* * Create the list which holds the workers. */ - FR_DLIST_INIT(sc->workers); + fr_dlist_init(&sc->workers, offsetof(fr_schedule_worker_t, entry)); memset(&sc->semaphore, 0, sizeof(sc->semaphore)); if (sem_init(&sc->semaphore, 0, SEMAPHORE_LOCKED) != 0) { @@ -474,8 +474,6 @@ fr_schedule_t *fr_schedule_create(TALLOC_CTX *ctx, fr_event_list_t *el, * Create all of the workers. */ for (i = 0; i < sc->max_workers; i++) { - fr_schedule_worker_t *sw; - fr_log(sc->log, L_DBG, "Creating %d/%d workers\n", i, sc->max_workers); /* @@ -490,7 +488,7 @@ fr_schedule_t *fr_schedule_create(TALLOC_CTX *ctx, fr_event_list_t *el, sw->id = i; sw->sc = sc; sw->status = FR_CHILD_INITIALIZING; - fr_dlist_insert_head(&sc->workers, &sw->entry); + fr_dlist_insert_head(&sc->workers, sw); if (fr_schedule_pthread_create(&sw->pthread_id, fr_schedule_worker_thread, sw) < 0) { fr_log(sc->log, L_ERR, "Failed creating worker %d: %s\n", i, fr_strerror()); @@ -514,18 +512,15 @@ fr_schedule_t *fr_schedule_create(TALLOC_CTX *ctx, fr_event_list_t *el, /* * See if all of the workers have started. */ - for (entry = FR_DLIST_FIRST(sc->workers); - entry != NULL; - entry = next) { - fr_schedule_worker_t *sw; - - next = FR_DLIST_NEXT(sc->workers, entry); + for (sw = fr_dlist_first(&sc->workers); + sw != NULL; + sw = next) { - sw = fr_ptr_to_type(fr_schedule_worker_t, entry, entry); + next = fr_dlist_next(&sc->workers, sw); if (sw->status != FR_CHILD_RUNNING) { sc->num_workers--; - fr_dlist_remove(entry); + fr_dlist_remove(&sc->workers, sw); continue; } } @@ -560,8 +555,6 @@ int fr_schedule_destroy(fr_schedule_t *sc) sc->running = false; #ifdef HAVE_PTHREAD_H - fr_dlist_t *entry; - /* * Single threaded mode: kill the only network / worker we have. */ @@ -592,10 +585,9 @@ int fr_schedule_destroy(fr_schedule_t *sc) /* * Signal all of the workers to exit. */ - for (entry = FR_DLIST_FIRST(sc->workers); - entry != NULL; - entry = FR_DLIST_NEXT(sc->workers, entry)) { - sw = fr_ptr_to_type(fr_schedule_worker_t, entry, entry); + for (sw = fr_dlist_first(&sc->workers); + sw != NULL; + sw = fr_dlist_next(&sc->workers, sw)) { fr_worker_exit(sw->worker); } @@ -612,9 +604,10 @@ int fr_schedule_destroy(fr_schedule_t *sc) /* * Clean up the exited workers. */ - while ((entry = FR_DLIST_FIRST(sc->workers)) != NULL) { + while ((sw = fr_dlist_first(&sc->workers)) != NULL) { sc->num_workers--; - fr_dlist_remove(entry); + + fr_dlist_remove(&sc->workers, sw); /* * Ensure that the thread has exited before @@ -624,7 +617,6 @@ int fr_schedule_destroy(fr_schedule_t *sc) * exited before the main thread cleans up the * module instances. */ - sw = fr_ptr_to_type(fr_schedule_worker_t, entry, entry); if (pthread_join(sw->pthread_id, NULL) != 0) { fr_log(sc->log, L_ERR, "Failed joining worker %i: %s", sw->id, fr_syserror(errno)); } else { diff --git a/src/lib/io/time.c b/src/lib/io/time.c index abc28e7d42d..596d38f5e12 100644 --- a/src/lib/io/time.c +++ b/src/lib/io/time.c @@ -148,7 +148,7 @@ void fr_time_to_timeval(struct timeval *tv, fr_time_t when) * @param[in] tt the time tracking structure. * @param[in] when the event happened */ -void fr_time_tracking_start(fr_time_tracking_t *tt, fr_time_t when) +void fr_time_tracking_start(fr_time_tracking_t *tt, fr_time_t when, fr_time_tracking_t *worker) { memset(tt, 0, sizeof(*tt)); @@ -156,7 +156,8 @@ void fr_time_tracking_start(fr_time_tracking_t *tt, fr_time_t when) tt->start = when; tt->resumed = when; - FR_DLIST_INIT(tt->list); + fr_dlist_init(&(worker->list), offsetof(fr_time_tracking_t, list.entry)); + fr_dlist_entry_init(&tt->list.entry); } @@ -180,8 +181,8 @@ void fr_time_tracking_end(fr_time_tracking_t *tt, fr_time_t when, fr_time_tracki /* * This request cannot be in any list. */ - rad_assert(tt->list.prev == &tt->list); - rad_assert(tt->list.next == &tt->list); + rad_assert(tt->list.entry.prev == &(tt->list.entry)); + rad_assert(tt->list.entry.next == &(tt->list.entry)); /* * Update the time that the worker spent processing the request. @@ -215,7 +216,7 @@ void fr_time_tracking_yield(fr_time_tracking_t *tt, fr_time_t when, fr_time_trac * Insert this request into the TAIL of the worker's list * of waiting requests. */ - fr_dlist_insert_head(&worker->list, &tt->list); + fr_dlist_insert_head(&worker->list, tt); } @@ -224,7 +225,7 @@ void fr_time_tracking_yield(fr_time_tracking_t *tt, fr_time_t when, fr_time_trac * @param[in] tt the time tracking structure. * @param[in] when the event happened */ -void fr_time_tracking_resume(fr_time_tracking_t *tt, fr_time_t when) +void fr_time_tracking_resume(fr_time_tracking_t *tt, fr_time_t when, fr_time_tracking_t *worker) { tt->when = when; tt->resumed = when; @@ -237,7 +238,7 @@ void fr_time_tracking_resume(fr_time_tracking_t *tt, fr_time_t when) * Remove this request into the workers list of waiting * requests. */ - fr_dlist_remove(&tt->list); + fr_dlist_remove(&worker->list, tt); } diff --git a/src/lib/io/time.h b/src/lib/io/time.h index 9950a555328..686bb2f2e63 100644 --- a/src/lib/io/time.h +++ b/src/lib/io/time.h @@ -68,7 +68,7 @@ typedef struct fr_time_tracking_t { fr_time_t running; //!< total time spent running fr_time_t waiting; //!< total time spent waiting - fr_dlist_t list; //!< for linking a request to various lists + fr_dlist_head_t list; //!< for linking a request to various lists } fr_time_tracking_t; #define NANOSEC (1000000000) @@ -78,10 +78,10 @@ int fr_time_start(void); fr_time_t fr_time(void); void fr_time_to_timeval(struct timeval *tv, fr_time_t when) CC_HINT(nonnull); -void fr_time_tracking_start(fr_time_tracking_t *tt, fr_time_t when) CC_HINT(nonnull); +void fr_time_tracking_start(fr_time_tracking_t *tt, fr_time_t when, fr_time_tracking_t *worker) CC_HINT(nonnull); void fr_time_tracking_end(fr_time_tracking_t *tt, fr_time_t when, fr_time_tracking_t *worker) CC_HINT(nonnull); void fr_time_tracking_yield(fr_time_tracking_t *tt, fr_time_t when, fr_time_tracking_t *worker) CC_HINT(nonnull); -void fr_time_tracking_resume(fr_time_tracking_t *tt, fr_time_t when) CC_HINT(nonnull); +void fr_time_tracking_resume(fr_time_tracking_t *tt, fr_time_t when, fr_time_tracking_t *worker) CC_HINT(nonnull); void fr_time_tracking_debug(fr_time_tracking_t *tt, FILE *fp) CC_HINT(nonnull); #ifdef __cplusplus diff --git a/src/lib/io/worker.c b/src/lib/io/worker.c index f5a79de72c4..3bf55e47988 100644 --- a/src/lib/io/worker.c +++ b/src/lib/io/worker.c @@ -72,7 +72,7 @@ RCSID("$Id$") * Track things by priority and time. */ typedef struct fr_worker_heap_t { - fr_dlist_t list; //!< list of things, ordered by time. + fr_dlist_head_t list; //!< list of things, ordered by time. fr_heap_t *heap; //!< heap, ordered by priority } fr_worker_heap_t; @@ -165,9 +165,9 @@ static void fr_worker_post_event(fr_event_list_t *el, struct timeval *now, void * We need wrapper macros because we have multiple instances of * the same code. */ -#define WORKER_HEAP_INIT(_name, _func, _type, _member) do { \ - FR_DLIST_INIT(worker->_name.list); \ - worker->_name.heap = fr_heap_create(worker, _func, _type, _member); \ +#define WORKER_HEAP_INIT(_name, _func) do { \ + fr_dlist_init(&worker->_name.list, offsetof(fr_channel_data_t, request.entry)); \ + worker->_name.heap = fr_heap_create(worker, _func, fr_channel_data_t, channel.heap_id); \ if (!worker->_name.heap) { \ (void) fr_event_user_delete(worker->el, fr_worker_evfilt_user, worker); \ talloc_free(worker); \ @@ -175,19 +175,19 @@ static void fr_worker_post_event(fr_event_list_t *el, struct timeval *now, void } \ } while (0) -#define WORKER_HEAP_INSERT(_name, _var, _member) do { \ - fr_dlist_insert_head(&worker->_name.list, &_var->_member); \ - (void) fr_heap_insert(worker->_name.heap, _var); \ +#define WORKER_HEAP_INSERT(_name, _var) do { \ + (void) fr_heap_insert(worker->_name.heap, _var); \ + fr_dlist_insert_head(&worker->_name.list, _var); \ } while (0) -#define WORKER_HEAP_POP(_name, _var, _member) do { \ - _var = fr_heap_pop(worker->_name.heap); \ - if (_var) fr_dlist_remove(&_var->_member); \ +#define WORKER_HEAP_POP(_name, _var) do { \ + _var = fr_heap_pop(worker->_name.heap); \ + if (_var) fr_dlist_remove(&worker->_name.list, _var); \ } while (0) -#define WORKER_HEAP_EXTRACT(_name, _var, _member) do { \ - (void) fr_heap_extract(worker->_name.heap, _var); \ - fr_dlist_remove(&_var->_member); \ +#define WORKER_HEAP_EXTRACT(_name, _var) do { \ + (void) fr_heap_extract(worker->_name.heap, _var); \ + fr_dlist_remove(&worker->_name.list, _var); \ } while (0) @@ -211,7 +211,7 @@ static bool fr_worker_drain_input(fr_worker_t *worker, fr_channel_t *ch, fr_chan worker->num_requests++; DEBUG3("\t%sreceived request %d", worker->name, worker->num_requests); cd->channel.ch = ch; - WORKER_HEAP_INSERT(to_decode, cd, request.list); + WORKER_HEAP_INSERT(to_decode, cd); } while ((cd = fr_channel_recv_request(ch)) != NULL); return true; @@ -568,7 +568,7 @@ finished: request->async->original_recv_time = NULL; request->async->el = NULL; request->async->process = NULL; - fr_dlist_remove(&request->async->tracking.list); + fr_dlist_remove(&worker->tracking.list, &request->async->tracking); request->async->channel = NULL; request->async->packet_ctx = NULL; request->async->listen = NULL; @@ -584,7 +584,7 @@ finished: */ static void worker_stop_request(fr_worker_t *worker, REQUEST *request, fr_time_t now) { - fr_time_tracking_resume(&request->async->tracking, now); + fr_time_tracking_resume(&request->async->tracking, now, &worker->tracking); (void) request->async->process(request->async->process_inst, request, FR_IO_ACTION_DONE); /* @@ -695,7 +695,7 @@ static void worker_reset_timer(fr_worker_t *worker) */ static void fr_worker_check_timeouts(fr_worker_t *worker, fr_time_t now) { - fr_dlist_t *entry; + fr_channel_data_t *cd; fr_time_t waiting; /* @@ -704,10 +704,7 @@ static void fr_worker_check_timeouts(fr_worker_t *worker, fr_time_t now) * We check it before the "to_decode" list, so that we * don't check packets twice. */ - while ((entry = FR_DLIST_TAIL(worker->localized.list)) != NULL) { - fr_channel_data_t *cd; - - cd = fr_ptr_to_type(fr_channel_data_t, request.list, entry); + while ((cd = fr_dlist_tail(&worker->localized.list)) != NULL) { waiting = now - cd->m.when; if (waiting < ((worker->max_request_time - 2) * (fr_time_t) NANOSEC)) break; @@ -715,7 +712,7 @@ static void fr_worker_check_timeouts(fr_worker_t *worker, fr_time_t now) /* * Waiting too long, delete it. */ - WORKER_HEAP_EXTRACT(localized, cd, request.list); + WORKER_HEAP_EXTRACT(localized, cd); DEBUG3("TIMEOUT: Extracting packet from localized list"); fr_worker_nak(worker, cd, now); } @@ -723,11 +720,9 @@ static void fr_worker_check_timeouts(fr_worker_t *worker, fr_time_t now) /* * Check the "to_decode" queue for old packets. */ - while ((entry = FR_DLIST_TAIL(worker->to_decode.list)) != NULL) { + while ((cd = fr_dlist_tail(&worker->to_decode.list)) != NULL) { fr_message_t *lm; - fr_channel_data_t *cd; - cd = fr_ptr_to_type(fr_channel_data_t, request.list, entry); waiting = now - cd->m.when; if (waiting < (NANOSEC / 100)) break; @@ -736,7 +731,7 @@ static void fr_worker_check_timeouts(fr_worker_t *worker, fr_time_t now) * Waiting too long, delete it. */ if (waiting > NANOSEC) { - WORKER_HEAP_EXTRACT(to_decode, cd, request.list); + WORKER_HEAP_EXTRACT(to_decode, cd); DEBUG3("TIMEOUT: Extracting packet from to_decode list"); nak: @@ -747,7 +742,7 @@ static void fr_worker_check_timeouts(fr_worker_t *worker, fr_time_t now) /* * 0.01 to 1s. Localize it. */ - WORKER_HEAP_EXTRACT(to_decode, cd, request.list); + WORKER_HEAP_EXTRACT(to_decode, cd); lm = fr_message_localize(worker, &cd->m, sizeof(*cd)); if (!lm) { DEBUG3("TIMEOUT: Failed localizing message from to_decode list: %s", fr_strerror()); @@ -755,7 +750,7 @@ static void fr_worker_check_timeouts(fr_worker_t *worker, fr_time_t now) } cd = (fr_channel_data_t *) lm; - WORKER_HEAP_INSERT(localized, cd, request.list); + WORKER_HEAP_INSERT(localized, cd); } } @@ -787,7 +782,7 @@ static REQUEST *fr_worker_get_request(fr_worker_t *worker, fr_time_t now) DEBUG3("Worker %i found runnable request", fr_schedule_worker_id()); REQUEST_VERIFY(request); rad_assert(request->runnable_id < 0); - fr_time_tracking_resume(&request->async->tracking, now); + fr_time_tracking_resume(&request->async->tracking, now, &worker->tracking); return request; } @@ -796,9 +791,9 @@ static REQUEST *fr_worker_get_request(fr_worker_t *worker, fr_time_t now) * the "to_decode" queue. */ do { - WORKER_HEAP_POP(localized, cd, request.list); + WORKER_HEAP_POP(localized, cd); if (!cd) { - WORKER_HEAP_POP(to_decode, cd, request.list); + WORKER_HEAP_POP(to_decode, cd); } if (!cd) { DEBUG3("Worker %i localized and decode lists are empty", fr_schedule_worker_id()); @@ -975,7 +970,7 @@ nak: * Bootstrap the async state machine with the initial * state of the request. */ - fr_time_tracking_start(&request->async->tracking, now); + fr_time_tracking_start(&request->async->tracking, now, &worker->tracking); worker->num_active++; rad_assert(request->runnable_id < 0); @@ -1210,13 +1205,13 @@ void fr_worker_destroy(fr_worker_t *worker) * mark them as unused. */ while (true) { - WORKER_HEAP_POP(to_decode, cd, request.list); + WORKER_HEAP_POP(to_decode, cd); if (!cd) break; fr_message_done(&cd->m); } while (true) { - WORKER_HEAP_POP(localized, cd, request.list); + WORKER_HEAP_POP(localized, cd); if (!cd) break; fr_message_done(&cd->m); } @@ -1312,7 +1307,7 @@ nomem: * the worker thread is running. */ memset(&worker->tracking, 0, sizeof(worker->tracking)); - FR_DLIST_INIT(worker->tracking.list); + fr_dlist_init(&worker->tracking.list, offsetof(fr_time_tracking_t, list.entry)); worker->kq = fr_event_list_kq(worker->el); rad_assert(worker->kq >= 0); @@ -1344,8 +1339,8 @@ nomem: goto fail2; } - WORKER_HEAP_INIT(to_decode, worker_message_cmp, fr_channel_data_t, channel.heap_id); - WORKER_HEAP_INIT(localized, worker_message_cmp, fr_channel_data_t, channel.heap_id); + WORKER_HEAP_INIT(to_decode, worker_message_cmp); + WORKER_HEAP_INIT(localized, worker_message_cmp); worker->runnable = fr_heap_talloc_create(worker, worker_runnable_cmp, REQUEST, runnable_id); if (!worker->runnable) { diff --git a/src/lib/util/dlist.h b/src/lib/util/dlist.h index f9543dd0684..9a31e091643 100644 --- a/src/lib/util/dlist.h +++ b/src/lib/util/dlist.h @@ -33,12 +33,30 @@ typedef struct fr_dlist_t { struct fr_dlist_t *next; } fr_dlist_t; +typedef struct fr_dlist_head_t { + size_t offset; + fr_dlist_t entry; +} fr_dlist_head_t; + /* * Functions to manage a doubly linked list. */ -#define FR_DLIST_INIT(head) do { head.prev = head.next = &head; } while (0) -static inline void fr_dlist_insert_head(fr_dlist_t *head, fr_dlist_t *entry) +static inline void fr_dlist_entry_init(fr_dlist_t *entry) +{ + entry->prev = entry->next = entry; +} + +static inline void fr_dlist_init(fr_dlist_head_t *head, size_t offset) +{ + fr_dlist_entry_init(&head->entry); + head->offset = offset; +} + +static inline void fr_dlist_insert_head(fr_dlist_head_t *list_head, void *ptr) { + fr_dlist_t *entry = (fr_dlist_t *) (((uint8_t *) ptr) + list_head->offset); + fr_dlist_t *head = &(list_head->entry); + if (!fr_cond_assert(head->next != NULL)) return; if (!fr_cond_assert(head->prev != NULL)) return; @@ -48,8 +66,11 @@ static inline void fr_dlist_insert_head(fr_dlist_t *head, fr_dlist_t *entry) head->next = entry; } -static inline void fr_dlist_insert_tail(fr_dlist_t *head, fr_dlist_t *entry) +static inline void fr_dlist_insert_tail(fr_dlist_head_t *list_head, void *ptr) { + fr_dlist_t *entry = (fr_dlist_t *) (((uint8_t *) ptr) + list_head->offset); + fr_dlist_t *head = &(list_head->entry); + if (!fr_cond_assert(head->next != NULL)) return; if (!fr_cond_assert(head->prev != NULL)) return; @@ -63,8 +84,10 @@ static inline void fr_dlist_insert_tail(fr_dlist_t *head, fr_dlist_t *entry) /* * Insert one list into the tail of another */ -static inline void fr_dlist_insert_tail_list(fr_dlist_t *head, fr_dlist_t *list) +static inline void fr_dlist_insert_tail_list(fr_dlist_head_t *list_head, fr_dlist_t *list) { + fr_dlist_t *head = &(list_head->entry); + if (!fr_cond_assert(head->next != NULL)) return; if (!fr_cond_assert(head->prev != NULL)) return; @@ -78,8 +101,10 @@ static inline void fr_dlist_insert_tail_list(fr_dlist_t *head, fr_dlist_t *list) } #endif -static inline void fr_dlist_remove(fr_dlist_t *entry) +static inline void fr_dlist_remove(fr_dlist_head_t *list_head, void *ptr) { + fr_dlist_t *entry = (fr_dlist_t *) (((uint8_t *) ptr) + list_head->offset); + if (!fr_cond_assert(entry->next != NULL)) return; if (!fr_cond_assert(entry->prev != NULL)) return; @@ -88,10 +113,37 @@ static inline void fr_dlist_remove(fr_dlist_t *entry) entry->prev = entry->next = entry; } -#define FR_DLIST_FIRST(head) ((head.next == &head) ? NULL : head.next) -#define FR_DLIST_NEXT(head, p_entry) ((p_entry->next == &head) ? NULL : p_entry->next) -#define FR_DLIST_TAIL(head) ((head.prev == &head) ? NULL : head.prev) +static inline void *fr_dlist_next(fr_dlist_head_t *list_head, void *ptr) +{ + fr_dlist_t *entry = (fr_dlist_t *) (((uint8_t *) ptr) + list_head->offset); + fr_dlist_t *head = &(list_head->entry); + + if (entry->next == head) return NULL; + entry = entry->next; + return (void *) (((uint8_t *) entry) - list_head->offset); +} +static inline void *fr_dlist_first(fr_dlist_head_t *list_head) +{ + fr_dlist_t *head = &(list_head->entry); + + if (head->next == head) return NULL; + + return (void *) (((uint8_t *) head->next) - list_head->offset); + +} + +static inline void *fr_dlist_tail(fr_dlist_head_t *list_head) +{ + fr_dlist_t *head = &(list_head->entry); + + if (head->prev == head) return NULL; + + return (void *) (((uint8_t *) head->prev) - list_head->offset); + +} + +#if 0 #ifdef WITH_VERIFY_PTR # define FR_DLIST_VERIFY(_head, _type, _member) \ do { \ @@ -105,6 +157,7 @@ do { \ #else # define FR_DLIST_VERIFY(_head, _type, _member) #endif +#endif /** Convert a pointer to a member into a pointer to the parent structure. * diff --git a/src/lib/util/event.c b/src/lib/util/event.c index f19674919c4..692a9a198ec 100644 --- a/src/lib/util/event.c +++ b/src/lib/util/event.c @@ -300,9 +300,9 @@ struct fr_event_list { int kq; //!< instance associated with this event list. - fr_dlist_t pre_callbacks; //!< callbacks when we may be idle... - fr_dlist_t user_callbacks; //!< EVFILT_USER callbacks - fr_dlist_t post_callbacks; //!< post-processing callbacks + fr_dlist_head_t pre_callbacks; //!< callbacks when we may be idle... + fr_dlist_head_t user_callbacks; //!< EVFILT_USER callbacks + fr_dlist_head_t post_callbacks; //!< post-processing callbacks struct kevent events[FR_EV_BATCH_FDS]; /* so it doesn't go on the stack every time */ @@ -1195,7 +1195,7 @@ uintptr_t fr_event_user_insert(fr_event_list_t *el, fr_event_user_handler_t call user->uctx = uctx; user->ident = (uintptr_t) user; - fr_dlist_insert_tail(&el->user_callbacks, &user->entry); + fr_dlist_insert_tail(&el->user_callbacks, user); return user->ident;; } @@ -1211,19 +1211,16 @@ uintptr_t fr_event_user_insert(fr_event_list_t *el, fr_event_user_handler_t call */ int fr_event_user_delete(fr_event_list_t *el, fr_event_user_handler_t callback, void *uctx) { - fr_dlist_t *entry, *next; + fr_event_user_t *user, *next; - for (entry = FR_DLIST_FIRST(el->user_callbacks); - entry != NULL; - entry = next) { - fr_event_user_t *user; + for (user = fr_dlist_first(&el->user_callbacks); + user != NULL; + user = next) { + next = fr_dlist_next(&el->user_callbacks, user); - next = FR_DLIST_NEXT(el->user_callbacks, entry); - - user = fr_ptr_to_type(fr_event_user_t, entry, entry); if ((user->callback == callback) && (user->uctx == uctx)) { - fr_dlist_remove(entry); + fr_dlist_remove(&el->user_callbacks, user); talloc_free(user); return 0; } @@ -1252,7 +1249,7 @@ int fr_event_pre_insert(fr_event_list_t *el, fr_event_status_cb_t callback, void pre->callback = callback; pre->uctx = uctx; - fr_dlist_insert_tail(&el->pre_callbacks, &pre->entry); + fr_dlist_insert_tail(&el->pre_callbacks, pre); return 0; } @@ -1268,19 +1265,16 @@ int fr_event_pre_insert(fr_event_list_t *el, fr_event_status_cb_t callback, void */ int fr_event_pre_delete(fr_event_list_t *el, fr_event_status_cb_t callback, void *uctx) { - fr_dlist_t *entry, *next; - - for (entry = FR_DLIST_FIRST(el->pre_callbacks); - entry != NULL; - entry = next) { - fr_event_pre_t *pre; + fr_event_pre_t *pre, *next; - next = FR_DLIST_NEXT(el->pre_callbacks, entry); + for (pre = fr_dlist_first(&el->pre_callbacks); + pre != NULL; + pre = next) { + next = fr_dlist_next(&el->pre_callbacks, pre); - pre = fr_ptr_to_type(fr_event_pre_t, entry, entry); if ((pre->callback == callback) && (pre->uctx == uctx)) { - fr_dlist_remove(entry); + fr_dlist_remove(&el->pre_callbacks, pre); talloc_free(pre); return 0; } @@ -1309,7 +1303,7 @@ int fr_event_post_insert(fr_event_list_t *el, fr_event_cb_t callback, void *uctx post->callback = callback; post->uctx = uctx; - fr_dlist_insert_tail(&el->post_callbacks, &post->entry); + fr_dlist_insert_tail(&el->post_callbacks, post); return 0; } @@ -1325,19 +1319,16 @@ int fr_event_post_insert(fr_event_list_t *el, fr_event_cb_t callback, void *uctx */ int fr_event_post_delete(fr_event_list_t *el, fr_event_cb_t callback, void *uctx) { - fr_dlist_t *entry, *next; - - for (entry = FR_DLIST_FIRST(el->post_callbacks); - entry != NULL; - entry = next) { - fr_event_post_t *post; + fr_event_post_t *post, *next; - next = FR_DLIST_NEXT(el->post_callbacks, entry); + for (post = fr_dlist_first(&el->post_callbacks); + post != NULL; + post = next) { + next = fr_dlist_next(&el->post_callbacks, post); - post = fr_ptr_to_type(fr_event_post_t, entry, entry); if ((post->callback == callback) && (post->uctx == uctx)) { - fr_dlist_remove(entry); + fr_dlist_remove(&el->post_callbacks, post); talloc_free(post); return 0; } @@ -1412,7 +1403,7 @@ int fr_event_corral(fr_event_list_t *el, bool wait) { struct timeval when, *wake; struct timespec ts_when, *ts_wake; - fr_dlist_t *entry; + fr_event_pre_t *pre; int num_fd_events, num_timer_events; el->num_fd_events = 0; @@ -1461,12 +1452,9 @@ int fr_event_corral(fr_event_list_t *el, bool wait) * application has more work to do, in which case we * re-set the timeout to be instant. */ - for (entry = FR_DLIST_FIRST(el->pre_callbacks); - entry != NULL; - entry = FR_DLIST_NEXT(el->pre_callbacks, entry)) { - fr_event_pre_t *pre; - - pre = fr_ptr_to_type(fr_event_pre_t, entry, entry); + for (pre = fr_dlist_first(&el->pre_callbacks); + pre != NULL; + pre = fr_dlist_next(&el->pre_callbacks, pre)) { if (pre->callback(pre->uctx, wake) > 0) { num_timer_events++; wake = &when; @@ -1514,7 +1502,7 @@ int fr_event_corral(fr_event_list_t *el, bool wait) void fr_event_service(fr_event_list_t *el) { int i; - fr_dlist_t *entry; + fr_event_post_t *post; struct timeval when; if (unlikely(el->exit)) return; @@ -1724,14 +1712,11 @@ service: /* * Run all of the post-processing events. */ - for (entry = FR_DLIST_FIRST(el->post_callbacks); - entry != NULL; - entry = FR_DLIST_NEXT(el->post_callbacks, entry)) { - fr_event_post_t *post; - + for (post = fr_dlist_first(&el->post_callbacks); + post != NULL; + post = fr_dlist_next(&el->post_callbacks, post)) { when = el->now; - post = fr_ptr_to_type(fr_event_post_t, entry, entry); post->callback(el, &when, post->uctx); } } @@ -1848,9 +1833,9 @@ fr_event_list_t *fr_event_list_alloc(TALLOC_CTX *ctx, fr_event_status_cb_t statu goto error; } - FR_DLIST_INIT(el->pre_callbacks); - FR_DLIST_INIT(el->post_callbacks); - FR_DLIST_INIT(el->user_callbacks); + fr_dlist_init(&el->pre_callbacks, offsetof(fr_event_pre_t, entry)); + fr_dlist_init(&el->post_callbacks, offsetof(fr_event_post_t, entry)); + fr_dlist_init(&el->user_callbacks, offsetof(fr_event_user_t, entry)); if (status) (void) fr_event_pre_insert(el, status, status_uctx); diff --git a/src/main/exec.c b/src/main/exec.c index 3ef92df5b68..8216ef2fa71 100644 --- a/src/main/exec.c +++ b/src/main/exec.c @@ -57,7 +57,7 @@ typedef struct fr_child_t { pid_t pid; } fr_child_t; -fr_thread_local_setup(fr_dlist_t *, fr_children) /* macro */ +fr_thread_local_setup(fr_dlist_head_t *, fr_children) /* macro */ static void _fr_children_free(void *arg) { @@ -102,7 +102,7 @@ pid_t radius_start_program(char const *cmd, REQUEST *request, bool exec_wait, char *envp[MAX_ENVP]; size_t envlen = 0; TALLOC_CTX *input_ctx = NULL; - fr_dlist_t *list; + fr_dlist_head_t *list; /* * Stupid array decomposition... @@ -123,38 +123,33 @@ pid_t radius_start_program(char const *cmd, REQUEST *request, bool exec_wait, list = fr_children; if (!list) { - list = talloc_zero(NULL, fr_dlist_t); + list = talloc_zero(NULL, fr_dlist_head_t); if (!list) { ERROR("Out of memory"); return -1; } - list->prev = list->next = list; + fr_dlist_init(list, offsetof(fr_child_t, entry)); fr_thread_local_set_destructor(fr_children, _fr_children_free, list); } else { - fr_dlist_t *entry, *next; - - entry = list->next; + fr_child_t *child, *next; /* * Clean up the children. ALL of them. This is * slow as heck, but correct. :( */ - while (entry != list) { + for (child = fr_dlist_first(fr_children); + child != NULL; + child = next) { int status; - fr_child_t *child; - - next = entry->next; - child = fr_ptr_to_type(fr_child_t, entry, entry); + next = fr_dlist_next(fr_children, child); pid = waitpid(child->pid, &status, WNOHANG); if (pid != 0) { - fr_dlist_remove(entry); + fr_dlist_remove(fr_children, child); talloc_free(child); } - - entry = next; } } @@ -378,7 +373,7 @@ pid_t radius_start_program(char const *cmd, REQUEST *request, bool exec_wait, fr_child_t *child; MEM(child = talloc_zero(fr_children, fr_child_t)); - fr_dlist_insert_tail(fr_children, &child->entry); + fr_dlist_insert_tail(fr_children, child); child->pid = pid; } diff --git a/src/main/state.c b/src/main/state.c index 7344e7ad5ea..4621ec35950 100644 --- a/src/main/state.c +++ b/src/main/state.c @@ -95,7 +95,7 @@ typedef struct state_entry { uint64_t seq_start; //!< Number of first request in this sequence. time_t cleanup; //!< When this entry should be cleaned up. - fr_dlist_t list; //!< Entry in the list of things to expire. + fr_dlist_t entry; //!< Entry in the list of things to expire. int tries; @@ -114,7 +114,7 @@ struct fr_state_tree_t { //!< timeout. uint32_t max_sessions; //!< Maximum number of sessions we track. rbtree_t *tree; //!< rbtree used to lookup state value. - fr_dlist_t to_expire; //!< Linked list of entries to free. + fr_dlist_head_t to_expire; //!< Linked list of entries to free. uint32_t timeout; //!< How long to wait before cleaning up state entires. @@ -146,16 +146,13 @@ static int state_entry_cmp(void const *one, void const *two) */ static int _state_tree_free(fr_state_tree_t *state) { - fr_dlist_t *next; + fr_state_entry_t *entry; if (main_config->spawn_workers) pthread_mutex_destroy(&state->mutex); DEBUG4("Freeing state tree %p", state); - while ((next = FR_DLIST_FIRST(state->to_expire))) { - fr_state_entry_t *entry; - - entry = fr_ptr_to_type(fr_state_entry_t, list, next); + while ((entry = fr_dlist_first(&state->to_expire))) { state_entry_unlink(state, entry); talloc_free(entry); } @@ -205,7 +202,7 @@ fr_state_tree_t *fr_state_tree_init(TALLOC_CTX *ctx, fr_dict_attr_t const *da, b return NULL; } - FR_DLIST_INIT(state->to_expire); + fr_dlist_init(&state->to_expire, offsetof(fr_state_entry_t, entry)); /* * We need to do controlled freeing of the @@ -236,7 +233,7 @@ static void state_entry_unlink(fr_state_tree_t *state, fr_state_entry_t *entry) */ (void) talloc_get_type_abort(entry, fr_state_entry_t); - fr_dlist_remove(&entry->list); + fr_dlist_remove(&state->to_expire, entry); rbtree_deletebydata(state->tree, entry); @@ -269,12 +266,6 @@ static int _state_entry_free(fr_state_entry_t *entry) * so we know it'll be cleaned up. */ if (entry->data) (void)fr_cond_assert(request_data_verify_parent(entry->ctx, entry->data)); - - /* - * Verify the state entry is no longer linked - */ - rad_assert(entry->list.prev == &entry->list); - rad_assert(entry->list.next == &entry->list); #endif /* @@ -298,24 +289,24 @@ static fr_state_entry_t *state_entry_create(fr_state_tree_t *state, REQUEST *req uint32_t x; time_t now = time(NULL); VALUE_PAIR *vp; - fr_state_entry_t *entry; + fr_state_entry_t *entry, *next; uint8_t old_state[sizeof(old->state)]; int old_tries = 0; uint64_t timed_out = 0; bool too_many = false; - fr_dlist_t to_free, *next; + fr_dlist_head_t to_free; - FR_DLIST_INIT(to_free); + fr_dlist_init(&to_free, offsetof(fr_state_entry_t, entry)); /* * Clean up old entries. */ - next = FR_DLIST_FIRST(state->to_expire); - while (next) { - entry = fr_ptr_to_type(fr_state_entry_t, list, next); + for (entry = fr_dlist_first(&state->to_expire); + entry != NULL; + entry = next) { (void)talloc_get_type_abort(entry, fr_state_entry_t); /* Allow examination */ - next = FR_DLIST_NEXT(state->to_expire, next); /* Advance *before* potential unlinking */ + next = fr_dlist_next(&state->to_expire, entry); /* Advance *before* potential unlinking */ if (entry == old) continue; @@ -324,7 +315,7 @@ static fr_state_entry_t *state_entry_create(fr_state_tree_t *state, REQUEST *req */ if (entry->cleanup < now) { state_entry_unlink(state, entry); - fr_dlist_insert_tail(&to_free, &entry->list); + fr_dlist_insert_tail(&to_free, entry); timed_out++; continue; } @@ -353,7 +344,7 @@ static fr_state_entry_t *state_entry_create(fr_state_tree_t *state, REQUEST *req */ if (!old->data) { state_entry_unlink(state, old); - fr_dlist_insert_tail(&to_free, &old->list); + fr_dlist_insert_tail(&to_free, old); } } PTHREAD_MUTEX_UNLOCK(&state->mutex); @@ -370,9 +361,9 @@ static fr_state_entry_t *state_entry_create(fr_state_tree_t *state, REQUEST *req * be freed also, and it may have complex destructors associated * with it. */ - while ((next = FR_DLIST_FIRST(to_free)) != NULL) { - fr_dlist_remove(next); - talloc_free(fr_ptr_to_type(fr_state_entry_t, list, next)); + while ((entry = fr_dlist_first(&to_free)) != NULL) { + fr_dlist_remove(&to_free, entry); + talloc_free(entry); } /* @@ -507,7 +498,7 @@ static fr_state_entry_t *state_entry_create(fr_state_tree_t *state, REQUEST *req * Link it to the end of the list, which is implicitely * ordered by cleanup time. */ - fr_dlist_insert_tail(&state->to_expire, &entry->list); + fr_dlist_insert_tail(&state->to_expire, entry); return entry; } diff --git a/src/modules/proto_detail/proto_detail.h b/src/modules/proto_detail/proto_detail.h index 69fc8319489..4586ed3dd32 100644 --- a/src/modules/proto_detail/proto_detail.h +++ b/src/modules/proto_detail/proto_detail.h @@ -99,7 +99,7 @@ typedef struct proto_detail_work_t { uint32_t max_outstanding; //!< number of packets to run in parallel uint32_t outstanding; //!< number of currently outstanding records; - fr_dlist_t list; //!< for retransmissions + fr_dlist_head_t list; //!< for retransmissions bool vnode; //!< are we the vnode instance, //!< or the filename_work instance? diff --git a/src/modules/proto_detail/proto_detail_work.c b/src/modules/proto_detail/proto_detail_work.c index 0aab049790b..6d7b7cd9e2f 100644 --- a/src/modules/proto_detail/proto_detail_work.c +++ b/src/modules/proto_detail/proto_detail_work.c @@ -146,7 +146,6 @@ static ssize_t mod_read(void *instance, void **packet_ctx, fr_time_t **recv_time uint8_t *partial, *end, *next, *p, *record_end; uint8_t *stopped_search; off_t done_offset; - fr_dlist_t *entry; rad_assert(*leftover < buffer_len); rad_assert(inst->fd >= 0); @@ -156,11 +155,9 @@ static ssize_t mod_read(void *instance, void **packet_ctx, fr_time_t **recv_time * Process retransmissions before anything else in the * file. */ - entry = FR_DLIST_FIRST(inst->list); - if (entry) { - track = fr_ptr_to_type(fr_detail_entry_t, entry, entry); - - fr_dlist_remove(&track->entry); + track = fr_dlist_first(&inst->list); + if (track) { + fr_dlist_remove(&inst->list, track); /* * Don't over-write "leftover" bytes! @@ -534,7 +531,7 @@ static void work_retransmit(UNUSED fr_event_list_t *el, UNUSED struct timeval *n DEBUG("%s - retransmitting packet %d", inst->name, track->id); track->count++; - fr_dlist_insert_tail(&inst->list, &track->entry); + fr_dlist_insert_tail(&inst->list, &track); if (inst->paused && (inst->outstanding < inst->max_outstanding)) { (void) fr_event_filter_update(inst->el, inst->fd, FR_EVENT_FILTER_IO, resume_read); @@ -817,7 +814,7 @@ static int mod_instantiate(void *instance, UNUSED CONF_SECTION *cs) proto_detail_work_t *inst = talloc_get_type_abort(instance, proto_detail_work_t); RADCLIENT *client; - FR_DLIST_INIT(inst->list); + fr_dlist_init(&inst->list, offsetof(fr_detail_entry_t, entry)); client = inst->client = talloc_zero(inst, RADCLIENT); if (!inst->client) return 0; diff --git a/src/modules/rlm_radius/rlm_radius.c b/src/modules/rlm_radius/rlm_radius.c index 687c1aa6d16..bbad3f34e3c 100644 --- a/src/modules/rlm_radius/rlm_radius.c +++ b/src/modules/rlm_radius/rlm_radius.c @@ -386,7 +386,7 @@ static int status_check_update_parse(UNUSED TALLOC_CTX *ctx, void *out, UNUSED v */ static int mod_link_free(rlm_radius_link_t *link) { - fr_dlist_remove(&link->entry); + fr_dlist_remove(&link->t->running, link); /* * Free the child's request io context. That will call @@ -564,7 +564,7 @@ static rlm_rcode_t CC_HINT(nonnull) mod_process(void *instance, void *thread, RE */ radius_fixups(inst, request); - fr_dlist_insert_tail(&t->running, &link->entry); + fr_dlist_insert_tail(&t->running, link); talloc_set_destructor(link, mod_link_free); /* @@ -819,7 +819,7 @@ static int mod_thread_instantiate(UNUSED CONF_SECTION const *cs, void *instance, t->inst = instance; t->el = el; - FR_DLIST_INIT(t->running); + fr_dlist_init(&t->running, offsetof(rlm_radius_link_t, entry)); /* * Allocate thread-specific data. The connections should @@ -849,7 +849,6 @@ static int mod_thread_detach(fr_event_list_t *el, void *thread) { rlm_radius_thread_t *t = talloc_get_type_abort(thread, rlm_radius_thread_t); rlm_radius_t const *inst = t->inst; - fr_dlist_t *entry; /* * Tell the submodule to shut down all of its @@ -867,8 +866,7 @@ static int mod_thread_detach(fr_event_list_t *el, void *thread) * marked DONE, and (in an ideal world) resumed / cleaned * up before this memory is freed. */ - entry = FR_DLIST_FIRST(t->running); - if (entry != NULL) { + if (fr_dlist_first(&t->running) != NULL) { ERROR("Module still has running requests!"); return -1; } diff --git a/src/modules/rlm_radius/rlm_radius.h b/src/modules/rlm_radius/rlm_radius.h index 337ad265f54..7c09145f5a1 100644 --- a/src/modules/rlm_radius/rlm_radius.h +++ b/src/modules/rlm_radius/rlm_radius.h @@ -127,7 +127,7 @@ typedef struct rlm_radius_thread_t { rlm_radius_t const *inst; //!< Instance of the module. fr_event_list_t *el; //!< This thread's event list. - fr_dlist_t running; //!< running requests + fr_dlist_head_t running; //!< running requests void *thread_io_ctx; //!< thread context for the IO submodule } rlm_radius_thread_t; diff --git a/src/modules/rlm_radius/rlm_radius_udp.c b/src/modules/rlm_radius/rlm_radius_udp.c index 1949ef9d99a..2f660810b16 100644 --- a/src/modules/rlm_radius/rlm_radius_udp.c +++ b/src/modules/rlm_radius/rlm_radius_udp.c @@ -71,10 +71,10 @@ typedef struct rlm_radius_udp_thread_t { fr_heap_t *queued; //!< Queued requests for some new connection. fr_heap_t *active; //!< Active connections. - fr_dlist_t blocked; //!< blocked connections, waiting for writable - fr_dlist_t full; //!< Full connections. - fr_dlist_t zombie; //!< Zombie connections. - fr_dlist_t opening; //!< Opening connections. + fr_dlist_head_t blocked; //!< blocked connections, waiting for writable + fr_dlist_head_t full; //!< Full connections. + fr_dlist_head_t zombie; //!< Zombie connections. + fr_dlist_head_t opening; //!< Opening connections. } rlm_radius_udp_thread_t; typedef enum rlm_radius_udp_connection_state_t { @@ -110,7 +110,7 @@ typedef struct rlm_radius_udp_connection_t { fr_event_timer_t const *zombie_ev; //!< Zombie timeout. struct timeval zombie_start; //!< When the zombie period started. - fr_dlist_t sent; //!< List of sent packets. + fr_dlist_head_t sent; //!< List of sent packets. uint32_t max_packet_size; //!< Our max packet size. may be different from the parent. int fd; //!< File descriptor. @@ -299,7 +299,7 @@ static void conn_check_idle(rlm_radius_udp_connection_t *c) /* * No outstanding packets, we're idle. */ - if (FR_DLIST_FIRST(c->sent) == NULL) { + if (fr_dlist_first(&c->sent) == NULL) { break; } @@ -494,7 +494,7 @@ static void state_transition(rlm_radius_udp_request_t *u, rlm_radius_request_sta rad_assert(u->rr != NULL); rad_assert(u->c != NULL); (void) rr_track_delete(u->c->id, u->rr); - fr_dlist_remove(&u->entry); + fr_dlist_remove(&u->c->sent, u); u->rr = NULL; u->c = NULL; break; @@ -520,7 +520,7 @@ static void state_transition(rlm_radius_udp_request_t *u, rlm_radius_request_sta case PACKET_STATE_SENT: rad_assert(u->rr != NULL); rad_assert(u->c != NULL); - fr_dlist_insert_tail(&u->c->sent, &u->entry); + fr_dlist_insert_tail(&u->c->sent, u); break; case PACKET_STATE_RESUMABLE: @@ -695,7 +695,7 @@ static void conn_transition(rlm_radius_udp_connection_t *c, rlm_radius_udp_conne case CONN_OPENING: case CONN_FULL: case CONN_BLOCKED: - fr_dlist_remove(&c->entry); + fr_dlist_remove(&c->thread->blocked, c); /* we only need 'offset' from the list */ break; case CONN_ACTIVE: @@ -712,7 +712,7 @@ static void conn_transition(rlm_radius_udp_connection_t *c, rlm_radius_udp_conne */ if (state == CONN_BLOCKED) return; - fr_dlist_remove(&c->entry); + fr_dlist_remove(&c->thread->blocked, c); if (c->zombie_ev) (void) fr_event_timer_delete(c->thread->el, &c->zombie_ev); break; } @@ -726,7 +726,7 @@ static void conn_transition(rlm_radius_udp_connection_t *c, rlm_radius_udp_conne break; case CONN_OPENING: - fr_dlist_insert_head(&c->thread->opening, &c->entry); + fr_dlist_insert_head(&c->thread->opening, c); break; case CONN_ACTIVE: @@ -738,19 +738,19 @@ static void conn_transition(rlm_radius_udp_connection_t *c, rlm_radius_udp_conne case CONN_BLOCKED: if (c->idle_ev) (void) fr_event_timer_delete(c->thread->el, &c->idle_ev); - fr_dlist_insert_head(&c->thread->blocked, &c->entry); + fr_dlist_insert_head(&c->thread->blocked, c); break; case CONN_FULL: if (c->idle_ev) (void) fr_event_timer_delete(c->thread->el, &c->idle_ev); - fr_dlist_insert_head(&c->thread->full, &c->entry); + fr_dlist_insert_head(&c->thread->full, c); break; case CONN_ZOMBIE: if (c->idle_ev) (void) fr_event_timer_delete(c->thread->el, &c->idle_ev); - fr_dlist_insert_head(&c->thread->zombie, &c->entry); + fr_dlist_insert_head(&c->thread->zombie, c); gettimeofday(&when, NULL); c->zombie_start = when; @@ -1974,13 +1974,13 @@ static fr_connection_state_t _conn_failed(UNUSED int fd, fr_connection_state_t s * timer events before reconnecting. */ if (state == FR_CONNECTION_STATE_CONNECTED) { - fr_dlist_t *entry; + rlm_radius_udp_request_t *u; /* * Reset the Status-Server checks. */ if (c->status_u) { - rlm_radius_udp_request_t *u = c->status_u; + u = c->status_u; if (u->timer.ev) (void) fr_event_timer_delete(c->thread->el, &u->timer.ev); @@ -2002,10 +2002,7 @@ static fr_connection_state_t _conn_failed(UNUSED int fd, fr_connection_state_t s /* * Move "sent" packets back to the thread queue, */ - while ((entry = FR_DLIST_FIRST(c->sent)) != NULL) { - rlm_radius_udp_request_t *u; - - u = fr_ptr_to_type(rlm_radius_udp_request_t, entry, entry); + while ((u = fr_dlist_first(&c->sent)) != NULL) { state_transition(u, PACKET_STATE_THREAD); } } @@ -2047,7 +2044,7 @@ static fr_connection_state_t _conn_open(UNUSED fr_event_list_t *el, int fd, void rad_assert(c->zombie_ev == NULL); memset(&c->zombie_start, 0, sizeof(c->zombie_start)); - FR_DLIST_INIT(c->sent); + fr_dlist_init(&c->sent, offsetof(rlm_radius_udp_request_t, entry)); /* * Status-Server checks. Manually build the packet, and @@ -2106,14 +2103,12 @@ static fr_connection_state_t _conn_open(UNUSED fr_event_list_t *el, int fd, void * Initialize the link. Note that we don't set * destructors. */ - FR_DLIST_INIT(link->entry); link->request = request; link->request_io_ctx = u; /* * Unitialize the UDP link. */ - FR_DLIST_INIT(u->entry); u->code = c->inst->parent->status_check; request->packet->code = u->code; u->c = c; @@ -2230,7 +2225,6 @@ static fr_connection_state_t _conn_init(int *fd_out, void *uctx) */ static int _conn_free(rlm_radius_udp_connection_t *c) { - fr_dlist_t *entry; rlm_radius_udp_request_t *u; rlm_radius_udp_thread_t *t = talloc_get_type_abort(c->thread, rlm_radius_udp_thread_t); @@ -2256,9 +2250,7 @@ static int _conn_free(rlm_radius_udp_connection_t *c) /* * Move "sent" packets back to the main thread queue */ - while ((entry = FR_DLIST_FIRST(c->sent)) != NULL) { - u = fr_ptr_to_type(rlm_radius_udp_request_t, entry, entry); - + while ((u = fr_dlist_first(&c->sent)) != NULL) { rad_assert(u->state == PACKET_STATE_SENT); rad_assert(u->c == c); @@ -2283,7 +2275,7 @@ static int _conn_free(rlm_radius_udp_connection_t *c) case CONN_OPENING: case CONN_FULL: case CONN_ZOMBIE: - fr_dlist_remove(&c->entry); + fr_dlist_remove(&c->thread->blocked, c); break; case CONN_ACTIVE: @@ -2341,7 +2333,7 @@ static void conn_alloc(rlm_radius_udp_t *inst, rlm_radius_udp_thread_t *t) talloc_free(c); return; } - FR_DLIST_INIT(c->sent); + fr_dlist_init(&c->sent, offsetof(rlm_radius_udp_request_t, entry)); c->conn = fr_connection_alloc(c, t->el, &inst->parent->connection_timeout, &inst->parent->reconnection_delay, _conn_init, @@ -2411,7 +2403,7 @@ static rlm_rcode_t mod_push(void *instance, REQUEST *request, rlm_radius_link_t u->thread = t; u->heap_id = -1; u->timer.retry = &inst->parent->retry[u->code]; - FR_DLIST_INIT(u->entry); + fr_dlist_entry_init(&u->entry); talloc_set_destructor(u, udp_request_free); @@ -2457,13 +2449,10 @@ static rlm_rcode_t mod_push(void *instance, REQUEST *request, rlm_radius_link_t */ c = fr_heap_peek(t->active); if (!c) { - fr_dlist_t *entry; - /* * Only open one new connection at a time. */ - entry = FR_DLIST_FIRST(t->opening); - if (!entry) conn_alloc(inst, t); + if (!fr_dlist_first(&t->opening)) conn_alloc(inst, t); /* * Add the request to the backlog. It will be @@ -2626,10 +2615,10 @@ static int mod_thread_instantiate(UNUSED CONF_SECTION const *cs, void *instance, t->el = el; t->queued = fr_heap_talloc_create(t, queue_cmp, rlm_radius_udp_request_t, heap_id); - FR_DLIST_INIT(t->blocked); - FR_DLIST_INIT(t->full); - FR_DLIST_INIT(t->zombie); - FR_DLIST_INIT(t->opening); + fr_dlist_init(&t->blocked, offsetof(rlm_radius_udp_connection_t, entry)); + fr_dlist_init(&t->full, offsetof(rlm_radius_udp_connection_t, entry)); + fr_dlist_init(&t->zombie, offsetof(rlm_radius_udp_connection_t, entry)); + fr_dlist_init(&t->opening, offsetof(rlm_radius_udp_connection_t, entry)); t->active = fr_heap_talloc_create(t, conn_cmp, rlm_radius_udp_connection_t, heap_id); @@ -2644,7 +2633,6 @@ static int mod_thread_instantiate(UNUSED CONF_SECTION const *cs, void *instance, static int mod_thread_detach(UNUSED fr_event_list_t *el, void *thread) { rlm_radius_udp_thread_t *t = talloc_get_type_abort(thread, rlm_radius_udp_thread_t); - fr_dlist_t *entry; if (fr_heap_num_elements(t->queued) != 0) { ERROR("There are still queued requests"); @@ -2656,8 +2644,7 @@ static int mod_thread_detach(UNUSED fr_event_list_t *el, void *thread) */ talloc_free_children(t); - entry = FR_DLIST_FIRST(t->opening); - if (entry != NULL) { + if (fr_dlist_first(&t->opening) != NULL) { ERROR("There are still partially open sockets"); return -1; } diff --git a/src/modules/rlm_radius/track.c b/src/modules/rlm_radius/track.c index e3a63a71d92..84e82f38a54 100644 --- a/src/modules/rlm_radius/track.c +++ b/src/modules/rlm_radius/track.c @@ -68,11 +68,11 @@ rlm_radius_id_t *rr_track_create(TALLOC_CTX *ctx) id = talloc_zero(ctx, rlm_radius_id_t); if (!id) return NULL; - FR_DLIST_INIT(id->free_list); + fr_dlist_init(&id->free_list, offsetof(rlm_radius_request_t, entry)); for (i = 0; i < 256; i++) { id->id[i].id = i; - fr_dlist_insert_tail(&id->free_list, &id->id[i].entry); + fr_dlist_insert_tail(&id->free_list, &id->id[i]); id->num_free++; } @@ -109,22 +109,19 @@ static int rr_cmp(void const *one, void const *two) rlm_radius_request_t *rr_track_alloc(rlm_radius_id_t *id, REQUEST *request, int code, rlm_radius_link_t *link, rlm_radius_retransmit_t *timer) { - fr_dlist_t *entry; rlm_radius_request_t *rr; retry: - entry = FR_DLIST_FIRST(id->free_list); - if (entry) { + rr = fr_dlist_first(&id->free_list); + if (rr) { rad_assert(id->num_free > 0); - rr = fr_ptr_to_type(rlm_radius_request_t, entry, entry); - rad_assert(rr->request == NULL); /* * Mark it as used, and remove it from the free list. */ - fr_dlist_remove(&rr->entry); + fr_dlist_remove(&id->free_list, rr); id->num_free--; /* @@ -167,7 +164,6 @@ retry: * Allocate a new one, and insert it into the appropriate subtree. */ rr = talloc_zero(id, rlm_radius_request_t); - FR_DLIST_INIT(rr->entry); rr->id = id->next_id; done: @@ -284,7 +280,7 @@ int rr_track_delete(rlm_radius_id_t *id, rlm_radius_request_t *rr) * Otherwise put it back on the free list. */ done: - fr_dlist_insert_tail(&id->free_list, &rr->entry); + fr_dlist_insert_tail(&id->free_list, rr); id->num_free++; return 0; diff --git a/src/modules/rlm_radius/track.h b/src/modules/rlm_radius/track.h index 4766b063338..17a3b96e47f 100644 --- a/src/modules/rlm_radius/track.h +++ b/src/modules/rlm_radius/track.h @@ -58,7 +58,7 @@ typedef struct rlm_radius_id_t { int num_requests; //!< number of requests in the allocation int num_free; //!< number of entries in the free list - fr_dlist_t free_list; //!< so we allocate by least recently used + fr_dlist_head_t free_list; //!< so we allocate by least recently used bool use_authenticator; //!< whether to use the request authenticator as an ID int next_id; //!< next ID to allocate diff --git a/src/modules/rlm_stats/rlm_stats.c b/src/modules/rlm_stats/rlm_stats.c index 17dd77e0e30..b0995d69004 100644 --- a/src/modules/rlm_stats/rlm_stats.c +++ b/src/modules/rlm_stats/rlm_stats.c @@ -54,7 +54,7 @@ typedef struct rlm_stats_t { fr_dict_attr_t const *type_da; //!< FreeRADIUS-Stats4-Type fr_dict_attr_t const *ipv4_da; //!< FreeRADIUS-Stats4-IPv4-Address fr_dict_attr_t const *ipv6_da; //!< FreeRADIUS-Stats4-IPv6-Address - fr_dlist_t entry; //!< for threads to know about each other + fr_dlist_head_t list; //!< for threads to know about each other uint64_t stats[FR_MAX_PACKET_CODE]; } rlm_stats_t; @@ -116,7 +116,6 @@ static void coalesce(uint64_t final_stats[FR_MAX_PACKET_CODE], rlm_stats_thread_ rlm_stats_data_t *mydata) { rlm_stats_data_t *stats; - fr_dlist_t *entry; rlm_stats_thread_t *other; #ifdef HAVE_PTHREAD_H pthread_mutex_t *mutex; @@ -141,10 +140,9 @@ static void coalesce(uint64_t final_stats[FR_MAX_PACKET_CODE], rlm_stats_thread_ * Loop over all of the other thread instances, locking * them, and adding their statistics in. */ - for (entry = FR_DLIST_FIRST(t->inst->entry); - entry != NULL; - entry = FR_DLIST_NEXT(t->inst->entry, entry)) { - other = fr_ptr_to_type(rlm_stats_thread_t, entry, entry); + for (other = fr_dlist_first(&t->inst->list); + other != NULL; + other = fr_dlist_next(&t->inst->list, other)) { int i; if (other == t) continue; @@ -389,7 +387,7 @@ static int mod_thread_instantiate(UNUSED CONF_SECTION const *cs, void *instance, t->dst = rbtree_talloc_create(t, data_cmp, rlm_stats_data_t, NULL, RBTREE_FLAG_NONE); PTHREAD_MUTEX_LOCK(&inst->mutex); - fr_dlist_insert_head(&inst->entry, &t->entry); + fr_dlist_insert_head(&inst->list, t); PTHREAD_MUTEX_UNLOCK(&inst->mutex); return 0; @@ -409,7 +407,7 @@ static int mod_thread_detach(UNUSED fr_event_list_t *el, void *thread) for (i = 0; i < FR_MAX_PACKET_CODE; i++) { inst->stats[i] += t->stats[i]; } - fr_dlist_remove(&t->entry); + fr_dlist_remove(&inst->list, t); PTHREAD_MUTEX_UNLOCK(&inst->mutex); return 0; @@ -423,7 +421,7 @@ static int mod_instantiate(void *instance, UNUSED CONF_SECTION *conf) pthread_mutex_init(&inst->mutex, NULL); #endif - FR_DLIST_INIT(inst->entry); + fr_dlist_init(&inst->list, offsetof(rlm_stats_thread_t, entry)); return 0; } diff --git a/src/unlang/op.c b/src/unlang/op.c index cf1b3a5bda4..ea0eaaf48fa 100644 --- a/src/unlang/op.c +++ b/src/unlang/op.c @@ -529,7 +529,7 @@ static REQUEST *unlang_child_alloc(REQUEST *request, unlang_t *instruction, rlm_ * Instead, all of it is done in the context of the * parent. */ - FR_DLIST_INIT(child->async->tracking.list); + fr_dlist_init(&child->async->tracking.list, 0); /* * create {...} creates an empty copy.