linux_futex.c (8fa0b743820f61c661ba5f3ea0e3be0dc137910e) | linux_futex.c (19e252baebe7a7466b33c27560420b7d95fe294d) |
---|---|
1/* $NetBSD: linux_futex.c,v 1.7 2006/07/24 19:01:49 manu Exp $ */ 2 3/*- 4 * Copyright (c) 2005 Emmanuel Dreyfus, all rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: --- 24 unchanged lines hidden (view full) --- 33 34#include <sys/cdefs.h> 35__FBSDID("$FreeBSD$"); 36#if 0 37__KERNEL_RCSID(1, "$NetBSD: linux_futex.c,v 1.7 2006/07/24 19:01:49 manu Exp $"); 38#endif 39 40#include "opt_compat.h" | 1/* $NetBSD: linux_futex.c,v 1.7 2006/07/24 19:01:49 manu Exp $ */ 2 3/*- 4 * Copyright (c) 2005 Emmanuel Dreyfus, all rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: --- 24 unchanged lines hidden (view full) --- 33 34#include <sys/cdefs.h> 35__FBSDID("$FreeBSD$"); 36#if 0 37__KERNEL_RCSID(1, "$NetBSD: linux_futex.c,v 1.7 2006/07/24 19:01:49 manu Exp $"); 38#endif 39 40#include "opt_compat.h" |
41#include "opt_kdtrace.h" |
|
41 42#include <sys/param.h> 43#include <sys/systm.h> 44#include <sys/imgact.h> 45#include <sys/kernel.h> 46#include <sys/ktr.h> 47#include <sys/lock.h> 48#include <sys/malloc.h> 49#include <sys/mutex.h> 50#include <sys/priv.h> 51#include <sys/proc.h> 52#include <sys/queue.h> 53#include <sys/sched.h> | 42 43#include <sys/param.h> 44#include <sys/systm.h> 45#include <sys/imgact.h> 46#include <sys/kernel.h> 47#include <sys/ktr.h> 48#include <sys/lock.h> 49#include <sys/malloc.h> 50#include <sys/mutex.h> 51#include <sys/priv.h> 52#include <sys/proc.h> 53#include <sys/queue.h> 54#include <sys/sched.h> |
55#include <sys/sdt.h> |
|
54#include <sys/sx.h> 55#include <sys/umtx.h> 56 57#ifdef COMPAT_LINUX32 58#include <machine/../linux32/linux.h> 59#include <machine/../linux32/linux32_proto.h> 60#else 61#include <machine/../linux/linux.h> 62#include <machine/../linux/linux_proto.h> 63#endif | 56#include <sys/sx.h> 57#include <sys/umtx.h> 58 59#ifdef COMPAT_LINUX32 60#include <machine/../linux32/linux.h> 61#include <machine/../linux32/linux32_proto.h> 62#else 63#include <machine/../linux/linux.h> 64#include <machine/../linux/linux_proto.h> 65#endif |
66#include <compat/linux/linux_dtrace.h> |
|
64#include <compat/linux/linux_emul.h> 65#include <compat/linux/linux_futex.h> 66#include <compat/linux/linux_util.h> 67 | 67#include <compat/linux/linux_emul.h> 68#include <compat/linux/linux_futex.h> 69#include <compat/linux/linux_util.h> 70 |
71/* DTrace init */ 72LIN_SDT_PROVIDER_DECLARE(LINUX_DTRACE); 73 74/* Linuxulator-global DTrace probes */ 75LIN_SDT_PROBE_DECLARE(locks, emul_lock, locked); 76LIN_SDT_PROBE_DECLARE(locks, emul_lock, unlock); 77 78/** 79 * Futex part for the special DTrace module "locks". 80 */ 81LIN_SDT_PROBE_DEFINE1(locks, futex_mtx, locked, "struct mtx *"); 82LIN_SDT_PROBE_DEFINE1(locks, futex_mtx, unlock, "struct mtx *"); 83 84/** 85 * Per futex probes. 86 */ 87LIN_SDT_PROBE_DEFINE1(futex, futex, create, "struct sx *"); 88LIN_SDT_PROBE_DEFINE1(futex, futex, destroy, "struct sx *"); 89 90/** 91 * DTrace probes in this module. 92 */ 93LIN_SDT_PROBE_DEFINE2(futex, futex_put, entry, "struct futex *", 94 "struct waiting_proc *"); 95LIN_SDT_PROBE_DEFINE3(futex, futex_put, destroy, "uint32_t *", "uint32_t", 96 "int"); 97LIN_SDT_PROBE_DEFINE3(futex, futex_put, unlock, "uint32_t *", "uint32_t", 98 "int"); 99LIN_SDT_PROBE_DEFINE0(futex, futex_put, return); 100LIN_SDT_PROBE_DEFINE3(futex, futex_get0, entry, "uint32_t *", "struct futex **", 101 "uint32_t"); 102LIN_SDT_PROBE_DEFINE1(futex, futex_get0, umtx_key_get_error, "int"); 103LIN_SDT_PROBE_DEFINE3(futex, futex_get0, shared, "uint32_t *", "uint32_t", 104 "int"); 105LIN_SDT_PROBE_DEFINE1(futex, futex_get0, null, "uint32_t *"); 106LIN_SDT_PROBE_DEFINE3(futex, futex_get0, new, "uint32_t *", "uint32_t", "int"); 107LIN_SDT_PROBE_DEFINE1(futex, futex_get0, return, "int"); 108LIN_SDT_PROBE_DEFINE3(futex, futex_get, entry, "uint32_t *", 109 "struct waiting_proc **", "struct futex **"); 110LIN_SDT_PROBE_DEFINE0(futex, futex_get, error); 111LIN_SDT_PROBE_DEFINE1(futex, futex_get, return, "int"); 112LIN_SDT_PROBE_DEFINE3(futex, futex_sleep, entry, "struct futex *", 113 "struct waiting_proc **", "int"); 114LIN_SDT_PROBE_DEFINE5(futex, futex_sleep, requeue_error, "int", "uint32_t *", 115 "struct waiting_proc *", "uint32_t *", "uint32_t"); 116LIN_SDT_PROBE_DEFINE3(futex, futex_sleep, sleep_error, "int", "uint32_t *", 117 "struct waiting_proc *"); 118LIN_SDT_PROBE_DEFINE1(futex, futex_sleep, return, "int"); 119LIN_SDT_PROBE_DEFINE3(futex, futex_wake, entry, "struct futex *", "int", 120 "uint32_t"); 121LIN_SDT_PROBE_DEFINE3(futex, futex_wake, iterate, "uint32_t", 122 "struct waiting_proc *", "uin32_t"); 123LIN_SDT_PROBE_DEFINE1(futex, futex_wake, wakeup, "struct waiting_proc *"); 124LIN_SDT_PROBE_DEFINE1(futex, futex_wake, return, "int"); 125LIN_SDT_PROBE_DEFINE4(futex, futex_requeue, entry, "struct futex *", "int", 126 "struct futex *", "int"); 127LIN_SDT_PROBE_DEFINE1(futex, futex_requeue, wakeup, "struct waiting_proc *"); 128LIN_SDT_PROBE_DEFINE3(futex, futex_requeue, requeue, "uint32_t *", 129 "struct waiting_proc *", "uint32_t"); 130LIN_SDT_PROBE_DEFINE1(futex, futex_requeue, return, "int"); 131LIN_SDT_PROBE_DEFINE4(futex, futex_wait, entry, "struct futex *", 132 "struct waiting_proc **", "struct l_timespec *", "uint32_t"); 133LIN_SDT_PROBE_DEFINE1(futex, futex_wait, copyin_error, "int"); 134LIN_SDT_PROBE_DEFINE1(futex, futex_wait, itimerfix_error, "int"); 135LIN_SDT_PROBE_DEFINE1(futex, futex_wait, sleep_error, "int"); 136LIN_SDT_PROBE_DEFINE1(futex, futex_wait, return, "int"); 137LIN_SDT_PROBE_DEFINE3(futex, futex_atomic_op, entry, "struct thread *", 138 "int", "uint32_t"); 139LIN_SDT_PROBE_DEFINE4(futex, futex_atomic_op, decoded_op, "int", "int", "int", 140 "int"); 141LIN_SDT_PROBE_DEFINE0(futex, futex_atomic_op, missing_access_check); 142LIN_SDT_PROBE_DEFINE1(futex, futex_atomic_op, unimplemented_op, "int"); 143LIN_SDT_PROBE_DEFINE1(futex, futex_atomic_op, unimplemented_cmp, "int"); 144LIN_SDT_PROBE_DEFINE1(futex, futex_atomic_op, return, "int"); 145LIN_SDT_PROBE_DEFINE2(futex, linux_sys_futex, entry, "struct thread *", 146 "struct linux_sys_futex_args *"); 147LIN_SDT_PROBE_DEFINE0(futex, linux_sys_futex, unimplemented_clockswitch); 148LIN_SDT_PROBE_DEFINE1(futex, linux_sys_futex, copyin_error, "int"); 149LIN_SDT_PROBE_DEFINE0(futex, linux_sys_futex, invalid_cmp_requeue_use); 150LIN_SDT_PROBE_DEFINE3(futex, linux_sys_futex, debug_wait, "uint32_t *", 151 "uint32_t", "uint32_t"); 152LIN_SDT_PROBE_DEFINE4(futex, linux_sys_futex, debug_wait_value_neq, 153 "uint32_t *", "uint32_t", "int", "uint32_t"); 154LIN_SDT_PROBE_DEFINE3(futex, linux_sys_futex, debug_wake, "uint32_t *", 155 "uint32_t", "uint32_t"); 156LIN_SDT_PROBE_DEFINE5(futex, linux_sys_futex, debug_cmp_requeue, "uint32_t *", 157 "uint32_t", "uint32_t", "uint32_t *", "struct l_timespec *"); 158LIN_SDT_PROBE_DEFINE2(futex, linux_sys_futex, debug_cmp_requeue_value_neq, 159 "uint32_t", "int"); 160LIN_SDT_PROBE_DEFINE5(futex, linux_sys_futex, debug_wake_op, "uint32_t *", 161 "int", "uint32_t", "uint32_t *", "uint32_t"); 162LIN_SDT_PROBE_DEFINE0(futex, linux_sys_futex, unhandled_efault); 163LIN_SDT_PROBE_DEFINE0(futex, linux_sys_futex, unimplemented_lock_pi); 164LIN_SDT_PROBE_DEFINE0(futex, linux_sys_futex, unimplemented_unlock_pi); 165LIN_SDT_PROBE_DEFINE0(futex, linux_sys_futex, unimplemented_trylock_pi); 166LIN_SDT_PROBE_DEFINE0(futex, linux_sys_futex, deprecated_requeue); 167LIN_SDT_PROBE_DEFINE0(futex, linux_sys_futex, unimplemented_wait_requeue_pi); 168LIN_SDT_PROBE_DEFINE0(futex, linux_sys_futex, unimplemented_cmp_requeue_pi); 169LIN_SDT_PROBE_DEFINE1(futex, linux_sys_futex, unknown_operation, "int"); 170LIN_SDT_PROBE_DEFINE1(futex, linux_sys_futex, return, "int"); 171LIN_SDT_PROBE_DEFINE2(futex, linux_set_robust_list, entry, "struct thread *", 172 "struct linux_set_robust_list_args *"); 173LIN_SDT_PROBE_DEFINE0(futex, linux_set_robust_list, size_error); 174LIN_SDT_PROBE_DEFINE1(futex, linux_set_robust_list, return, "int"); 175LIN_SDT_PROBE_DEFINE2(futex, linux_get_robust_list, entry, "struct thread *", 176 "struct linux_get_robust_list_args *"); 177LIN_SDT_PROBE_DEFINE1(futex, linux_get_robust_list, copyout_error, "int"); 178LIN_SDT_PROBE_DEFINE1(futex, linux_get_robust_list, return, "int"); 179LIN_SDT_PROBE_DEFINE3(futex, handle_futex_death, entry, "struct proc *", 180 "uint32_t *", "int"); 181LIN_SDT_PROBE_DEFINE1(futex, handle_futex_death, copyin_error, "int"); 182LIN_SDT_PROBE_DEFINE1(futex, handle_futex_death, return, "int"); 183LIN_SDT_PROBE_DEFINE3(futex, fetch_robust_entry, entry, 184 "struct linux_robust_list **", "struct linux_robust_list **", "int *"); 185LIN_SDT_PROBE_DEFINE1(futex, fetch_robust_entry, copyin_error, "int"); 186LIN_SDT_PROBE_DEFINE1(futex, fetch_robust_entry, return, "int"); 187LIN_SDT_PROBE_DEFINE1(futex, release_futexes, entry, "struct proc *"); 188LIN_SDT_PROBE_DEFINE1(futex, release_futexes, copyin_error, "int"); 189LIN_SDT_PROBE_DEFINE0(futex, release_futexes, return); 190 |
|
68static MALLOC_DEFINE(M_FUTEX, "futex", "Linux futexes"); 69static MALLOC_DEFINE(M_FUTEX_WP, "futex wp", "Linux futexes wp"); 70 71struct futex; 72 73struct waiting_proc { 74 uint32_t wp_flags; 75 struct futex *wp_futex; --- 9 unchanged lines hidden (view full) --- 85 LIST_ENTRY(futex) f_list; 86 TAILQ_HEAD(lf_waiting_proc, waiting_proc) f_waiting_proc; 87}; 88 89struct futex_list futex_list; 90 91#define FUTEX_LOCK(f) sx_xlock(&(f)->f_lck) 92#define FUTEX_UNLOCK(f) sx_xunlock(&(f)->f_lck) | 191static MALLOC_DEFINE(M_FUTEX, "futex", "Linux futexes"); 192static MALLOC_DEFINE(M_FUTEX_WP, "futex wp", "Linux futexes wp"); 193 194struct futex; 195 196struct waiting_proc { 197 uint32_t wp_flags; 198 struct futex *wp_futex; --- 9 unchanged lines hidden (view full) --- 208 LIST_ENTRY(futex) f_list; 209 TAILQ_HEAD(lf_waiting_proc, waiting_proc) f_waiting_proc; 210}; 211 212struct futex_list futex_list; 213 214#define FUTEX_LOCK(f) sx_xlock(&(f)->f_lck) 215#define FUTEX_UNLOCK(f) sx_xunlock(&(f)->f_lck) |
93#define FUTEX_INIT(f) sx_init_flags(&(f)->f_lck, "ftlk", SX_DUPOK) 94#define FUTEX_DESTROY(f) sx_destroy(&(f)->f_lck) | 216#define FUTEX_INIT(f) do { \ 217 sx_init_flags(&(f)->f_lck, "ftlk", \ 218 SX_DUPOK); \ 219 LIN_SDT_PROBE1(futex, futex, create, \ 220 &(f)->f_lck); \ 221 } while (0) 222#define FUTEX_DESTROY(f) do { \ 223 LIN_SDT_PROBE1(futex, futex, destroy, \ 224 &(f)->f_lck); \ 225 sx_destroy(&(f)->f_lck); \ 226 } while (0) |
95#define FUTEX_ASSERT_LOCKED(f) sx_assert(&(f)->f_lck, SA_XLOCKED) 96 97struct mtx futex_mtx; /* protects the futex list */ | 227#define FUTEX_ASSERT_LOCKED(f) sx_assert(&(f)->f_lck, SA_XLOCKED) 228 229struct mtx futex_mtx; /* protects the futex list */ |
98#define FUTEXES_LOCK mtx_lock(&futex_mtx) 99#define FUTEXES_UNLOCK mtx_unlock(&futex_mtx) | 230#define FUTEXES_LOCK do { \ 231 mtx_lock(&futex_mtx); \ 232 LIN_SDT_PROBE1(locks, futex_mtx, \ 233 locked, &futex_mtx); \ 234 } while (0) 235#define FUTEXES_UNLOCK do { \ 236 LIN_SDT_PROBE1(locks, futex_mtx, \ 237 unlock, &futex_mtx); \ 238 mtx_unlock(&futex_mtx); \ 239 } while (0) |
100 101/* flags for futex_get() */ 102#define FUTEX_CREATE_WP 0x1 /* create waiting_proc */ 103#define FUTEX_DONTCREATE 0x2 /* don't create futex if not exists */ 104#define FUTEX_DONTEXISTS 0x4 /* return EINVAL if futex exists */ 105#define FUTEX_SHARED 0x8 /* shared futex */ 106 107/* wp_flags */ --- 10 unchanged lines hidden (view full) --- 118int futex_addl(int oparg, uint32_t *uaddr, int *oldval); 119int futex_orl(int oparg, uint32_t *uaddr, int *oldval); 120int futex_andl(int oparg, uint32_t *uaddr, int *oldval); 121int futex_xorl(int oparg, uint32_t *uaddr, int *oldval); 122 123static void 124futex_put(struct futex *f, struct waiting_proc *wp) 125{ | 240 241/* flags for futex_get() */ 242#define FUTEX_CREATE_WP 0x1 /* create waiting_proc */ 243#define FUTEX_DONTCREATE 0x2 /* don't create futex if not exists */ 244#define FUTEX_DONTEXISTS 0x4 /* return EINVAL if futex exists */ 245#define FUTEX_SHARED 0x8 /* shared futex */ 246 247/* wp_flags */ --- 10 unchanged lines hidden (view full) --- 258int futex_addl(int oparg, uint32_t *uaddr, int *oldval); 259int futex_orl(int oparg, uint32_t *uaddr, int *oldval); 260int futex_andl(int oparg, uint32_t *uaddr, int *oldval); 261int futex_xorl(int oparg, uint32_t *uaddr, int *oldval); 262 263static void 264futex_put(struct futex *f, struct waiting_proc *wp) 265{ |
266 LIN_SDT_PROBE2(futex, futex_put, entry, f, wp); |
|
126 127 FUTEX_ASSERT_LOCKED(f); 128 if (wp != NULL) { 129 if ((wp->wp_flags & FUTEX_WP_REMOVED) == 0) 130 TAILQ_REMOVE(&f->f_waiting_proc, wp, wp_list); 131 free(wp, M_FUTEX_WP); 132 } 133 134 FUTEXES_LOCK; 135 if (--f->f_refcount == 0) { 136 LIST_REMOVE(f, f_list); 137 FUTEXES_UNLOCK; 138 FUTEX_UNLOCK(f); 139 | 267 268 FUTEX_ASSERT_LOCKED(f); 269 if (wp != NULL) { 270 if ((wp->wp_flags & FUTEX_WP_REMOVED) == 0) 271 TAILQ_REMOVE(&f->f_waiting_proc, wp, wp_list); 272 free(wp, M_FUTEX_WP); 273 } 274 275 FUTEXES_LOCK; 276 if (--f->f_refcount == 0) { 277 LIST_REMOVE(f, f_list); 278 FUTEXES_UNLOCK; 279 FUTEX_UNLOCK(f); 280 |
281 LIN_SDT_PROBE3(futex, futex_put, destroy, f->f_uaddr, 282 f->f_refcount, f->f_key.shared); |
|
140 LINUX_CTR3(sys_futex, "futex_put destroy uaddr %p ref %d " 141 "shared %d", f->f_uaddr, f->f_refcount, f->f_key.shared); 142 umtx_key_release(&f->f_key); 143 FUTEX_DESTROY(f); 144 free(f, M_FUTEX); | 283 LINUX_CTR3(sys_futex, "futex_put destroy uaddr %p ref %d " 284 "shared %d", f->f_uaddr, f->f_refcount, f->f_key.shared); 285 umtx_key_release(&f->f_key); 286 FUTEX_DESTROY(f); 287 free(f, M_FUTEX); |
288 289 LIN_SDT_PROBE0(futex, futex_put, return); |
|
145 return; 146 } 147 | 290 return; 291 } 292 |
293 LIN_SDT_PROBE3(futex, futex_put, unlock, f->f_uaddr, f->f_refcount, 294 f->f_key.shared); |
|
148 LINUX_CTR3(sys_futex, "futex_put uaddr %p ref %d shared %d", 149 f->f_uaddr, f->f_refcount, f->f_key.shared); 150 FUTEXES_UNLOCK; 151 FUTEX_UNLOCK(f); | 295 LINUX_CTR3(sys_futex, "futex_put uaddr %p ref %d shared %d", 296 f->f_uaddr, f->f_refcount, f->f_key.shared); 297 FUTEXES_UNLOCK; 298 FUTEX_UNLOCK(f); |
299 300 LIN_SDT_PROBE0(futex, futex_put, return); |
|
152} 153 154static int 155futex_get0(uint32_t *uaddr, struct futex **newf, uint32_t flags) 156{ 157 struct futex *f, *tmpf; 158 struct umtx_key key; 159 int error; 160 | 301} 302 303static int 304futex_get0(uint32_t *uaddr, struct futex **newf, uint32_t flags) 305{ 306 struct futex *f, *tmpf; 307 struct umtx_key key; 308 int error; 309 |
310 LIN_SDT_PROBE3(futex, futex_get0, entry, uaddr, newf, flags); 311 |
|
161 *newf = tmpf = NULL; 162 163 error = umtx_key_get(uaddr, TYPE_FUTEX, (flags & FUTEX_SHARED) ? 164 AUTO_SHARE : THREAD_SHARE, &key); | 312 *newf = tmpf = NULL; 313 314 error = umtx_key_get(uaddr, TYPE_FUTEX, (flags & FUTEX_SHARED) ? 315 AUTO_SHARE : THREAD_SHARE, &key); |
165 if (error) | 316 if (error) { 317 LIN_SDT_PROBE1(futex, futex_get0, umtx_key_get_error, error); 318 LIN_SDT_PROBE1(futex, futex_get0, return, error); |
166 return (error); | 319 return (error); |
320 } |
|
167retry: 168 FUTEXES_LOCK; 169 LIST_FOREACH(f, &futex_list, f_list) { 170 if (umtx_key_match(&f->f_key, &key)) { 171 if (tmpf != NULL) { 172 FUTEX_UNLOCK(tmpf); 173 FUTEX_DESTROY(tmpf); 174 free(tmpf, M_FUTEX); 175 } 176 if (flags & FUTEX_DONTEXISTS) { 177 FUTEXES_UNLOCK; 178 umtx_key_release(&key); | 321retry: 322 FUTEXES_LOCK; 323 LIST_FOREACH(f, &futex_list, f_list) { 324 if (umtx_key_match(&f->f_key, &key)) { 325 if (tmpf != NULL) { 326 FUTEX_UNLOCK(tmpf); 327 FUTEX_DESTROY(tmpf); 328 free(tmpf, M_FUTEX); 329 } 330 if (flags & FUTEX_DONTEXISTS) { 331 FUTEXES_UNLOCK; 332 umtx_key_release(&key); |
333 334 LIN_SDT_PROBE1(futex, futex_get0, return, 335 EINVAL); |
|
179 return (EINVAL); 180 } 181 182 /* 183 * Increment refcount of the found futex to 184 * prevent it from deallocation before FUTEX_LOCK() 185 */ 186 ++f->f_refcount; 187 FUTEXES_UNLOCK; 188 umtx_key_release(&key); 189 190 FUTEX_LOCK(f); 191 *newf = f; | 336 return (EINVAL); 337 } 338 339 /* 340 * Increment refcount of the found futex to 341 * prevent it from deallocation before FUTEX_LOCK() 342 */ 343 ++f->f_refcount; 344 FUTEXES_UNLOCK; 345 umtx_key_release(&key); 346 347 FUTEX_LOCK(f); 348 *newf = f; |
349 LIN_SDT_PROBE3(futex, futex_get0, shared, uaddr, 350 f->f_refcount, f->f_key.shared); |
|
192 LINUX_CTR3(sys_futex, "futex_get uaddr %p ref %d shared %d", 193 uaddr, f->f_refcount, f->f_key.shared); | 351 LINUX_CTR3(sys_futex, "futex_get uaddr %p ref %d shared %d", 352 uaddr, f->f_refcount, f->f_key.shared); |
353 354 LIN_SDT_PROBE1(futex, futex_get0, return, 0); |
|
194 return (0); 195 } 196 } 197 198 if (flags & FUTEX_DONTCREATE) { 199 FUTEXES_UNLOCK; 200 umtx_key_release(&key); | 355 return (0); 356 } 357 } 358 359 if (flags & FUTEX_DONTCREATE) { 360 FUTEXES_UNLOCK; 361 umtx_key_release(&key); |
362 LIN_SDT_PROBE1(futex, futex_get0, null, uaddr); |
|
201 LINUX_CTR1(sys_futex, "futex_get uaddr %p null", uaddr); | 363 LINUX_CTR1(sys_futex, "futex_get uaddr %p null", uaddr); |
364 365 LIN_SDT_PROBE1(futex, futex_get0, return, 0); |
|
202 return (0); 203 } 204 205 if (tmpf == NULL) { 206 FUTEXES_UNLOCK; 207 tmpf = malloc(sizeof(*tmpf), M_FUTEX, M_WAITOK | M_ZERO); 208 tmpf->f_uaddr = uaddr; 209 tmpf->f_key = key; --- 8 unchanged lines hidden (view full) --- 218 */ 219 FUTEX_LOCK(tmpf); 220 goto retry; 221 } 222 223 LIST_INSERT_HEAD(&futex_list, tmpf, f_list); 224 FUTEXES_UNLOCK; 225 | 366 return (0); 367 } 368 369 if (tmpf == NULL) { 370 FUTEXES_UNLOCK; 371 tmpf = malloc(sizeof(*tmpf), M_FUTEX, M_WAITOK | M_ZERO); 372 tmpf->f_uaddr = uaddr; 373 tmpf->f_key = key; --- 8 unchanged lines hidden (view full) --- 382 */ 383 FUTEX_LOCK(tmpf); 384 goto retry; 385 } 386 387 LIST_INSERT_HEAD(&futex_list, tmpf, f_list); 388 FUTEXES_UNLOCK; 389 |
390 LIN_SDT_PROBE3(futex, futex_get0, new, uaddr, tmpf->f_refcount, 391 tmpf->f_key.shared); |
|
226 LINUX_CTR3(sys_futex, "futex_get uaddr %p ref %d shared %d new", 227 uaddr, tmpf->f_refcount, tmpf->f_key.shared); 228 *newf = tmpf; | 392 LINUX_CTR3(sys_futex, "futex_get uaddr %p ref %d shared %d new", 393 uaddr, tmpf->f_refcount, tmpf->f_key.shared); 394 *newf = tmpf; |
395 396 LIN_SDT_PROBE1(futex, futex_get0, return, 0); |
|
229 return (0); 230} 231 232static int 233futex_get(uint32_t *uaddr, struct waiting_proc **wp, struct futex **f, 234 uint32_t flags) 235{ 236 int error; 237 | 397 return (0); 398} 399 400static int 401futex_get(uint32_t *uaddr, struct waiting_proc **wp, struct futex **f, 402 uint32_t flags) 403{ 404 int error; 405 |
406 LIN_SDT_PROBE3(futex, futex_get, entry, uaddr, wp, f); 407 |
|
238 if (flags & FUTEX_CREATE_WP) { 239 *wp = malloc(sizeof(struct waiting_proc), M_FUTEX_WP, M_WAITOK); 240 (*wp)->wp_flags = 0; 241 } 242 error = futex_get0(uaddr, f, flags); 243 if (error) { | 408 if (flags & FUTEX_CREATE_WP) { 409 *wp = malloc(sizeof(struct waiting_proc), M_FUTEX_WP, M_WAITOK); 410 (*wp)->wp_flags = 0; 411 } 412 error = futex_get0(uaddr, f, flags); 413 if (error) { |
414 LIN_SDT_PROBE0(futex, futex_get, error); 415 |
|
244 if (flags & FUTEX_CREATE_WP) 245 free(*wp, M_FUTEX_WP); | 416 if (flags & FUTEX_CREATE_WP) 417 free(*wp, M_FUTEX_WP); |
418 419 LIN_SDT_PROBE1(futex, futex_get, return, error); |
|
246 return (error); 247 } 248 if (flags & FUTEX_CREATE_WP) { 249 TAILQ_INSERT_HEAD(&(*f)->f_waiting_proc, *wp, wp_list); 250 (*wp)->wp_futex = *f; 251 } 252 | 420 return (error); 421 } 422 if (flags & FUTEX_CREATE_WP) { 423 TAILQ_INSERT_HEAD(&(*f)->f_waiting_proc, *wp, wp_list); 424 (*wp)->wp_futex = *f; 425 } 426 |
427 LIN_SDT_PROBE1(futex, futex_get, return, error); |
|
253 return (error); 254} 255 256static int 257futex_sleep(struct futex *f, struct waiting_proc *wp, int timeout) 258{ 259 int error; 260 261 FUTEX_ASSERT_LOCKED(f); | 428 return (error); 429} 430 431static int 432futex_sleep(struct futex *f, struct waiting_proc *wp, int timeout) 433{ 434 int error; 435 436 FUTEX_ASSERT_LOCKED(f); |
437 LIN_SDT_PROBE3(futex, futex_sleep, entry, f, wp, timeout); |
|
262 LINUX_CTR4(sys_futex, "futex_sleep enter uaddr %p wp %p timo %d ref %d", 263 f->f_uaddr, wp, timeout, f->f_refcount); 264 error = sx_sleep(wp, &f->f_lck, PCATCH, "futex", timeout); 265 if (wp->wp_flags & FUTEX_WP_REQUEUED) { 266 KASSERT(f != wp->wp_futex, ("futex != wp_futex")); | 438 LINUX_CTR4(sys_futex, "futex_sleep enter uaddr %p wp %p timo %d ref %d", 439 f->f_uaddr, wp, timeout, f->f_refcount); 440 error = sx_sleep(wp, &f->f_lck, PCATCH, "futex", timeout); 441 if (wp->wp_flags & FUTEX_WP_REQUEUED) { 442 KASSERT(f != wp->wp_futex, ("futex != wp_futex")); |
267 LINUX_CTR5(sys_futex, "futex_sleep out error %d uaddr %p w" | 443 444 if (error) { 445 LIN_SDT_PROBE5(futex, futex_sleep, requeue_error, error, 446 f->f_uaddr, wp, wp->wp_futex->f_uaddr, 447 wp->wp_futex->f_refcount); 448 } 449 450 LINUX_CTR5(sys_futex, "futex_sleep out error %d uaddr %p wp" |
268 " %p requeued uaddr %p ref %d", 269 error, f->f_uaddr, wp, wp->wp_futex->f_uaddr, 270 wp->wp_futex->f_refcount); 271 futex_put(f, NULL); 272 f = wp->wp_futex; 273 FUTEX_LOCK(f); | 451 " %p requeued uaddr %p ref %d", 452 error, f->f_uaddr, wp, wp->wp_futex->f_uaddr, 453 wp->wp_futex->f_refcount); 454 futex_put(f, NULL); 455 f = wp->wp_futex; 456 FUTEX_LOCK(f); |
274 } else | 457 } else { 458 if (error) { 459 LIN_SDT_PROBE3(futex, futex_sleep, sleep_error, error, 460 f->f_uaddr, wp); 461 } |
275 LINUX_CTR3(sys_futex, "futex_sleep out error %d uaddr %p wp %p", 276 error, f->f_uaddr, wp); | 462 LINUX_CTR3(sys_futex, "futex_sleep out error %d uaddr %p wp %p", 463 error, f->f_uaddr, wp); |
464 } |
|
277 278 futex_put(f, wp); | 465 466 futex_put(f, wp); |
467 468 LIN_SDT_PROBE1(futex, futex_sleep, return, error); |
|
279 return (error); 280} 281 282static int 283futex_wake(struct futex *f, int n, uint32_t bitset) 284{ 285 struct waiting_proc *wp, *wpt; 286 int count = 0; 287 | 469 return (error); 470} 471 472static int 473futex_wake(struct futex *f, int n, uint32_t bitset) 474{ 475 struct waiting_proc *wp, *wpt; 476 int count = 0; 477 |
288 if (bitset == 0) | 478 LIN_SDT_PROBE3(futex, futex_wake, entry, f, n, bitset); 479 480 if (bitset == 0) { 481 LIN_SDT_PROBE1(futex, futex_wake, return, EINVAL); |
289 return (EINVAL); | 482 return (EINVAL); |
483 } |
|
290 291 FUTEX_ASSERT_LOCKED(f); 292 TAILQ_FOREACH_SAFE(wp, &f->f_waiting_proc, wp_list, wpt) { | 484 485 FUTEX_ASSERT_LOCKED(f); 486 TAILQ_FOREACH_SAFE(wp, &f->f_waiting_proc, wp_list, wpt) { |
487 LIN_SDT_PROBE3(futex, futex_wake, iterate, f->f_uaddr, wp, 488 f->f_refcount); |
|
293 LINUX_CTR3(sys_futex, "futex_wake uaddr %p wp %p ref %d", 294 f->f_uaddr, wp, f->f_refcount); 295 /* 296 * Unless we find a matching bit in 297 * the bitset, continue searching. 298 */ 299 if (!(wp->wp_futex->f_bitset & bitset)) 300 continue; 301 302 wp->wp_flags |= FUTEX_WP_REMOVED; 303 TAILQ_REMOVE(&f->f_waiting_proc, wp, wp_list); | 489 LINUX_CTR3(sys_futex, "futex_wake uaddr %p wp %p ref %d", 490 f->f_uaddr, wp, f->f_refcount); 491 /* 492 * Unless we find a matching bit in 493 * the bitset, continue searching. 494 */ 495 if (!(wp->wp_futex->f_bitset & bitset)) 496 continue; 497 498 wp->wp_flags |= FUTEX_WP_REMOVED; 499 TAILQ_REMOVE(&f->f_waiting_proc, wp, wp_list); |
500 LIN_SDT_PROBE1(futex, futex_wake, wakeup, wp); |
|
304 wakeup_one(wp); 305 if (++count == n) 306 break; 307 } 308 | 501 wakeup_one(wp); 502 if (++count == n) 503 break; 504 } 505 |
506 LIN_SDT_PROBE1(futex, futex_wake, return, count); |
|
309 return (count); 310} 311 312static int 313futex_requeue(struct futex *f, int n, struct futex *f2, int n2) 314{ 315 struct waiting_proc *wp, *wpt; 316 int count = 0; 317 | 507 return (count); 508} 509 510static int 511futex_requeue(struct futex *f, int n, struct futex *f2, int n2) 512{ 513 struct waiting_proc *wp, *wpt; 514 int count = 0; 515 |
516 LIN_SDT_PROBE4(futex, futex_requeue, entry, f, n, f2, n2); 517 |
|
318 FUTEX_ASSERT_LOCKED(f); 319 FUTEX_ASSERT_LOCKED(f2); 320 321 TAILQ_FOREACH_SAFE(wp, &f->f_waiting_proc, wp_list, wpt) { 322 if (++count <= n) { 323 LINUX_CTR2(sys_futex, "futex_req_wake uaddr %p wp %p", 324 f->f_uaddr, wp); 325 wp->wp_flags |= FUTEX_WP_REMOVED; 326 TAILQ_REMOVE(&f->f_waiting_proc, wp, wp_list); | 518 FUTEX_ASSERT_LOCKED(f); 519 FUTEX_ASSERT_LOCKED(f2); 520 521 TAILQ_FOREACH_SAFE(wp, &f->f_waiting_proc, wp_list, wpt) { 522 if (++count <= n) { 523 LINUX_CTR2(sys_futex, "futex_req_wake uaddr %p wp %p", 524 f->f_uaddr, wp); 525 wp->wp_flags |= FUTEX_WP_REMOVED; 526 TAILQ_REMOVE(&f->f_waiting_proc, wp, wp_list); |
527 LIN_SDT_PROBE1(futex, futex_requeue, wakeup, wp); |
|
327 wakeup_one(wp); 328 } else { | 528 wakeup_one(wp); 529 } else { |
530 LIN_SDT_PROBE3(futex, futex_requeue, requeue, 531 f->f_uaddr, wp, f2->f_uaddr); |
|
329 LINUX_CTR3(sys_futex, "futex_requeue uaddr %p wp %p to %p", 330 f->f_uaddr, wp, f2->f_uaddr); 331 wp->wp_flags |= FUTEX_WP_REQUEUED; 332 /* Move wp to wp_list of f2 futex */ 333 TAILQ_REMOVE(&f->f_waiting_proc, wp, wp_list); 334 TAILQ_INSERT_HEAD(&f2->f_waiting_proc, wp, wp_list); 335 336 /* --- 5 unchanged lines hidden (view full) --- 342 FUTEXES_LOCK; 343 ++f2->f_refcount; 344 FUTEXES_UNLOCK; 345 if (count - n >= n2) 346 break; 347 } 348 } 349 | 532 LINUX_CTR3(sys_futex, "futex_requeue uaddr %p wp %p to %p", 533 f->f_uaddr, wp, f2->f_uaddr); 534 wp->wp_flags |= FUTEX_WP_REQUEUED; 535 /* Move wp to wp_list of f2 futex */ 536 TAILQ_REMOVE(&f->f_waiting_proc, wp, wp_list); 537 TAILQ_INSERT_HEAD(&f2->f_waiting_proc, wp, wp_list); 538 539 /* --- 5 unchanged lines hidden (view full) --- 545 FUTEXES_LOCK; 546 ++f2->f_refcount; 547 FUTEXES_UNLOCK; 548 if (count - n >= n2) 549 break; 550 } 551 } 552 |
553 LIN_SDT_PROBE1(futex, futex_requeue, return, count); |
|
350 return (count); 351} 352 353static int 354futex_wait(struct futex *f, struct waiting_proc *wp, struct l_timespec *ts, 355 uint32_t bitset) 356{ 357 struct l_timespec timeout; 358 struct timeval tv; 359 int timeout_hz; 360 int error; 361 | 554 return (count); 555} 556 557static int 558futex_wait(struct futex *f, struct waiting_proc *wp, struct l_timespec *ts, 559 uint32_t bitset) 560{ 561 struct l_timespec timeout; 562 struct timeval tv; 563 int timeout_hz; 564 int error; 565 |
362 if (bitset == 0) | 566 LIN_SDT_PROBE4(futex, futex_wait, entry, f, wp, ts, bitset); 567 568 if (bitset == 0) { 569 LIN_SDT_PROBE1(futex, futex_wait, return, EINVAL); |
363 return (EINVAL); | 570 return (EINVAL); |
571 } 572 |
|
364 f->f_bitset = bitset; 365 366 if (ts != NULL) { 367 error = copyin(ts, &timeout, sizeof(timeout)); | 573 f->f_bitset = bitset; 574 575 if (ts != NULL) { 576 error = copyin(ts, &timeout, sizeof(timeout)); |
368 if (error) | 577 if (error) { 578 LIN_SDT_PROBE1(futex, futex_wait, copyin_error, error); 579 LIN_SDT_PROBE1(futex, futex_wait, return, error); |
369 return (error); | 580 return (error); |
581 } |
|
370 TIMESPEC_TO_TIMEVAL(&tv, &timeout); 371 error = itimerfix(&tv); | 582 TIMESPEC_TO_TIMEVAL(&tv, &timeout); 583 error = itimerfix(&tv); |
372 if (error) | 584 if (error) { 585 LIN_SDT_PROBE1(futex, futex_wait, itimerfix_error, 586 error); 587 LIN_SDT_PROBE1(futex, futex_wait, return, error); |
373 return (error); | 588 return (error); |
589 } |
|
374 timeout_hz = tvtohz(&tv); 375 } else 376 timeout_hz = 0; 377 378 error = futex_sleep(f, wp, timeout_hz); | 590 timeout_hz = tvtohz(&tv); 591 } else 592 timeout_hz = 0; 593 594 error = futex_sleep(f, wp, timeout_hz); |
595 if (error) { 596 LIN_SDT_PROBE1(futex, futex_wait, sleep_error, error); 597 } |
|
379 if (error == EWOULDBLOCK) 380 error = ETIMEDOUT; 381 | 598 if (error == EWOULDBLOCK) 599 error = ETIMEDOUT; 600 |
601 LIN_SDT_PROBE1(futex, futex_wait, return, error); |
|
382 return (error); 383} 384 385static int 386futex_atomic_op(struct thread *td, int encoded_op, uint32_t *uaddr) 387{ 388 int op = (encoded_op >> 28) & 7; 389 int cmp = (encoded_op >> 24) & 15; 390 int oparg = (encoded_op << 8) >> 20; 391 int cmparg = (encoded_op << 20) >> 20; 392 int oldval = 0, ret; 393 | 602 return (error); 603} 604 605static int 606futex_atomic_op(struct thread *td, int encoded_op, uint32_t *uaddr) 607{ 608 int op = (encoded_op >> 28) & 7; 609 int cmp = (encoded_op >> 24) & 15; 610 int oparg = (encoded_op << 8) >> 20; 611 int cmparg = (encoded_op << 20) >> 20; 612 int oldval = 0, ret; 613 |
614 LIN_SDT_PROBE3(futex, futex_atomic_op, entry, td, encoded_op, uaddr); 615 |
|
394 if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) 395 oparg = 1 << oparg; 396 | 616 if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) 617 oparg = 1 << oparg; 618 |
397#ifdef DEBUG 398 if (ldebug(sys_futex)) 399 printf("futex_atomic_op: op = %d, cmp = %d, oparg = %x, " 400 "cmparg = %x, uaddr = %p\n", 401 op, cmp, oparg, cmparg, uaddr); 402#endif | 619 LIN_SDT_PROBE4(futex, futex_atomic_op, decoded_op, op, cmp, oparg, 620 cmparg); 621 |
403 /* XXX: Linux verifies access here and returns EFAULT */ | 622 /* XXX: Linux verifies access here and returns EFAULT */ |
623 LIN_SDT_PROBE0(futex, futex_atomic_op, missing_access_check); |
|
404 405 switch (op) { 406 case FUTEX_OP_SET: 407 ret = futex_xchgl(oparg, uaddr, &oldval); 408 break; 409 case FUTEX_OP_ADD: 410 ret = futex_addl(oparg, uaddr, &oldval); 411 break; 412 case FUTEX_OP_OR: 413 ret = futex_orl(oparg, uaddr, &oldval); 414 break; 415 case FUTEX_OP_ANDN: 416 ret = futex_andl(~oparg, uaddr, &oldval); 417 break; 418 case FUTEX_OP_XOR: 419 ret = futex_xorl(oparg, uaddr, &oldval); 420 break; 421 default: | 624 625 switch (op) { 626 case FUTEX_OP_SET: 627 ret = futex_xchgl(oparg, uaddr, &oldval); 628 break; 629 case FUTEX_OP_ADD: 630 ret = futex_addl(oparg, uaddr, &oldval); 631 break; 632 case FUTEX_OP_OR: 633 ret = futex_orl(oparg, uaddr, &oldval); 634 break; 635 case FUTEX_OP_ANDN: 636 ret = futex_andl(~oparg, uaddr, &oldval); 637 break; 638 case FUTEX_OP_XOR: 639 ret = futex_xorl(oparg, uaddr, &oldval); 640 break; 641 default: |
642 LIN_SDT_PROBE1(futex, futex_atomic_op, unimplemented_op, op); |
|
422 ret = -ENOSYS; 423 break; 424 } 425 | 643 ret = -ENOSYS; 644 break; 645 } 646 |
426 if (ret) | 647 if (ret) { 648 LIN_SDT_PROBE1(futex, futex_atomic_op, return, ret); |
427 return (ret); | 649 return (ret); |
650 } |
|
428 429 switch (cmp) { 430 case FUTEX_OP_CMP_EQ: | 651 652 switch (cmp) { 653 case FUTEX_OP_CMP_EQ: |
431 return (oldval == cmparg); | 654 ret = (oldval == cmparg); 655 break; |
432 case FUTEX_OP_CMP_NE: | 656 case FUTEX_OP_CMP_NE: |
433 return (oldval != cmparg); | 657 ret = (oldval != cmparg); 658 break; |
434 case FUTEX_OP_CMP_LT: | 659 case FUTEX_OP_CMP_LT: |
435 return (oldval < cmparg); | 660 ret = (oldval < cmparg); 661 break; |
436 case FUTEX_OP_CMP_GE: | 662 case FUTEX_OP_CMP_GE: |
437 return (oldval >= cmparg); | 663 ret = (oldval >= cmparg); 664 break; |
438 case FUTEX_OP_CMP_LE: | 665 case FUTEX_OP_CMP_LE: |
439 return (oldval <= cmparg); | 666 ret = (oldval <= cmparg); 667 break; |
440 case FUTEX_OP_CMP_GT: | 668 case FUTEX_OP_CMP_GT: |
441 return (oldval > cmparg); | 669 ret = (oldval > cmparg); 670 break; |
442 default: | 671 default: |
443 return (-ENOSYS); | 672 LIN_SDT_PROBE1(futex, futex_atomic_op, unimplemented_cmp, cmp); 673 ret = -ENOSYS; |
444 } | 674 } |
675 676 LIN_SDT_PROBE1(futex, futex_atomic_op, return, ret); 677 return (ret); |
|
445} 446 447int 448linux_sys_futex(struct thread *td, struct linux_sys_futex_args *args) 449{ 450 int clockrt, nrwake, op_ret, ret, val; 451 struct linux_emuldata *em; 452 struct waiting_proc *wp; 453 struct futex *f, *f2; 454 int error; 455 uint32_t flags; 456 | 678} 679 680int 681linux_sys_futex(struct thread *td, struct linux_sys_futex_args *args) 682{ 683 int clockrt, nrwake, op_ret, ret, val; 684 struct linux_emuldata *em; 685 struct waiting_proc *wp; 686 struct futex *f, *f2; 687 int error; 688 uint32_t flags; 689 |
690 LIN_SDT_PROBE2(futex, linux_sys_futex, entry, td, args); 691 |
|
457 if (args->op & LINUX_FUTEX_PRIVATE_FLAG) { 458 flags = 0; 459 args->op &= ~LINUX_FUTEX_PRIVATE_FLAG; 460 } else 461 flags = FUTEX_SHARED; 462 463 /* 464 * Currently support for switching between CLOCK_MONOTONIC and 465 * CLOCK_REALTIME is not present. However Linux forbids the use of 466 * FUTEX_CLOCK_REALTIME with any op except FUTEX_WAIT_BITSET and 467 * FUTEX_WAIT_REQUEUE_PI. 468 */ 469 clockrt = args->op & LINUX_FUTEX_CLOCK_REALTIME; 470 args->op = args->op & ~LINUX_FUTEX_CLOCK_REALTIME; 471 if (clockrt && args->op != LINUX_FUTEX_WAIT_BITSET && | 692 if (args->op & LINUX_FUTEX_PRIVATE_FLAG) { 693 flags = 0; 694 args->op &= ~LINUX_FUTEX_PRIVATE_FLAG; 695 } else 696 flags = FUTEX_SHARED; 697 698 /* 699 * Currently support for switching between CLOCK_MONOTONIC and 700 * CLOCK_REALTIME is not present. However Linux forbids the use of 701 * FUTEX_CLOCK_REALTIME with any op except FUTEX_WAIT_BITSET and 702 * FUTEX_WAIT_REQUEUE_PI. 703 */ 704 clockrt = args->op & LINUX_FUTEX_CLOCK_REALTIME; 705 args->op = args->op & ~LINUX_FUTEX_CLOCK_REALTIME; 706 if (clockrt && args->op != LINUX_FUTEX_WAIT_BITSET && |
472 args->op != LINUX_FUTEX_WAIT_REQUEUE_PI) | 707 args->op != LINUX_FUTEX_WAIT_REQUEUE_PI) { 708 LIN_SDT_PROBE0(futex, linux_sys_futex, 709 unimplemented_clockswitch); 710 LIN_SDT_PROBE1(futex, linux_sys_futex, return, ENOSYS); |
473 return (ENOSYS); | 711 return (ENOSYS); |
712 } |
|
474 475 error = 0; 476 f = f2 = NULL; 477 478 switch (args->op) { 479 case LINUX_FUTEX_WAIT: 480 args->val3 = FUTEX_BITSET_MATCH_ANY; 481 /* FALLTHROUGH */ 482 483 case LINUX_FUTEX_WAIT_BITSET: | 713 714 error = 0; 715 f = f2 = NULL; 716 717 switch (args->op) { 718 case LINUX_FUTEX_WAIT: 719 args->val3 = FUTEX_BITSET_MATCH_ANY; 720 /* FALLTHROUGH */ 721 722 case LINUX_FUTEX_WAIT_BITSET: |
484 | 723 LIN_SDT_PROBE3(futex, linux_sys_futex, debug_wait, args->uaddr, 724 args->val, args->val3); |
485 LINUX_CTR3(sys_futex, "WAIT uaddr %p val %d val3 %d", 486 args->uaddr, args->val, args->val3); | 725 LINUX_CTR3(sys_futex, "WAIT uaddr %p val %d val3 %d", 726 args->uaddr, args->val, args->val3); |
487#ifdef DEBUG 488 if (ldebug(sys_futex)) 489 printf(ARGS(sys_futex, 490 "futex_wait uaddr %p val %d val3 %d"), 491 args->uaddr, args->val, args->val3); 492#endif | 727 |
493 error = futex_get(args->uaddr, &wp, &f, 494 flags | FUTEX_CREATE_WP); | 728 error = futex_get(args->uaddr, &wp, &f, 729 flags | FUTEX_CREATE_WP); |
495 if (error) | 730 if (error) { 731 LIN_SDT_PROBE1(futex, linux_sys_futex, return, error); |
496 return (error); | 732 return (error); |
733 } 734 |
|
497 error = copyin(args->uaddr, &val, sizeof(val)); 498 if (error) { | 735 error = copyin(args->uaddr, &val, sizeof(val)); 736 if (error) { |
737 LIN_SDT_PROBE1(futex, linux_sys_futex, copyin_error, 738 error); |
|
499 LINUX_CTR1(sys_futex, "WAIT copyin failed %d", 500 error); 501 futex_put(f, wp); | 739 LINUX_CTR1(sys_futex, "WAIT copyin failed %d", 740 error); 741 futex_put(f, wp); |
742 743 LIN_SDT_PROBE1(futex, linux_sys_futex, return, error); |
|
502 return (error); 503 } 504 if (val != args->val) { | 744 return (error); 745 } 746 if (val != args->val) { |
747 LIN_SDT_PROBE4(futex, linux_sys_futex, 748 debug_wait_value_neq, args->uaddr, args->val, val, 749 args->val3); |
|
505 LINUX_CTR4(sys_futex, 506 "WAIT uaddr %p val %d != uval %d val3 %d", 507 args->uaddr, args->val, val, args->val3); 508 futex_put(f, wp); | 750 LINUX_CTR4(sys_futex, 751 "WAIT uaddr %p val %d != uval %d val3 %d", 752 args->uaddr, args->val, val, args->val3); 753 futex_put(f, wp); |
754 755 LIN_SDT_PROBE1(futex, linux_sys_futex, return, 756 EWOULDBLOCK); |
|
509 return (EWOULDBLOCK); 510 } 511 512 error = futex_wait(f, wp, args->timeout, args->val3); 513 break; 514 515 case LINUX_FUTEX_WAKE: 516 args->val3 = FUTEX_BITSET_MATCH_ANY; 517 /* FALLTHROUGH */ 518 519 case LINUX_FUTEX_WAKE_BITSET: | 757 return (EWOULDBLOCK); 758 } 759 760 error = futex_wait(f, wp, args->timeout, args->val3); 761 break; 762 763 case LINUX_FUTEX_WAKE: 764 args->val3 = FUTEX_BITSET_MATCH_ANY; 765 /* FALLTHROUGH */ 766 767 case LINUX_FUTEX_WAKE_BITSET: |
520 | 768 LIN_SDT_PROBE3(futex, linux_sys_futex, debug_wake, args->uaddr, 769 args->val, args->val3); |
521 LINUX_CTR3(sys_futex, "WAKE uaddr %p val % d val3 %d", 522 args->uaddr, args->val, args->val3); 523 | 770 LINUX_CTR3(sys_futex, "WAKE uaddr %p val % d val3 %d", 771 args->uaddr, args->val, args->val3); 772 |
524#ifdef DEBUG 525 if (ldebug(sys_futex)) 526 printf(ARGS(sys_futex, "futex_wake uaddr %p val %d val3 %d"), 527 args->uaddr, args->val, args->val3); 528#endif | |
529 error = futex_get(args->uaddr, NULL, &f, 530 flags | FUTEX_DONTCREATE); | 773 error = futex_get(args->uaddr, NULL, &f, 774 flags | FUTEX_DONTCREATE); |
531 if (error) | 775 if (error) { 776 LIN_SDT_PROBE1(futex, linux_sys_futex, return, error); |
532 return (error); | 777 return (error); |
778 } 779 |
|
533 if (f == NULL) { 534 td->td_retval[0] = 0; | 780 if (f == NULL) { 781 td->td_retval[0] = 0; |
782 783 LIN_SDT_PROBE1(futex, linux_sys_futex, return, error); |
|
535 return (error); 536 } 537 td->td_retval[0] = futex_wake(f, args->val, args->val3); 538 futex_put(f, NULL); 539 break; 540 541 case LINUX_FUTEX_CMP_REQUEUE: | 784 return (error); 785 } 786 td->td_retval[0] = futex_wake(f, args->val, args->val3); 787 futex_put(f, NULL); 788 break; 789 790 case LINUX_FUTEX_CMP_REQUEUE: |
542 | 791 LIN_SDT_PROBE5(futex, linux_sys_futex, debug_cmp_requeue, 792 args->uaddr, args->val, args->val3, args->uaddr2, 793 args->timeout); |
543 LINUX_CTR5(sys_futex, "CMP_REQUEUE uaddr %p " 544 "val %d val3 %d uaddr2 %p val2 %d", 545 args->uaddr, args->val, args->val3, args->uaddr2, 546 (int)(unsigned long)args->timeout); 547 | 794 LINUX_CTR5(sys_futex, "CMP_REQUEUE uaddr %p " 795 "val %d val3 %d uaddr2 %p val2 %d", 796 args->uaddr, args->val, args->val3, args->uaddr2, 797 (int)(unsigned long)args->timeout); 798 |
548#ifdef DEBUG 549 if (ldebug(sys_futex)) 550 printf(ARGS(sys_futex, "futex_cmp_requeue uaddr %p " 551 "val %d val3 %d uaddr2 %p val2 %d"), 552 args->uaddr, args->val, args->val3, args->uaddr2, 553 (int)(unsigned long)args->timeout); 554#endif 555 | |
556 /* 557 * Linux allows this, we would not, it is an incorrect 558 * usage of declared ABI, so return EINVAL. 559 */ | 799 /* 800 * Linux allows this, we would not, it is an incorrect 801 * usage of declared ABI, so return EINVAL. 802 */ |
560 if (args->uaddr == args->uaddr2) | 803 if (args->uaddr == args->uaddr2) { 804 LIN_SDT_PROBE0(futex, linux_sys_futex, 805 invalid_cmp_requeue_use); 806 LIN_SDT_PROBE1(futex, linux_sys_futex, return, EINVAL); |
561 return (EINVAL); | 807 return (EINVAL); |
808 } 809 |
|
562 error = futex_get(args->uaddr, NULL, &f, flags); | 810 error = futex_get(args->uaddr, NULL, &f, flags); |
563 if (error) | 811 if (error) { 812 LIN_SDT_PROBE1(futex, linux_sys_futex, return, error); |
564 return (error); | 813 return (error); |
814 } |
|
565 566 /* 567 * To avoid deadlocks return EINVAL if second futex 568 * exists at this time. 569 * 570 * Glibc fall back to FUTEX_WAKE in case of any error 571 * returned by FUTEX_CMP_REQUEUE. 572 */ 573 error = futex_get(args->uaddr2, NULL, &f2, 574 flags | FUTEX_DONTEXISTS); 575 if (error) { 576 futex_put(f, NULL); | 815 816 /* 817 * To avoid deadlocks return EINVAL if second futex 818 * exists at this time. 819 * 820 * Glibc fall back to FUTEX_WAKE in case of any error 821 * returned by FUTEX_CMP_REQUEUE. 822 */ 823 error = futex_get(args->uaddr2, NULL, &f2, 824 flags | FUTEX_DONTEXISTS); 825 if (error) { 826 futex_put(f, NULL); |
827 828 LIN_SDT_PROBE1(futex, linux_sys_futex, return, error); |
|
577 return (error); 578 } 579 error = copyin(args->uaddr, &val, sizeof(val)); 580 if (error) { | 829 return (error); 830 } 831 error = copyin(args->uaddr, &val, sizeof(val)); 832 if (error) { |
833 LIN_SDT_PROBE1(futex, linux_sys_futex, copyin_error, 834 error); |
|
581 LINUX_CTR1(sys_futex, "CMP_REQUEUE copyin failed %d", 582 error); 583 futex_put(f2, NULL); 584 futex_put(f, NULL); | 835 LINUX_CTR1(sys_futex, "CMP_REQUEUE copyin failed %d", 836 error); 837 futex_put(f2, NULL); 838 futex_put(f, NULL); |
839 840 LIN_SDT_PROBE1(futex, linux_sys_futex, return, error); |
|
585 return (error); 586 } 587 if (val != args->val3) { | 841 return (error); 842 } 843 if (val != args->val3) { |
844 LIN_SDT_PROBE2(futex, linux_sys_futex, 845 debug_cmp_requeue_value_neq, args->val, val); |
|
588 LINUX_CTR2(sys_futex, "CMP_REQUEUE val %d != uval %d", 589 args->val, val); 590 futex_put(f2, NULL); 591 futex_put(f, NULL); | 846 LINUX_CTR2(sys_futex, "CMP_REQUEUE val %d != uval %d", 847 args->val, val); 848 futex_put(f2, NULL); 849 futex_put(f, NULL); |
850 851 LIN_SDT_PROBE1(futex, linux_sys_futex, return, EAGAIN); |
|
592 return (EAGAIN); 593 } 594 595 nrwake = (int)(unsigned long)args->timeout; 596 td->td_retval[0] = futex_requeue(f, args->val, f2, nrwake); 597 futex_put(f2, NULL); 598 futex_put(f, NULL); 599 break; 600 601 case LINUX_FUTEX_WAKE_OP: | 852 return (EAGAIN); 853 } 854 855 nrwake = (int)(unsigned long)args->timeout; 856 td->td_retval[0] = futex_requeue(f, args->val, f2, nrwake); 857 futex_put(f2, NULL); 858 futex_put(f, NULL); 859 break; 860 861 case LINUX_FUTEX_WAKE_OP: |
602 | 862 LIN_SDT_PROBE5(futex, linux_sys_futex, debug_wake_op, 863 args->uaddr, args->op, args->val, args->uaddr2, args->val3); |
603 LINUX_CTR5(sys_futex, "WAKE_OP " 604 "uaddr %p op %d val %x uaddr2 %p val3 %x", 605 args->uaddr, args->op, args->val, 606 args->uaddr2, args->val3); 607 | 864 LINUX_CTR5(sys_futex, "WAKE_OP " 865 "uaddr %p op %d val %x uaddr2 %p val3 %x", 866 args->uaddr, args->op, args->val, 867 args->uaddr2, args->val3); 868 |
608#ifdef DEBUG 609 if (ldebug(sys_futex)) 610 printf(ARGS(sys_futex, "futex_wake_op " 611 "uaddr %p op %d val %x uaddr2 %p val3 %x"), 612 args->uaddr, args->op, args->val, 613 args->uaddr2, args->val3); 614#endif | |
615 error = futex_get(args->uaddr, NULL, &f, flags); | 869 error = futex_get(args->uaddr, NULL, &f, flags); |
616 if (error) | 870 if (error) { 871 LIN_SDT_PROBE1(futex, linux_sys_futex, return, error); |
617 return (error); | 872 return (error); |
873 } 874 |
|
618 if (args->uaddr != args->uaddr2) 619 error = futex_get(args->uaddr2, NULL, &f2, flags); 620 if (error) { 621 futex_put(f, NULL); | 875 if (args->uaddr != args->uaddr2) 876 error = futex_get(args->uaddr2, NULL, &f2, flags); 877 if (error) { 878 futex_put(f, NULL); |
879 880 LIN_SDT_PROBE1(futex, linux_sys_futex, return, error); |
|
622 return (error); 623 } 624 625 /* 626 * This function returns positive number as results and 627 * negative as errors 628 */ 629 op_ret = futex_atomic_op(td, args->val3, args->uaddr2); 630 631 if (op_ret < 0) { 632 /* XXX: We don't handle the EFAULT yet. */ 633 if (op_ret != -EFAULT) { 634 if (f2 != NULL) 635 futex_put(f2, NULL); 636 futex_put(f, NULL); | 881 return (error); 882 } 883 884 /* 885 * This function returns positive number as results and 886 * negative as errors 887 */ 888 op_ret = futex_atomic_op(td, args->val3, args->uaddr2); 889 890 if (op_ret < 0) { 891 /* XXX: We don't handle the EFAULT yet. */ 892 if (op_ret != -EFAULT) { 893 if (f2 != NULL) 894 futex_put(f2, NULL); 895 futex_put(f, NULL); |
896 897 LIN_SDT_PROBE1(futex, linux_sys_futex, return, 898 -op_ret); |
|
637 return (-op_ret); | 899 return (-op_ret); |
900 } else { 901 LIN_SDT_PROBE0(futex, linux_sys_futex, 902 unhandled_efault); |
|
638 } 639 if (f2 != NULL) 640 futex_put(f2, NULL); 641 futex_put(f, NULL); | 903 } 904 if (f2 != NULL) 905 futex_put(f2, NULL); 906 futex_put(f, NULL); |
907 908 LIN_SDT_PROBE1(futex, linux_sys_futex, return, EFAULT); |
|
642 return (EFAULT); 643 } 644 645 ret = futex_wake(f, args->val, args->val3); 646 647 if (op_ret > 0) { 648 op_ret = 0; 649 nrwake = (int)(unsigned long)args->timeout; --- 11 unchanged lines hidden (view full) --- 661 td->td_retval[0] = ret; 662 break; 663 664 case LINUX_FUTEX_LOCK_PI: 665 /* not yet implemented */ 666 linux_msg(td, 667 "linux_sys_futex: " 668 "op LINUX_FUTEX_LOCK_PI not implemented\n"); | 909 return (EFAULT); 910 } 911 912 ret = futex_wake(f, args->val, args->val3); 913 914 if (op_ret > 0) { 915 op_ret = 0; 916 nrwake = (int)(unsigned long)args->timeout; --- 11 unchanged lines hidden (view full) --- 928 td->td_retval[0] = ret; 929 break; 930 931 case LINUX_FUTEX_LOCK_PI: 932 /* not yet implemented */ 933 linux_msg(td, 934 "linux_sys_futex: " 935 "op LINUX_FUTEX_LOCK_PI not implemented\n"); |
936 LIN_SDT_PROBE0(futex, linux_sys_futex, unimplemented_lock_pi); 937 LIN_SDT_PROBE1(futex, linux_sys_futex, return, ENOSYS); |
|
669 return (ENOSYS); 670 671 case LINUX_FUTEX_UNLOCK_PI: 672 /* not yet implemented */ 673 linux_msg(td, 674 "linux_sys_futex: " 675 "op LINUX_FUTEX_UNLOCK_PI not implemented\n"); | 938 return (ENOSYS); 939 940 case LINUX_FUTEX_UNLOCK_PI: 941 /* not yet implemented */ 942 linux_msg(td, 943 "linux_sys_futex: " 944 "op LINUX_FUTEX_UNLOCK_PI not implemented\n"); |
945 LIN_SDT_PROBE0(futex, linux_sys_futex, unimplemented_unlock_pi); 946 LIN_SDT_PROBE1(futex, linux_sys_futex, return, ENOSYS); |
|
676 return (ENOSYS); 677 678 case LINUX_FUTEX_TRYLOCK_PI: 679 /* not yet implemented */ 680 linux_msg(td, 681 "linux_sys_futex: " 682 "op LINUX_FUTEX_TRYLOCK_PI not implemented\n"); | 947 return (ENOSYS); 948 949 case LINUX_FUTEX_TRYLOCK_PI: 950 /* not yet implemented */ 951 linux_msg(td, 952 "linux_sys_futex: " 953 "op LINUX_FUTEX_TRYLOCK_PI not implemented\n"); |
954 LIN_SDT_PROBE0(futex, linux_sys_futex, 955 unimplemented_trylock_pi); 956 LIN_SDT_PROBE1(futex, linux_sys_futex, return, ENOSYS); |
|
683 return (ENOSYS); 684 685 case LINUX_FUTEX_REQUEUE: 686 687 /* 688 * Glibc does not use this operation since version 2.3.3, 689 * as it is racy and replaced by FUTEX_CMP_REQUEUE operation. 690 * Glibc versions prior to 2.3.3 fall back to FUTEX_WAKE when 691 * FUTEX_REQUEUE returned EINVAL. 692 */ 693 em = em_find(td->td_proc, EMUL_DONTLOCK); 694 if ((em->flags & LINUX_XDEPR_REQUEUEOP) == 0) { 695 linux_msg(td, 696 "linux_sys_futex: " 697 "unsupported futex_requeue op\n"); 698 em->flags |= LINUX_XDEPR_REQUEUEOP; | 957 return (ENOSYS); 958 959 case LINUX_FUTEX_REQUEUE: 960 961 /* 962 * Glibc does not use this operation since version 2.3.3, 963 * as it is racy and replaced by FUTEX_CMP_REQUEUE operation. 964 * Glibc versions prior to 2.3.3 fall back to FUTEX_WAKE when 965 * FUTEX_REQUEUE returned EINVAL. 966 */ 967 em = em_find(td->td_proc, EMUL_DONTLOCK); 968 if ((em->flags & LINUX_XDEPR_REQUEUEOP) == 0) { 969 linux_msg(td, 970 "linux_sys_futex: " 971 "unsupported futex_requeue op\n"); 972 em->flags |= LINUX_XDEPR_REQUEUEOP; |
973 LIN_SDT_PROBE0(futex, linux_sys_futex, 974 deprecated_requeue); |
|
699 } | 975 } |
976 977 LIN_SDT_PROBE1(futex, linux_sys_futex, return, EINVAL); |
|
700 return (EINVAL); 701 702 case LINUX_FUTEX_WAIT_REQUEUE_PI: 703 /* not yet implemented */ 704 linux_msg(td, 705 "linux_sys_futex: " 706 "op FUTEX_WAIT_REQUEUE_PI not implemented\n"); | 978 return (EINVAL); 979 980 case LINUX_FUTEX_WAIT_REQUEUE_PI: 981 /* not yet implemented */ 982 linux_msg(td, 983 "linux_sys_futex: " 984 "op FUTEX_WAIT_REQUEUE_PI not implemented\n"); |
985 LIN_SDT_PROBE0(futex, linux_sys_futex, 986 unimplemented_wait_requeue_pi); 987 LIN_SDT_PROBE1(futex, linux_sys_futex, return, ENOSYS); |
|
707 return (ENOSYS); 708 709 case LINUX_FUTEX_CMP_REQUEUE_PI: 710 /* not yet implemented */ 711 linux_msg(td, 712 "linux_sys_futex: " 713 "op LINUX_FUTEX_CMP_REQUEUE_PI not implemented\n"); | 988 return (ENOSYS); 989 990 case LINUX_FUTEX_CMP_REQUEUE_PI: 991 /* not yet implemented */ 992 linux_msg(td, 993 "linux_sys_futex: " 994 "op LINUX_FUTEX_CMP_REQUEUE_PI not implemented\n"); |
995 LIN_SDT_PROBE0(futex, linux_sys_futex, 996 unimplemented_cmp_requeue_pi); 997 LIN_SDT_PROBE1(futex, linux_sys_futex, return, ENOSYS); |
|
714 return (ENOSYS); 715 716 default: 717 linux_msg(td, 718 "linux_sys_futex: unknown op %d\n", args->op); | 998 return (ENOSYS); 999 1000 default: 1001 linux_msg(td, 1002 "linux_sys_futex: unknown op %d\n", args->op); |
1003 LIN_SDT_PROBE1(futex, linux_sys_futex, unknown_operation, 1004 args->op); 1005 LIN_SDT_PROBE1(futex, linux_sys_futex, return, ENOSYS); |
|
719 return (ENOSYS); 720 } 721 | 1006 return (ENOSYS); 1007 } 1008 |
1009 LIN_SDT_PROBE1(futex, linux_sys_futex, return, error); |
|
722 return (error); 723} 724 725int 726linux_set_robust_list(struct thread *td, struct linux_set_robust_list_args *args) 727{ 728 struct linux_emuldata *em; 729 | 1010 return (error); 1011} 1012 1013int 1014linux_set_robust_list(struct thread *td, struct linux_set_robust_list_args *args) 1015{ 1016 struct linux_emuldata *em; 1017 |
730#ifdef DEBUG 731 if (ldebug(set_robust_list)) 732 printf(ARGS(set_robust_list, "head %p len %d"), 733 args->head, args->len); 734#endif | 1018 LIN_SDT_PROBE2(futex, linux_set_robust_list, entry, td, args); |
735 | 1019 |
736 if (args->len != sizeof(struct linux_robust_list_head)) | 1020 if (args->len != sizeof(struct linux_robust_list_head)) { 1021 LIN_SDT_PROBE0(futex, linux_set_robust_list, size_error); 1022 LIN_SDT_PROBE1(futex, linux_set_robust_list, return, EINVAL); |
737 return (EINVAL); | 1023 return (EINVAL); |
1024 } |
|
738 739 em = em_find(td->td_proc, EMUL_DOLOCK); 740 em->robust_futexes = args->head; 741 EMUL_UNLOCK(&emul_lock); 742 | 1025 1026 em = em_find(td->td_proc, EMUL_DOLOCK); 1027 em->robust_futexes = args->head; 1028 EMUL_UNLOCK(&emul_lock); 1029 |
1030 LIN_SDT_PROBE1(futex, linux_set_robust_list, return, 0); |
|
743 return (0); 744} 745 746int 747linux_get_robust_list(struct thread *td, struct linux_get_robust_list_args *args) 748{ 749 struct linux_emuldata *em; 750 struct linux_robust_list_head *head; 751 l_size_t len = sizeof(struct linux_robust_list_head); 752 int error = 0; 753 | 1031 return (0); 1032} 1033 1034int 1035linux_get_robust_list(struct thread *td, struct linux_get_robust_list_args *args) 1036{ 1037 struct linux_emuldata *em; 1038 struct linux_robust_list_head *head; 1039 l_size_t len = sizeof(struct linux_robust_list_head); 1040 int error = 0; 1041 |
754#ifdef DEBUG 755 if (ldebug(get_robust_list)) 756 printf(ARGS(get_robust_list, "")); 757#endif | 1042 LIN_SDT_PROBE2(futex, linux_get_robust_list, entry, td, args); |
758 759 if (!args->pid) { 760 em = em_find(td->td_proc, EMUL_DONTLOCK); 761 head = em->robust_futexes; 762 } else { 763 struct proc *p; 764 765 p = pfind(args->pid); | 1043 1044 if (!args->pid) { 1045 em = em_find(td->td_proc, EMUL_DONTLOCK); 1046 head = em->robust_futexes; 1047 } else { 1048 struct proc *p; 1049 1050 p = pfind(args->pid); |
766 if (p == NULL) | 1051 if (p == NULL) { 1052 LIN_SDT_PROBE1(futex, linux_get_robust_list, return, 1053 ESRCH); |
767 return (ESRCH); | 1054 return (ESRCH); |
1055 } |
|
768 769 em = em_find(p, EMUL_DONTLOCK); 770 /* XXX: ptrace? */ 771 if (priv_check(td, PRIV_CRED_SETUID) || 772 priv_check(td, PRIV_CRED_SETEUID) || 773 p_candebug(td, p)) { 774 PROC_UNLOCK(p); | 1056 1057 em = em_find(p, EMUL_DONTLOCK); 1058 /* XXX: ptrace? */ 1059 if (priv_check(td, PRIV_CRED_SETUID) || 1060 priv_check(td, PRIV_CRED_SETEUID) || 1061 p_candebug(td, p)) { 1062 PROC_UNLOCK(p); |
1063 1064 LIN_SDT_PROBE1(futex, linux_get_robust_list, return, 1065 EPERM); |
|
775 return (EPERM); 776 } 777 head = em->robust_futexes; 778 779 PROC_UNLOCK(p); 780 } 781 782 error = copyout(&len, args->len, sizeof(l_size_t)); | 1066 return (EPERM); 1067 } 1068 head = em->robust_futexes; 1069 1070 PROC_UNLOCK(p); 1071 } 1072 1073 error = copyout(&len, args->len, sizeof(l_size_t)); |
783 if (error) | 1074 if (error) { 1075 LIN_SDT_PROBE1(futex, linux_get_robust_list, copyout_error, 1076 error); 1077 LIN_SDT_PROBE1(futex, linux_get_robust_list, return, EFAULT); |
784 return (EFAULT); | 1078 return (EFAULT); |
1079 } |
|
785 786 error = copyout(head, args->head, sizeof(struct linux_robust_list_head)); | 1080 1081 error = copyout(head, args->head, sizeof(struct linux_robust_list_head)); |
1082 if (error) { 1083 LIN_SDT_PROBE1(futex, linux_get_robust_list, copyout_error, 1084 error); 1085 } |
|
787 | 1086 |
1087 LIN_SDT_PROBE1(futex, linux_get_robust_list, return, error); |
|
788 return (error); 789} 790 791static int 792handle_futex_death(struct proc *p, uint32_t *uaddr, int pi) 793{ 794 uint32_t uval, nval, mval; 795 struct futex *f; 796 int error; 797 | 1088 return (error); 1089} 1090 1091static int 1092handle_futex_death(struct proc *p, uint32_t *uaddr, int pi) 1093{ 1094 uint32_t uval, nval, mval; 1095 struct futex *f; 1096 int error; 1097 |
1098 LIN_SDT_PROBE3(futex, handle_futex_death, entry, p, uaddr, pi); 1099 |
|
798retry: | 1100retry: |
799 if (copyin(uaddr, &uval, 4)) | 1101 error = copyin(uaddr, &uval, 4); 1102 if (error) { 1103 LIN_SDT_PROBE1(futex, handle_futex_death, copyin_error, error); 1104 LIN_SDT_PROBE1(futex, handle_futex_death, return, EFAULT); |
800 return (EFAULT); | 1105 return (EFAULT); |
1106 } |
|
801 if ((uval & FUTEX_TID_MASK) == p->p_pid) { 802 mval = (uval & FUTEX_WAITERS) | FUTEX_OWNER_DIED; 803 nval = casuword32(uaddr, uval, mval); 804 | 1107 if ((uval & FUTEX_TID_MASK) == p->p_pid) { 1108 mval = (uval & FUTEX_WAITERS) | FUTEX_OWNER_DIED; 1109 nval = casuword32(uaddr, uval, mval); 1110 |
805 if (nval == -1) | 1111 if (nval == -1) { 1112 LIN_SDT_PROBE1(futex, handle_futex_death, return, 1113 EFAULT); |
806 return (EFAULT); | 1114 return (EFAULT); |
1115 } |
|
807 808 if (nval != uval) 809 goto retry; 810 811 if (!pi && (uval & FUTEX_WAITERS)) { 812 error = futex_get(uaddr, NULL, &f, 813 FUTEX_DONTCREATE | FUTEX_SHARED); | 1116 1117 if (nval != uval) 1118 goto retry; 1119 1120 if (!pi && (uval & FUTEX_WAITERS)) { 1121 error = futex_get(uaddr, NULL, &f, 1122 FUTEX_DONTCREATE | FUTEX_SHARED); |
814 if (error) | 1123 if (error) { 1124 LIN_SDT_PROBE1(futex, handle_futex_death, 1125 return, error); |
815 return (error); | 1126 return (error); |
1127 } |
|
816 if (f != NULL) { 817 futex_wake(f, 1, FUTEX_BITSET_MATCH_ANY); 818 futex_put(f, NULL); 819 } 820 } 821 } 822 | 1128 if (f != NULL) { 1129 futex_wake(f, 1, FUTEX_BITSET_MATCH_ANY); 1130 futex_put(f, NULL); 1131 } 1132 } 1133 } 1134 |
1135 LIN_SDT_PROBE1(futex, handle_futex_death, return, 0); |
|
823 return (0); 824} 825 826static int 827fetch_robust_entry(struct linux_robust_list **entry, 828 struct linux_robust_list **head, int *pi) 829{ 830 l_ulong uentry; | 1136 return (0); 1137} 1138 1139static int 1140fetch_robust_entry(struct linux_robust_list **entry, 1141 struct linux_robust_list **head, int *pi) 1142{ 1143 l_ulong uentry; |
1144 int error; |
|
831 | 1145 |
832 if (copyin((const void *)head, &uentry, sizeof(l_ulong))) | 1146 LIN_SDT_PROBE3(futex, fetch_robust_entry, entry, entry, head, pi); 1147 1148 error = copyin((const void *)head, &uentry, sizeof(l_ulong)); 1149 if (error) { 1150 LIN_SDT_PROBE1(futex, fetch_robust_entry, copyin_error, error); 1151 LIN_SDT_PROBE1(futex, fetch_robust_entry, return, EFAULT); |
833 return (EFAULT); | 1152 return (EFAULT); |
1153 } |
|
834 835 *entry = (void *)(uentry & ~1UL); 836 *pi = uentry & 1; 837 | 1154 1155 *entry = (void *)(uentry & ~1UL); 1156 *pi = uentry & 1; 1157 |
1158 LIN_SDT_PROBE1(futex, fetch_robust_entry, return, 0); |
|
838 return (0); 839} 840 841/* This walks the list of robust futexes releasing them. */ 842void 843release_futexes(struct proc *p) 844{ 845 struct linux_robust_list_head *head = NULL; 846 struct linux_robust_list *entry, *next_entry, *pending; 847 unsigned int limit = 2048, pi, next_pi, pip; 848 struct linux_emuldata *em; 849 l_long futex_offset; | 1159 return (0); 1160} 1161 1162/* This walks the list of robust futexes releasing them. */ 1163void 1164release_futexes(struct proc *p) 1165{ 1166 struct linux_robust_list_head *head = NULL; 1167 struct linux_robust_list *entry, *next_entry, *pending; 1168 unsigned int limit = 2048, pi, next_pi, pip; 1169 struct linux_emuldata *em; 1170 l_long futex_offset; |
850 int rc; | 1171 int rc, error; |
851 | 1172 |
1173 LIN_SDT_PROBE1(futex, release_futexes, entry, p); 1174 |
|
852 em = em_find(p, EMUL_DONTLOCK); 853 head = em->robust_futexes; 854 | 1175 em = em_find(p, EMUL_DONTLOCK); 1176 head = em->robust_futexes; 1177 |
855 if (head == NULL) | 1178 if (head == NULL) { 1179 LIN_SDT_PROBE0(futex, release_futexes, return); |
856 return; | 1180 return; |
1181 } |
|
857 | 1182 |
858 if (fetch_robust_entry(&entry, PTRIN(&head->list.next), &pi)) | 1183 if (fetch_robust_entry(&entry, PTRIN(&head->list.next), &pi)) { 1184 LIN_SDT_PROBE0(futex, release_futexes, return); |
859 return; | 1185 return; |
1186 } |
|
860 | 1187 |
861 if (copyin(&head->futex_offset, &futex_offset, sizeof(futex_offset))) | 1188 error = copyin(&head->futex_offset, &futex_offset, 1189 sizeof(futex_offset)); 1190 if (error) { 1191 LIN_SDT_PROBE1(futex, release_futexes, copyin_error, error); 1192 LIN_SDT_PROBE0(futex, release_futexes, return); |
862 return; | 1193 return; |
1194 } |
|
863 | 1195 |
864 if (fetch_robust_entry(&pending, PTRIN(&head->pending_list), &pip)) | 1196 if (fetch_robust_entry(&pending, PTRIN(&head->pending_list), &pip)) { 1197 LIN_SDT_PROBE0(futex, release_futexes, return); |
865 return; | 1198 return; |
1199 } |
|
866 867 while (entry != &head->list) { 868 rc = fetch_robust_entry(&next_entry, PTRIN(&entry->next), &next_pi); 869 870 if (entry != pending) | 1200 1201 while (entry != &head->list) { 1202 rc = fetch_robust_entry(&next_entry, PTRIN(&entry->next), &next_pi); 1203 1204 if (entry != pending) |
871 if (handle_futex_death(p, (uint32_t *)entry + futex_offset, pi)) | 1205 if (handle_futex_death(p, 1206 (uint32_t *)entry + futex_offset, pi)) { 1207 LIN_SDT_PROBE0(futex, release_futexes, return); |
872 return; | 1208 return; |
873 if (rc) | 1209 } 1210 if (rc) { 1211 LIN_SDT_PROBE0(futex, release_futexes, return); |
874 return; | 1212 return; |
1213 } |
|
875 876 entry = next_entry; 877 pi = next_pi; 878 879 if (!--limit) 880 break; 881 882 sched_relinquish(curthread); 883 } 884 885 if (pending) 886 handle_futex_death(p, (uint32_t *)pending + futex_offset, pip); | 1214 1215 entry = next_entry; 1216 pi = next_pi; 1217 1218 if (!--limit) 1219 break; 1220 1221 sched_relinquish(curthread); 1222 } 1223 1224 if (pending) 1225 handle_futex_death(p, (uint32_t *)pending + futex_offset, pip); |
1226 1227 LIN_SDT_PROBE0(futex, release_futexes, return); |
|
887} | 1228} |