Evdev auto wakelock Introduction
This article introduces the event lock mechanism of kernel-2.6.25, and explores the Linux lock mechanism.
The kernel version is old. Compared with 2.6.32, it is found that the kernel has not changed in terms of the lock mechanism, but the implementation of the Mechanism has changed a lot.
1. evdev module initialization
module_init(evdev_init);
2. evdev Initialization
static int __init evdev_init(void){return input_register_handler(&evdev_handler);}
3. Define a callback method set
static struct input_handler evdev_handler = {.event= evdev_event,.connect= evdev_connect,.disconnect= evdev_disconnect,.fops= &evdev_fops,.minor= EVDEV_MINOR_BASE,.name= "evdev",.id_table= evdev_ids,};
4. Implementation Functions of the event Method
static void evdev_event(struct input_handle *handle,unsigned int type, unsigned int code, int value){//...rcu_read_lock();//...if (client)evdev_pass_event(client, &event);elselist_for_each_entry_rcu(client, &evdev->client_list, node)evdev_pass_event(client, &event);//...rcu_read_unlock();//...}
5. The processing of the event is locked! Obtain the evdev timeout lock. The timeout value is 5 * Hz. Hz depends on the CPU usage. The timeout value is 50 ms.
static void evdev_pass_event(struct evdev_client *client, struct input_event *event){//...#ifdef CONFIG_ANDROID_POWERandroid_lock_suspend_auto_expire(&client->suspend_lock, 5 * HZ); //50ms#endif//...}
6. Implement the method for opening the evdev node and initialize the lock named "evdev". The lock type is not declared here. It is declared as a timeout lock or a non-Timeout lock only when applying for a lock.
static int evdev_open(struct inode *inode, struct file *file){//...#ifdef CONFIG_ANDROID_POWERclient->suspend_lock.name = "evdev";android_init_suspend_lock(&client->suspend_lock);#endif//...}static int evdev_release(struct inode *inode, struct file *file){//...#ifdef CONFIG_ANDROID_POWERandroid_uninit_suspend_lock(&client->suspend_lock);#endif//...}
7. Apply for The Implementation of The timeout lock and add the lock to the active array. There are three types of arrays. here is one of them.
void android_lock_suspend_auto_expire(android_suspend_lock_t *lock, int timeout){unsigned long irqflags;spin_lock_irqsave(&g_list_lock, irqflags);#ifdef CONFIG_ANDROID_POWER_STATif(!(lock->flags & ANDROID_SUSPEND_LOCK_ACTIVE)) {lock->flags |= ANDROID_SUSPEND_LOCK_ACTIVE;lock->stat.last_time = ktime_get();}#endifif (android_power_debug_mask & ANDROID_POWER_DEBUG_WAKE_LOCK)printk(KERN_INFO "android_power: acquire wake lock: %s, ""timeout %d.%03lu\n", lock->name, timeout / HZ,(timeout % HZ) * MSEC_PER_SEC / HZ);lock->expires = jiffies + timeout;lock->flags |= ANDROID_SUSPEND_LOCK_AUTO_EXPIRE;list_del(&lock->link);list_add(&lock->link, &g_active_partial_wake_locks);g_current_event_num++;wake_up(&g_wait_queue);spin_unlock_irqrestore(&g_list_lock, irqflags);}