OLD | NEW |
1 #include <futex_emulation.h> | 1 #include <futex_emulation.h> |
2 | 2 |
3 #include <assert.h> | 3 #include <assert.h> |
4 #include <errno.h> | 4 #include <errno.h> |
5 #include <irt_syscalls.h> | 5 #include <irt_syscalls.h> |
6 #include <tls.h> | 6 #include <tls.h> |
7 | 7 |
8 | 8 |
9 static int global_futex_emulation_mutex_desc = -1; | 9 static int global_futex_emulation_mutex_desc = -1; |
10 static LIST_HEAD (waiters_list); | 10 static LIST_HEAD (waiters_list); |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
83 | 83 |
84 ret_unlock: | 84 ret_unlock: |
85 if (!__nacl_irt_mutex_unlock (global_futex_emulation_mutex_desc)) | 85 if (!__nacl_irt_mutex_unlock (global_futex_emulation_mutex_desc)) |
86 retcode = 0; | 86 retcode = 0; |
87 ret_no_unlock: | 87 ret_no_unlock: |
88 return retcode; | 88 return retcode; |
89 } | 89 } |
90 | 90 |
91 /* Note: global_futex_emulation_mutex_desc must be taken when called. */ | 91 /* Note: global_futex_emulation_mutex_desc must be taken when called. */ |
92 static int nacl_futex_wake_nolock (volatile int *addr, int nwake, | 92 static int nacl_futex_wake_nolock (volatile int *addr, int nwake, |
93 » » » » unsigned int bitset) | 93 » » » » unsigned int bitset, |
| 94 » » » » int *count) |
94 { | 95 { |
95 int retcode = 0; | 96 int retcode = 0; |
96 list_t *entry; | 97 list_t *entry; |
97 list_t *prev; | 98 list_t *prev; |
| 99 *count = 0; |
98 | 100 |
99 if (nwake <= 0) | 101 if (nwake <= 0) |
100 return retcode; | 102 return 0; |
101 | 103 |
102 list_for_each_prev_safe (entry, prev, &waiters_list) | 104 list_for_each_prev_safe (entry, prev, &waiters_list) |
103 { | 105 { |
104 struct thread_wait_list_node *curr; | 106 struct thread_wait_list_node *curr; |
105 | 107 |
106 curr = list_entry (entry, struct thread_wait_list_node, list); | 108 curr = list_entry (entry, struct thread_wait_list_node, list); |
107 | 109 |
108 if ((curr->addr == addr) && (curr->bitset & bitset)) | 110 if ((curr->addr == addr) && (curr->bitset & bitset)) |
109 { | 111 { |
110 list_del (entry); | 112 list_del (entry); |
111 /* Mark the list entry as freed */ | 113 /* Mark the list entry as freed */ |
112 entry->next = NULL; | 114 entry->next = NULL; |
113 /* Cannot really do anything if error happens here. */ | 115 /* Cannot really do anything if error happens here. */ |
114 __nacl_irt_cond_signal (curr->condvar_desc); | 116 __nacl_irt_cond_signal (curr->condvar_desc); |
115 » retcode++; | 117 » (*count)++; |
116 nwake--; | 118 nwake--; |
117 if (nwake <= 0) | 119 if (nwake <= 0) |
118 » return retcode; | 120 » return 0; |
119 } | 121 } |
120 } | 122 } |
121 | 123 |
122 return retcode; | 124 return retcode; |
123 } | 125 } |
124 | 126 |
125 int __nacl_futex_wake (volatile int *addr, int nwake, unsigned int bitset) | 127 int __nacl_futex_wake (volatile int *addr, int nwake, unsigned int bitset, |
| 128 » » int *count) |
126 { | 129 { |
127 int retcode = 0; | 130 int retcode = 0; |
128 | 131 |
129 if (__nacl_irt_mutex_lock (global_futex_emulation_mutex_desc)) | 132 if (__nacl_irt_mutex_lock (global_futex_emulation_mutex_desc)) |
130 goto ret_no_unlock; | 133 goto ret_no_unlock; |
131 | 134 |
132 retcode = nacl_futex_wake_nolock (addr, nwake, bitset); | 135 retcode = nacl_futex_wake_nolock (addr, nwake, bitset, count); |
133 | 136 |
134 /* Cannot really do anything if error happens here. */ | 137 /* Cannot really do anything if error happens here. */ |
135 __nacl_irt_mutex_unlock (global_futex_emulation_mutex_desc); | 138 __nacl_irt_mutex_unlock (global_futex_emulation_mutex_desc); |
136 ret_no_unlock: | 139 ret_no_unlock: |
137 return retcode; | 140 return retcode; |
138 } | 141 } |
139 | 142 |
140 struct __attribute__ ((__packed__)) decoded_wake_op_operation | 143 struct __attribute__ ((__packed__)) decoded_wake_op_operation |
141 { | 144 { |
142 unsigned int compare_argument :12; | 145 unsigned int compare_argument :12; |
143 unsigned int operation_argument :12; | 146 unsigned int operation_argument :12; |
144 unsigned int compare :4; | 147 unsigned int compare :4; |
145 unsigned int operation :3; | 148 unsigned int operation :3; |
146 unsigned int operation_argument_shifted :1; | 149 unsigned int operation_argument_shifted :1; |
147 }; | 150 }; |
148 | 151 |
149 int __nacl_futex_wake_op (volatile int *addr1, volatile int *addr2, | 152 int __nacl_futex_wake_op (volatile int *addr1, volatile int *addr2, |
150 int nwake1, int nwake2, | 153 int nwake1, int nwake2, |
151 union __attribute__ ((__transparent_union__)) | 154 union __attribute__ ((__transparent_union__)) |
152 { | 155 { |
153 int encoded_futex_operation; | 156 int encoded_futex_operation; |
154 struct decoded_wake_op_operation | 157 struct decoded_wake_op_operation |
155 decoded_wake_op_operation; | 158 decoded_wake_op_operation; |
156 » » » } futex_operation) | 159 » » » } futex_operation, |
| 160 » » » int *count) |
157 { | 161 { |
158 int retcode = 0; | 162 int retcode = 0; |
159 int operation_argument; | 163 int operation_argument; |
160 int old_value; | 164 int old_value; |
161 | 165 |
162 if (__nacl_irt_mutex_lock (global_futex_emulation_mutex_desc)) | 166 if (__nacl_irt_mutex_lock (global_futex_emulation_mutex_desc)) |
163 goto ret_no_unlock; | 167 goto ret_no_unlock; |
164 | 168 |
165 operation_argument = | 169 operation_argument = |
166 futex_operation.decoded_wake_op_operation.operation_argument; | 170 futex_operation.decoded_wake_op_operation.operation_argument; |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
213 break; | 217 break; |
214 case 5/*FUTEX_OP_CMP_GE*/: | 218 case 5/*FUTEX_OP_CMP_GE*/: |
215 old_value = old_value | 219 old_value = old_value |
216 >= futex_operation.decoded_wake_op_operation.compare_argument; | 220 >= futex_operation.decoded_wake_op_operation.compare_argument; |
217 break; | 221 break; |
218 default: | 222 default: |
219 retcode = -ENOSYS; | 223 retcode = -ENOSYS; |
220 goto ret_unlock; | 224 goto ret_unlock; |
221 } | 225 } |
222 | 226 |
223 retcode = nacl_futex_wake_nolock (addr1, nwake1, __FUTEX_BITSET_MATCH_ANY); | 227 retcode = nacl_futex_wake_nolock (addr1, nwake1, __FUTEX_BITSET_MATCH_ANY, |
| 228 » » » » count); |
224 | 229 |
225 if (old_value) | 230 if (!retcode && old_value) |
226 retcode += nacl_futex_wake_nolock (addr2, nwake2, __FUTEX_BITSET_MATCH_ANY); | 231 { |
| 232 int count2; |
| 233 retcode = nacl_futex_wake_nolock (addr2, nwake2, __FUTEX_BITSET_MATCH_ANY, |
| 234 » » » » » &count2); |
| 235 (*count) += count2; |
| 236 } |
227 | 237 |
228 ret_unlock: | 238 ret_unlock: |
229 /* Cannot really do anything if error happens here. */ | 239 /* Cannot really do anything if error happens here. */ |
230 __nacl_irt_mutex_unlock (global_futex_emulation_mutex_desc); | 240 __nacl_irt_mutex_unlock (global_futex_emulation_mutex_desc); |
231 ret_no_unlock: | 241 ret_no_unlock: |
232 return retcode; | 242 return retcode; |
233 } | 243 } |
234 | 244 |
235 int __nacl_futex_cmp_requeue (volatile int *addr1, volatile int *addr2, | 245 int __nacl_futex_cmp_requeue (volatile int *addr1, volatile int *addr2, |
236 » » » int nwake, int nrequeue, int val) | 246 » » » int nwake, int nrequeue, int val, int *count) |
237 { | 247 { |
238 int retcode = -EINTR; | 248 int retcode = -EINTR; |
239 | 249 |
240 if (__nacl_irt_mutex_lock (global_futex_emulation_mutex_desc)) | 250 if (__nacl_irt_mutex_lock (global_futex_emulation_mutex_desc)) |
241 goto ret_no_unlock; | 251 goto ret_no_unlock; |
242 | 252 |
243 if (*addr1 != val) | 253 if (*addr1 != val) |
244 { | 254 { |
245 retcode = -EAGAIN; | 255 retcode = -EAGAIN; |
246 goto ret_unlock; | 256 goto ret_unlock; |
247 } | 257 } |
248 else | 258 else |
249 { | 259 { |
250 list_t *entry; | 260 list_t *entry; |
251 retcode = nacl_futex_wake_nolock (addr1, nwake, __FUTEX_BITSET_MATCH_ANY); | 261 retcode = nacl_futex_wake_nolock (addr1, nwake, __FUTEX_BITSET_MATCH_ANY, |
| 262 » » » » » count); |
252 | 263 |
253 if (retcode <= 0 || (waiters_list.next == &waiters_list) || nrequeue <= 0) | 264 if (retcode <= 0 || (waiters_list.next == &waiters_list) || nrequeue <= 0) |
254 goto ret_unlock_nocheck; | 265 goto ret_unlock_nocheck; |
255 | 266 |
256 list_for_each_prev (entry, &waiters_list) | 267 list_for_each_prev (entry, &waiters_list) |
257 { | 268 { |
258 struct thread_wait_list_node *curr; | 269 struct thread_wait_list_node *curr; |
259 | 270 |
260 if (!nrequeue) | 271 if (!nrequeue) |
261 break; | 272 break; |
262 | 273 |
263 curr = list_entry (entry, struct thread_wait_list_node, list); | 274 curr = list_entry (entry, struct thread_wait_list_node, list); |
264 | 275 |
265 if (curr->addr == addr1) | 276 if (curr->addr == addr1) |
266 { | 277 { |
267 curr->addr = addr2; | 278 curr->addr = addr2; |
268 » retcode++; | 279 » count++; |
269 nrequeue--; | 280 nrequeue--; |
270 } | 281 } |
271 } | 282 } |
272 | 283 |
273 ret_unlock_nocheck: | 284 ret_unlock_nocheck: |
274 /* Cannot really do anything if error happens here. */ | 285 /* Cannot really do anything if error happens here. */ |
275 __nacl_irt_mutex_unlock (global_futex_emulation_mutex_desc); | 286 __nacl_irt_mutex_unlock (global_futex_emulation_mutex_desc); |
276 return retcode; | 287 return retcode; |
277 } | 288 } |
278 | 289 |
279 ret_unlock: | 290 ret_unlock: |
280 if (!__nacl_irt_mutex_unlock (global_futex_emulation_mutex_desc)) | 291 if (!__nacl_irt_mutex_unlock (global_futex_emulation_mutex_desc)) |
281 retcode = 0; | 292 retcode = 0; |
282 ret_no_unlock: | 293 ret_no_unlock: |
283 return retcode; | 294 return retcode; |
284 } | 295 } |
OLD | NEW |