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, ×pec_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
next prev parent 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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox