简体   繁体   中英

How to know if system has just woken up from a mem sleep?

I have a Qt application that runs on Linux.

The user can switch the system to mem sleep using this application.

Switching to mem sleep is trivial, but catching the wake up event in user space isn't.

My current solution is to use a infinite loop to trap the mem sleep, so that when the system wakes up, my application always continues from a predictable point.

Here is my code:

void MainWindow::memSleep()
{   
    int fd;
    fd = ::open("/sys/power/state", O_RDWR);// see update 1)
    QTime start=QTime::currentTime();
    write(fd,"mem",3); // command that triggers mem sleep
    while(1){
        usleep(5000);  // delay 5ms
        const QTime &end=QTime::currentTime();// check system clock
        if(start.msecsTo(end)>5*2){// if time gap is more than 10ms
            break;         // it means this thread was frozen for more
        }                  // than 5ms, indicating a wake up after a sleep
        start=end;
    }
    :: close(fd);          // the end of this function marks a wake up event
}

I described this method as a comment on this question , and it was pointed out that it's not a good solution, which I agree.

Question: Is there a C API that I can use to catch the wake up event?

Update:

1) what is mem sleep?

https://www.kernel.org/doc/Documentation/power/states.txt

The kernel supports up to four system sleep states generically, although three of them depend on the platform support code to implement the low-level details for each state.

The states are represented by strings that can be read or written to the /sys/power/state file. Those strings may be "mem" , "standby", "freeze" and "disk", where the last one always represents hibernation (Suspend-To-Disk) and the meaning of the remaining ones depends on the relative_sleep_states command line argument.

2) why do I want to catch the wake up event?

Because some hardware need to be reset after a wake up. A hardware input device generates erroneous input events after system wakes up, so it has to be disabled before sleep(easy) and enable after wake up(this question).

This should/could be handled by the driver in the kernel, which I have access to, or fixed in hardware, which my team can do but does not have the time to do it.(why I, a app developer, need to fix it in user space)

3) constraints

This is embedded linux, kernel 2.6.37, arch:arm, march:omap2, distro:arago . It's not as convenient as PC distros to add packages, not does it have ACPI. And mem sleep support in kernel 2.6.37 isn't mature at all.

Linux device drivers for PCI devices can optionally handle suspend and resume which, presumably, the kernel calls, respectively, just before the system is suspended, and just after resuming from a suspend. The PCI entrypoints are in struct pci_driver .

You could write and install a trivial device driver which does nothing more than sense resume operations and provides an indication to any interested processes. The simplest might be to support a file read() which returns a single byte whenever a resume is sensed. The program only need open the device and leave a thread stuck reading a single character. Whenever the read succeeds, the system just resumed.


More to the point, if the devices your application is handling have device drivers, the drivers should be updated to react appropriately to a resume .

Check pm-utils which you can place a hook at /etc/pm/sleep.d In the hook you can deliver signal to your application, eg by kill or any IPC.

You can also let pm-utils to do the computer suspend, which IMO is far more compatible with different configurations.

EDIT:

I'm not familiar with arago but pm-utils comes with arch and ubuntu. Also note that, on newer system that uses systemd , pm-utils is obsoleted and you should instead put hooks on systemd .

REF: systemd power events

When the system wakes from sleep, it should generate an ACPI event, so acpid should let you detect and handle that: via an /etc/acpi/events script, by connecting to /var/run/acpid.socket , or by using acpi_listen . ( acpi_listen should be an easy way to test if this will work.)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM