lk中的event siganl

本文详细解析了fastboot_init函数中USB gadget的注册过程。重点介绍了fastboot_gadget的配置及fastboot_notify函数如何通过event_signal通知USB在线事件。同时,深入探讨了event_signal和wait_queue_wake_one函数的工作原理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >



在fastboot_init 函数中会注册一个usb的gadget
int fastboot_init(void *base, unsigned size)
{


if (udc_register_gadget(&fastboot_gadget))
goto fail_udc_register;
}
我们来看看fastboot_gadget的实现
static void fastboot_notify(struct udc_gadget *gadget, unsigned event)
{
if (event == UDC_EVENT_ONLINE) {
event_signal(&usb_online, 0);
}
}


static struct udc_endpoint *fastboot_endpoints[2];


static struct udc_gadget fastboot_gadget = {
.notify = fastboot_notify,
.ifc_class = 0xff,
.ifc_subclass = 0x42,
.ifc_protocol = 0x03,
.ifc_endpoints = 2,
.ifc_string = "fastboot",
.ept = fastboot_endpoints,
};


注意到原来是在fastboot_notify函数中调用event_signal来siganl这个usb_online的event事件啊
status_t event_signal(event_t *e, bool reschedule)
{
enter_critical_section();


if (!e->signalled) {
if (e->flags & EVENT_FLAG_AUTOUNSIGNAL) {
/* try to release one thread and leave unsignalled if successful */
if (wait_queue_wake_one(&e->wait, reschedule, NO_ERROR) <= 0) {
/*
* if we didn't actually find a thread to wake up, go to
* signalled state and let the next call to event_wait
* unsignal the event.
*/
e->signalled = true;
}
} else {
/* release all threads and remain signalled */
e->signalled = true;
wait_queue_wake_all(&e->wait, reschedule, NO_ERROR);
}
}


exit_critical_section();


return NO_ERROR;
}
如果e->signalled==true说明这个event已经siganl过了,就什么事情也不做


我们在fastboot_init中初始化usb_online这个event的时候有设置EVENT_FLAG_AUTOUNSIGNAL。
event_init(&usb_online, 0, EVENT_FLAG_AUTOUNSIGNAL);


所以我们在event_signal中
if (e->flags & EVENT_FLAG_AUTOUNSIGNAL) 条件成立
会调用wait_queue_wake_one 来wake正在等待usb_online这个event的thread
我们继续来看wait_queue_wake_one的实现
int wait_queue_wake_one(wait_queue_t *wait, bool reschedule, status_t wait_queue_error)
{
thread_t *t;
int ret = 0;


t = list_remove_head_type(&wait->list, thread_t, queue_node);
if (t) {
wait->count--;


t->state = THREAD_READY;
t->wait_queue_block_ret = wait_queue_error;
t->blocking_wait_queue = NULL;


if (reschedule) {
current_thread->state = THREAD_READY;
insert_in_run_queue_head(current_thread);
}
insert_in_run_queue_head(t);
if (reschedule)
thread_resched();
ret = 1;
}


return ret;
}
在wait_queue_wake_one中首先从wait list中找到一个thread,然后将thread的状态设置为
THREAD_READY,最后调用insert_in_run_queue_head 将这个thread 放到run_queue的前面,这个下次调度是这个thread就会被运行。
需要注意的是event_signal(&usb_online, 0);的第二个参数是0说明signal发出后等下一次调度才运行这个从wait list上取下来的thread。
如果设为1,在wait_queue_wake_one 中(reschedule) == 1则当前也就是发送event的thread的状态设定为THREAD_READY,将其插入到run_queue中,然后又将wait这个event的thread加到run_queue中,这个当前thread就处于run_queue的第二位,然后调用thread_resched来调度,这样等待这个signal的thread就直接运行了,不用等下一次调度.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值