Skip to content

Commit

Permalink
Merge branch 'core-rcu-for-linus' of git://git.kernel.org/pub/scm/lin…
Browse files Browse the repository at this point in the history
…ux/kernel/git/tip/linux-2.6-tip

* 'core-rcu-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip: (78 commits)
  Revert "rcu: Decrease memory-barrier usage based on semi-formal proof"
  net,rcu: convert call_rcu(prl_entry_destroy_rcu) to kfree
  batman,rcu: convert call_rcu(softif_neigh_free_rcu) to kfree_rcu
  batman,rcu: convert call_rcu(neigh_node_free_rcu) to kfree()
  batman,rcu: convert call_rcu(gw_node_free_rcu) to kfree_rcu
  net,rcu: convert call_rcu(kfree_tid_tx) to kfree_rcu()
  net,rcu: convert call_rcu(xt_osf_finger_free_rcu) to kfree_rcu()
  net/mac80211,rcu: convert call_rcu(work_free_rcu) to kfree_rcu()
  net,rcu: convert call_rcu(wq_free_rcu) to kfree_rcu()
  net,rcu: convert call_rcu(phonet_device_rcu_free) to kfree_rcu()
  perf,rcu: convert call_rcu(swevent_hlist_release_rcu) to kfree_rcu()
  perf,rcu: convert call_rcu(free_ctx) to kfree_rcu()
  net,rcu: convert call_rcu(__nf_ct_ext_free_rcu) to kfree_rcu()
  net,rcu: convert call_rcu(net_generic_release) to kfree_rcu()
  net,rcu: convert call_rcu(netlbl_unlhsh_free_addr6) to kfree_rcu()
  net,rcu: convert call_rcu(netlbl_unlhsh_free_addr4) to kfree_rcu()
  security,rcu: convert call_rcu(sel_netif_free) to kfree_rcu()
  net,rcu: convert call_rcu(xps_dev_maps_release) to kfree_rcu()
  net,rcu: convert call_rcu(xps_map_release) to kfree_rcu()
  net,rcu: convert call_rcu(rps_map_release) to kfree_rcu()
  ...
  • Loading branch information
torvalds committed May 20, 2011
2 parents 5765040 + 80d0208 commit eb04f2f
Show file tree
Hide file tree
Showing 56 changed files with 1,724 additions and 833 deletions.
2 changes: 1 addition & 1 deletion Documentation/RCU/00-INDEX
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ rcu.txt
RTFP.txt
- List of RCU papers (bibliography) going back to 1980.
stallwarn.txt
- RCU CPU stall warnings (CONFIG_RCU_CPU_STALL_DETECTOR)
- RCU CPU stall warnings (module parameter rcu_cpu_stall_suppress)
torture.txt
- RCU Torture Test Operation (CONFIG_RCU_TORTURE_TEST)
trace.txt
Expand Down
23 changes: 13 additions & 10 deletions Documentation/RCU/stallwarn.txt
Original file line number Diff line number Diff line change
@@ -1,22 +1,25 @@
Using RCU's CPU Stall Detector

The CONFIG_RCU_CPU_STALL_DETECTOR kernel config parameter enables
RCU's CPU stall detector, which detects conditions that unduly delay
RCU grace periods. The stall detector's idea of what constitutes
"unduly delayed" is controlled by a set of C preprocessor macros:
The rcu_cpu_stall_suppress module parameter enables RCU's CPU stall
detector, which detects conditions that unduly delay RCU grace periods.
This module parameter enables CPU stall detection by default, but
may be overridden via boot-time parameter or at runtime via sysfs.
The stall detector's idea of what constitutes "unduly delayed" is
controlled by a set of kernel configuration variables and cpp macros:

RCU_SECONDS_TILL_STALL_CHECK
CONFIG_RCU_CPU_STALL_TIMEOUT

This macro defines the period of time that RCU will wait from
the beginning of a grace period until it issues an RCU CPU
stall warning. This time period is normally ten seconds.
This kernel configuration parameter defines the period of time
that RCU will wait from the beginning of a grace period until it
issues an RCU CPU stall warning. This time period is normally
ten seconds.

RCU_SECONDS_TILL_STALL_RECHECK

This macro defines the period of time that RCU will wait after
issuing a stall warning until it issues another stall warning
for the same stall. This time period is normally set to thirty
seconds.
for the same stall. This time period is normally set to three
times the check interval plus thirty seconds.

RCU_STALL_RAT_DELAY

Expand Down
278 changes: 231 additions & 47 deletions Documentation/RCU/trace.txt

Large diffs are not rendered by default.

