|  | /* Copyright (c) 2018 Google Inc | 
|  | * Barret Rhoden <brho@cs.berkeley.edu> | 
|  | * See LICENSE for details. | 
|  | * | 
|  | * RCU.  See rcu.c for notes. | 
|  | */ | 
|  |  | 
|  | #pragma once | 
|  |  | 
|  | #include <arch/membar.h> | 
|  | #include <arch/topology.h> | 
|  | #include <percpu.h> | 
|  | #include <list.h> | 
|  |  | 
|  | struct rcu_head; | 
|  | typedef void (*rcu_callback_t)(struct rcu_head *head); | 
|  | typedef void (*call_rcu_func_t)(struct rcu_head *head, rcu_callback_t func); | 
|  |  | 
|  | struct rcu_head { | 
|  | struct list_head		link; | 
|  | rcu_callback_t			func; | 
|  | unsigned long			gpnum; | 
|  | }; | 
|  |  | 
|  | #include <rcupdate.h> | 
|  |  | 
|  | /* This is a little nasty.  We can't undef it, since NUM_RCU_NODES is used in a | 
|  | * few places.  We could get this from Kconfig, like Linux does. */ | 
|  | #define NR_CPUS 4096 | 
|  |  | 
|  | #include <rcu_helper.h> | 
|  | #include <rculist.h> | 
|  | #include <rendez.h> | 
|  |  | 
|  | struct rcu_node { | 
|  | struct rcu_node			*parent; | 
|  | unsigned long			qsmask;	/* cores that need to check in*/ | 
|  | unsigned long			qsmaskinit; | 
|  | unsigned int			level; | 
|  | unsigned int			grplo;	/* lowest nr CPU here */ | 
|  | unsigned int			grphi;	/* highest nr CPU here */ | 
|  | unsigned int			grpnum;	/* our number in our parent */ | 
|  | unsigned long			grpmask;/* our bit in our parent */ | 
|  | }; | 
|  |  | 
|  | struct rcu_state { | 
|  | struct rcu_node			node[NUM_RCU_NODES]; | 
|  | struct rcu_node			*level[RCU_NUM_LVLS]; | 
|  |  | 
|  | /* These are read by everyone but only written by the GP kthread */ | 
|  | unsigned long			gpnum; | 
|  | unsigned long			completed; | 
|  |  | 
|  | /* These are written by anyone trying to wake the gp kthread, which can | 
|  | * be any core whose CB list is long or does an rcu_barrier() */ | 
|  | /* TODO: make a ktask struct and use a read-only pointer. */ | 
|  | struct rendez			gp_ktask_rv; | 
|  | int				gp_ktask_ctl; | 
|  | }; | 
|  |  | 
|  | struct rcu_pcpui { | 
|  | struct rcu_state		*rsp; | 
|  | struct rcu_node			*my_node; | 
|  | int				coreid; | 
|  | unsigned int			grpnum; | 
|  | unsigned long			grpmask; | 
|  | bool				booted; | 
|  |  | 
|  | spinlock_t			lock; | 
|  | struct list_head		cbs; | 
|  | unsigned int			nr_cbs; | 
|  | unsigned long			gp_acked; | 
|  |  | 
|  | struct rendez			mgmt_ktask_rv; | 
|  | int				mgmt_ktask_ctl; | 
|  | }; | 
|  | DECLARE_PERCPU(struct rcu_pcpui, rcu_pcpui); | 
|  |  | 
|  | void rcu_init(void); | 
|  | void rcu_report_qs(void); | 
|  | void rcu_barrier(void); | 
|  | void rcu_force_quiescent_state(void); | 
|  | unsigned long get_state_synchronize_rcu(void); | 
|  | void cond_synchronize_rcu(unsigned long oldstate); | 
|  | void kfree_call_rcu(struct rcu_head *head, rcu_callback_t off); | 
|  |  | 
|  | /* Internal Helpers (rcu.c) */ | 
|  | void rcu_init_pcpui(struct rcu_state *rsp, struct rcu_pcpui *rpi, int coreid); | 
|  |  | 
|  | /* Internal Helpers (rcu_tree_helper.c) */ | 
|  | void rcu_init_one(struct rcu_state *rsp); | 
|  | void rcu_init_geometry(void); | 
|  | void rcu_dump_rcu_node_tree(struct rcu_state *rsp); |