All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Arve Hjønnevåg" <arve@android.com>
To: linux-pm@lists.linux-foundation.org
Cc: ncunningham@crca.org.au, u.luckas@road.de, swetland@google.com
Subject: [PATCH 03/10] PM: wakelock: Add driver to access wakelocks from user-space
Date: Tue, 10 Feb 2009 17:49:08 -0800	[thread overview]
Message-ID: <1234316955-31304-4-git-send-email-arve@android.com> (raw)
In-Reply-To: <1234316955-31304-3-git-send-email-arve@android.com>

Adds ioctls to create a wakelock, and to lock and unlock the wakelock.
To delete the wakelock, close the device.

Signed-off-by: Arve Hjønnevåg <arve@android.com>
---
 Documentation/power/wakelocks.txt |   24 ++++++
 include/linux/wakelock-dev.h      |   26 +++++++
 kernel/power/Kconfig              |    9 +++
 kernel/power/Makefile             |    1 +
 kernel/power/userwakelock.c       |  145 +++++++++++++++++++++++++++++++++++++
 5 files changed, 205 insertions(+), 0 deletions(-)
 create mode 100644 include/linux/wakelock-dev.h
 create mode 100644 kernel/power/userwakelock.c

diff --git a/Documentation/power/wakelocks.txt b/Documentation/power/wakelocks.txt
index 893a438..939908f 100644
--- a/Documentation/power/wakelocks.txt
+++ b/Documentation/power/wakelocks.txt
@@ -78,3 +78,27 @@ still need to run. Avoid this when possible, since it will waste power
 if the timeout is long or may fail to finish needed work if the timeout is
 short.
 
+User-space API
+==============
+
+To create a wakelock from user-space, open the wakelock device:
+    fd = open("/dev/wakelock", O_RDWR | O_CLOEXEC);
+then call:
+    ioctl(fd, WAKELOCK_IOCTL_INIT(strlen(name)), name);
+
+To lock a wakelock call:
+    ioctl(fd, WAKELOCK_IOCTL_LOCK);
+or
+    ioctl(fd, WAKELOCK_IOCTL_LOCK_TIMEOUT, &timespec_timeout);
+
+To unlock call:
+    ioctl(fd, WAKELOCK_IOCTL_UNLOCK);
+
+To destroy the wakelock, close the device:
+    close(fd);
+
+A module parameter, unclean_exit_grace_period, can be set to allow servers
+some time to restart if they crash with a wakelock held. If the process dies or
+the device is closed while the wakelock is locked, a wakelock will be held for
+the number of seconds specified.
+
diff --git a/include/linux/wakelock-dev.h b/include/linux/wakelock-dev.h
new file mode 100644
index 0000000..5dfb1c6
--- /dev/null
+++ b/include/linux/wakelock-dev.h
@@ -0,0 +1,26 @@
+/* include/linux/wakelock-dev.h
+ *
+ * Copyright (C) 2009 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+ */
+
+#ifndef _LINUX_WAKELOCK_DEV_H
+#define _LINUX_WAKELOCK_DEV_H
+
+#include <linux/ioctl.h>
+
+#define WAKELOCK_IOCTL_INIT(len)	_IOC(_IOC_WRITE,'w',0,len)
+#define WAKELOCK_IOCTL_LOCK		_IO('w', 1)
+#define WAKELOCK_IOCTL_LOCK_TIMEOUT	_IOW('w', 2, struct timespec)
+#define WAKELOCK_IOCTL_UNLOCK		_IO('w', 3)
+
+#endif
diff --git a/kernel/power/Kconfig b/kernel/power/Kconfig
index 9abd97e..6abd5f2 100644
--- a/kernel/power/Kconfig
+++ b/kernel/power/Kconfig
@@ -133,6 +133,15 @@ config WAKELOCK_STAT
 	---help---
 	  Report wake lock stats in /proc/wakelocks
 
+config USER_WAKELOCK
+	bool "Userspace wake locks"
+	depends on WAKELOCK
+	default y
+	---help---
+	  User-space wake lock api. Creates a misc device with ioctls
+	  to create, lock and unlock a wakelock. The wakelock will be
+	  deleted when the device is closed.
+
 config HIBERNATION
 	bool "Hibernation (aka 'suspend to disk')"
 	depends on PM && SWAP && ARCH_HIBERNATION_POSSIBLE
diff --git a/kernel/power/Makefile b/kernel/power/Makefile
index 8d8672b..63d30db 100644
--- a/kernel/power/Makefile
+++ b/kernel/power/Makefile
@@ -7,6 +7,7 @@ obj-y				:= main.o
 obj-$(CONFIG_PM_SLEEP)		+= console.o
 obj-$(CONFIG_FREEZER)		+= process.o
 obj-$(CONFIG_WAKELOCK)		+= wakelock.o
