proc_yield() will return if you have an event
[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 to work 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 /* Defined by glibc; Must be implemented by a user level threading library */
31 extern void vcore_entry();
32 /* Declared in glibc's start.c */
33 extern __thread bool __vcore_context;
34
35 /* Utility Functions */
36 void *allocate_tls(void);
37 void free_tls(void *tcb);
38
39 /* Vcore API functions */
40 static inline size_t max_vcores(void);
41 static inline size_t num_vcores(void);
42 static inline int vcore_id(void);
43 static inline bool in_vcore_context(void);
44 static inline bool in_multi_mode(void);
45 static inline void __enable_notifs(uint32_t vcoreid);
46 static inline void __disable_notifs(uint32_t vcoreid);
47 static inline bool notif_is_enabled(uint32_t vcoreid);
48 int vcore_init(void);
49 int vcore_request(size_t k);
50 void vcore_yield(bool preempt_pending);
51 bool clear_notif_pending(uint32_t vcoreid);
52 void enable_notifs(uint32_t vcoreid);
53 void disable_notifs(uint32_t vcoreid);
54 void vcore_idle(void);
55
56 /* Static inlines */
57 static inline size_t max_vcores(void)
58 {
59         return MIN(__procinfo.max_vcores, MAX_VCORES);
60 }
61
62 static inline size_t num_vcores(void)
63 {
64         return __procinfo.num_vcores;
65 }
66
67 static inline int vcore_id(void)
68 {
69         return __vcoreid;
70 }
71
72 static inline bool in_vcore_context(void)
73 {
74         return __vcore_context;
75 }
76
77 static inline bool in_multi_mode(void)
78 {
79         return (num_vcores() > 0) ? TRUE : FALSE;
80 }
81
82 /* Only call this if you know what you are doing. */
83 static inline void __enable_notifs(uint32_t vcoreid)
84 {
85         __procdata.vcore_preempt_data[vcoreid].notif_enabled = TRUE;
86 }
87
88 static inline void __disable_notifs(uint32_t vcoreid)
89 {
90         __procdata.vcore_preempt_data[vcoreid].notif_enabled = FALSE;
91 }
92
93 static inline bool notif_is_enabled(uint32_t vcoreid)
94 {
95         return __procdata.vcore_preempt_data[vcoreid].notif_enabled;
96 }
97
98 #ifdef __cplusplus
99 }
100 #endif
101
102 #endif