2
0
mirror of https://gitlab.isc.org/isc-projects/bind9 synced 2025-09-05 09:05:40 +00:00
Files
bind/lib/isc/loop_p.h
Ondřej Surý 6eb1340d1b Use atomic stack for async job queue
Previously, the async job queue would use a locked-list (ISC_LIST).
With introduction of atomic stack (that has to be drained at once), we
could use it to remove some contention between the threads and simplify
the async queue.

Fortunately, the reverse order still works for us - instead of append
and tail/prev operation on the list, we are now using prepend and
head/next operation on the atomic stack.
2023-02-22 16:13:37 +00:00

149 lines
2.8 KiB
C

/*
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
*
* SPDX-License-Identifier: MPL-2.0
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, you can obtain one at https://mozilla.org/MPL/2.0/.
*
* See the COPYRIGHT file distributed with this work for additional
* information regarding copyright ownership.
*/
#pragma once
#include <inttypes.h>
#include <isc/barrier.h>
#include <isc/lang.h>
#include <isc/loop.h>
#include <isc/magic.h>
#include <isc/mem.h>
#include <isc/refcount.h>
#include <isc/result.h>
#include <isc/signal.h>
#include <isc/stack.h>
#include <isc/thread.h>
#include <isc/types.h>
#include <isc/uv.h>
#include <isc/work.h>
/*
* Per-thread loop
*/
#define LOOP_MAGIC ISC_MAGIC('L', 'O', 'O', 'P')
#define VALID_LOOP(t) ISC_MAGIC_VALID(t, LOOP_MAGIC)
typedef ISC_LIST(isc_job_t) isc_joblist_t;
typedef ISC_ASTACK(isc_job_t) isc_jobstack_t;
struct isc_loop {
int magic;
isc_refcount_t references;
isc_thread_t thread;
isc_loopmgr_t *loopmgr;
uv_loop_t loop;
uint32_t tid;
isc_mem_t *mctx;
/* states */
bool paused;
atomic_bool finished;
bool shuttingdown;
/* Async queue */
uv_async_t queue_trigger;
isc_jobstack_t queue_jobs;
/* Pause */
uv_async_t pause_trigger;
/* Shutdown */
uv_async_t shutdown_trigger;
isc_joblist_t setup_jobs;
isc_joblist_t teardown_jobs;
/* Destroy */
uv_async_t destroy_trigger;
};
/*
* Loop Manager
*/
#define LOOPMGR_MAGIC ISC_MAGIC('L', 'o', 'o', 'M')
#define VALID_LOOPMGR(t) ISC_MAGIC_VALID(t, LOOPMGR_MAGIC)
struct isc_loopmgr {
int magic;
isc_mem_t *mctx;
uint_fast32_t nloops;
atomic_bool shuttingdown;
atomic_bool running;
atomic_bool paused;
/* signal handling */
isc_signal_t *sigint;
isc_signal_t *sigterm;
/* pause/resume */
isc_barrier_t pausing;
isc_barrier_t resuming;
/* start/stop */
isc_barrier_t starting;
/* stopping */
isc_barrier_t stopping;
/* per-thread objects */
isc_loop_t *loops;
};
/*
* Signal Handler
*/
struct isc_signal {
uv_signal_t signal;
isc_loop_t *loop;
isc_signal_cb cb;
void *cbarg;
int signum;
};
/*
* Job to be scheduled in an event loop
*/
#define JOB_MAGIC ISC_MAGIC('J', 'O', 'B', ' ')
#define VALID_JOB(t) ISC_MAGIC_VALID(t, JOB_MAGIC)
struct isc_job {
int magic;
uv_idle_t idle;
isc_loop_t *loop;
isc_job_cb cb;
void *cbarg;
ISC_LINK(isc_job_t) link;
};
/*
* Work to be offloaded to an external thread.
*/
struct isc_work {
uv_work_t work;
isc_loop_t *loop;
isc_work_cb work_cb;
isc_after_work_cb after_work_cb;
void *cbarg;
};
#define DEFAULT_LOOP(loopmgr) (&(loopmgr)->loops[0])
#define CURRENT_LOOP(loopmgr) (&(loopmgr)->loops[isc_tid()])
#define LOOP(loopmgr, tid) (&(loopmgr)->loops[tid])
#define ON_LOOP(loop) ((loop) == CURRENT_LOOP((loop)->loopmgr))