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