1 change: 0 additions & 1 deletion Documentation/filesystems/proc.txt
Original file line number Diff line number Diff line change
Expand Up @@ -836,7 +836,6 @@ Provides counts of softirq handlers serviced since boot time, for each cpu.
TASKLET: 0 0 0 290
SCHED: 27035 26983 26971 26746
HRTIMER: 0 0 0 0
RCU: 1678 1769 2178 2250


1.3 IDE devices in /proc/ide
Expand Down
7 changes: 1 addition & 6 deletions drivers/net/ixgbe/ixgbe_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -5100,11 +5100,6 @@ int ixgbe_init_interrupt_scheme(struct ixgbe_adapter *adapter)
return err;
}

static void ring_free_rcu(struct rcu_head *head)
{
kfree(container_of(head, struct ixgbe_ring, rcu));
}

/**
* ixgbe_clear_interrupt_scheme - Clear the current interrupt scheme settings
* @adapter: board private structure to clear interrupt scheme on
Expand All @@ -5126,7 +5121,7 @@ void ixgbe_clear_interrupt_scheme(struct ixgbe_adapter *adapter)
/* ixgbe_get_stats64() might access this ring, we must wait
* a grace period before freeing it.
*/
call_rcu(&ring->rcu, ring_free_rcu);
kfree_rcu(ring, rcu);
adapter->rx_ring[i] = NULL;
}

Expand Down
10 changes: 1 addition & 9 deletions drivers/net/macvlan.c
Original file line number Diff line number Diff line change
Expand Up @@ -603,21 +603,13 @@ static int macvlan_port_create(struct net_device *dev)
return err;
}

static void macvlan_port_rcu_free(struct rcu_head *head)
{
struct macvlan_port *port;

port = container_of(head, struct macvlan_port, rcu);
kfree(port);
}

static void macvlan_port_destroy(struct net_device *dev)
{
struct macvlan_port *port = macvlan_port_get(dev);

dev->priv_flags &= ~IFF_MACVLAN_PORT;
netdev_rx_handler_unregister(dev);
call_rcu(&port->rcu, macvlan_port_rcu_free);
kfree_rcu(port, rcu);
}

static int macvlan_validate(struct nlattr *tb[], struct nlattr *data[])
Expand Down
1 change: 0 additions & 1 deletion include/linux/interrupt.h
Original file line number Diff line number Diff line change
Expand Up @@ -414,7 +414,6 @@ enum
TASKLET_SOFTIRQ,
SCHED_SOFTIRQ,
HRTIMER_SOFTIRQ,
RCU_SOFTIRQ, /* Preferable RCU should always be the last softirq */

NR_SOFTIRQS
};
Expand Down
70 changes: 69 additions & 1 deletion include/linux/rcupdate.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,18 @@
extern int rcutorture_runnable; /* for sysctl */
#endif /* #ifdef CONFIG_RCU_TORTURE_TEST */

#if defined(CONFIG_TREE_RCU) || defined(CONFIG_TREE_PREEMPT_RCU)
extern void rcutorture_record_test_transition(void);
extern void rcutorture_record_progress(unsigned long vernum);
#else
static inline void rcutorture_record_test_transition(void)
{
}
static inline void rcutorture_record_progress(unsigned long vernum)
{
}
#endif

