| 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 |