1 /*
2  * Copyright (C) 2018-2022 Intel Corporation.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 #include <asm/cpu.h>
7 #include <schedule.h>
8 #include <event.h>
9 #include <logmsg.h>
10 
init_event(struct sched_event * event)11 void init_event(struct sched_event *event)
12 {
13 	spinlock_init(&event->lock);
14 	event->set = false;
15 	event->waiting_thread = NULL;
16 }
17 
reset_event(struct sched_event * event)18 void reset_event(struct sched_event *event)
19 {
20 	uint64_t rflag;
21 
22 	spinlock_irqsave_obtain(&event->lock, &rflag);
23 	event->set = false;
24 	event->waiting_thread = NULL;
25 	spinlock_irqrestore_release(&event->lock, rflag);
26 }
27 
28 /* support exclusive waiting only
29  *
30  * During wait, the pCPU could be scheduled to run the idle thread when run queue
31  * is empty. Signal_event() can happen when schedule() is in process.
32  * This signal_event is not going to be lost, for the idle thread will always
33  * check need_reschedule() after it is switched to at schedule().
34  */
wait_event(struct sched_event * event)35 void wait_event(struct sched_event *event)
36 {
37 	uint64_t rflag;
38 
39 	spinlock_irqsave_obtain(&event->lock, &rflag);
40 	ASSERT((event->waiting_thread == NULL), "only support exclusive waiting");
41 	event->waiting_thread = sched_get_current(get_pcpu_id());
42 	while (!event->set && (event->waiting_thread != NULL)) {
43 		sleep_thread(event->waiting_thread);
44 		spinlock_irqrestore_release(&event->lock, rflag);
45 		schedule();
46 		spinlock_irqsave_obtain(&event->lock, &rflag);
47 	}
48 	event->set = false;
49 	event->waiting_thread = NULL;
50 	spinlock_irqrestore_release(&event->lock, rflag);
51 }
52 
signal_event(struct sched_event * event)53 void signal_event(struct sched_event *event)
54 {
55 	uint64_t rflag;
56 
57 	spinlock_irqsave_obtain(&event->lock, &rflag);
58 	event->set = true;
59 	if (event->waiting_thread != NULL) {
60 		wake_thread(event->waiting_thread);
61 	}
62 	spinlock_irqrestore_release(&event->lock, rflag);
63 }
64