c语言编程笔录

首页 >   > 笔记大全

笔记大全

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、内核、驱动程序和网络等方面的开发。