1 /* 2 * RCU-based infrastructure for lightweight reader-writer locking 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation; either version 2 of the License, or 7 * (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program; if not, you can access it online at 16 * http://www.gnu.org/licenses/gpl-2.0.html. 17 * 18 * Copyright (c) 2015, Red Hat, Inc. 19 * 20 * Author: Oleg Nesterov <oleg@redhat.com> 21 */ 22 23 #ifndef _LINUX_RCU_SYNC_H_ 24 #define _LINUX_RCU_SYNC_H_ 25 26 #include <linux/wait.h> 27 #include <linux/rcupdate.h> 28 29 enum rcu_sync_type { RCU_SYNC, RCU_SCHED_SYNC, RCU_BH_SYNC }; 30 31 /* Structure to mediate between updaters and fastpath-using readers. */ 32 struct rcu_sync { 33 int gp_state; 34 int gp_count; 35 wait_queue_head_t gp_wait; 36 37 int cb_state; 38 struct rcu_head cb_head; 39 40 enum rcu_sync_type gp_type; 41 }; 42 43 extern void rcu_sync_lockdep_assert(struct rcu_sync *); 44 45 /** 46 * rcu_sync_is_idle() - Are readers permitted to use their fastpaths? 47 * @rsp: Pointer to rcu_sync structure to use for synchronization 48 * 49 * Returns true if readers are permitted to use their fastpaths. 50 * Must be invoked within an RCU read-side critical section whose 51 * flavor matches that of the rcu_sync struture. 52 */ 53 static inline bool rcu_sync_is_idle(struct rcu_sync *rsp) 54 { 55 #ifdef CONFIG_PROVE_RCU 56 rcu_sync_lockdep_assert(rsp); 57 #endif 58 return !rsp->gp_state; /* GP_IDLE */ 59 } 60 61 extern void rcu_sync_init(struct rcu_sync *, enum rcu_sync_type); 62 extern void rcu_sync_enter(struct rcu_sync *); 63 extern void rcu_sync_exit(struct rcu_sync *); 64 extern void rcu_sync_dtor(struct rcu_sync *); 65 66 #define __RCU_SYNC_INITIALIZER(name, type) { \ 67 .gp_state = 0, \ 68 .gp_count = 0, \ 69 .gp_wait = __WAIT_QUEUE_HEAD_INITIALIZER(name.gp_wait), \ 70 .cb_state = 0, \ 71 .gp_type = type, \ 72 } 73 74 #define __DEFINE_RCU_SYNC(name, type) \ 75 struct rcu_sync_struct name = __RCU_SYNC_INITIALIZER(name, type) 76 77 #define DEFINE_RCU_SYNC(name) \ 78 __DEFINE_RCU_SYNC(name, RCU_SYNC) 79 80 #define DEFINE_RCU_SCHED_SYNC(name) \ 81 __DEFINE_RCU_SYNC(name, RCU_SCHED_SYNC) 82 83 #define DEFINE_RCU_BH_SYNC(name) \ 84 __DEFINE_RCU_SYNC(name, RCU_BH_SYNC) 85 86 #endif /* _LINUX_RCU_SYNC_H_ */ 87