blob: e67553d1d0262f48d6369827c47e42989496d005 [file] [log] [blame]
/* 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);