Evdev auto wakelock 介绍
介绍kernel-2.6.25 关于event 加锁的机制,从中窥探linux的锁机制。
kernel版本比较旧,对比2.6.32发现kernel在锁机制方面基本没变,但是在机制的实现上有很大的变化。
1.evdev模块初始化
module_init(evdev_init);
2.evdev初始化
static int __init evdev_init(void) { return input_register_handler(&evdev_handler); }
3.回调方法集定义
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.event方法的实现函数
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); else list_for_each_entry_rcu(client, &evdev->client_list, node) evdev_pass_event(client, &event); //... rcu_read_unlock(); //... }
5.event发生时的处理,加锁了!获取evdev的超时锁,超时时间是5*HZ,HZ根据不同CPU而定,这里是50ms
static void evdev_pass_event(struct evdev_client *client, struct input_event *event) { //... #ifdef CONFIG_ANDROID_POWER android_lock_suspend_auto_expire(&client->suspend_lock, 5 * HZ); //50ms #endif //... }
6.evdev节点打开方法的实现,初始化名为“evdev”的锁,锁的类型不在这里声明,在申请锁的时候才声明是超时锁还是非超时锁
static int evdev_open(struct inode *inode, struct file *file) { //... #ifdef CONFIG_ANDROID_POWER client->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_POWER android_uninit_suspend_lock(&client->suspend_lock); #endif //... }
7.申请超时锁的实现,把锁加入活跃数组。共有三种数组,这里是之一。
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_STAT if(!(lock->flags & ANDROID_SUSPEND_LOCK_ACTIVE)) { lock->flags |= ANDROID_SUSPEND_LOCK_ACTIVE; lock->stat.last_time = ktime_get(); } #endif if (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); }