User code can tell if it is in vcore context (XCC)
[akaros.git] / user / parlib / include / vcore.h
1 #ifndef _VCORE_H
2 #define _VCORE_H
3
4 #ifdef __cplusplus
5 extern "C" {
6 #endif
7
8 #include <arch/vcore.h>
9 #include <sys/param.h>
10 #include <string.h>
11
12 /*****************************************************************************/
13 /* TODO: This is a complete hack, but necessary for vcore stuff tow ork for now
14  * The issue is that exit sometimes calls sys_yield(), and we can't recover from
15  * that properly under our vcore model (we shouldn't though).  We really need to
16  * rethink what sys_yield 'should' do when in multicore mode, or else come up 
17  * with a different syscall entirely. */
18 #include <stdlib.h>
19 #include <unistd.h>
20 #undef exit
21 #define exit(status) ros_syscall(SYS_proc_destroy, getpid(), status, 0, 0, 0, 0)
22 /*****************************************************************************/
23
24 #define LOG2_MAX_VCORES 6
25 #define MAX_VCORES (1 << LOG2_MAX_VCORES)
26
27 #define TRANSITION_STACK_PAGES 2
28 #define TRANSITION_STACK_SIZE (TRANSITION_STACK_PAGES*PGSIZE)
29
30 /* 2L-Scheduler operations.  Can be 0. */
31 struct schedule_ops {
32         void (*preempt_pending)(void);
33         void (*spawn_thread)(uintptr_t pc_start, void *data);   /* don't run yet */
34 };
35 extern struct schedule_ops *sched_ops;
36
37 /* Defined by glibc; Must be implemented by a user level threading library */
38 extern void vcore_entry();
39 /* Declared in glibc's start.c */
40 extern __thread bool __vcore_context;
41
42 /* Utility Functions */
43 void *allocate_tls(void);
44
45 /* Vcore API functions */
46 static inline size_t max_vcores(void);
47 static inline size_t num_vcores(void);
48 static inline int vcore_id(void);
49 static inline bool in_vcore_context(void);
50 static inline void enable_notifs(uint32_t vcoreid);
51 static inline void disable_notifs(uint32_t vcoreid);
52 int vcore_init(void);
53 int vcore_request(size_t k);
54 void vcore_yield(void);
55 bool check_preempt_pending(uint32_t vcoreid);
56 void clear_notif_pending(uint32_t vcoreid);
57
58 /* Inlines */
59 static inline size_t max_vcores(void)
60 {
61         return MIN(__procinfo.max_vcores, MAX_VCORES);
62 }
63
64 static inline size_t num_vcores(void)
65 {
66         return __procinfo.num_vcores;
67 }
68
69 static inline int vcore_id(void)
70 {
71         return __vcoreid;
72 }
73
74 static inline bool in_vcore_context(void)
75 {
76         return __vcore_context;
77 }
78
79 static inline void enable_notifs(uint32_t vcoreid)
80 {
81         __procdata.vcore_preempt_data[vcoreid].notif_enabled = TRUE;
82 }
83
84 static inline void disable_notifs(uint32_t vcoreid)
85 {
86         __procdata.vcore_preempt_data[vcoreid].notif_enabled = FALSE;
87 }
88
89 #ifdef __cplusplus
90 }
91 #endif
92
93 #endif