1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3 *
4 * Copyright (c) 2018 The FreeBSD Foundation
5 *
6 * This software was developed by Konstantin Belousov <kib@FreeBSD.org>
7 * under sponsorship from the FreeBSD Foundation.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE.
29 */
30
31 #include <sys/cdefs.h>
32 __FBSDID("$FreeBSD$");
33
34 #include "opt_compat.h"
35
36 #include <sys/param.h>
37 #include <sys/systm.h>
38 #include <sys/imgact.h>
39 #include <sys/lock.h>
40 #include <sys/sx.h>
41 #include <vm/vm.h>
42 #include <vm/vm_param.h>
43 #include <vm/vm_extern.h>
44 #include <vm/pmap.h>
45
46 #include <machine/atomic.h>
47 #include <machine/md_var.h>
48
49 #include <compat/linux/linux_emul.h>
50 #include <compat/linux/linux_futex.h>
51
52 struct futex_st0 {
53 int oparg;
54 int *oldval;
55 };
56
57 static void
58 futex_xchgl_slow0(vm_offset_t kva, void *arg)
59 {
60 struct futex_st0 *st;
61
62 st = arg;
63 *st->oldval = atomic_swap_int((int *)kva, st->oparg);
64 }
65
66 int
67 futex_xchgl(int oparg, uint32_t *uaddr, int *oldval)
68 {
69 struct futex_st0 st;
70
71 st.oparg = oparg;
72 st.oldval = oldval;
73 if (cp_slow0((vm_offset_t)uaddr, sizeof(uint32_t), true,
74 futex_xchgl_slow0, &st) != 0)
75 return (EFAULT);
76 return (0);
77 }
78
79 static void
80 futex_addl_slow0(vm_offset_t kva, void *arg)
81 {
82 struct futex_st0 *st;
83
84 st = arg;
85 *st->oldval = atomic_fetchadd_int((int *)kva, st->oparg);
86 }
87
88 int
89 futex_addl(int oparg, uint32_t *uaddr, int *oldval)
90 {
91 struct futex_st0 st;
92
93 st.oparg = oparg;
94 st.oldval = oldval;
95 if (cp_slow0((vm_offset_t)uaddr, sizeof(uint32_t), true,
96 futex_addl_slow0, &st) != 0)
97 return (EFAULT);
98 return (0);
99 }
100
101 static void
102 futex_orl_slow0(vm_offset_t kva, void *arg)
103 {
104 struct futex_st0 *st;
105 int old;
106
107 st = arg;
108 old = *(int *)kva;
109 while (!atomic_fcmpset_int((int *)kva, &old, old | st->oparg))
110 ;
111 *st->oldval = old;
112 }
113
114 int
115 futex_orl(int oparg, uint32_t *uaddr, int *oldval)
116 {
117 struct futex_st0 st;
118
119 st.oparg = oparg;
120 st.oldval = oldval;
121 if (cp_slow0((vm_offset_t)uaddr, sizeof(uint32_t), true,
122 futex_orl_slow0, &st) != 0)
123 return (EFAULT);
124 return (0);
125 }
126
127 static void
128 futex_andl_slow0(vm_offset_t kva, void *arg)
129 {
130 struct futex_st0 *st;
131 int old;
132
133 st = arg;
134 old = *(int *)kva;
135 while (!atomic_fcmpset_int((int *)kva, &old, old & st->oparg))
136 ;
137 *st->oldval = old;
138 }
139
140 int
141 futex_andl(int oparg, uint32_t *uaddr, int *oldval)
142 {
143 struct futex_st0 st;
144
145 st.oparg = oparg;
146 st.oldval = oldval;
147 if (cp_slow0((vm_offset_t)uaddr, sizeof(uint32_t), true,
148 futex_andl_slow0, &st) != 0)
149 return (EFAULT);
150 return (0);
151 }
152
153 static void
154 futex_xorl_slow0(vm_offset_t kva, void *arg)
155 {
156 struct futex_st0 *st;
157 int old;
158
159 st = arg;
160 old = *(int *)kva;
161 while (!atomic_fcmpset_int((int *)kva, &old, old ^ st->oparg))
162 ;
163 *st->oldval = old;
164 }
165
166 int
167 futex_xorl(int oparg, uint32_t *uaddr, int *oldval)
168 {
169 struct futex_st0 st;
170
171 st.oparg = oparg;
172 st.oldval = oldval;
173 if (cp_slow0((vm_offset_t)uaddr, sizeof(uint32_t), true,
174 futex_xorl_slow0, &st) != 0)
175 return (EFAULT);
176 return (0);
177 }
Cache object: 8e1e555c9cac3c103c9d8fe1fc91eff5
|