+obj-$(CONFIG_USER_WAKELOCK)	+= userwakelock.o
 obj-$(CONFIG_HIBERNATION)	+= swsusp.o disk.o snapshot.o swap.o user.o
 
 obj-$(CONFIG_MAGIC_SYSRQ)	+= poweroff.o
diff --git a/kernel/power/userwakelock.c b/kernel/power/userwakelock.c
new file mode 100644
index 0000000..c27c2f7
--- /dev/null
+++ b/kernel/power/userwakelock.c
@@ -0,0 +1,145 @@
+/* kernel/power/userwakelock.c
+ *
+ * Copyright (C) 2009 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+ */
+
+#include <linux/fs.h>
+#include <linux/miscdevice.h>
+#include <linux/module.h>
+#include <linux/uaccess.h>
+#include <linux/wakelock.h>
+#include <linux/wakelock-dev.h>
+
+enum {
+	DEBUG_FAILURE	= BIT(0),
+};
+static int debug_mask = DEBUG_FAILURE;
+module_param_named(debug_mask, debug_mask, int, S_IRUGO | S_IWUSR | S_IWGRP);
+
+static int unclean_exit_grace_period = 0;
+module_param_named(unclean_exit_grace_period, unclean_exit_grace_period, int, S_IRUGO | S_IWUSR | S_IWGRP);
+
+static DEFINE_MUTEX(ioctl_lock);
+static struct wake_lock unclean_exit_wake_lock;
+
+struct user_wake_lock {
+	struct wake_lock	wake_lock;
+	char			name[0];
+};
+
+static int create_user_wake_lock(struct file *file, void __user *name,
+				 size_t name_len)
+{
+	struct user_wake_lock *l;
+	if (file->private_data)
+		return -EBUSY;
+	l = kzalloc(sizeof(*l) + name_len + 1, GFP_KERNEL);
+	if (!l)
+		return -ENOMEM;
+	if (copy_from_user(l->name, name, name_len))
+		goto err_fault;
+	wake_lock_init(&l->wake_lock, WAKE_LOCK_SUSPEND, l->name);
+	file->private_data = l;
+	return 0;
+
+err_fault:
+	kfree(l);
+	return -EFAULT;
+}
+
+static long user_wakelock_ioctl(struct file *file, unsigned int cmd,
+				unsigned long _arg)
+{
+	void __user *arg = (void __user *)_arg;
+	struct user_wake_lock *l;
+	struct timespec ts;
+	unsigned long timeout;
+	long ret;
+
+	mutex_lock(&ioctl_lock);
+	if ((cmd & ~IOCSIZE_MASK) == WAKELOCK_IOCTL_INIT(0)) {
+		ret = create_user_wake_lock(file, arg, _IOC_SIZE(cmd));
+		goto done;
+	}
+	l = file->private_data;
+	if (!l) {
+		ret = -ENOENT;
+		goto done;
+	}
+	switch (cmd) {
+	case WAKELOCK_IOCTL_LOCK:
+		wake_lock(&l->wake_lock);
+		ret = 0;
+		break;
+	case WAKELOCK_IOCTL_LOCK_TIMEOUT:
+		if (copy_from_user(&ts, arg, sizeof(ts))) {
+			ret = -EFAULT;
+			goto done;
+		}
+		timeout  = timespec_to_jiffies(&ts);
+		wake_lock_timeout(&l->wake_lock, timeout);
+		ret = 0;
+		break;
+	case WAKELOCK_IOCTL_UNLOCK:
+		wake_unlock(&l->wake_lock);
+		ret = 0;
+		break;
+	default:
+		ret = -ENOTSUPP;
+	}
+done:
+	if (ret && debug_mask & DEBUG_FAILURE)
+		pr_err("user_wakelock_ioctl: cmd %x failed, %ld\n", cmd, ret);
+	mutex_unlock(&ioctl_lock);
+	return ret;
+}
+
+static int user_wakelock_release(struct inode *inode, struct file *file)
+{
+	struct user_wake_lock *l = file->private_data;
+	if (!l)
+		return 0;
+	if (wake_lock_active(&l->wake_lock) && unclean_exit_grace_period)
+		wake_lock_timeout(&unclean_exit_wake_lock,
+				  unclean_exit_grace_period * HZ);
+	wake_lock_destroy(&l->wake_lock);
+	kfree(l);
+	return 0;
+}
+
+const struct file_operations user_wakelock_fops = {
+	.release = user_wakelock_release,
+	.unlocked_ioctl = user_wakelock_ioctl,
+};
+
+struct miscdevice user_wakelock_device = {
+	.minor = MISC_DYNAMIC_MINOR,
+	.name = "wakelock",
+	.fops = &user_wakelock_fops,
+};
+
+static int __init user_wakelock_init(void)
+{
+	wake_lock_init(&unclean_exit_wake_lock, WAKE_LOCK_SUSPEND,
+		       "user-unclean-exit");
+	return misc_register(&user_wakelock_device);
+}
+
+static void __exit user_wakelock_exit(void)
+{
+	misc_deregister(&user_wakelock_device);
+	wake_lock_destroy(&unclean_exit_wake_lock);
+}
+
+module_init(user_wakelock_init);
+module_exit(user_wakelock_exit);
-- 
1.6.1

