/* SPDX-License-Identifier: GPL-2.0+ */ /* * Sleepable Read-Copy Update mechanism for mutual exclusion, * tree variant. * * Copyright (C) IBM Corporation, 2017 * * Author: Paul McKenney <[email protected]> */ #ifndef _LINUX_SRCU_TREE_H #define _LINUX_SRCU_TREE_H #include <linux/rcu_node_tree.h> #include <linux/completion.h> struct srcu_node; struct srcu_struct; /* * Per-CPU structure feeding into leaf srcu_node, similar in function * to rcu_node. */ struct srcu_data { … }; /* * Node in SRCU combining tree, similar in function to rcu_data. */ struct srcu_node { … }; /* * Per-SRCU-domain structure, update-side data linked from srcu_struct. */ struct srcu_usage { … }; /* * Per-SRCU-domain structure, similar in function to rcu_state. */ struct srcu_struct { … }; // Values for size state variable (->srcu_size_state). Once the state // has been set to SRCU_SIZE_ALLOC, the grace-period code advances through // this state machine one step per grace period until the SRCU_SIZE_BIG state // is reached. Otherwise, the state machine remains in the SRCU_SIZE_SMALL // state indefinitely. #define SRCU_SIZE_SMALL … #define SRCU_SIZE_ALLOC … // and then referenced by ->node. It will not be used. #define SRCU_SIZE_WAIT_BARRIER … // except call_srcu(), especially by srcu_barrier(). // By the end of this state, all CPUs and threads // are aware of this tree's existence. #define SRCU_SIZE_WAIT_CALL … // By the end of this state, all of the call_srcu() // invocations that were running on a non-boot CPU // and using the boot CPU's callback queue will have // completed. #define SRCU_SIZE_WAIT_CBS1 … #define SRCU_SIZE_WAIT_CBS2 … #define SRCU_SIZE_WAIT_CBS3 … #define SRCU_SIZE_WAIT_CBS4 … #define SRCU_SIZE_BIG … // and all aspects of it are being put to use. /* Values for state variable (bottom bits of ->srcu_gp_seq). */ #define SRCU_STATE_IDLE … #define SRCU_STATE_SCAN1 … #define SRCU_STATE_SCAN2 … /* * Values for initializing gp sequence fields. Higher values allow wrap arounds to * occur earlier. * The second value with state is useful in the case of static initialization of * srcu_usage where srcu_gp_seq_needed is expected to have some state value in its * lower bits (or else it will appear to be already initialized within * the call check_init_srcu_struct()). */ #define SRCU_GP_SEQ_INITIAL_VAL … #define SRCU_GP_SEQ_INITIAL_VAL_WITH_STATE … #define __SRCU_USAGE_INIT(name) … #define __SRCU_STRUCT_INIT_COMMON(name, usage_name) … #define __SRCU_STRUCT_INIT_MODULE(name, usage_name) … #define __SRCU_STRUCT_INIT(name, usage_name, pcpu_name) … /* * Define and initialize a srcu struct at build time. * Do -not- call init_srcu_struct() nor cleanup_srcu_struct() on it. * * Note that although DEFINE_STATIC_SRCU() hides the name from other * files, the per-CPU variable rules nevertheless require that the * chosen name be globally unique. These rules also prohibit use of * DEFINE_STATIC_SRCU() within a function. If these rules are too * restrictive, declare the srcu_struct manually. For example, in * each file: * * static struct srcu_struct my_srcu; * * Then, before the first use of each my_srcu, manually initialize it: * * init_srcu_struct(&my_srcu); * * See include/linux/percpu-defs.h for the rules on per-CPU variables. */ #ifdef MODULE #define __DEFINE_SRCU … #else #define __DEFINE_SRCU(name, is_static) … #endif #define DEFINE_SRCU(name) … #define DEFINE_STATIC_SRCU(name) … void synchronize_srcu_expedited(struct srcu_struct *ssp); void srcu_barrier(struct srcu_struct *ssp); void srcu_torture_stats_print(struct srcu_struct *ssp, char *tt, char *tf); #endif