PM / Wakeup: Use rcu callbacks for better performance

Use rcu to free objects in wakeup_source_unregister(). These objects must
be allocated through wakeup_source_register().

Replacing synchronize_rcu() with call_rcu() allows multiple calls to
wakeup_source_unregister() to be combined into a single grace period.

CRs-Fixed: 845110
Change-Id: Ib4002db042cf63abb28e6b3df6e3c70c97043bd9
Signed-off-by: Patrick Daly <pdaly@codeaurora.org>
This commit is contained in:
Patrick Daly 2015-06-25 19:21:28 -07:00 committed by Artem Borisov
parent b38b86cfb7
commit 09919ab798
2 changed files with 32 additions and 2 deletions

View file

@ -121,6 +121,15 @@ void wakeup_source_destroy(struct wakeup_source *ws)
}
EXPORT_SYMBOL_GPL(wakeup_source_destroy);
/**
* wakeup_source_destroy_cb
* defer processing until all rcu references have expired
*/
static void wakeup_source_destroy_cb(struct rcu_head *head)
{
wakeup_source_destroy(container_of(head, struct wakeup_source, rcu));
}
/**
* wakeup_source_add - Add given object to the list of wakeup sources.
* @ws: Wakeup source object to add to the list.
@ -157,6 +166,26 @@ void wakeup_source_remove(struct wakeup_source *ws)
}
EXPORT_SYMBOL_GPL(wakeup_source_remove);
/**
* wakeup_source_remove_async - Remove given object from the wakeup sources
* list.
* @ws: Wakeup source object to remove from the list.
*
* Use only for wakeup source objects created with wakeup_source_create().
* Memory for ws must be freed via rcu.
*/
static void wakeup_source_remove_async(struct wakeup_source *ws)
{
unsigned long flags;
if (WARN_ON(!ws))
return;
spin_lock_irqsave(&events_lock, flags);
list_del_rcu(&ws->entry);
spin_unlock_irqrestore(&events_lock, flags);
}
/**
* wakeup_source_register - Create wakeup source and add it to the list.
* @name: Name of the wakeup source to register.
@ -180,8 +209,8 @@ EXPORT_SYMBOL_GPL(wakeup_source_register);
void wakeup_source_unregister(struct wakeup_source *ws)
{
if (ws) {
wakeup_source_remove(ws);
wakeup_source_destroy(ws);
wakeup_source_remove_async(ws);
call_rcu(&ws->rcu, wakeup_source_destroy_cb);
}
}
EXPORT_SYMBOL_GPL(wakeup_source_unregister);

View file

@ -46,6 +46,7 @@
struct wakeup_source {
const char *name;
struct list_head entry;
struct rcu_head rcu;
spinlock_t lock;
struct timer_list timer;
unsigned long timer_expires;