Remove the option to spawn_thread for an evq (XCC)
[akaros.git] / user / parlib / thread0_sched.c
1 /* Copyright (c) 2015 Google, Inc.
2  * Barret Rhoden <brho@cs.berkeley.edu>
3  * See LICENSE for details.
4  *
5  * thread0_sched: a basic scheduler for thread0, used by SCPs without a
6  * multithreaded 2LS linked in.
7  *
8  * This is closely coupled with uthread.c */
9
10 #include <ros/arch/membar.h>
11 #include <parlib/arch/atomic.h>
12 #include <parlib/parlib.h>
13 #include <parlib/vcore.h>
14 #include <parlib/uthread.h>
15 #include <parlib/event.h>
16 #include <stdlib.h>
17
18 static void thread0_sched_entry(void);
19 static void thread0_thread_blockon_sysc(struct uthread *uthread, void *sysc);
20 static void thread0_thread_refl_fault(struct uthread *uthread,
21                                       unsigned int trap_nr, unsigned int err,
22                                       unsigned long aux);
23 static void thread0_thread_runnable(struct uthread *uth);
24 static void thread0_thread_has_blocked(struct uthread *uth, int flags);
25
26 /* externed into uthread.c */
27 struct schedule_ops thread0_2ls_ops = {
28         .sched_entry = thread0_sched_entry,
29         .thread_blockon_sysc = thread0_thread_blockon_sysc,
30         .thread_refl_fault = thread0_thread_refl_fault,
31         .thread_runnable = thread0_thread_runnable,
32         .thread_has_blocked = thread0_thread_has_blocked,
33 };
34
35 /* externed into uthread.c */
36 struct uthread *thread0_uth;
37
38 /* Our thread0 is actually allocated in uthread as just a struct uthread, so we
39  * don't actually attach this mgmt info to it.  But since we just have one
40  * thread, it doesn't matter. */
41 struct thread0_info {
42         bool                                            is_blocked;
43 };
44 static struct thread0_info thread0_info;
45 static struct event_queue *sysc_evq;
46
47 static void thread0_handle_syscall(struct event_msg *ev_msg,
48                                    unsigned int ev_type, void *data)
49 {
50         thread0_info.is_blocked = FALSE;
51 }
52
53 void thread0_lib_init(void)
54 {
55         memset(&thread0_info, 0, sizeof(thread0_info));
56         sysc_evq = get_big_event_q();
57         sysc_evq->ev_flags = EVENT_INDIR | EVENT_WAKEUP;
58         register_ev_handler(EV_SYSCALL, thread0_handle_syscall, 0);
59 }
60
61 /* Thread0 scheduler ops (for processes that haven't linked in a full 2LS) */
62 static void thread0_sched_entry(void)
63 {
64         /* TODO: support signal handling whenever we run a uthread */
65         if (current_uthread) {
66                 run_current_uthread();
67                 assert(0);
68         }
69         while (1) {
70                 if (!thread0_info.is_blocked) {
71                         run_uthread(thread0_uth);
72                         assert(0);
73                 }
74                 sys_yield(FALSE);
75                 handle_events(0);
76         }
77 }
78
79 static void thread0_thread_blockon_sysc(struct uthread *uthread, void *arg)
80 {
81         struct syscall *sysc = (struct syscall*)arg;
82         thread0_thread_has_blocked(uthread, 0);
83         if (!register_evq(sysc, sysc_evq))
84                 thread0_thread_runnable(uthread);
85 }
86
87 static void thread0_thread_refl_fault(struct uthread *uthread,
88                                       unsigned int trap_nr, unsigned int err,
89                                       unsigned long aux)
90 {
91         printf("SCP has unhandled fault: %d, err: %d, aux: %p\n", trap_nr, err,
92                aux);
93         print_user_context(&uthread->u_ctx);
94         printf("Turn on printx to spew unhandled, malignant trap info\n");
95         exit(-1);
96 }
97
98 static void thread0_thread_runnable(struct uthread *uth)
99 {
100         thread0_info.is_blocked = FALSE;
101 }
102
103 static void thread0_thread_has_blocked(struct uthread *uth, int flags)
104 {
105         thread0_info.is_blocked = TRUE;
106 }