#define UINT_CMP_GE(a, b) (UINT_MAX / 2 >= (a) - (b))
#define UINT_CMP_LT(a, b) (UINT_MAX / 2 < (a) - (b))
#define ULONG_CMP_GE(a, b) (ULONG_MAX / 2 >= (a) - (b))
Expand All @@ -68,7 +80,6 @@ extern void call_rcu_sched(struct rcu_head *head,
extern void synchronize_sched(void);
extern void rcu_barrier_bh(void);
extern void rcu_barrier_sched(void);
extern int sched_expedited_torture_stats(char *page);

static inline void __rcu_read_lock_bh(void)
{
Expand Down Expand Up @@ -774,6 +785,7 @@ extern struct debug_obj_descr rcuhead_debug_descr;

static inline void debug_rcu_head_queue(struct rcu_head *head)
{
WARN_ON_ONCE((unsigned long)head & 0x3);
debug_object_activate(head, &rcuhead_debug_descr);
debug_object_active_state(head, &rcuhead_debug_descr,
STATE_RCU_HEAD_READY,
Expand All @@ -797,4 +809,60 @@ static inline void debug_rcu_head_unqueue(struct rcu_head *head)
}
#endif /* #else !CONFIG_DEBUG_OBJECTS_RCU_HEAD */

static __always_inline bool __is_kfree_rcu_offset(unsigned long offset)
{
return offset < 4096;
}

static __always_inline
void __kfree_rcu(struct rcu_head *head, unsigned long offset)
{
typedef void (*rcu_callback)(struct rcu_head *);

BUILD_BUG_ON(!__builtin_constant_p(offset));

/* See the kfree_rcu() header comment. */
BUILD_BUG_ON(!__is_kfree_rcu_offset(offset));

call_rcu(head, (rcu_callback)offset);
}

extern void kfree(const void *);

static inline void __rcu_reclaim(struct rcu_head *head)
{
unsigned long offset = (unsigned long)head->func;

if (__is_kfree_rcu_offset(offset))
kfree((void *)head - offset);
else
head->func(head);
}

/**
* kfree_rcu() - kfree an object after a grace period.
* @ptr: pointer to kfree
* @rcu_head: the name of the struct rcu_head within the type of @ptr.
*
* Many rcu callbacks functions just call kfree() on the base structure.
* These functions are trivial, but their size adds up, and furthermore
* when they are used in a kernel module, that module must invoke the
* high-latency rcu_barrier() function at module-unload time.
*
* The kfree_rcu() function handles this issue. Rather than encoding a
* function address in the embedded rcu_head structure, kfree_rcu() instead
* encodes the offset of the rcu_head structure within the base structure.
* Because the functions are not allowed in the low-order 4096 bytes of
* kernel virtual memory, offsets up to 4095 bytes can be accommodated.
* If the offset is larger than 4095 bytes, a compile-time error will
* be generated in __kfree_rcu(). If this error is triggered, you can
* either fall back to use of call_rcu() or rearrange the structure to
* position the rcu_head structure into the first 4096 bytes.
*
* Note that the allowable offset might decrease in the future, for example,
* to allow something like kmem_cache_free_rcu().
*/
#define kfree_rcu(ptr, rcu_head) \
__kfree_rcu(&((ptr)->rcu_head), offsetof(typeof(*(ptr)), rcu_head))

#endif /* __LINUX_RCUPDATE_H */
8 changes: 8 additions & 0 deletions include/linux/rcutiny.h
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,14 @@ static inline void rcu_note_context_switch(int cpu)
rcu_preempt_note_context_switch();
}

/*
* Take advantage of the fact that there is only one CPU, which
* allows us to ignore virtualization-based context switches.
*/
static inline void rcu_virt_note_context_switch(int cpu)
{
}

/*
* Return the number of grace periods.
*/
Expand Down
13 changes: 13 additions & 0 deletions include/linux/rcutree.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,16 @@ extern void rcu_note_context_switch(int cpu);
extern int rcu_needs_cpu(int cpu);
extern void rcu_cpu_stall_reset(void);

/*
* Note a virtualization-based context switch. This is simply a
* wrapper around rcu_note_context_switch(), which allows TINY_RCU
* to save a few bytes.
*/
static inline void rcu_virt_note_context_switch(int cpu)
{
rcu_note_context_switch(cpu);
}

#ifdef CONFIG_TREE_PREEMPT_RCU

extern void exit_rcu(void);
Expand All @@ -58,9 +68,12 @@ static inline void synchronize_rcu_bh_expedited(void)

extern void rcu_barrier(void);

extern unsigned long rcutorture_testseq;
extern unsigned long rcutorture_vernum;
extern long rcu_batches_completed(void);
extern long rcu_batches_completed_bh(void);
extern long rcu_batches_completed_sched(void);

extern void rcu_force_quiescent_state(void);
extern void rcu_bh_force_quiescent_state(void);
extern void rcu_sched_force_quiescent_state(void);
Expand Down
1 change: 0 additions & 1 deletion include/net/sctp/sctp.h
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,6 @@
* sctp/protocol.c
*/
extern struct sock *sctp_get_ctl_sock(void);
extern void sctp_local_addr_free(struct rcu_head *head);
extern int sctp_copy_local_addr_list(struct sctp_bind_addr *,
sctp_scope_t, gfp_t gfp,
int flags);
Expand Down
3 changes: 1 addition & 2 deletions include/trace/events/irq.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,7 @@ struct softirq_action;
softirq_name(BLOCK_IOPOLL), \
softirq_name(TASKLET), \
softirq_name(SCHED), \
softirq_name(HRTIMER), \
softirq_name(RCU))
softirq_name(HRTIMER))

