Linux sleep wake-up mechanism-kernel state

Source: Internet
Author: User
Tags linux sleep

1. Introduction to sleep (suspend)
In Linux, sleep mainly involves three steps:
1) Freeze user-State processes and kernel-state tasks
2) Call the suspend callback function of the registered device in the order of registration
3) sleep the core device and enable the CPU to sleep. The frozen process is the kernel that sets the state of all processes in the process list to stop and stores the context of all processes. when these processes are restored, they do not know that they have been frozen, but simply continue to execute.
How can we break Linux into sleep? You can read and write the Sys File/sys/power/State to enable the control system to sleep. For example
# Echo mem>/sys/power/State
The command system goes to sleep. You can also use

# Cat/sys/power/State
Which sleep modes are supported by the kernel.

Ii. Linux suspend Process
1. Related code

• Kernel/kernel/power/Main. c
• Kernel/ARCH/ARM/Mach-xxx/PM. c
• Kernel/driver/base/power/Main. c

Next, let's take a detailed look at how Linux sleeps/wakes up:
The user's read/write operations on/sys/power/State will call kernel/power/main. state_store () in C. You can write strings defined in const char * const pm_states [], such as "mem" and "standby ".

Const char * const pm_states [pm_suspend_max] = {
# Ifdef config_earlysuspend
[Pm_suspend_on] = "on ",
# Endif
[Pm_suspend_standby] = "standby ",
[Pm_suspend_mem] = "mem ",
};
Usually there are standby (suspend to ram), Mem (suspend to ram) and disk (suspend to disk), but standby consumes more power and returns to the normal working state for a shorter time.

Then state_store () will call enter_state () <Note: This is a classic Linux call process. In the Android system, kernel will call request_suspend_state instead of enter_state>. It will first check some status parameters, then synchronize the file system.
 

