Merge branch 'net-dev'. See body of commit for details.
[akaros.git] / kern / include / ivy / sharc.h
1 #include <assert.h>
2 #include <string.h>
3
4 #define SINLINE inline
5 #define SUNUSED __attribute__((unused))
6
7 typedef struct __ivy_sharC_thread {
8 #define SHARC_MAX_LOCKS 16
9     void *held_locks[SHARC_MAX_LOCKS];
10     unsigned int max_lock;
11 } sharC_env_t;
12
13 #include <env.h>
14
15 extern int __ivy_checking_on;
16
17 #pragma cilnoremove("sharC_env_init")
18 static SINLINE void sharC_env_init(sharC_env_t *sharC_env) TRUSTED;
19 static SINLINE void sharC_env_init(sharC_env_t *sharC_env)
20 WRITES(sharC_env->max_lock,sharC_env->held_locks)
21 {
22         sharC_env->max_lock = 0;
23         memset(sharC_env->held_locks,0,SHARC_MAX_LOCKS);
24         return;
25 }
26
27 #pragma cilnoremove("__sharc_single_threaded")
28 static SINLINE void __sharc_single_threaded(void *msg) TRUSTED;
29 static SINLINE void __sharc_single_threaded(void *msg)
30 {
31         // TODO: how do I know how many threads/cores are running?
32     //assert(1);
33     return;
34 }
35
36
37 #define GET_SHARC_THREAD() current->sharC_env
38
39 #define THREAD_LOCKS(thread,i) (thread.held_locks[(i)])
40 #define THREAD_MAX_LOCK(thread) (thread.max_lock)
41
42 #define THIS_LOCKS(i)        (THREAD_LOCKS(GET_SHARC_THREAD(),(i)))
43 #define THIS_MAX_LOCK        (THREAD_MAX_LOCK(GET_SHARC_THREAD()))
44
45 /*
46  * Locks
47  */
48
49 extern void
50 __sharc_lock_error(const void *lck, const void *what,
51                    unsigned int sz, char *msg);
52
53 extern void
54 __sharc_lock_coerce_error(void *dstlck, void *srclck, char *msg);
55
56 /* assumes no double-locking */
57 #pragma cilnoremove("__sharc_add_lock")
58 static SINLINE void __sharc_add_lock(void *lck) TRUSTED;
59 static SINLINE void __sharc_add_lock(void *lck)
60 {
61     unsigned int i;
62
63         if (!__ivy_checking_on || !current) return;
64
65     for (i = 0; i <= THIS_MAX_LOCK; i++)
66         if (!THIS_LOCKS(i))
67             break;
68
69     if (i > THIS_MAX_LOCK && THIS_MAX_LOCK < SHARC_MAX_LOCKS)
70             THIS_MAX_LOCK++;
71
72     THIS_LOCKS(i) = lck;
73     return;
74 }
75
76 /* this will be very inefficient if the lock isn't actually held */
77 #pragma cilnoremove("__sharc_rm_lock")
78 static SINLINE void __sharc_rm_lock(void *lck) TRUSTED;
79 static SINLINE void __sharc_rm_lock(void *lck)
80 {
81     unsigned int i;
82
83         if (!__ivy_checking_on || !current) return;
84
85     for (i = 0; i <= THIS_MAX_LOCK; i++)
86         if (THIS_LOCKS(i) == lck)
87             break;
88
89     if (i == THIS_MAX_LOCK && THIS_MAX_LOCK > 0)
90             THIS_MAX_LOCK--;
91
92     THIS_LOCKS(i) = (void *)0;
93     return;
94 }
95
96 #pragma cilnoremove("__sharc_chk_lock")
97 static SINLINE void
98 __sharc_chk_lock(void *lck, void *what, unsigned int sz, char *msg) TRUSTED;
99 static SINLINE void
100 __sharc_chk_lock(void *lck, void *what, unsigned int sz, char *msg)
101 {
102     unsigned int i;
103
104         // TODO: how do I find how many threads are running?
105     //if (__sharc_num_threads == 1) return;
106
107         if (!__ivy_checking_on || !current) return;
108
109     for (i = 0; i <= THIS_MAX_LOCK; i++)
110         if (THIS_LOCKS(i) == lck)
111             break;
112
113     if (i > THIS_MAX_LOCK) {
114             __sharc_lock_error(lck,what,sz,msg);
115     }
116 }
117
118 #pragma cilnoremove("__sharc_coerce_lock")
119 static SINLINE void
120 __sharc_coerce_lock(void *dstlck, void *srclck, char *msg) TRUSTED;
121 static SINLINE void
122 __sharc_coerce_lock(void *dstlck, void *srclck, char *msg)
123 {
124         if (!__ivy_checking_on) return;
125
126     if (dstlck != srclck)
127         __sharc_lock_coerce_error(dstlck,srclck,msg);
128 }
129
130 /*
131  * The sharing cast.
132  *
133  */
134
135 extern void __sharc_group_cast_error(int, void *, void *, char *);
136
137 #pragma cilnoremove("__sharc_check_group_cast")
138 static inline void
139 __sharc_check_group_cast(int hassame, void *srcg, void *src, char *msg) TRUSTED;
140 static inline void
141 __sharc_check_group_cast(int hassame, void *srcg, void *src, char *msg)
142 {
143         int old;
144         if (!__ivy_checking_on) return;
145         old = __ivy_checking_on;
146         __ivy_checking_on = 0;
147         panic("sharc group cast unimplemented");
148         __ivy_checking_on = old;
149 }
150
151
152 extern void __sharc_cast_error(void *addr, unsigned long sz, char *msg);
153
154 #pragma cilnoremove("__sharc_sharing_cast")
155 static SINLINE void *
156 __sharc_sharing_cast(void *addr,void **slot, unsigned int localslot SUNUSED,
157                      unsigned long lo, unsigned long hi,
158                      char *msg) TRUSTED;
159 static SINLINE void *
160 __sharc_sharing_cast(void *addr,void **slot, unsigned int localslot SUNUSED,
161                      unsigned long lo, unsigned long hi,
162                      char *msg)
163 {
164         int old;
165         if (!__ivy_checking_on) return NULL;
166         old = __ivy_checking_on;
167         __ivy_checking_on = 0;
168         panic("sharc sharing cast unimplemented");
169         __ivy_checking_on = old;
170         return NULL;
171 }