make hlt start at 0x2000
[akaros.git] / kern / include / ivy / sharc.h
1 #include <assert.h>
2 #include <string.h>
3
4 #ifdef IVY_FAST_CHECKS
5   #define SINLINE __attribute__((always_inline))
6 #else
7   #define SINLINE inline
8 #endif
9
10 #define SUNUSED __attribute__((unused))
11
12 #ifndef sasmlinkage
13 #define sasmlinkage __attribute__((regparm(0)))
14 #endif
15
16 #ifndef snoreturn
17 #define snoreturn __attribute__((noreturn))
18 #endif
19
20 typedef struct __ivy_sharC_thread {
21 #define SHARC_MAX_LOCKS 16
22     const void *held_locks[SHARC_MAX_LOCKS];
23     unsigned int max_lock;
24 } sharC_env_t;
25
26 #include <smp.h>
27 #include <process.h>
28
29 extern int booting;
30 extern int __ivy_checking_on;
31
32 #pragma cilnoremove("sharC_env_init")
33 static SINLINE void sharC_env_init(sharC_env_t *sharC_env) TRUSTED;
34 static SINLINE void sharC_env_init(sharC_env_t *sharC_env)
35 WRITES(sharC_env->max_lock,sharC_env->held_locks)
36 {
37         sharC_env->max_lock = 0;
38         memset(sharC_env->held_locks,0,SHARC_MAX_LOCKS);
39         return;
40 }
41
42 static __attribute__((always_inline)) int
43 is_single_threaded() TRUSTED
44 {
45         return booting || (num_idlecores == num_cpus - 1);
46 }
47
48 extern void sasmlinkage
49 __sharc_single_thread_error_mayreturn(const char *msg);
50
51 extern void sasmlinkage snoreturn
52 __sharc_single_thread_error_noreturn(const char *msg);
53
54 #ifdef IVY_FAST_CHECKS
55 #define __sharc_single_thread_error __sharc_single_thread_error_noreturn
56 #else
57 #define __sharc_single_thread_error __sharc_single_thread_error_mayreturn
58 #endif
59
60 #pragma cilnoremove("__sharc_single_threaded")
61 static SINLINE void __sharc_single_threaded(const void *msg) TRUSTED;
62 static SINLINE void __sharc_single_threaded(const void *msg)
63 {
64         if (is_single_threaded()) return;
65         __sharc_single_thread_error(msg);
66     return;
67 }
68
69 #define sharc_current      (&per_cpu_info[core_id()])
70 #define GET_SHARC_THREAD() sharc_current->sharC_env
71
72 #define THREAD_LOCKS(thread,i) (thread.held_locks[(i)])
73 #define THREAD_MAX_LOCK(thread) (thread.max_lock)
74
75 #define THIS_LOCKS(i)        (THREAD_LOCKS(GET_SHARC_THREAD(),(i)))
76 #define THIS_MAX_LOCK        (THREAD_MAX_LOCK(GET_SHARC_THREAD()))
77
78 /*
79  * Locks
80  */
81
82 extern void sasmlinkage snoreturn
83 __sharc_lock_error_noreturn(const void *lck, const void *what,
84                             unsigned int sz, const char *msg);
85
86 extern void sasmlinkage
87 __sharc_lock_error_mayreturn(const void *lck, const void *what,
88                              unsigned int sz, const char *msg);
89
90 extern void sasmlinkage snoreturn
91 __sharc_lock_coerce_error_noreturn(const void *dstlck, const void *srclck,
92                                    const char *msg);
93
94 extern void sasmlinkage
95 __sharc_lock_coerce_error_mayreturn(const void *dstlck, const void *srclck,
96                                     const char *msg);
97
98 #ifdef IVY_FAST_CHECKS
99 #define __sharc_lock_error         __sharc_lock_error_noreturn
100 #define __sharc_lock_coerce_error  __sharc_lock_coerce_error_noreturn
101 #else
102 #define __sharc_lock_error         __sharc_lock_error_mayreturn
103 #define __sharc_lock_coerce_error  __sharc_lock_coerce_error_mayreturn
104 #endif
105
106 /* assumes no double-locking */
107 #pragma cilnoremove("__sharc_add_lock")
108 static SINLINE void __sharc_add_lock(const void *lck) TRUSTED;
109 static SINLINE void __sharc_add_lock(const void *lck)
110 {
111     unsigned int i;
112
113         if (!__ivy_checking_on || is_single_threaded()) return;
114
115     for (i = 0; i <= THIS_MAX_LOCK; i++)
116         if (!THIS_LOCKS(i))
117             break;
118
119     if (i > THIS_MAX_LOCK && THIS_MAX_LOCK < SHARC_MAX_LOCKS)
120             THIS_MAX_LOCK++;
121
122     THIS_LOCKS(i) = lck;
123     return;
124 }
125
126 /* this will be very inefficient if the lock isn't actually held */
127 #pragma cilnoremove("__sharc_rm_lock")
128 static SINLINE void __sharc_rm_lock(const void *lck) TRUSTED;
129 static SINLINE void __sharc_rm_lock(const void *lck)
130 {
131     unsigned int i;
132
133         if (!__ivy_checking_on || is_single_threaded()) return;
134
135     for (i = 0; i <= THIS_MAX_LOCK; i++)
136         if (THIS_LOCKS(i) == lck)
137             break;
138
139     if (i == THIS_MAX_LOCK && THIS_MAX_LOCK > 0)
140             THIS_MAX_LOCK--;
141
142     THIS_LOCKS(i) = (void *)0;
143     return;
144 }
145
146 #pragma cilnoremove("__sharc_chk_lock")
147 static SINLINE void
148 __sharc_chk_lock(const void *lck, const void *what, unsigned int sz,
149                  const char *msg) TRUSTED;
150 static SINLINE void
151 __sharc_chk_lock(const void *lck, const void *what, unsigned int sz,
152                  const char *msg)
153 {
154     unsigned int i;
155
156         // TODO: how do I find how many threads are running?
157     //if (__sharc_num_threads == 1) return;
158
159         if (!__ivy_checking_on || is_single_threaded()) return;
160
161     for (i = 0; i <= THIS_MAX_LOCK; i++)
162         if (THIS_LOCKS(i) == lck)
163             break;
164
165     if (i > THIS_MAX_LOCK) {
166             __sharc_lock_error(lck,what,sz,msg);
167     }
168 }
169
170 #pragma cilnoremove("__sharc_coerce_lock")
171 static SINLINE void
172 __sharc_coerce_lock(const void *dstlck, const void *srclck,
173                     const char *msg) TRUSTED;
174 static SINLINE void
175 __sharc_coerce_lock(const void *dstlck, const void *srclck,
176                     const char *msg)
177 {
178         if (!__ivy_checking_on || is_single_threaded()) return;
179
180     if (dstlck != srclck)
181         __sharc_lock_coerce_error(dstlck,srclck,msg);
182 }
183
184 /*
185  * The sharing cast.
186  *
187  */
188
189 extern void __sharc_group_cast_error(int, void *, void *, char *);
190
191 #pragma cilnoremove("__sharc_check_group_cast")
192 static inline void
193 __sharc_check_group_cast(int hassame, void *srcg, void *src, char *msg) TRUSTED;
194 static inline void
195 __sharc_check_group_cast(int hassame, void *srcg, void *src, char *msg)
196 {
197         int old;
198         if (!__ivy_checking_on) return;
199         old = __ivy_checking_on;
200         __ivy_checking_on = 0;
201         panic("sharc group cast unimplemented");
202         __ivy_checking_on = old;
203 }
204
205
206 extern void __sharc_cast_error(void *addr, unsigned long sz, char *msg);
207
208 #pragma cilnoremove("__sharc_sharing_cast")
209 static SINLINE void *
210 __sharc_sharing_cast(void *addr,void **slot, unsigned int localslot SUNUSED,
211                      unsigned long lo, unsigned long hi,
212                      char *msg) TRUSTED;
213 static SINLINE void *
214 __sharc_sharing_cast(void *addr,void **slot, unsigned int localslot SUNUSED,
215                      unsigned long lo, unsigned long hi,
216                      char *msg)
217 {
218         int old;
219         if (!__ivy_checking_on) return NULL;
220         old = __ivy_checking_on;
221         __ivy_checking_on = 0;
222         panic("sharc sharing cast unimplemented");
223         __ivy_checking_on = old;
224         return NULL;
225 }