lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Date:	Fri, 23 Jul 2010 12:06:59 +0200
From:	florian@...kler.org
To:	pm list <linux-pm@...ts.linux-foundation.org>
Cc:	Florian Mickler <florian@...kler.org>,
	Frederic Weisbecker <fweisbec@...il.com>,
	James Bottomley <James.Bottomley@...e.de>,
	linux-kernel@...r.kernel.org, mark gross <markgross@...gnar.org>,
	"Rafael J. Wysocki" <rjw@...k.pl>
Subject: [PATCH 2/2] [RFC] pm_qos: add atomic notifier chain

This allows for atomic notifications.

This is unecessary at the moment, but I had it flying around and it may be
necessary to have in some future scenarios.

The atomic listeners get called for _every_ change
of the target value, whereas the blocking notifiers, when called from
interrupt context, may be "folded" to notify just once.

Signed-off-by: Florian Mickler <florian@...kler.org>
---
 include/linux/pm_qos_params.h |    2 +
 kernel/pm_qos_params.c        |   61 ++++++++++++++++++++++++++++++++++-------
 2 files changed, 53 insertions(+), 10 deletions(-)

diff --git a/include/linux/pm_qos_params.h b/include/linux/pm_qos_params.h
index fdd8a78..4c0d209 100644
--- a/include/linux/pm_qos_params.h
+++ b/include/linux/pm_qos_params.h
@@ -30,6 +30,8 @@ void pm_qos_remove_request(struct pm_qos_request_list *pm_qos_req);
 
 int pm_qos_request(int pm_qos_class);
 int pm_qos_add_notifier(int pm_qos_class, struct notifier_block *notifier);
+int pm_qos_add_atomic_notifier(int pm_qos_class,
+		struct notifier_block *notifier);
 int pm_qos_remove_notifier(int pm_qos_class, struct notifier_block *notifier);
 int pm_qos_request_active(struct pm_qos_request_list *req);
 
