Fix strlen bug in devattach
[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         /* we don't care about the message, so don't bother with a UCQ */
57         sysc_evq = get_eventq(EV_MBOX_BITMAP);
58         sysc_evq->ev_flags = EVENT_INDIR | EVENT_WAKEUP;
59         register_ev_handler(EV_SYSCALL, thread0_handle_syscall, 0);
60 }
61
62 /* Thread0 scheduler ops (for processes that haven't linked in a full 2LS) */
63 static void thread0_sched_entry(void)
64 {
65         /* TODO: support signal handling whenever we run a uthread */
66         if (current_uthread) {
67                 run_current_uthread();
68                 assert(0);
69         }
70         while (1) {
71                 if (!thread0_info.is_blocked) {
72                         run_uthread(thread0_uth);
73                         assert(0);
74                 }
75                 sys_yield(FALSE);
76                 handle_events(0);
77         }
78 }
79
80 static void thread0_thread_blockon_sysc(struct uthread *uthread, void *arg)
81 {
82         struct syscall *sysc = (struct syscall*)arg;
83         thread0_thread_has_blocked(uthread, 0);
84         if (!register_evq(sysc, sysc_evq))
85                 thread0_thread_runnable(uthread);
86 }
87
88 static void thread0_thread_refl_fault(struct uthread *uthread,
89                                       unsigned int trap_nr, unsigned int err,
90                                       unsigned long aux)
91 {
92         printf("SCP has unhandled fault: %d, err: %d, aux: %p\n", trap_nr, err,
93                aux);
94         print_user_context(&uthread->u_ctx);
95         printf("Turn on printx to spew unhandled, malignant trap info\n");
96         exit(-1);
97 }
98
99 static void thread0_thread_runnable(struct uthread *uth)
100 {
101         thread0_info.is_blocked = FALSE;
102 }
103
104 static void thread0_thread_has_blocked(struct uthread *uth, int flags)
105 {
106         thread0_info.is_blocked = TRUE;
107 }