The standby mechanism of Android 4.0 is similar to that of the previous version. It can be said that the mechanism is relatively complete and there is not much feedback. However, there is a detailed point, and the change scope is large. Let's take a look.
In the linux standby mechanism, the sys_sync function is called when the standby mode starts. The sys_sync system call is called by the user space function,
This interface is used to write data in the cache to block devices. sys_sync calls the system to write buffer, inode, and super data in the cache to the device.
For more information about this function, see http://www.bkjia.com/ OS /201204/126687.html.
The length of sys_sync function execution varies depending on the file system. The length ranges from hundreds of milliseconds to several milliseconds. What is the necessity of function execution?
If there is a need, it takes a short period of time (within milliseconds) to go in and out of the standby mode. Does the sys_sync function need to be executed every time?
If it is executed for the first time, what are the risks?
Because the standby request has timed out automatically and the button enters the standby mode, it is not a problem to automatically enter the standby mode. Basically, it is an alarm or timing event,
Different buttons go to the standby mode, and the key time goes through the kernel to the android upper layer, involving node processing and file system operations,
So there is a need to synchronize the node data sys_sync. It can be seen that android4.0 is modifying the call to sys_sync, which also takes into account the hidden problem of pressing the key to enter the standby mode.
So what changes have you made?
Suspend_sys_sync_queue is called in three places
Earlysuspend. c
(Kernel \ power)
Suspend. c
(Kernel \ power ):
Wakelock. c
(Kernel \ power ):
It is defined in Wakelock. c
(Kernel \ power)
This function implements suspend_sys_sync_work in the execution queue.
[Csharp]
Void suspend_sys_sync_queue (void)
{
Int ret;
Spin_lock (& suspend_sys_sync_lock );
Ret = queue_work (suspend_sys_sync_work_queue, & suspend_sys_sync_work );
If (ret)
Suspend_sys_sync_count ++;
Spin_unlock (& suspend_sys_sync_lock );
}
[Csharp]
Suspend_sys_sync_work_queue =
Create_singlethread_workqueue ("suspend_sys_sync ");
[Csharp]
Static void suspend_sys_sync (struct work_struct * work)
{
If (debug_mask & DEBUG_SUSPEND)
Pr_info ("PM: Syncing filesystems... \ n ");
Sys_sync ();
If (debug_mask & DEBUG_SUSPEND)
Pr_info ("sync done. \ n ");
Spin_lock (& suspend_sys_sync_lock );
Suspend_sys_sync_count --;
Spin_unlock (& suspend_sys_sync_lock );
}
Static DECLARE_WORK (suspend_sys_sync_work, suspend_sys_sync );
Therefore, when we call suspend_sys_sync_queue, we call sys_sync to increase the number of sys_sync executions, and the queue mode is not executed immediately.
Queue-based execution requires the execution time. How long does it need to wait? What wait is relative?
Standby: for the system, it is frozen. When you exit the standby mode, nothing happens to the system.
Standard linux standby will freeze all processes and tasks at the beginning of the standby mode and resume them when they are awakened.
Due to the complexity of processing processes in the kernel space, linux does not support running processes in the kernel space when Freezing Processes and tasks. Otherwise, it is abort processing.
The problem arises, and the last time the button enters the standby mode, key time collection, key value reporting, Round Robin of the reported value on the upper layer, distribution of key events, processing of key time, etc,
It takes some time. If the process fails to return to the user space quickly, when freeze_processes
[Csharp]
Printk ("Freezing user space processes ...");
Error = try_to_freeze_tasks (true );
If (error)
Goto Exit;
Printk ("done. \ n ");
In freezing user space processes, it will be abort.
Note: The last button is not all used here. We know that in order to increase the user experience, android will start a 5-second scheduled alarm when the timeout enters the standby mode,
In this way, the real standby mode is prevented within five seconds. In terms of user experience, the screen is hidden within five seconds. As long as the user lights up the screen in time, the system does not actually stand by and there will be no screen lock screen.
In this process, the developer will see freezing
User space processes abort, because the system starts alarm, so as to launch the standby mode and recover the system.
A timer is added to wait for sys_sync to be executed.
[Csharp]
Error = suspend_sys_sync_wait ();
If (error)
Goto Exit;
[Csharp]
Int suspend_sys_sync_wait (void)
{
Suspend_sys_sync_abort = false;
If (suspend_sys_sync_count! = 0 ){
Mod_timer (& suspend_sys_sync_timer, jiffies +
SUSPEND_SYS_SYNC_TIMEOUT );
Wait_for_completion (& suspend_sys_sync_comp );
}
If (suspend_sys_sync_abort ){
Pr_info ("suspend aborted... while waiting for sys_sync \ n ");
Return-EAGAIN;
}
Return 0;
}
[Csharp]
Static bool suspend_sys_sync_abort;
Static void suspend_sys_sync_handler (unsigned long );
Static DEFINE_TIMER (suspend_sys_sync_timer, suspend_sys_sync_handler, 0, 0 );
/* Value shoshould be less then half of input event wake lock timeout value
* Which is currently set to 5 * HZ (see drivers/input/evdev. c)
*/
# Define SUSPEND_SYS_SYNC_TIMEOUT (HZ/4)
Static void suspend_sys_sync_handler (unsigned long arg)
{
If (suspend_sys_sync_count = 0 ){
Complete (& suspend_sys_sync_comp );
} Else if (has_wake_lock (WAKE_LOCK_SUSPEND )){
Suspend_sys_sync_abort = true;
Complete (& suspend_sys_sync_comp );
} Else {
Mod_timer (& suspend_sys_sync_timer, jiffies +
SUSPEND_SYS_SYNC_TIMEOUT );
}
}
Wait time shocould be less then half of input event wake lock timeout value,
The evdev event times out for 50 ms. Here, the timeout value must be less than 25 ms. Here, it is set to 2.5 ms.
The timeout requirement should be to execute the timer handler faster after evdev times out.
The above code can be traced to the macro definition of CONFIG_SUSPEND_SYNC_WORKQUEUE.
From J. A. Y's column