| // Main public header file for our user-land support library, |
| // whose code lives in the lib directory. |
| // This library is roughly our OS's version of a standard C library, |
| // and is intended to be linked into all user-mode applications |
| // (NOT the kernel or boot loader). |
| |
| #pragma once |
| |
| #ifndef __ASSEMBLER__ |
| |
| #include <parlib/common.h> |
| #include <parlib/vcore.h> |
| #include <parlib/core_set.h> |
| #include <ros/memlayout.h> |
| #include <ros/syscall.h> |
| #include <ros/procinfo.h> |
| #include <ros/procdata.h> |
| #include <signal.h> |
| #include <stdint.h> |
| #include <errno.h> |
| #include <ros/fdtap.h> |
| |
| __BEGIN_DECLS |
| |
| enum { |
| PG_RDONLY = 4, |
| PG_RDWR = 6, |
| }; |
| |
| extern const char *const __syscall_tbl[]; |
| extern int __syscall_tbl_sz; |
| |
| int sys_null(void); |
| size_t sys_getpcoreid(void); |
| int sys_proc_destroy(int pid, int exitcode); |
| void sys_yield(bool being_nice); |
| int sys_proc_create(const char *path, size_t path_l, char *const argv[], |
| char *const envp[], int flags); |
| int sys_proc_run(int pid); |
| ssize_t sys_shared_page_alloc(void **addr, pid_t p2, int p1_flags, |
| int p2_flags); |
| ssize_t sys_shared_page_free(void *addr, pid_t p2); |
| void sys_reboot(); |
| void *sys_mmap(void *addr, size_t length, int prot, int flags, int fd, |
| size_t offset); |
| int sys_provision(int pid, unsigned int res_type, long res_val); |
| int sys_notify(int pid, unsigned int ev_type, struct event_msg *u_msg); |
| int sys_self_notify(uint32_t vcoreid, unsigned int ev_type, |
| struct event_msg *u_msg, bool priv); |
| int sys_send_event(struct event_queue *ev_q, struct event_msg *ev_msg, |
| uint32_t vcoreid); |
| int sys_halt_core(unsigned long usec); |
| void *sys_init_arsc(void); |
| int sys_block(unsigned long usec); |
| int sys_change_vcore(uint32_t vcoreid, bool enable_my_notif); |
| int sys_change_to_m(void); |
| int sys_poke_ksched(int pid, unsigned int res_type); |
| int sys_abort_sysc(struct syscall *sysc); |
| int sys_abort_sysc_fd(int fd); |
| int sys_tap_fds(struct fd_tap_req *tap_reqs, size_t nr_reqs); |
| |
| void syscall_async(struct syscall *sysc, unsigned long num, ...); |
| void syscall_async_evq(struct syscall *sysc, struct event_queue *evq, unsigned |
| long num, ...); |
| |
| /* Control variables */ |
| extern bool parlib_wants_to_be_mcp; /* instructs the 2LS to be an MCP */ |
| extern bool parlib_never_yield; /* instructs the 2LS to not yield vcores */ |
| extern bool parlib_never_vc_request;/* 2LS: do not request vcores */ |
| |
| /* Process Management */ |
| pid_t create_child(const char *exe, int argc, char *const argv[], |
| char *const envp[]); |
| pid_t create_child_with_stdfds(const char *exe, int argc, char *const argv[], |
| char *const envp[]); |
| int provision_core_set(pid_t pid, const struct core_set *cores); |
| |
| /* Once */ |
| typedef struct { |
| bool ran_once; |
| bool is_running; |
| } parlib_once_t; |
| |
| #define PARLIB_ONCE_INIT {FALSE, FALSE} |
| |
| /* Makes sure func is run exactly once. Can handle concurrent callers, and |
| * other callers spin til the func is complete. */ |
| static inline void parlib_run_once(parlib_once_t *once_ctl, |
| void (*init_fn)(void *), void *arg) |
| { |
| if (!once_ctl->ran_once) { |
| /* fetch and set TRUE, without a header or test_and_set |
| * weirdness */ |
| if (!__sync_fetch_and_or(&once_ctl->is_running, TRUE)) { |
| /* we won the race and get to run the func */ |
| init_fn(arg); |
| /* don't let the ran_once write pass previous writes */ |
| wmb(); |
| once_ctl->ran_once = TRUE; |
| } else { |
| /* someone else won */ |
| while (!once_ctl->ran_once) |
| cpu_relax_any(); |
| } |
| } |
| } |
| |
| /* Unprotected, single-threaded version, makes sure func is run exactly once */ |
| static inline void parlib_run_once_racy(parlib_once_t *once_ctl, |
| void (*init_fn)(void *), void *arg) |
| { |
| if (!once_ctl->ran_once) { |
| init_fn(arg); |
| once_ctl->ran_once = TRUE; |
| } |
| } |
| |
| static inline void parlib_set_ran_once(parlib_once_t *once_ctl) |
| { |
| once_ctl->ran_once = TRUE; |
| } |
| |
| /* Aborts with 'retcmd' if this function has already been called. Compared to |
| * run_once, this is put at the top of a function that can be called from |
| * multiple sources but should only execute once. */ |
| #define parlib_init_once_racy(retcmd) \ |
| do { \ |
| static bool initialized = FALSE; \ |
| if (initialized) { \ |
| retcmd; \ |
| } \ |
| initialized = TRUE; \ |
| } while (0) |
| |
| __END_DECLS |
| |
| #endif // !ASSEMBLER |