_______________________________________________
linux-pm mailing list
linux-pm@lists.linux-foundation.org
https://lists.linux-foundation.org/mailman/listinfo/linux-pm

  reply	other threads:[~2009-02-11  1:49 UTC|newest]

Thread overview: 34+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-02-11  1:49 [RFC][PATCH 00/11] Android PM extensions (version 3) Arve Hjønnevåg
2009-02-11  1:49 ` [PATCH 01/10] PM: Add wake lock api Arve Hjønnevåg
2009-02-11  1:49   ` [PATCH 02/10] PM: wakelock: Override wakelocks when not using /sys/power/request_state Arve Hjønnevåg
2009-02-11  1:49     ` Arve Hjønnevåg [this message]
2009-02-11  1:49       ` [PATCH 04/10] PM: wakelock: Abort task freezing if a wakelock is locked Arve Hjønnevåg
2009-02-11  1:49         ` [PATCH 05/10] PM: Add option to disable /sys/power/state interface Arve Hjønnevåg
2009-02-11  1:49           ` [PATCH 06/10] PM: Add early suspend api Arve Hjønnevåg
2009-02-11  1:49             ` [PATCH 07/10] PM: earlysuspend: Add console switch when user requested sleep state changes Arve Hjønnevåg
2009-02-11  1:49               ` [PATCH 08/10] PM: earlysuspend: Removing dependence on console Arve Hjønnevåg
2009-02-11  1:49                 ` [PATCH 09/10] Input: Hold wake lock while event queue is not empty Arve Hjønnevåg
2009-02-11  1:49                   ` [PATCH 10/10] ledtrig-sleep: Add led trigger for sleep debugging Arve Hjønnevåg
2009-02-12 11:31                   ` [PATCH 09/10] Input: Hold wake lock while event queue is not empty Matthew Garrett
2009-02-13  0:27                     ` Arve Hjønnevåg
2009-02-13  0:34                       ` Matthew Garrett
2009-02-13  0:38                         ` Arve Hjønnevåg
2009-02-13  0:40                           ` Matthew Garrett
2009-02-13  0:52                             ` Arve Hjønnevåg
2009-02-13  0:57                               ` Matthew Garrett
2009-02-13 23:06                                 ` Rafael J. Wysocki
2009-02-13 23:51                                 ` Arve Hjønnevåg
2009-02-14  0:09                                   ` Matthew Garrett
2009-02-14  0:13                                     ` Arve Hjønnevåg
2009-02-14  0:18                                       ` Matthew Garrett
2009-02-12 11:28               ` [PATCH 07/10] PM: earlysuspend: Add console switch when user requested sleep state changes Matthew Garrett
2009-02-12 11:34             ` [PATCH 06/10] PM: Add early suspend api Matthew Garrett
2009-02-12 22:00   ` [PATCH 01/10] PM: Add wake lock api mark gross
2009-02-12 23:06     ` Arve Hjønnevåg
2009-02-17 21:05 ` [RFC][PATCH 00/11] Android PM extensions (version 3) Pavel Machek
2009-02-19  1:43   ` Arve Hjønnevåg
2009-02-19 12:54     ` Rafael J. Wysocki
2009-02-22 13:48     ` Pavel Machek
2009-02-23 23:31       ` Arve Hjønnevåg
2009-02-23 23:54         ` Rafael J. Wysocki
2009-02-25 13:23         ` Pavel Machek

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1234316955-31304-4-git-send-email-arve@android.com \
    --to=arve@android.com \
    --cc=linux-pm@lists.linux-foundation.org \
    --cc=ncunningham@crca.org.au \
    --cc=swetland@google.com \
    --cc=u.luckas@road.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.