parlib: Move the provisioning of cores to a PID
[akaros.git] / user / parlib / include / parlib / parlib.h
1 // Main public header file for our user-land support library,
2 // whose code lives in the lib directory.
3 // This library is roughly our OS's version of a standard C library,
4 // and is intended to be linked into all user-mode applications
5 // (NOT the kernel or boot loader).
6
7 #pragma once
8
9 #ifndef __ASSEMBLER__
10
11 #include <parlib/common.h>
12 #include <parlib/vcore.h>
13 #include <parlib/core_set.h>
14 #include <ros/memlayout.h>
15 #include <ros/syscall.h>
16 #include <ros/procinfo.h>
17 #include <ros/procdata.h>
18 #include <signal.h>
19 #include <stdint.h>
20 #include <errno.h>
21 #include <ros/fdtap.h>
22
23 __BEGIN_DECLS
24
25 enum {
26         PG_RDONLY = 4,
27         PG_RDWR   = 6,
28 };
29
30 extern const char *const __syscall_tbl[];
31 extern int __syscall_tbl_sz;
32
33 int         sys_null(void);
34 size_t      sys_getpcoreid(void);
35 int         sys_proc_destroy(int pid, int exitcode);
36 void        sys_yield(bool being_nice);
37 int         sys_proc_create(const char *path, size_t path_l, char *const argv[],
38                             char *const envp[], int flags);
39 int         sys_proc_run(int pid);
40 ssize_t     sys_shared_page_alloc(void **addr, pid_t p2, 
41                                   int p1_flags, int p2_flags);
42 ssize_t     sys_shared_page_free(void *addr, pid_t p2);
43 void        sys_reboot();
44 void            *sys_mmap(void *addr, size_t length, int prot, int flags,
45                       int fd, size_t offset);
46 int                     sys_provision(int pid, unsigned int res_type, long res_val);
47 int         sys_notify(int pid, unsigned int ev_type, struct event_msg *u_msg);
48 int         sys_self_notify(uint32_t vcoreid, unsigned int ev_type,
49                             struct event_msg *u_msg, bool priv);
50 int         sys_send_event(struct event_queue *ev_q, struct event_msg *ev_msg,
51                            uint32_t vcoreid);
52 int         sys_halt_core(unsigned long usec);
53 void*           sys_init_arsc();
54 int         sys_block(unsigned long usec);
55 int         sys_change_vcore(uint32_t vcoreid, bool enable_my_notif);
56 int         sys_change_to_m(void);
57 int         sys_poke_ksched(int pid, unsigned int res_type);
58 int         sys_abort_sysc(struct syscall *sysc);
59 int         sys_abort_sysc_fd(int fd);
60 int         sys_tap_fds(struct fd_tap_req *tap_reqs, size_t nr_reqs);
61
62 void            syscall_async(struct syscall *sysc, unsigned long num, ...);
63 void        syscall_async_evq(struct syscall *sysc, struct event_queue *evq,
64                               unsigned long num, ...);
65
66 /* Control variables */
67 extern bool parlib_wants_to_be_mcp;     /* instructs the 2LS to be an MCP */
68 extern bool parlib_never_yield;         /* instructs the 2LS to not yield vcores */
69 extern bool parlib_never_vc_request;/* 2LS: do not request vcores */
70
71 /* Process Management */
72 pid_t create_child(const char *exe, int argc, char *const argv[],
73                    char *const envp[]);
74 pid_t create_child_with_stdfds(const char *exe, int argc, char *const argv[],
75                                char *const envp[]);
76 int provision_core_set(pid_t pid, const struct core_set *cores);
77
78 /* Once */
79 typedef struct {
80         bool ran_once;
81         bool is_running;
82 } parlib_once_t;
83
84 #define PARLIB_ONCE_INIT {FALSE, FALSE}
85
86 /* Makes sure func is run exactly once.  Can handle concurrent callers, and
87  * other callers spin til the func is complete. */
88 static inline void parlib_run_once(parlib_once_t *once_ctl,
89                                    void (*init_fn)(void *), void *arg)
90 {
91         if (!once_ctl->ran_once) {
92                 /* fetch and set TRUE, without a header or test_and_set weirdness */
93                 if (!__sync_fetch_and_or(&once_ctl->is_running, TRUE)) {
94                         /* we won the race and get to run the func */
95                         init_fn(arg);
96                         wmb();  /* don't let the ran_once write pass previous writes */
97                         once_ctl->ran_once = TRUE;
98                 } else {
99                         /* someone else won, wait til they are done to break out */
100                         while (!once_ctl->ran_once)
101                                 cpu_relax_any();
102                 }
103         }
104 }
105
106 /* Unprotected, single-threaded version, makes sure func is run exactly once */
107 static inline void parlib_run_once_racy(parlib_once_t *once_ctl,
108                                         void (*init_fn)(void *), void *arg)
109 {
110         if (!once_ctl->ran_once) {
111                 init_fn(arg);
112                 once_ctl->ran_once = TRUE;
113         }
114 }
115
116 static inline void parlib_set_ran_once(parlib_once_t *once_ctl)
117 {
118         once_ctl->ran_once = TRUE;
119 }
120
121 /* Aborts with 'retcmd' if this function has already been called.  Compared to
122  * run_once, this is put at the top of a function that can be called from
123  * multiple sources but should only execute once. */
124 #define parlib_init_once_racy(retcmd)                                          \
125 do {                                                                           \
126         static bool initialized = FALSE;                                           \
127         if (initialized) {                                                         \
128                 retcmd;                                                                \
129         }                                                                          \
130         initialized = TRUE;                                                        \
131 } while (0)
132
133 __END_DECLS
134
135 #endif  // !ASSEMBLER