mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: "Rafael J. Wysocki" <rjw@sisk.pl>
To: John Stultz <john.stultz@linaro.org>
Cc: Linux PM list <linux-pm@vger.kernel.org>,
	mark gross <markgross@thegnar.org>,
	LKML <linux-kernel@vger.kernel.org>,
	Alan Stern <stern@rowland.harvard.edu>, NeilBrown <neilb@suse.de>
Subject: Re: [RFC][PATCH 2/2] PM / Sleep: Introduce cooperative suspend/hibernate mode
Date: Sat, 15 Oct 2011 00:49:39 +0200	[thread overview]
Message-ID: <201110150049.39219.rjw@sisk.pl> (raw)
In-Reply-To: <1318546686.3375.231.camel@work-vm>

Hi,

On Friday, October 14, 2011, John Stultz wrote:
> On Thu, 2011-10-13 at 21:50 +0200, Rafael J. Wysocki wrote:
> > From: Rafael J. Wysocki <rjw@sisk.pl>
> > 
> > The currently available mechanism allowing the suspend process to
> > avoid racing with wakeup events registered by the kernel appears
> > to be difficult to use.  Moreover, it requires that the suspend
> > process communicate with other user space processes that may take
> > part in the handling of wakeup events to make sure that they have
> > done their job before suspend is started.  Therefore all of the
> > wakeup-handling applications are expected to use an IPC mechanism
> > allowing them to exchange information with the suspend process, but
> > this expectation turns out to be unrealistic in practice.  For this
> > reason, it seems reasonable to add a mechanism allowing the
> > wakeup-handling processes to communicate with the suspend process
> > to the kernel.
> 
> Hey Rafael! 
> 
> I'm *very* excited to see some alternate approaches here, as I'll very
> much admit that my proposal does have some complexities. While I still
> prefer my approach, I'm pragmatic and would be happy with other
> solutions as long as they solve the issue.
> 
> I've not yet dug deeply into the code of your patch, but some conceptual
> thoughts and issues below.
> 
> > This change introduces a new sleep mode, called "cooperative" sleep
> > mode, which needs to be selected via the /sys/power/sleep_mode sysfs
> > attribute and causes detection of wakeup events to be always
> > enabled, among other things, and a mechanism allowing user space
> > processes to prevent the system from being put into a sleep state
> > while in this mode.
> > 
> > The mechanism introduced by this change is based on a new special
> > device file, /dev/sleepctl.  A process wanting to prevent the system
> > from being put into a sleep state is expected to open /dev/sleepctl
> > and execute the SLEEPCTL_STAY_AWAKE ioctl() with the help of it.
> > This will make all attempts to suspend or hibernate the system block
> > until (1) the process executes the SLEEPCTL_RELAX ioctl() or (2)
> > a predefined timeout expires.  The timeout is set to 500 ms by
> > default, but the process can change it by writing the new timeout
> > value (in milliseconds) to /dev/sleepctl, in binary (unsigned int)
> > format.
> 
> Just a nit, but is there any reason not to use u64 nanosecond value
> instead of the jiffies-like granularity and range? Maybe u64 ns is
> over-design, but milliseconds are getting a bit coarse these days.
> 
> >   The current timeout value can be read from /dev/sleepctl.
> > Setting the timeout to 0 disables it, i.e. it makes the
> > SLEEPCTL_STAY_AWAKE ioctl() block attempts to suspend or hibernate
> > the system until the SLEEPCTL_RELAX ioctl() is executed.
> > 
> > In addition to that, when system is resuming from suspend or
> > hibernation, the kernel automatically carries out an operation
> 
> Only when resuming from suspend/hibernation? Hrmm.. See below for my
> concerns about this specifically.
> 
> > equivalent to the SLEEPCTL_STAY_AWAKE ioctl() for all processes
> > that have /dev/sleepctl open at that time and whose timeouts are
> > greater than 0 (i.e. enabled), to allows those processes to
> > complete the handling of wakeup events before the system can be
> > put to a sleep state again.
> 
> So the application psudocode looks like the following?

