Add the 'current_kthread' helper
[akaros.git] / kern / include / rcu.h
index cbd7c8b..578a303 100644 (file)
@@ -2,35 +2,92 @@
  * Barret Rhoden <brho@cs.berkeley.edu>
  * See LICENSE for details.
  *
- * Junk, racy implementation of RCU
+ * RCU.  See rcu.c for notes.
  */
 
 #pragma once
 
-#include <trap.h>
+#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 */
 };
 
-static void __call_rcu_kmsg(uint32_t srcid, long a0, long a1, long a2)
-{
-       void (*f)(struct rcu_head *) = (void*)a0;
+struct rcu_state {
+       struct rcu_node                         node[NUM_RCU_NODES];
+       struct rcu_node                         *level[RCU_NUM_LVLS];
 
-       f((void*)a1);
-}
+       /* 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);
 
-static void call_rcu(struct rcu_head *head, void (*func)(struct rcu_head *head))
-{
-       send_kernel_message(core_id(), __call_rcu_kmsg, (long)func, (long)head, 0,
-                           KMSG_ROUTINE);
-}
+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);
 
-#define hlist_for_each_entry_rcu hlist_for_each_entry
-#define hlist_add_head_rcu hlist_add_head
-#define hlist_del_rcu hlist_del
+/* Internal Helpers (rcu.c) */
+void rcu_init_pcpui(struct rcu_state *rsp, struct rcu_pcpui *rpi, int coreid);
 
-#define rcu_read_lock()
-#define rcu_read_unlock()
-#define synchronize_rcu()
-#define rcu_dereference(x) (x)
-#define rcu_barrier() kthread_usleep(10000)
+/* 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);