/**
* irq_handler_entry - called immediately before the irq action handler
Expand Down
2 changes: 1 addition & 1 deletion init/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -485,7 +485,7 @@ config TREE_RCU_TRACE

config RCU_BOOST
bool "Enable RCU priority boosting"
depends on RT_MUTEXES && TINY_PREEMPT_RCU
depends on RT_MUTEXES && PREEMPT_RCU
default n
help
This option boosts the priority of preempted RCU readers that
Expand Down
27 changes: 3 additions & 24 deletions kernel/cgroup.c
Original file line number Diff line number Diff line change
Expand Up @@ -326,12 +326,6 @@ static struct hlist_head *css_set_hash(struct cgroup_subsys_state *css[])
return &css_set_table[index];
}

static void free_css_set_rcu(struct rcu_head *obj)
{
struct css_set *cg = container_of(obj, struct css_set, rcu_head);
kfree(cg);
}

/* We don't maintain the lists running through each css_set to its
* task until after the first call to cgroup_iter_start(). This
* reduces the fork()/exit() overhead for people who have cgroups
Expand Down Expand Up @@ -375,7 +369,7 @@ static void __put_css_set(struct css_set *cg, int taskexit)
}

write_unlock(&css_set_lock);
call_rcu(&cg->rcu_head, free_css_set_rcu);
kfree_rcu(cg, rcu_head);
}

/*
Expand Down Expand Up @@ -812,13 +806,6 @@ static int cgroup_call_pre_destroy(struct cgroup *cgrp)
return ret;
}

static void free_cgroup_rcu(struct rcu_head *obj)
{
struct cgroup *cgrp = container_of(obj, struct cgroup, rcu_head);

kfree(cgrp);
}

static void cgroup_diput(struct dentry *dentry, struct inode *inode)
{
/* is dentry a directory ? if so, kfree() associated cgroup */
Expand Down Expand Up @@ -856,7 +843,7 @@ static void cgroup_diput(struct dentry *dentry, struct inode *inode)
*/
BUG_ON(!list_empty(&cgrp->pidlists));

call_rcu(&cgrp->rcu_head, free_cgroup_rcu);
kfree_rcu(cgrp, rcu_head);
}
iput(inode);
}
Expand Down Expand Up @@ -4623,14 +4610,6 @@ bool css_is_ancestor(struct cgroup_subsys_state *child,
return ret;
}

static void __free_css_id_cb(struct rcu_head *head)
{
struct css_id *id;

id = container_of(head, struct css_id, rcu_head);
kfree(id);
}

void free_css_id(struct cgroup_subsys *ss, struct cgroup_subsys_state *css)
{
struct css_id *id = css->id;
Expand All @@ -4645,7 +4624,7 @@ void free_css_id(struct cgroup_subsys *ss, struct cgroup_subsys_state *css)
spin_lock(&ss->id_lock);
idr_remove(&ss->idr, id->id);
spin_unlock(&ss->id_lock);
call_rcu(&id->rcu_head, __free_css_id_cb);
kfree_rcu(id, rcu_head);
}
EXPORT_SYMBOL_GPL(free_css_id);

Expand Down
20 changes: 2 additions & 18 deletions kernel/events/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -586,22 +586,14 @@ static void get_ctx(struct perf_event_context *ctx)
WARN_ON(!atomic_inc_not_zero(&ctx->refcount));
}

static void free_ctx(struct rcu_head *head)
{
struct perf_event_context *ctx;

ctx = container_of(head, struct perf_event_context, rcu_head);
kfree(ctx);
}

static void put_ctx(struct perf_event_context *ctx)
{
if (atomic_dec_and_test(&ctx->refcount)) {
if (ctx->parent_ctx)
put_ctx(ctx->parent_ctx);
if (ctx->task)
put_task_struct(ctx->task);
call_rcu(&ctx->rcu_head, free_ctx);
kfree_rcu(ctx, rcu_head);
}
}

Expand Down Expand Up @@ -5331,14 +5323,6 @@ swevent_hlist_deref(struct swevent_htable *swhash)
lockdep_is_held(&swhash->hlist_mutex));
}

static void swevent_hlist_release_rcu(struct rcu_head *rcu_head)
{
struct swevent_hlist *hlist;

hlist = container_of(rcu_head, struct swevent_hlist, rcu_head);
kfree(hlist);
}

static void swevent_hlist_release(struct swevent_htable *swhash)
{
struct swevent_hlist *hlist = swevent_hlist_deref(swhash);
Expand All @@ -5347,7 +5331,7 @@ static void swevent_hlist_release(struct swevent_htable *swhash)
return;

rcu_assign_pointer(swhash->swevent_hlist, NULL);
call_rcu(&hlist->rcu_head, swevent_hlist_release_rcu);
kfree_rcu(hlist, rcu_head);
}

static void swevent_hlist_put_cpu(struct perf_event *event, int cpu)
Expand Down
Loading

0 comments on commit eb04f2f

Please sign in to comment.