Not really.

> Example 1:
> ----------
> sleepfd = open("/dev/sleepctl",...);
> devfd = open("/dev/wakeup-button",...);
> ...
> count = read(devfd, buf, bufsize);
> ioctl(sleepfd, SLEEP_STAY_AWAKE, 0); /* no timeout */

No, this doesn't work like this.  You'd need to do:

write(sleepfd, zero_buf, sizeof(unsigned int));
ioctl(sleepfd, SLEEP_STAY_AWAKE);

> do_stuff(buf,count);
> ioctl(sleepfd, SLEEP_RELAX);
> 
> 
> And the assumption is that when *any* wakeup event occurs, even if its
> not the /dev/wakeup-button, the system will stay awake on this
> application's behalf for 500ms (or the max value provided to sleepctl)
> 
> Then, the hope is that if the wakeup-button did wake the system up, the
> application would get woken up from the read() call and hopefully
> complete the STAY_AWAKE ioctl within the provided 500ms.
> 
> 
> A minor nit, first: With the code above, after we call SLEEP_RELAX, the
> timeout has been set to zero, so if we're the only one, the next wakeup
> will not actually inhibit suspend for any amount of time. It might be
> good to separate the ioctl used to set the timeout length, and the one
> to inhibit suspend.

It is separate.  The timeout is set by a write().

> 
> Now, my opinion: So, again, I'd welcome any solution to the problem, but
> I'm personally not a big fan of the timeout usage found in this
> proposal, as well as the Android wakelocks implementation. Its simply
> racy, and would break down under heavy load or when interacting with
> cpuhogging SCHED_FIFO tasks. Practically, it can be made to work, but I
> worry the extra safety-margins folks will add to the timeouts will
> result in inefficient power wasting.

That's the cost of simplicity.

> Now, an actual problem: Further, I'm worried this still doesn't address
> the main race in the alarmtimer triggered system backup case:
> 
> Example 2:
> ----------
> sleepfd = open("/dev/sleepctl",...);
> ...
> /* wait till 5pm */
> clock_nanosleep(CLOCK_REALTIME_ALARM, TIMER_ABSTIME, backup_ts); 
> ioctl(sleepfd, SLEEP_STAY_AWAKE, 0); /* no timeout */
> do_backup();
> ioctl(sleepfd, SLEEP_RELAX);
> 
> 
> Which is basically identical to the above. At 5pm the alarmtimer fires,
> and increments the wakeup_count. 
> 
> At the same time, maybe on a different cpu, the PM daemon reads the
> updated wakeup_count, writes it back and triggers suspend.

It doesn't really have to write it back, but that's a minor thing.

> All of this happens before my backup application gets scheduled and can
> call the ioctl.

So the solution for your backup application is to (1) open "/dev/sleepctl",
(2) set a suitable timeout (using write()), (3) call
ioctl(sleepfd, SLEEP_STAY_AWAKE) and go to sleep, (4) (when woken up)
open "/dev/sleepctl" again, set the timeout on sleepfd2 to 0 and call
ioctl(sleepfd2, SLEEP_STAY_AWAKE), (5) close sleepfd (the first instance),
(6) do whatever it wants and (7) call ioctl(sleepfd2, SLEEP_RELAX).

> I think in order to avoid this with your approach, I think you're going
> to need to have the kernel take the SLEEPCTL_STAY_AWAKE timeout for
> every open fd upon *any* wakeup event, even when the system is running
> and not just at resume.
> 
> The same bad behavior could also be tripped in example #1, with the
> wakeup button being pressed while the system was running, right as a
> suspend was triggered.
> 
> 
> I think this is in part an issue with the "globalness" of the
> wakeup_count value. We know an event happened, but we don't *which*
> event, or if anyone was waiting for that event, or if the event has been
> consumed. Thus with your approach, its necessary to use a timeout to try
> to cover everyone, since there's not enough knowledge. 
> 
> Basically it breaks down to three questions I think we have to answer:
> 1) What event is being waited on?
> 2) Who is waiting?
> 3) Has the event been consumed?