diff --git a/kernel/pm_qos_params.c b/kernel/pm_qos_params.c
index 640c367..fbd0a6d 100644
--- a/kernel/pm_qos_params.c
+++ b/kernel/pm_qos_params.c
@@ -57,6 +57,7 @@ enum pm_qos_type {
 struct pm_qos_object {
 	struct plist_head requests;
 	struct blocking_notifier_head notifiers;
+	struct atomic_notifier_head atomic_notifiers;
 	struct miscdevice pm_qos_power_miscdev;
 	struct work_struct notify;
 	char *name;
@@ -73,9 +74,14 @@ static struct pm_qos_object pm_qos_objects[] = {
 	{
 		.requests = PLIST_HEAD_INIT(
 			pm_qos_objects[PM_QOS_CPU_DMA_LATENCY].requests,
-			pm_qos_lock),
+			pm_qos_lock
+			),
 		.notifiers = BLOCKING_NOTIFIER_INIT(
-			pm_qos_objects[PM_QOS_CPU_DMA_LATENCY].notifiers),
+			pm_qos_objects[PM_QOS_CPU_DMA_LATENCY].notifiers
+			),
+		.atomic_notifiers = ATOMIC_NOTIFIER_INIT(
+			pm_qos_objects[PM_QOS_CPU_DMA_LATENCY].atomic_notifiers
+			),
 		.notify = __WORK_INITIALIZER(
 			pm_qos_objects[PM_QOS_CPU_DMA_LATENCY].notify,
 			update_notify),
@@ -91,6 +97,9 @@ static struct pm_qos_object pm_qos_objects[] = {
 		.notifiers = BLOCKING_NOTIFIER_INIT(
 			pm_qos_objects[PM_QOS_NETWORK_LATENCY].notifiers
 			),
+		.atomic_notifiers = ATOMIC_NOTIFIER_INIT(
+			pm_qos_objects[PM_QOS_NETWORK_LATENCY].atomic_notifiers
+			),
 		.notify = __WORK_INITIALIZER(
 			pm_qos_objects[PM_QOS_NETWORK_LATENCY].notify,
 			update_notify
@@ -107,6 +116,9 @@ static struct pm_qos_object pm_qos_objects[] = {
 		.notifiers = BLOCKING_NOTIFIER_INIT(
 			pm_qos_objects[PM_QOS_NETWORK_THROUGHPUT].notifiers
 			),
+		.atomic_notifiers = ATOMIC_NOTIFIER_INIT(
+			pm_qos_objects[PM_QOS_NETWORK_THROUGHPUT].atomic_notifiers
+			),
 		.notify = __WORK_INITIALIZER(
 			pm_qos_objects[PM_QOS_NETWORK_THROUGHPUT].notify,
 			update_notify
@@ -147,14 +159,15 @@ static inline int pm_qos_get_value(struct pm_qos_object *o)
 	}
 }
 
-static void call_notifiers(struct pm_qos_object *o, unsigned long val)
+static void call_notifiers(struct pm_qos_object *o, unsigned long curr_value)
 {
 
+	atomic_notifier_call_chain(&o->atomic_notifiers, curr_value, NULL);
+
 	if (in_interrupt())
 		schedule_work(&o->notify);
 	else
-		blocking_notifier_call_chain(&o->notifiers, val,
-				NULL);
+		blocking_notifier_call_chain(&o->notifiers, curr_value, NULL);
 
 
 }
@@ -361,13 +374,14 @@ EXPORT_SYMBOL_GPL(pm_qos_remove_request);
 
 /**
  * pm_qos_add_notifier - sets notification entry for changes to target value
- * @pm_qos_class: identifies which qos target changes should be notified.
+ * @pm_qos_class: identifies which qos target changes should trigger
+ *     notifications.
  * @notifier: notifier block managed by caller.
  *
  * Will register the notifier into a notification chain that gets called
  * upon changes to the pm_qos_class target value.
  */
-int pm_qos_add_notifier(int pm_qos_class, struct notifier_block *notifier)
+int pm_qos_add_notifier(int pm_qos_class, struct notifier_block *nb)
 {
 	int retval;
 	if (!pm_qos_valid_class(pm_qos_class)) {
@@ -375,13 +389,37 @@ int pm_qos_add_notifier(int pm_qos_class, struct notifier_block *notifier)
 		return -EINVAL;
 	}
 	retval = blocking_notifier_chain_register(
-			&pm_qos_objects[pm_qos_class].notifiers, notifier);
+			&pm_qos_objects[pm_qos_class].notifiers, nb);
 
 	return retval;
 }
 EXPORT_SYMBOL_GPL(pm_qos_add_notifier);
 
 /**
+ * pm_qos_add_atomic_notifier - sets notification entry for changes to target value
+ * @pm_qos_class: identifies which qos target changes should trigger
+ *	notifications.
+ * @notifier: notifier block managed by caller.
+ *
+ * Will register the notifier into a notification chain that gets
+ * called upon changes to the pm_qos_class target value.  The notifier
+ * may be called from atomic context.  use @pm_qos_remove_notifier to
+ * unregister.
+ */
+int pm_qos_add_atomic_notifier(int pm_qos_class, struct notifier_block *nb)
+{
+	int ret = 0;
+	if (!pm_qos_valid_class(pm_qos_class)) {
+		WARN(1, KERN_ERR "pm_qos_add_atmoic_notifier called for unknown qos class\n");
+		ret = -EINVAL;
+	} else
+		ret = atomic_notifier_chain_register(
+			&pm_qos_objects[pm_qos_class].atomic_notifiers, nb);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(pm_qos_add_atomic_notifier);
+
+/**
  * pm_qos_remove_notifier - deletes notification entry from chain.
  * @pm_qos_class: identifies which qos target changes are notified.
  * @notifier: notifier block to be removed.
@@ -389,7 +427,7 @@ EXPORT_SYMBOL_GPL(pm_qos_add_notifier);
  * Will remove the notifier from the notification chain that gets called
  * upon changes to the pm_qos_class target value.
  */
-int pm_qos_remove_notifier(int pm_qos_class, struct notifier_block *notifier)
+int pm_qos_remove_notifier(int pm_qos_class, struct notifier_block *nb)
 {
 	int retval;
 	if (!pm_qos_valid_class(pm_qos_class)) {
@@ -398,7 +436,10 @@ int pm_qos_remove_notifier(int pm_qos_class, struct notifier_block *notifier)
 	}
 
 	retval = blocking_notifier_chain_unregister(
-			&pm_qos_objects[pm_qos_class].notifiers, notifier);
+			&pm_qos_objects[pm_qos_class].notifiers, nb);
+	if (retval)
+		retval = atomic_notifier_chain_unregister(
+			&pm_qos_objects[pm_qos_class].atomic_notifiers, nb);
 
 	return retval;
 }
-- 
1.7.1.1

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