/* * Read-Copy Update definitions shared among RCU implementations. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * Copyright IBM Corporation, 2011 * * Author: Paul E. McKenney */ #ifndef __LINUX_RCU_H #define __LINUX_RCU_H #ifdef CONFIG_RCU_TRACE #define RCU_TRACE(stmt) stmt #else #define RCU_TRACE(stmt) #endif #define DYNTICK_TASK_NEST_WIDTH 7 #define DYNTICK_TASK_NEST_VALUE ((LLONG_MAX >> DYNTICK_TASK_NEST_WIDTH) + 1) #define DYNTICK_TASK_NEST_MASK (LLONG_MAX - DYNTICK_TASK_NEST_VALUE + 1) #define DYNTICK_TASK_FLAG ((DYNTICK_TASK_NEST_VALUE / 8) * 2) #define DYNTICK_TASK_MASK ((DYNTICK_TASK_NEST_VALUE / 8) * 3) #define DYNTICK_TASK_EXIT_IDLE (DYNTICK_TASK_NEST_VALUE + \ DYNTICK_TASK_FLAG) #ifdef CONFIG_DEBUG_OBJECTS_RCU_HEAD # define STATE_RCU_HEAD_READY 0 # define STATE_RCU_HEAD_QUEUED 1 extern struct debug_obj_descr rcuhead_debug_descr; static inline void debug_rcu_head_queue(struct rcu_head *head) { debug_object_activate(head, &rcuhead_debug_descr); debug_object_active_state(head, &rcuhead_debug_descr, STATE_RCU_HEAD_READY, STATE_RCU_HEAD_QUEUED); } static inline void debug_rcu_head_unqueue(struct rcu_head *head) { debug_object_active_state(head, &rcuhead_debug_descr, STATE_RCU_HEAD_QUEUED, STATE_RCU_HEAD_READY); debug_object_deactivate(head, &rcuhead_debug_descr); } #else static inline void debug_rcu_head_queue(struct rcu_head *head) { } static inline void debug_rcu_head_unqueue(struct rcu_head *head) { } #endif extern void kfree(const void *); static inline bool __rcu_reclaim(char *rn, struct rcu_head *head) { unsigned long offset = (unsigned long)head->func; if (__is_kfree_rcu_offset(offset)) { RCU_TRACE(trace_rcu_invoke_kfree_callback(rn, head, offset)); kfree((void *)head - offset); return 1; } else { RCU_TRACE(trace_rcu_invoke_callback(rn, head)); head->func(head); return 0; } } #endif