Which only is relevant if we want to have a very fine grained resolution
of things.  I'm not really sure that very fine grained resolution is
achievable at all anyway, though.

> To summarize my understanding of other recently proposed approaches to
> this core issue:
> 
> Again, in your proposal (if adjusted as I suggest to avoid the backup
> race) tasks register their wakeup-interest (#2), by opening the sleepctl
> file, and then you inhibit suspend for the maximum specified timeout on
> every wakeup event (#1) assuming that gives enough time for whichever
> task was waiting on the triggered event to consume it (#3).

To be precise, the maximum specified timeout is only used for the events
that either aborted suspend in progress, or actually woke up the system.

> Neil's userspace approach (as best as I understand it) tries to resolve
> this knowledge issue by requiring *everyone* who might be waiting to
> consume wakeup events check-in with the PM daemon prior to *any* suspend
> (If the PM daemon is aggressive, trying to suspend frequently, this
> results in requiring every consumer to check in on every wakeup event).
> So in this model, we get a list of waiters (#2) communicating with the
> PM daemon, and for any event (#1), we require all waiters to ack (#3)
> that its ok to suspend.
> 
> Mark's approach uses per-wakeup-device files in order to inform the
> kernel about interest, allowing the kernel to inhibit suspend when a
> wakeup event occurs on that device for each open fd (#1 & #2). Then it
> requires each consumer to "ack" the events consumption (#3) back to the
> fd, where the suspend inhibition is dropped. 
> 
> My approach is using a per-task flag of power-importance(#2), which
> inhibits suspend if any task has such a flag. Any blocking call upon a
> wakeup device (#1) will drop the flag, allowing suspend to occur, and
> the kernel re-raises the flag when the task is woken up, which the task
> can drop when its done (#3). 
> 
> Finally, Android's wakelock's are actually very conceptually similar to
> Mark's, but utilize existing device files (#1&#2) (so its a little more
> implicit) and uses read()  as the "ack" (#3) to allow the kernel to drop
> the wakelock.

I don't think it works this way.  The Android's interface for using wakelocks
from user space is just that a user space process can create and use a
wakelock with the help of a special device file or something like this,
IIRC.

> Does that seem reasonably accurate/fair?

It would be fair if you said that your approach and the Android's one had been
frowned upon by the scheduler people, so I don't think we can realistically
regard them as doable. :-)

Thanks,
Rafael

  reply	other threads:[~2011-10-14 22:47 UTC|newest]

Thread overview: 80+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-10-13 19:45 [RFC][PATCH 0/2] PM / Sleep: Extended control of suspend/hibernate interfaces Rafael J. Wysocki
2011-10-13 19:49 ` [RFC][PATCH 1/2] PM / Sleep: Add mechanism to disable suspend and hibernation Rafael J. Wysocki
2011-10-13 19:50 ` [RFC][PATCH 2/2] PM / Sleep: Introduce cooperative suspend/hibernate mode Rafael J. Wysocki
2011-10-13 22:58   ` John Stultz
2011-10-14 22:49     ` Rafael J. Wysocki [this message]
2011-10-15  0:04       ` John Stultz
2011-10-15 21:29         ` Rafael J. Wysocki
2011-10-17 16:48           ` John Stultz
2011-10-17 18:19             ` Alan Stern
2011-10-17 19:08               ` John Stultz
2011-10-17 20:07                 ` Alan Stern
2011-10-17 20:34                   ` John Stultz
2011-10-17 20:38                 ` Rafael J. Wysocki
2011-10-17 21:20                   ` John Stultz
2011-10-17 21:19                 ` NeilBrown
2011-10-17 21:43                   ` John Stultz
2011-10-17 23:06                     ` NeilBrown
2011-10-17 23:14                     ` NeilBrown
2011-10-17 21:13             ` Rafael J. Wysocki
2011-10-14  5:52 ` [RFC][PATCH 0/2] PM / Sleep: Extended control of suspend/hibernate interfaces NeilBrown
2011-10-14 16:00   ` Alan Stern
2011-10-14 21:07     ` NeilBrown
2011-10-15 18:34       ` Alan Stern
2011-10-15 21:43         ` NeilBrown
2011-10-15 22:10   ` Rafael J. Wysocki
2011-10-16  2:49     ` Alan Stern
2011-10-16 14:51       ` Alan Stern
2011-10-16 20:32         ` Rafael J. Wysocki
2011-10-17 15:33           ` Alan Stern
2011-10-17 21:10             ` Rafael J. Wysocki
2011-10-17 21:27             ` Rafael J. Wysocki
2011-10-18 17:30               ` Alan Stern
2011-10-16 22:34         ` NeilBrown
2011-10-17 14:45           ` Alan Stern
2011-10-17 22:49             ` NeilBrown
2011-10-17 23:47               ` John Stultz
2011-10-18  2:13                 ` NeilBrown
2011-10-18 17:11                   ` Alan Stern
2011-10-18 22:55                     ` NeilBrown
2011-10-19 16:19                       ` Alan Stern
2011-10-20  0:17                         ` NeilBrown
2011-10-20 14:29                           ` Alan Stern
2011-10-21  5:05                             ` NeilBrown
2011-10-21  5:23                             ` lsusd - The Linux SUSpend Daemon NeilBrown
2011-10-21 16:07                               ` Alan Stern
2011-10-21 22:34                                 ` NeilBrown
2011-10-22  2:00                                   ` Alan Stern
2011-10-22 16:31                                     ` Alan Stern
2011-10-23  3:31                                       ` NeilBrown
2011-10-23  8:21                                     ` NeilBrown
2011-10-23 12:48                                       ` Rafael J. Wysocki
2011-10-23 23:04                                         ` NeilBrown
2011-10-23 16:17                                       ` Alan Stern
2011-10-21 20:10                               ` david
2011-10-21 22:09                                 ` NeilBrown
2011-10-26 14:31                               ` Jan Engelhardt
2011-10-27  4:34                                 ` NeilBrown
2011-10-31 15:11           ` [RFC][PATCH 0/2] PM / Sleep: Extended control of suspend/hibernate interfaces Richard Hughes
2011-10-16 20:26       ` Rafael J. Wysocki
2011-10-16 23:48     ` NeilBrown
2011-10-17 15:43       ` Alan Stern
2011-10-17 22:02       ` Rafael J. Wysocki
2011-10-17 23:36         ` NeilBrown
2011-10-22 22:07           ` Rafael J. Wysocki
2011-10-23  2:57             ` NeilBrown
2011-10-23 13:16               ` Rafael J. Wysocki
2011-10-23 23:44                 ` NeilBrown
2011-10-24 10:23                   ` Rafael J. Wysocki
2011-10-25  2:52                     ` NeilBrown
2011-10-25  7:47                       ` Valdis.Kletnieks
2011-10-25  8:35                         ` Rafael J. Wysocki
2011-10-23 15:50             ` Alan Stern
2011-10-27 21:06               ` Rafael J. Wysocki
2011-10-28  0:02               ` NeilBrown
2011-10-28  8:27                 ` Rafael J. Wysocki
2011-10-28 15:08                   ` Alan Stern
2011-10-28 17:26                     ` Rafael J. Wysocki
2011-10-31 19:55 ` Ming Lei
2011-10-31 21:15   ` NeilBrown
2011-10-31 21:23     ` Ming Lei

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=201110150049.39219.rjw@sisk.pl \
    --to=rjw@sisk.pl \
    --cc=john.stultz@linaro.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-pm@vger.kernel.org \
    --cc=markgross@thegnar.org \
    --cc=neilb@suse.de \
    --cc=stern@rowland.harvard.edu \
    /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

all inboxes | Powered by JetHome®