Android内核wake_up源码分析
更新时间:2023-10-12什么是Android内核wake_up机制?
Android系统中的wake_up机制是一种用于充当触发器的进程间通信机制,用于唤醒正在等待某个特定事件的线程。它是通过函数调用wake_up()来实现的。
/* * Wake up threads blocked in this waitqueue_head_t. * * @arg: wait_queue_head_t *q * @arg: unsigned int mode * @arg: int nr_exclusive * @arg: void *key * * This function wakes up all threads that are waiting on the waitqueue_head_t * pointed to by @q. The @mode argument is one of the @WakeFlags values defined * above and determines whether the threads to be woken should be exclusive * or not. Wakeups occur in the order in which the threads blocked * */ void wake_up(wait_queue_head_t *q, unsigned int mode, int nr_exclusive, void *key)
上述代码是源自于内核的wake_up()函数,它带有四个参数分别指定唤醒队列、唤醒类型、独占线程数和附加键。这个函数将唤醒所有等待在指定wait_queue_head_t队列中的线程,唤醒顺序是按照线程阻塞时间的顺序来进行的。唤醒类型分为独占和共享两种,独占模式用于只唤醒一个线程的场景,共享模式则用于唤醒所有线程。
wake_up机制在Linux内核中的应用
wake_up点位于Linux内核中的多处位置,这些位置需要唤醒Linux内核等待事件的进程或线程,例如:任务调度机制、文件系统、设备驱动程序和网络协议栈等等地方都需要与wake_up机制进行交互。
/* * amdgpu_job_timedout - Unconditionally release a job on timeout * * @job: The job that has timed out. * * This function unconditionally releases a job that has timed out. This means * that all gc activities for the job are done and that the gpu can ignore the * job status. */ static void amdgpu_job_timedout(struct amdgpu_job *job) { struct amdgpu_device *adev = job->adev; spin_lock(&adev->jobs_lock); if (job->ring->sched.timeout == job) { job->ring->sched.timeout = NULL; wake_up(&adev->sched_jobs, AMDGPU_SCHED_PRIORITY_NORMAL, NULL, NULL); } spin_unlock(&adev->jobs_lock); DRM_INFO("Unrecoverable stuck job: %d %s %s\n", job->pid, job->name, radeon_job_priority_name(job->priority)); job->hang = true; amdgpu_job_abort(adev, job); }
上述实现中void amdgpu_job_timedout(struct amdgpu_job *job)函数利用wake_up机制退出一个被超时的任务。它的作用是将当前GPU上的超时job置空并将调度器作业唤醒,这个唤醒操作是在一个并发链表上完成的。
wake_up机制在Android中的应用
在Android系统中,wake_up机制有多个应用场景,例如:唤醒ADB服务、在文件系统中唤醒异步操作、唤醒I/O操作、唤醒网络设备、唤醒多媒体设备等等,下面是唤醒ADB服务的示例代码:
/* * android_usb_power_control_enable. * @entry : Kernel power symbol entry used to fetch the kobject for this device. * @control_name : The name of the android adb subsystem's "power" control. * * This function is to enable wakeup events on the usb device for adb. * This function is typically called after the USB cable is plugged-in. * * Returns a negative errno value on error. */ static int android_usb_power_control_enable(struct kernel_symbol_entry *entry, char *control_name) { struct kobject *kobj = container_of((void *)entry, struct kobject, entry); struct device *dev = container_of(kobj, struct device, kobj); struct usb_device *usbdev = dev_get_drvdata(dev); if (usbdev == NULL) return -ENODEV; /* Allow wakeups to be signaled on this usb device. */ usb_enable_autosuspend(usbdev); usb_autopm_put_interface_no_suspend(usbdev->actconfig->interface[0]); usb_autopm_put_interface_async(usbdev->actconfig->interface[0]); /* Finally, enable autosuspend related processing. */ pm_wakeup_event(&usbdev->dev, PM_EVENT_AUTO_SUSPEND, 0, &android_usb_pm_callback); return 0; }
上述代码实现了android_usb_power_control_enable()函数,它是用于唤醒ADB服务的,它通过调用pm_wakeup_event()函数来唤醒Android系统的USB设备,这意味着当在USB端口上插入设备时,ADB服务将被唤醒并开始在设备上进行调试。这里,唤醒事件类型是PM_EVENT_AUTO_SUSPEND。
总结
在Android系统中,wake_up机制可以帮助唤醒等待特定事件的进程或线程。此机制通过调用wake_up()函数实现,该函数将向指定的wait_queue_head_t队列中的所有线程发送唤醒信号。wake_up点位于Linux内核中的许多位置处,例如:任务调度、文件系统、设备驱动程序和网络协议栈等。此外,在Android系统中,wake_up机制还有其他的应用场景,例如:唤醒ADB服务、文件系统异步操作、唤醒I/O操作、唤醒网络设备、唤醒多媒体设备等。作为Android开发者,熟练掌握wake_up机制,可以更好地掌握系统的I/O、内核、驱动程序和网络等方面的开发。