/** *enter_state - Do common work of entering low-power state. *@state:pm_state structure for state we're entering. * *Make sure we're the only ones trying to enter a sleep state. Fail *if someone has beat us to it, since we don't want anything weird to *happen when we wake up. *Then, do the setup for suspend, enter the state, and cleaup (after *we've woken up). */int enter_state(suspend_state_t state){int error;if (!valid_state(state))return -ENODEV;if (!mutex_trylock(&pm_mutex))return -EBUSY;#ifdef CONFIG_SUSPEND_SYNC_WORKQUEUEsuspend_sys_sync_queue();#elseprintk(KERN_INFO "PM: Syncing filesystems ... ");sys_sync();printk("done.\n");#endifpr_debug("PM: Preparing system for %s sleep\n", pm_states[state]);error = suspend_prepare();if (error)goto Unlock;if (suspend_test(TEST_FREEZER))goto Finish;pr_debug("PM: Entering %s sleep\n", pm_states[state]);pm_restrict_gfp_mask();error = suspend_devices_and_enter(state);pm_restore_gfp_mask(); Finish:pr_debug("PM: Finishing wakeup.\n");suspend_finish(); Unlock:mutex_unlock(&pm_mutex);return error;}

2. Prepare and freeze the process
After entering suspend_prepare (), it will allocate a virtual terminal for suspend to output information, broadcast a system to enter suspend's ipvy, and disable the user-mode helper process, then call suspend_freeze_processes () to freeze all processes. The current state of all processes will be saved here. Some processes may refuse to enter the frozen state. When such a process exists, this function will stop freezing processes and restore all the frozen processes.

 

/** *suspend_prepare - Do prep work before entering low-power state. * *This is common code that is called for each state that we're entering. *Run suspend notifiers, allocate a console and stop all processes. */static int suspend_prepare(void){int error;if (!suspend_ops || !suspend_ops->enter)return -EPERM;pm_prepare_console();error = pm_notifier_call_chain(PM_SUSPEND_PREPARE);if (error)goto Finish;error = usermodehelper_disable();if (error)goto Finish;error = suspend_freeze_processes();if (!error)return 0;suspend_thaw_processes();usermodehelper_enable(); Finish:pm_notifier_call_chain(PM_POST_SUSPEND);pm_restore_console();return error;}

3. Sleep the peripherals
Now, all processes (including workqueue/kthread) have stopped, and kernel-state characters may hold some semaphores when they are stopped, so if you unlock the semaphores In the peripherals at this time, there may be deadlocks, so you should be very careful when making the lock/unlock lock in the suspend () function of the peripherals, we recommend that you do not wait for the lock in suspend () during design. In addition, some logs cannot be output during suspend, so once a problem occurs, debugging is very difficult.

Then the kernel will try to release some memory here.

At last, we will call suspend_devices_and_enter () to sleep all peripherals. In this function, if the platform registers suspend_ops (usually defined and registered in the board-level definition, in kernel/ARCH/ARM/Mach-XX/PM. call suspend_set_ops in c). Here we will call suspend_ops-> begin (); then call dpm_suspend_start, And they will call the suspend () of the driver in turn ()
Callback to sleep all devices.

When all devices sleep, suspend_ops-> prepare () will be called. This function usually makes some preparations to let the machine sleep. In Linux, the non-startup CPU in the multi-core CPU will be turned off. The comment shows that it is to avoid these other CPUs from causing race condio. In the future, only one CPU is running.

Suspend_ops is an on-board power management operation, which is usually registered in the file ARCH/Mach-xxx/PM. C.

Next, suspend_enter () will be called. This function will disable arch IRQ and call device_power_down (). It will call the suspend_late () function, this function is the function that the system actually calls after sleep. It usually performs the final check in this function. If the check is correct, sleep all the system devices and buses and call suspend_pos-> enter () to enable CPU power-saving. Then, the CPU is sleep. Code execution stops here.

/*** Suspend_devices_and_enter-suspend devices and enter the desired system * sleep state. * @ State: State to enter */INT suspend_devices_and_enter (suspend_state_t state) {int error; If (! Suspend_ops) Return-enosys; trace_machine_suspend (State); // if the platform registers suspend_ops (usually defined and registered in the board-level definition, // In kernel/ARCH/ARM/Mach-XX/PM. call suspend_set_ops in C), // suspend_ops-> begin (); If (suspend_ops-> begin) {error = suspend_ops-> begin (State ); if (error) goto close;} suspend_console (); suspend_test_start (); // call the suspend () callback of the driver in sequence to sleep all devices. Error = failed (pmsg_suspend); If (error) {printk (kern_err "PM: Some devices failed to suspend \ n"); goto recover_platform;} suspend_test_finish ("suspend devices "); if (suspend_test (test_devices) goto recover_platform; // This function will disable arch IRQ and call device_power_down (). It will call the suspend_late () function, // This function is the function that the system actually calls after sleep. It usually performs the final check in this function. // If the check is correct, sleep all the system devices and buses and call suspend_pos-> enter () // to enable the CPU to enter the power-saving state. Then, the CPU is sleep. Code execution stops here. Error = suspend_enter (State); resume_devices: sums (); sums (pmsg_resume); suspend_test_finish ("resume devices"); resume_console (); close: If (suspend_ops-> end) suspend_ops-> end (); trace_machine_suspend (pwr_event_exit); Return Error; recover_platform: If (suspend_ops-> recover) suspend_ops-> recover (); goto resume_devices ;}

3. Linux resume process

If the system is interrupted or other events are awakened during sleep, the following code starts to run. The wake-up sequence is the opposite to that of sleep, therefore, the system device and bus will first wake up, enable system interruption, enable non-startup CPU to stop during sleep, and call suspend_ops-> finish (), and in suspend_devices_and_enter () the function will also wake up each device, enable the virtual terminal, and finally call suspend_ops-> end ().

In the return to the enter_state () function, when suspend_devices_and_enter () returns, the peripherals are awakened, but the processes and tasks are still frozen. suspend_finish () is called here () to unfreeze these processes and tasks, and send a running y to indicate that the system has exited from the suspend status and wakened the terminal.

By now, all sleep and wakeup are completed, and the system continues to run.

From: http://bbs.ednchina.com/BLOG_ARTICLE_1784575.HTM

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.