1*b30d1939SAndy Fiddaman /***********************************************************************
2*b30d1939SAndy Fiddaman *                                                                      *
3*b30d1939SAndy Fiddaman *               This software is part of the ast package               *
4*b30d1939SAndy Fiddaman *          Copyright (c) 1985-2012 AT&T Intellectual Property          *
5*b30d1939SAndy Fiddaman *                      and is licensed under the                       *
6*b30d1939SAndy Fiddaman *                 Eclipse Public License, Version 1.0                  *
7*b30d1939SAndy Fiddaman *                    by AT&T Intellectual Property                     *
8*b30d1939SAndy Fiddaman *                                                                      *
9*b30d1939SAndy Fiddaman *                A copy of the License is available at                 *
10*b30d1939SAndy Fiddaman *          http://www.eclipse.org/org/documents/epl-v10.html           *
11*b30d1939SAndy Fiddaman *         (with md5 checksum b35adb5213ca9657e911e9befb180842)         *
12*b30d1939SAndy Fiddaman *                                                                      *
13*b30d1939SAndy Fiddaman *              Information and Software Systems Research               *
14*b30d1939SAndy Fiddaman *                            AT&T Research                             *
15*b30d1939SAndy Fiddaman *                           Florham Park NJ                            *
16*b30d1939SAndy Fiddaman *                                                                      *
17*b30d1939SAndy Fiddaman *                 Glenn Fowler <gsf@research.att.com>                  *
18*b30d1939SAndy Fiddaman *                  David Korn <dgk@research.att.com>                   *
19*b30d1939SAndy Fiddaman *                   Phong Vo <kpv@research.att.com>                    *
20*b30d1939SAndy Fiddaman *                                                                      *
21*b30d1939SAndy Fiddaman ***********************************************************************/
22*b30d1939SAndy Fiddaman #pragma prototyped
23*b30d1939SAndy Fiddaman 
24*b30d1939SAndy Fiddaman #include "asohdr.h"
25*b30d1939SAndy Fiddaman #include "FEATURE/aso"
26*b30d1939SAndy Fiddaman 
27*b30d1939SAndy Fiddaman #if defined(_UWIN) && defined(_BLD_ast)
28*b30d1939SAndy Fiddaman 
29*b30d1939SAndy Fiddaman NoN(aso)
30*b30d1939SAndy Fiddaman 
31*b30d1939SAndy Fiddaman #else
32*b30d1939SAndy Fiddaman 
33*b30d1939SAndy Fiddaman /*
34*b30d1939SAndy Fiddaman  * ast atomic scalar operations
35*b30d1939SAndy Fiddaman  * AT&T Research
36*b30d1939SAndy Fiddaman  *
37*b30d1939SAndy Fiddaman  * cas { 8 16 32 [64] } subset snarfed from the work by
38*b30d1939SAndy Fiddaman  * Adam Edgar and Kiem-Phong Vo 2010-10-10
39*b30d1939SAndy Fiddaman  *
40*b30d1939SAndy Fiddaman  * lock methods and emulations by
41*b30d1939SAndy Fiddaman  * Glenn Fowler 2011-11-11
42*b30d1939SAndy Fiddaman  *
43*b30d1939SAndy Fiddaman  * hopefully stable by 2012-12-12
44*b30d1939SAndy Fiddaman  */
45*b30d1939SAndy Fiddaman 
46*b30d1939SAndy Fiddaman #if !_PACKAGE_ast
47*b30d1939SAndy Fiddaman 
48*b30d1939SAndy Fiddaman #if _UWIN
49*b30d1939SAndy Fiddaman 
50*b30d1939SAndy Fiddaman extern ssize_t		sfsprintf(char*, size_t, const char*, ...);
51*b30d1939SAndy Fiddaman 
52*b30d1939SAndy Fiddaman #else
53*b30d1939SAndy Fiddaman 
54*b30d1939SAndy Fiddaman #include <stdio.h>
55*b30d1939SAndy Fiddaman 
56*b30d1939SAndy Fiddaman #define sfsprintf	snprintf
57*b30d1939SAndy Fiddaman 
58*b30d1939SAndy Fiddaman #endif
59*b30d1939SAndy Fiddaman 
60*b30d1939SAndy Fiddaman #endif
61*b30d1939SAndy Fiddaman 
62*b30d1939SAndy Fiddaman #if defined(_aso_casptr) && (defined(_aso_cas32) || defined(_aso_cas64))
63*b30d1939SAndy Fiddaman #define ASO_METHOD		(&_aso_meth_intrinsic)
64*b30d1939SAndy Fiddaman #define ASO_LOCKF		0
65*b30d1939SAndy Fiddaman #else
66*b30d1939SAndy Fiddaman #define ASO_METHOD		(&_aso_meth_signal)
67*b30d1939SAndy Fiddaman #define ASO_LOCKF		_aso_lock_signal
68*b30d1939SAndy Fiddaman #endif
69*b30d1939SAndy Fiddaman 
70*b30d1939SAndy Fiddaman typedef union
71*b30d1939SAndy Fiddaman {
72*b30d1939SAndy Fiddaman 	uint8_t			c[2];
73*b30d1939SAndy Fiddaman 	uint16_t		i;
74*b30d1939SAndy Fiddaman } U16_8_t;
75*b30d1939SAndy Fiddaman 
76*b30d1939SAndy Fiddaman typedef union
77*b30d1939SAndy Fiddaman {
78*b30d1939SAndy Fiddaman 	uint8_t			c[4];
79*b30d1939SAndy Fiddaman 	uint32_t		i;
80*b30d1939SAndy Fiddaman } U32_8_t;
81*b30d1939SAndy Fiddaman 
82*b30d1939SAndy Fiddaman typedef union
83*b30d1939SAndy Fiddaman {
84*b30d1939SAndy Fiddaman 	uint16_t		c[2];
85*b30d1939SAndy Fiddaman 	uint32_t		i;
86*b30d1939SAndy Fiddaman } U32_16_t;
87*b30d1939SAndy Fiddaman 
88*b30d1939SAndy Fiddaman #ifdef _ast_int8_t
89*b30d1939SAndy Fiddaman 
90*b30d1939SAndy Fiddaman typedef union
91*b30d1939SAndy Fiddaman {
92*b30d1939SAndy Fiddaman 	uint8_t			c[8];
93*b30d1939SAndy Fiddaman 	uint64_t		i;
94*b30d1939SAndy Fiddaman } U64_8_t;
95*b30d1939SAndy Fiddaman 
96*b30d1939SAndy Fiddaman typedef union
97*b30d1939SAndy Fiddaman {
98*b30d1939SAndy Fiddaman 	uint16_t		c[4];
99*b30d1939SAndy Fiddaman 	uint64_t		i;
100*b30d1939SAndy Fiddaman } U64_16_t;
101*b30d1939SAndy Fiddaman 
102*b30d1939SAndy Fiddaman typedef union
103*b30d1939SAndy Fiddaman {
104*b30d1939SAndy Fiddaman 	uint32_t		c[2];
105*b30d1939SAndy Fiddaman 	uint64_t		i;
106*b30d1939SAndy Fiddaman } U64_32_t;
107*b30d1939SAndy Fiddaman 
108*b30d1939SAndy Fiddaman #endif
109*b30d1939SAndy Fiddaman 
110*b30d1939SAndy Fiddaman typedef struct State_s
111*b30d1939SAndy Fiddaman {
112*b30d1939SAndy Fiddaman 	Asometh_t*		meth;
113*b30d1939SAndy Fiddaman 	Asolock_f		lockf;
114*b30d1939SAndy Fiddaman 	Asoerror_f		errorf;
115*b30d1939SAndy Fiddaman 	uintmax_t		hung;
116*b30d1939SAndy Fiddaman 	unsigned int		hung2;
117*b30d1939SAndy Fiddaman 	void*			data;
118*b30d1939SAndy Fiddaman 	pid_t			pid;
119*b30d1939SAndy Fiddaman } State_t;
120*b30d1939SAndy Fiddaman 
121*b30d1939SAndy Fiddaman static unsigned int		_aso_data_signal;
122*b30d1939SAndy Fiddaman 
123*b30d1939SAndy Fiddaman static ssize_t
124*b30d1939SAndy Fiddaman _aso_lock_signal(void* data, ssize_t k, void volatile* p)
125*b30d1939SAndy Fiddaman {
126*b30d1939SAndy Fiddaman 	if (k >= 0)
127*b30d1939SAndy Fiddaman 	{
128*b30d1939SAndy Fiddaman 		_aso_data_signal--;
129*b30d1939SAndy Fiddaman 		return 0;
130*b30d1939SAndy Fiddaman 	}
131*b30d1939SAndy Fiddaman 	while (_aso_data_signal++)
132*b30d1939SAndy Fiddaman 		_aso_data_signal--;
133*b30d1939SAndy Fiddaman 	return 1;
134*b30d1939SAndy Fiddaman }
135*b30d1939SAndy Fiddaman 
136*b30d1939SAndy Fiddaman static Asometh_t	_aso_meth_signal =    { "signal",    ASO_SIGNAL,    0, _aso_lock_signal };
137*b30d1939SAndy Fiddaman extern Asometh_t	_aso_meth_semaphore;
138*b30d1939SAndy Fiddaman extern Asometh_t	_aso_meth_fcntl;
139*b30d1939SAndy Fiddaman static Asometh_t	_aso_meth_intrinsic = { "intrinsic", ASO_INTRINSIC|ASO_PROCESS|ASO_THREAD|ASO_SIGNAL, 0, 0 };
140*b30d1939SAndy Fiddaman 
141*b30d1939SAndy Fiddaman static Asometh_t*	method[] =
142*b30d1939SAndy Fiddaman {
143*b30d1939SAndy Fiddaman 	&_aso_meth_signal,
144*b30d1939SAndy Fiddaman #if defined(_ast_int8_t) && defined(_aso_cas64) || !defined(_ast_int8_t) && defined(_aso_cas32)
145*b30d1939SAndy Fiddaman 	&_aso_meth_intrinsic,
146*b30d1939SAndy Fiddaman #endif
147*b30d1939SAndy Fiddaman #if _aso_semaphore
148*b30d1939SAndy Fiddaman 	&_aso_meth_semaphore,
149*b30d1939SAndy Fiddaman #endif
150*b30d1939SAndy Fiddaman #if _aso_fcntl
151*b30d1939SAndy Fiddaman 	&_aso_meth_fcntl,
152*b30d1939SAndy Fiddaman #endif
153*b30d1939SAndy Fiddaman };
154*b30d1939SAndy Fiddaman 
155*b30d1939SAndy Fiddaman static State_t			state =
156*b30d1939SAndy Fiddaman {
157*b30d1939SAndy Fiddaman 	ASO_METHOD, ASO_LOCKF
158*b30d1939SAndy Fiddaman };
159*b30d1939SAndy Fiddaman 
160*b30d1939SAndy Fiddaman static int
161*b30d1939SAndy Fiddaman asoerror(int type, const char* format, const char* a, const char* b, long n)
162*b30d1939SAndy Fiddaman {
163*b30d1939SAndy Fiddaman 	char	buf[128];
164*b30d1939SAndy Fiddaman 
165*b30d1939SAndy Fiddaman 	if (b)
166*b30d1939SAndy Fiddaman 		sfsprintf(buf, sizeof(buf), format, a, b, n);
167*b30d1939SAndy Fiddaman 	else if (a)
168*b30d1939SAndy Fiddaman 		sfsprintf(buf, sizeof(buf), format, a, n);
169*b30d1939SAndy Fiddaman 	else
170*b30d1939SAndy Fiddaman 		sfsprintf(buf, sizeof(buf), format, n);
171*b30d1939SAndy Fiddaman 	return state.errorf(type, buf);
172*b30d1939SAndy Fiddaman }
173*b30d1939SAndy Fiddaman 
174*b30d1939SAndy Fiddaman /*
175*b30d1939SAndy Fiddaman  * if type!=0 return lock method for type with name details
176*b30d1939SAndy Fiddaman  * else if name!=0 return lock method matching <name>[,<details>]
177*b30d1939SAndy Fiddaman  * else return the current lock method
178*b30d1939SAndy Fiddaman  * 0 returned on error
179*b30d1939SAndy Fiddaman  *
180*b30d1939SAndy Fiddaman  * the user visible asometh() calls this function
181*b30d1939SAndy Fiddaman  * it allows, e.g., for -ltaso to provide an asometh() intercept
182*b30d1939SAndy Fiddaman  * that prepends its ASO_THREAD methods ahead of the _asometh() methods
183*b30d1939SAndy Fiddaman  */
184*b30d1939SAndy Fiddaman 
185*b30d1939SAndy Fiddaman Asometh_t*
186*b30d1939SAndy Fiddaman _asometh(int type, void* data)
187*b30d1939SAndy Fiddaman {
188*b30d1939SAndy Fiddaman 	size_t		n;
189*b30d1939SAndy Fiddaman 	int		i;
190*b30d1939SAndy Fiddaman 	char*		e;
191*b30d1939SAndy Fiddaman 	Asometh_t*	meth;
192*b30d1939SAndy Fiddaman 	char*		name;
193*b30d1939SAndy Fiddaman 
194*b30d1939SAndy Fiddaman 	if (type == ASO_NEXT)
195*b30d1939SAndy Fiddaman 	{
196*b30d1939SAndy Fiddaman 		if (!(meth = (Asometh_t*)data))
197*b30d1939SAndy Fiddaman 			return method[0];
198*b30d1939SAndy Fiddaman 		for (i = 0; i < elementsof(method) - 1; i++)
199*b30d1939SAndy Fiddaman 			if (meth == method[i])
200*b30d1939SAndy Fiddaman 				return method[i+1];
201*b30d1939SAndy Fiddaman 		return 0;
202*b30d1939SAndy Fiddaman 	}
203*b30d1939SAndy Fiddaman 	if (type)
204*b30d1939SAndy Fiddaman 	{
205*b30d1939SAndy Fiddaman 		for (i = 0; i < elementsof(method); i++)
206*b30d1939SAndy Fiddaman 			if (method[i]->type & type)
207*b30d1939SAndy Fiddaman 			{
208*b30d1939SAndy Fiddaman 				method[i]->details = (char*)data;
209*b30d1939SAndy Fiddaman 				return method[i];
210*b30d1939SAndy Fiddaman 			}
211*b30d1939SAndy Fiddaman 		return 0;
212*b30d1939SAndy Fiddaman 	}
213*b30d1939SAndy Fiddaman 	if (!(name = (char*)data))
214*b30d1939SAndy Fiddaman 		return state.meth;
215*b30d1939SAndy Fiddaman 	n = (e = strchr(name, ',')) ? (e - name) : strlen(name);
216*b30d1939SAndy Fiddaman 	for (i = 0; i < elementsof(method); i++)
217*b30d1939SAndy Fiddaman 		if (strncmp(name, method[i]->name, n) == 0)
218*b30d1939SAndy Fiddaman 		{
219*b30d1939SAndy Fiddaman 			if (e)
220*b30d1939SAndy Fiddaman 				method[i]->details = e + 1;
221*b30d1939SAndy Fiddaman 			return method[i];
222*b30d1939SAndy Fiddaman 		}
223*b30d1939SAndy Fiddaman 	return 0;
224*b30d1939SAndy Fiddaman }
225*b30d1939SAndy Fiddaman 
226*b30d1939SAndy Fiddaman /*
227*b30d1939SAndy Fiddaman  * clean up lock method on exit
228*b30d1939SAndy Fiddaman  */
229*b30d1939SAndy Fiddaman 
230*b30d1939SAndy Fiddaman static void
231*b30d1939SAndy Fiddaman asoexit(void)
232*b30d1939SAndy Fiddaman {
233*b30d1939SAndy Fiddaman 	if (state.meth && state.meth->initf && state.data && state.pid == getpid())
234*b30d1939SAndy Fiddaman 	{
235*b30d1939SAndy Fiddaman 		state.lockf = ASO_METHOD->lockf;
236*b30d1939SAndy Fiddaman 		state.meth->initf(state.data, 0);
237*b30d1939SAndy Fiddaman 		state.data = 0;
238*b30d1939SAndy Fiddaman 	}
239*b30d1939SAndy Fiddaman }
240*b30d1939SAndy Fiddaman 
241*b30d1939SAndy Fiddaman /*
242*b30d1939SAndy Fiddaman  * initialize lock method
243*b30d1939SAndy Fiddaman  */
244*b30d1939SAndy Fiddaman 
245*b30d1939SAndy Fiddaman int
246*b30d1939SAndy Fiddaman asoinit(const char* details, Asometh_t* meth, Asodisc_t* disc)
247*b30d1939SAndy Fiddaman {
248*b30d1939SAndy Fiddaman 	void*		data;
249*b30d1939SAndy Fiddaman 
250*b30d1939SAndy Fiddaman 	if (disc)
251*b30d1939SAndy Fiddaman 	{
252*b30d1939SAndy Fiddaman 		state.errorf = disc->errorf;
253*b30d1939SAndy Fiddaman 		state.hung2 = disc->hung;
254*b30d1939SAndy Fiddaman 		state.hung = 1;
255*b30d1939SAndy Fiddaman 		state.hung <<= state.hung2;
256*b30d1939SAndy Fiddaman 		state.hung--;
257*b30d1939SAndy Fiddaman 	}
258*b30d1939SAndy Fiddaman 	if (!meth)
259*b30d1939SAndy Fiddaman 		return state.pid != 0;
260*b30d1939SAndy Fiddaman 	if (!meth->lockf && !(meth->type & ASO_INTRINSIC))
261*b30d1939SAndy Fiddaman 	{
262*b30d1939SAndy Fiddaman 		if (state.errorf)
263*b30d1939SAndy Fiddaman 			asoerror(ASO_EMETHOD, "%s method has no lock function", meth->name, 0, 0);
264*b30d1939SAndy Fiddaman 		return -1;
265*b30d1939SAndy Fiddaman 	}
266*b30d1939SAndy Fiddaman 	state.lockf = ASO_METHOD->lockf;
267*b30d1939SAndy Fiddaman 	if (state.meth && state.meth->initf && state.data)
268*b30d1939SAndy Fiddaman 	{
269*b30d1939SAndy Fiddaman 		state.meth->initf(state.data, 0);
270*b30d1939SAndy Fiddaman 		state.data = 0;
271*b30d1939SAndy Fiddaman 	}
272*b30d1939SAndy Fiddaman 	if (!meth->initf)
273*b30d1939SAndy Fiddaman 		data = 0;
274*b30d1939SAndy Fiddaman 	else if (!(data = meth->initf(0, details ? details : meth->details)))
275*b30d1939SAndy Fiddaman 	{
276*b30d1939SAndy Fiddaman 		state.meth = ASO_METHOD;
277*b30d1939SAndy Fiddaman 		if (state.errorf)
278*b30d1939SAndy Fiddaman 			asoerror(ASO_EMETHOD, "%s method initialization failed -- reverting to the %s method", meth->name, state.meth->name, 0);
279*b30d1939SAndy Fiddaman 		return -1;
280*b30d1939SAndy Fiddaman 	}
281*b30d1939SAndy Fiddaman 	state.meth = meth;
282*b30d1939SAndy Fiddaman 	state.data = data;
283*b30d1939SAndy Fiddaman 	state.lockf = meth->lockf;
284*b30d1939SAndy Fiddaman 	if (!state.pid)
285*b30d1939SAndy Fiddaman 	{
286*b30d1939SAndy Fiddaman 		state.pid = getpid();
287*b30d1939SAndy Fiddaman 		atexit(asoexit);
288*b30d1939SAndy Fiddaman 	}
289*b30d1939SAndy Fiddaman 	return 0;
290*b30d1939SAndy Fiddaman }
291*b30d1939SAndy Fiddaman 
292*b30d1939SAndy Fiddaman /*
293*b30d1939SAndy Fiddaman  * loop check for hung spin locks
294*b30d1939SAndy Fiddaman  * and periodic relinquishing of the processor
295*b30d1939SAndy Fiddaman  */
296*b30d1939SAndy Fiddaman 
297*b30d1939SAndy Fiddaman int
298*b30d1939SAndy Fiddaman asoloop(uintmax_t rep)
299*b30d1939SAndy Fiddaman {
300*b30d1939SAndy Fiddaman 	if (state.hung && !(rep & state.hung) && state.errorf)
301*b30d1939SAndy Fiddaman 		return asoerror(ASO_EHUNG, "spin lock possibly hung after 2^%u attempts", 0, 0, state.hung2);
302*b30d1939SAndy Fiddaman 	return (rep & ASO_RELAX) ? 0 : asorelax(1);
303*b30d1939SAndy Fiddaman }
304*b30d1939SAndy Fiddaman 
305*b30d1939SAndy Fiddaman /*
306*b30d1939SAndy Fiddaman  * error checking state.lockf() call
307*b30d1939SAndy Fiddaman  */
308*b30d1939SAndy Fiddaman 
309*b30d1939SAndy Fiddaman static ssize_t
310*b30d1939SAndy Fiddaman lock(void* data, ssize_t k, void volatile* p)
311*b30d1939SAndy Fiddaman {
312*b30d1939SAndy Fiddaman 	ssize_t		r;
313*b30d1939SAndy Fiddaman 
314*b30d1939SAndy Fiddaman 	if ((r = state.lockf(data, k, p)) < 0 && state.errorf)
315*b30d1939SAndy Fiddaman 		asoerror(ASO_EMETHOD, "%s method lock failed", state.meth->name, 0, 0);
316*b30d1939SAndy Fiddaman 	return r;
317*b30d1939SAndy Fiddaman }
318*b30d1939SAndy Fiddaman 
319*b30d1939SAndy Fiddaman /*
320*b30d1939SAndy Fiddaman  * sync and return "current" value
321*b30d1939SAndy Fiddaman  */
322*b30d1939SAndy Fiddaman 
323*b30d1939SAndy Fiddaman uint8_t
324*b30d1939SAndy Fiddaman asoget8(uint8_t volatile* p)
325*b30d1939SAndy Fiddaman {
326*b30d1939SAndy Fiddaman 	int	o;
327*b30d1939SAndy Fiddaman 
328*b30d1939SAndy Fiddaman 	do
329*b30d1939SAndy Fiddaman 	{
330*b30d1939SAndy Fiddaman 		o = *p;
331*b30d1939SAndy Fiddaman 	} while (asocas8(p, o, o) != o);
332*b30d1939SAndy Fiddaman 	return o;
333*b30d1939SAndy Fiddaman }
334*b30d1939SAndy Fiddaman 
335*b30d1939SAndy Fiddaman uint16_t
336*b30d1939SAndy Fiddaman asoget16(uint16_t volatile* p)
337*b30d1939SAndy Fiddaman {
338*b30d1939SAndy Fiddaman 	int	o;
339*b30d1939SAndy Fiddaman 
340*b30d1939SAndy Fiddaman 	do
341*b30d1939SAndy Fiddaman 	{
342*b30d1939SAndy Fiddaman 		o = *p;
343*b30d1939SAndy Fiddaman 	} while (asocas16(p, o, o) != o);
344*b30d1939SAndy Fiddaman 	return o;
345*b30d1939SAndy Fiddaman }
346*b30d1939SAndy Fiddaman 
347*b30d1939SAndy Fiddaman uint32_t
348*b30d1939SAndy Fiddaman asoget32(uint32_t volatile* p)
349*b30d1939SAndy Fiddaman {
350*b30d1939SAndy Fiddaman 	uint32_t	o;
351*b30d1939SAndy Fiddaman 
352*b30d1939SAndy Fiddaman 	do
353*b30d1939SAndy Fiddaman 	{
354*b30d1939SAndy Fiddaman 		o = *p;
355*b30d1939SAndy Fiddaman 	} while (asocas32(p, o, o) != o);
356*b30d1939SAndy Fiddaman 	return o;
357*b30d1939SAndy Fiddaman }
358*b30d1939SAndy Fiddaman 
359*b30d1939SAndy Fiddaman #ifdef _ast_int8_t
360*b30d1939SAndy Fiddaman 
361*b30d1939SAndy Fiddaman uint64_t
362*b30d1939SAndy Fiddaman asoget64(uint64_t volatile* p)
363*b30d1939SAndy Fiddaman {
364*b30d1939SAndy Fiddaman 	uint64_t	o;
365*b30d1939SAndy Fiddaman 
366*b30d1939SAndy Fiddaman 	do
367*b30d1939SAndy Fiddaman 	{
368*b30d1939SAndy Fiddaman 		o = *p;
369*b30d1939SAndy Fiddaman 	} while (asocas64(p, o, o) != o);
370*b30d1939SAndy Fiddaman 	return o;
371*b30d1939SAndy Fiddaman }
372*b30d1939SAndy Fiddaman 
373*b30d1939SAndy Fiddaman #endif
374*b30d1939SAndy Fiddaman 
375*b30d1939SAndy Fiddaman void*
376*b30d1939SAndy Fiddaman asogetptr(void volatile* p)
377*b30d1939SAndy Fiddaman {
378*b30d1939SAndy Fiddaman 	void*	o;
379*b30d1939SAndy Fiddaman 
380*b30d1939SAndy Fiddaman 	do
381*b30d1939SAndy Fiddaman 	{
382*b30d1939SAndy Fiddaman 		o = *(void* volatile*)p;
383*b30d1939SAndy Fiddaman 	} while (asocasptr(p, o, o) != o);
384*b30d1939SAndy Fiddaman 	return o;
385*b30d1939SAndy Fiddaman }
386*b30d1939SAndy Fiddaman 
387*b30d1939SAndy Fiddaman /*
388*b30d1939SAndy Fiddaman  * increment and return old value
389*b30d1939SAndy Fiddaman  */
390*b30d1939SAndy Fiddaman 
391*b30d1939SAndy Fiddaman uint8_t
392*b30d1939SAndy Fiddaman asoinc8(uint8_t volatile* p)
393*b30d1939SAndy Fiddaman {
394*b30d1939SAndy Fiddaman 	ssize_t		k;
395*b30d1939SAndy Fiddaman 	int		o;
396*b30d1939SAndy Fiddaman 
397*b30d1939SAndy Fiddaman #if defined(_aso_inc8)
398*b30d1939SAndy Fiddaman 	if (!state.lockf)
399*b30d1939SAndy Fiddaman 		return _aso_inc8(p);
400*b30d1939SAndy Fiddaman #else
401*b30d1939SAndy Fiddaman 	if (!state.lockf)
402*b30d1939SAndy Fiddaman 	{
403*b30d1939SAndy Fiddaman 		do
404*b30d1939SAndy Fiddaman 		{
405*b30d1939SAndy Fiddaman 			o = *p;
406*b30d1939SAndy Fiddaman 		} while (asocas8(p, o, o + 1) != o);
407*b30d1939SAndy Fiddaman 		return o;
408*b30d1939SAndy Fiddaman 	}
409*b30d1939SAndy Fiddaman #endif
410*b30d1939SAndy Fiddaman 	k = lock(state.data, 0, p);
411*b30d1939SAndy Fiddaman 	o = (*p)++;
412*b30d1939SAndy Fiddaman 	lock(state.data, k, p);
413*b30d1939SAndy Fiddaman 	return o;
414*b30d1939SAndy Fiddaman }
415*b30d1939SAndy Fiddaman 
416*b30d1939SAndy Fiddaman uint16_t
417*b30d1939SAndy Fiddaman asoinc16(uint16_t volatile* p)
418*b30d1939SAndy Fiddaman {
419*b30d1939SAndy Fiddaman 	ssize_t		k;
420*b30d1939SAndy Fiddaman 	int		o;
421*b30d1939SAndy Fiddaman 
422*b30d1939SAndy Fiddaman #if defined(_aso_inc16)
423*b30d1939SAndy Fiddaman 	if (!state.lockf)
424*b30d1939SAndy Fiddaman 		return _aso_inc16(p);
425*b30d1939SAndy Fiddaman #else
426*b30d1939SAndy Fiddaman 	if (!state.lockf)
427*b30d1939SAndy Fiddaman 	{
428*b30d1939SAndy Fiddaman 		do
429*b30d1939SAndy Fiddaman 		{
430*b30d1939SAndy Fiddaman 			o = *p;
431*b30d1939SAndy Fiddaman 		} while (asocas16(p, o, o + 1) != o);
432*b30d1939SAndy Fiddaman 		return o;
433*b30d1939SAndy Fiddaman 	}
434*b30d1939SAndy Fiddaman #endif
435*b30d1939SAndy Fiddaman 	k = lock(state.data, 0, p);
436*b30d1939SAndy Fiddaman 	o = (*p)++;
437*b30d1939SAndy Fiddaman 	lock(state.data, k, p);
438*b30d1939SAndy Fiddaman 	return o;
439*b30d1939SAndy Fiddaman }
440*b30d1939SAndy Fiddaman 
441*b30d1939SAndy Fiddaman uint32_t
442*b30d1939SAndy Fiddaman asoinc32(uint32_t volatile* p)
443*b30d1939SAndy Fiddaman {
444*b30d1939SAndy Fiddaman 	ssize_t		k;
445*b30d1939SAndy Fiddaman 	int		o;
446*b30d1939SAndy Fiddaman 
447*b30d1939SAndy Fiddaman #if defined(_aso_inc32)
448*b30d1939SAndy Fiddaman 	if (!state.lockf)
449*b30d1939SAndy Fiddaman 		return _aso_inc32(p);
450*b30d1939SAndy Fiddaman #else
451*b30d1939SAndy Fiddaman 	if (!state.lockf)
452*b30d1939SAndy Fiddaman 	{
453*b30d1939SAndy Fiddaman 		do
454*b30d1939SAndy Fiddaman 		{
455*b30d1939SAndy Fiddaman 			o = *p;
456*b30d1939SAndy Fiddaman 		} while (asocas32(p, o, o + 1) != o);
457*b30d1939SAndy Fiddaman 		return o;
458*b30d1939SAndy Fiddaman 	}
459*b30d1939SAndy Fiddaman #endif
460*b30d1939SAndy Fiddaman 	k = lock(state.data, 0, p);
461*b30d1939SAndy Fiddaman 	o = (*p)++;
462*b30d1939SAndy Fiddaman 	lock(state.data, k, p);
463*b30d1939SAndy Fiddaman 	return o;
464*b30d1939SAndy Fiddaman }
465*b30d1939SAndy Fiddaman 
466*b30d1939SAndy Fiddaman #ifdef _ast_int8_t
467*b30d1939SAndy Fiddaman 
468*b30d1939SAndy Fiddaman uint64_t
469*b30d1939SAndy Fiddaman asoinc64(uint64_t volatile* p)
470*b30d1939SAndy Fiddaman {
471*b30d1939SAndy Fiddaman 	ssize_t		k;
472*b30d1939SAndy Fiddaman 	uint64_t	o;
473*b30d1939SAndy Fiddaman 
474*b30d1939SAndy Fiddaman #if defined(_aso_inc64)
475*b30d1939SAndy Fiddaman 	if (!state.lockf)
476*b30d1939SAndy Fiddaman 		return _aso_inc64(p);
477*b30d1939SAndy Fiddaman #else
478*b30d1939SAndy Fiddaman 	if (!state.lockf)
479*b30d1939SAndy Fiddaman 	{
480*b30d1939SAndy Fiddaman 		do
481*b30d1939SAndy Fiddaman 		{
482*b30d1939SAndy Fiddaman 			o = *p;
483*b30d1939SAndy Fiddaman 		} while (asocas64(p, o, o + 1) != o);
484*b30d1939SAndy Fiddaman 		return o;
485*b30d1939SAndy Fiddaman 	}
486*b30d1939SAndy Fiddaman #endif
487*b30d1939SAndy Fiddaman 	k = lock(state.data, 0, p);
488*b30d1939SAndy Fiddaman 	o = (*p)++;
489*b30d1939SAndy Fiddaman 	lock(state.data, k, p);
490*b30d1939SAndy Fiddaman 	return o;
491*b30d1939SAndy Fiddaman }
492*b30d1939SAndy Fiddaman 
493*b30d1939SAndy Fiddaman #endif
494*b30d1939SAndy Fiddaman 
495*b30d1939SAndy Fiddaman /*
496*b30d1939SAndy Fiddaman  * decrement and return old value
497*b30d1939SAndy Fiddaman  */
498*b30d1939SAndy Fiddaman 
499*b30d1939SAndy Fiddaman uint8_t
500*b30d1939SAndy Fiddaman asodec8(uint8_t volatile* p)
501*b30d1939SAndy Fiddaman {
502*b30d1939SAndy Fiddaman 	ssize_t		k;
503*b30d1939SAndy Fiddaman 	int		o;
504*b30d1939SAndy Fiddaman 
505*b30d1939SAndy Fiddaman #if defined(_aso_dec8)
506*b30d1939SAndy Fiddaman 	if (!state.lockf)
507*b30d1939SAndy Fiddaman 		return _aso_dec8(p);
508*b30d1939SAndy Fiddaman #else
509*b30d1939SAndy Fiddaman 	if (!state.lockf)
510*b30d1939SAndy Fiddaman 	{
511*b30d1939SAndy Fiddaman 		do
512*b30d1939SAndy Fiddaman 		{
513*b30d1939SAndy Fiddaman 			o = *p;
514*b30d1939SAndy Fiddaman 		} while (asocas8(p, o, o - 1) != o);
515*b30d1939SAndy Fiddaman 		return o;
516*b30d1939SAndy Fiddaman 	}
517*b30d1939SAndy Fiddaman #endif
518*b30d1939SAndy Fiddaman 	k = lock(state.data, 0, p);
519*b30d1939SAndy Fiddaman 	o = (*p)--;
520*b30d1939SAndy Fiddaman 	lock(state.data, k, p);
521*b30d1939SAndy Fiddaman 	return o;
522*b30d1939SAndy Fiddaman }
523*b30d1939SAndy Fiddaman 
524*b30d1939SAndy Fiddaman uint16_t
525*b30d1939SAndy Fiddaman asodec16(uint16_t volatile* p)
526*b30d1939SAndy Fiddaman {
527*b30d1939SAndy Fiddaman 	ssize_t		k;
528*b30d1939SAndy Fiddaman 	int		o;
529*b30d1939SAndy Fiddaman 
530*b30d1939SAndy Fiddaman #if defined(_aso_dec16)
531*b30d1939SAndy Fiddaman 	if (!state.lockf)
532*b30d1939SAndy Fiddaman 		return _aso_dec16(p);
533*b30d1939SAndy Fiddaman #else
534*b30d1939SAndy Fiddaman 	if (!state.lockf)
535*b30d1939SAndy Fiddaman 	{
536*b30d1939SAndy Fiddaman 		do
537*b30d1939SAndy Fiddaman 		{
538*b30d1939SAndy Fiddaman 			o = *p;
539*b30d1939SAndy Fiddaman 		} while (asocas16(p, o, o - 1) != o);
540*b30d1939SAndy Fiddaman 		return o;
541*b30d1939SAndy Fiddaman 	}
542*b30d1939SAndy Fiddaman #endif
543*b30d1939SAndy Fiddaman 	k = lock(state.data, 0, p);
544*b30d1939SAndy Fiddaman 	o = (*p)--;
545*b30d1939SAndy Fiddaman 	lock(state.data, k, p);
546*b30d1939SAndy Fiddaman 	return o;
547*b30d1939SAndy Fiddaman }
548*b30d1939SAndy Fiddaman 
549*b30d1939SAndy Fiddaman uint32_t
550*b30d1939SAndy Fiddaman asodec32(uint32_t volatile* p)
551*b30d1939SAndy Fiddaman {
552*b30d1939SAndy Fiddaman 	ssize_t		k;
553*b30d1939SAndy Fiddaman 	int		o;
554*b30d1939SAndy Fiddaman 
555*b30d1939SAndy Fiddaman #if defined(_aso_dec32)
556*b30d1939SAndy Fiddaman 	if (!state.lockf)
557*b30d1939SAndy Fiddaman 		return _aso_dec32(p);
558*b30d1939SAndy Fiddaman #else
559*b30d1939SAndy Fiddaman 	if (!state.lockf)
560*b30d1939SAndy Fiddaman 	{
561*b30d1939SAndy Fiddaman 		do
562*b30d1939SAndy Fiddaman 		{
563*b30d1939SAndy Fiddaman 			o = *p;
564*b30d1939SAndy Fiddaman 		} while (asocas32(p, o, o - 1) != o);
565*b30d1939SAndy Fiddaman 		return o;
566*b30d1939SAndy Fiddaman 	}
567*b30d1939SAndy Fiddaman #endif
568*b30d1939SAndy Fiddaman 	k = lock(state.data, 0, p);
569*b30d1939SAndy Fiddaman 	o = (*p)--;
570*b30d1939SAndy Fiddaman 	lock(state.data, k, p);
571*b30d1939SAndy Fiddaman 	return o;
572*b30d1939SAndy Fiddaman }
573*b30d1939SAndy Fiddaman 
574*b30d1939SAndy Fiddaman #ifdef _ast_int8_t
575*b30d1939SAndy Fiddaman 
576*b30d1939SAndy Fiddaman uint64_t
577*b30d1939SAndy Fiddaman asodec64(uint64_t volatile* p)
578*b30d1939SAndy Fiddaman {
579*b30d1939SAndy Fiddaman 	ssize_t		k;
580*b30d1939SAndy Fiddaman 	uint64_t	o;
581*b30d1939SAndy Fiddaman 
582*b30d1939SAndy Fiddaman #if defined(_aso_dec64)
583*b30d1939SAndy Fiddaman 	if (!state.lockf)
584*b30d1939SAndy Fiddaman 		return _aso_dec64(p);
585*b30d1939SAndy Fiddaman #else
586*b30d1939SAndy Fiddaman 	if (!state.lockf)
587*b30d1939SAndy Fiddaman 	{
588*b30d1939SAndy Fiddaman 		do
589*b30d1939SAndy Fiddaman 		{
590*b30d1939SAndy Fiddaman 			o = *p;
591*b30d1939SAndy Fiddaman 		} while (asocas64(p, o, o - 1) != o);
592*b30d1939SAndy Fiddaman 		return o;
593*b30d1939SAndy Fiddaman 	}
594*b30d1939SAndy Fiddaman #endif
595*b30d1939SAndy Fiddaman 	k = lock(state.data, 0, p);
596*b30d1939SAndy Fiddaman 	o = (*p)--;
597*b30d1939SAndy Fiddaman 	lock(state.data, k, p);
598*b30d1939SAndy Fiddaman 	return o;
599*b30d1939SAndy Fiddaman }
600*b30d1939SAndy Fiddaman 
601*b30d1939SAndy Fiddaman #endif
602*b30d1939SAndy Fiddaman 
603*b30d1939SAndy Fiddaman /*
604*b30d1939SAndy Fiddaman  * { 8 16 32 [64] } compare with old, swap with new if same, and return old value
605*b30d1939SAndy Fiddaman  */
606*b30d1939SAndy Fiddaman 
607*b30d1939SAndy Fiddaman uint8_t
608*b30d1939SAndy Fiddaman asocas8(uint8_t volatile* p, int o, int n)
609*b30d1939SAndy Fiddaman {
610*b30d1939SAndy Fiddaman 	ssize_t		k;
611*b30d1939SAndy Fiddaman 
612*b30d1939SAndy Fiddaman #if defined(_aso_cas8)
613*b30d1939SAndy Fiddaman 	if (!state.lockf)
614*b30d1939SAndy Fiddaman 		return _aso_cas8(p, o, n);
615*b30d1939SAndy Fiddaman #elif defined(_aso_cas16)
616*b30d1939SAndy Fiddaman 	if (!state.lockf)
617*b30d1939SAndy Fiddaman 	{
618*b30d1939SAndy Fiddaman 		U16_8_t		u;
619*b30d1939SAndy Fiddaman 		U16_8_t		v;
620*b30d1939SAndy Fiddaman 		U16_8_t*	a;
621*b30d1939SAndy Fiddaman 		int		s;
622*b30d1939SAndy Fiddaman 		int		i;
623*b30d1939SAndy Fiddaman 
624*b30d1939SAndy Fiddaman 		s = (int)(integralof(p) & (sizeof(u.i) - 1));
625*b30d1939SAndy Fiddaman 		a = (U16_8_t*)((char*)0 + (integralof(p) & ~(sizeof(u.i) - 1)));
626*b30d1939SAndy Fiddaman 		for (;;)
627*b30d1939SAndy Fiddaman 		{
628*b30d1939SAndy Fiddaman 			u.i = a->i;
629*b30d1939SAndy Fiddaman 			u.c[s] = o;
630*b30d1939SAndy Fiddaman 			v.i = u.i;
631*b30d1939SAndy Fiddaman 			v.c[s] = n;
632*b30d1939SAndy Fiddaman 			if (_aso_cas16(&a->i, u.i, v.i) == u.i)
633*b30d1939SAndy Fiddaman 				break;
634*b30d1939SAndy Fiddaman 			for (i = 0;; i++)
635*b30d1939SAndy Fiddaman 				if (i >= elementsof(u.c))
636*b30d1939SAndy Fiddaman 					return a->c[s];
637*b30d1939SAndy Fiddaman 				else if (i != s && u.c[i] != a->c[i])
638*b30d1939SAndy Fiddaman 					break;
639*b30d1939SAndy Fiddaman 		}
640*b30d1939SAndy Fiddaman 		return o;
641*b30d1939SAndy Fiddaman 	}
642*b30d1939SAndy Fiddaman #elif defined(_aso_cas32)
643*b30d1939SAndy Fiddaman 	if (!state.lockf)
644*b30d1939SAndy Fiddaman 	{
645*b30d1939SAndy Fiddaman 		U32_8_t		u;
646*b30d1939SAndy Fiddaman 		U32_8_t		v;
647*b30d1939SAndy Fiddaman 		U32_8_t*	a;
648*b30d1939SAndy Fiddaman 		int		s;
649*b30d1939SAndy Fiddaman 		int		i;
650*b30d1939SAndy Fiddaman 
651*b30d1939SAndy Fiddaman 		s = (int)(integralof(p) & (sizeof(u.i) - 1));
652*b30d1939SAndy Fiddaman 		a = (U32_8_t*)((char*)0 + (integralof(p) & ~(sizeof(u.i) - 1)));
653*b30d1939SAndy Fiddaman 		for (;;)
654*b30d1939SAndy Fiddaman 		{
655*b30d1939SAndy Fiddaman 			u.i = a->i;
656*b30d1939SAndy Fiddaman 			u.c[s] = o;
657*b30d1939SAndy Fiddaman 			v.i = u.i;
658*b30d1939SAndy Fiddaman 			v.c[s] = n;
659*b30d1939SAndy Fiddaman 			if (_aso_cas32(&a->i, u.i, v.i) == u.i)
660*b30d1939SAndy Fiddaman 				break;
661*b30d1939SAndy Fiddaman 			for (i = 0;; i++)
662*b30d1939SAndy Fiddaman 				if (i >= elementsof(u.c))
663*b30d1939SAndy Fiddaman 					return a->c[s];
664*b30d1939SAndy Fiddaman 				else if (i != s && u.c[i] != a->c[i])
665*b30d1939SAndy Fiddaman 					break;
666*b30d1939SAndy Fiddaman 		}
667*b30d1939SAndy Fiddaman 		return o;
668*b30d1939SAndy Fiddaman 	}
669*b30d1939SAndy Fiddaman #elif defined(_aso_cas64)
670*b30d1939SAndy Fiddaman 	if (!state.lockf)
671*b30d1939SAndy Fiddaman 	{
672*b30d1939SAndy Fiddaman 		U64_8_t		u;
673*b30d1939SAndy Fiddaman 		U64_8_t		v;
674*b30d1939SAndy Fiddaman 		U64_8_t*	a;
675*b30d1939SAndy Fiddaman 		int		s;
676*b30d1939SAndy Fiddaman 		int		i;
677*b30d1939SAndy Fiddaman 
678*b30d1939SAndy Fiddaman 		s = (int)(integralof(p) & (sizeof(u.i) - 1));
679*b30d1939SAndy Fiddaman 		a = (U64_8_t*)((char*)0 + (integralof(p) & ~(sizeof(u.i) - 1)));
680*b30d1939SAndy Fiddaman 		for (;;)
681*b30d1939SAndy Fiddaman 		{
682*b30d1939SAndy Fiddaman 			u.i = a->i;
683*b30d1939SAndy Fiddaman 			u.c[s] = o;
684*b30d1939SAndy Fiddaman 			v.i = u.i;
685*b30d1939SAndy Fiddaman 			v.c[s] = n;
686*b30d1939SAndy Fiddaman 			if (_aso_cas64(&a->i, u.i, v.i) == u.i)
687*b30d1939SAndy Fiddaman 				break;
688*b30d1939SAndy Fiddaman 			for (i = 0;; i++)
689*b30d1939SAndy Fiddaman 				if (i >= elementsof(u.c))
690*b30d1939SAndy Fiddaman 					return a->c[s];
691*b30d1939SAndy Fiddaman 				else if (i != s && u.c[i] != a->c[i])
692*b30d1939SAndy Fiddaman 					break;
693*b30d1939SAndy Fiddaman 		}
694*b30d1939SAndy Fiddaman 		return o;
695*b30d1939SAndy Fiddaman 	}
696*b30d1939SAndy Fiddaman #endif
697*b30d1939SAndy Fiddaman 	k = lock(state.data, 0, p);
698*b30d1939SAndy Fiddaman 	if (*p == o)
699*b30d1939SAndy Fiddaman 		*p = n;
700*b30d1939SAndy Fiddaman 	else
701*b30d1939SAndy Fiddaman 		o = *p;
702*b30d1939SAndy Fiddaman 	lock(state.data, k, p);
703*b30d1939SAndy Fiddaman 	return o;
704*b30d1939SAndy Fiddaman }
705*b30d1939SAndy Fiddaman 
706*b30d1939SAndy Fiddaman uint16_t
707*b30d1939SAndy Fiddaman asocas16(uint16_t volatile* p, uint16_t o, uint16_t n)
708*b30d1939SAndy Fiddaman {
709*b30d1939SAndy Fiddaman 	ssize_t		k;
710*b30d1939SAndy Fiddaman 
711*b30d1939SAndy Fiddaman #if defined(_aso_cas16)
712*b30d1939SAndy Fiddaman 	if (!state.lockf)
713*b30d1939SAndy Fiddaman 		return _aso_cas16(p, o, n);
714*b30d1939SAndy Fiddaman #elif defined(_aso_cas32)
715*b30d1939SAndy Fiddaman 	if (!state.lockf)
716*b30d1939SAndy Fiddaman 	{
717*b30d1939SAndy Fiddaman 		U32_16_t	u;
718*b30d1939SAndy Fiddaman 		U32_16_t	v;
719*b30d1939SAndy Fiddaman 		U32_16_t*	a;
720*b30d1939SAndy Fiddaman 		int		s;
721*b30d1939SAndy Fiddaman 		int		i;
722*b30d1939SAndy Fiddaman 
723*b30d1939SAndy Fiddaman 		s = (int)(integralof(p) & (sizeof(u.i) - 1)) / 2;
724*b30d1939SAndy Fiddaman 		a = (U32_16_t*)((char*)0 + (integralof(p) & ~(sizeof(u.i) - 1)));
725*b30d1939SAndy Fiddaman 		for (;;)
726*b30d1939SAndy Fiddaman 		{
727*b30d1939SAndy Fiddaman 			u.i = a->i;
728*b30d1939SAndy Fiddaman 			u.c[s] = o;
729*b30d1939SAndy Fiddaman 			v.i = u.i;
730*b30d1939SAndy Fiddaman 			v.c[s] = n;
731*b30d1939SAndy Fiddaman 			if (_aso_cas32(&a->i, u.i, v.i) == u.i)
732*b30d1939SAndy Fiddaman 				break;
733*b30d1939SAndy Fiddaman 			for (i = 0;; i++)
734*b30d1939SAndy Fiddaman 				if (i >= elementsof(u.c))
735*b30d1939SAndy Fiddaman 					return a->c[s];
736*b30d1939SAndy Fiddaman 				else if (i != s && u.c[i] != a->c[i])
737*b30d1939SAndy Fiddaman 					break;
738*b30d1939SAndy Fiddaman 		}
739*b30d1939SAndy Fiddaman 		return o;
740*b30d1939SAndy Fiddaman 	}
741*b30d1939SAndy Fiddaman #elif defined(_aso_cas64)
742*b30d1939SAndy Fiddaman 	if (!state.lockf)
743*b30d1939SAndy Fiddaman 	{
744*b30d1939SAndy Fiddaman 		U64_16_t	u;
745*b30d1939SAndy Fiddaman 		U64_16_t	v;
746*b30d1939SAndy Fiddaman 		U64_16_t*	a;
747*b30d1939SAndy Fiddaman 		int		s;
748*b30d1939SAndy Fiddaman 		int		i;
749*b30d1939SAndy Fiddaman 
750*b30d1939SAndy Fiddaman 		s = (int)(integralof(p) & (sizeof(u.i) - 1)) / 2;
751*b30d1939SAndy Fiddaman 		a = (U64_16_t*)((char*)0 + (integralof(p) & ~(sizeof(u.i) - 1)));
752*b30d1939SAndy Fiddaman 		for (;;)
753*b30d1939SAndy Fiddaman 		{
754*b30d1939SAndy Fiddaman 			u.i = a->i;
755*b30d1939SAndy Fiddaman 			u.c[s] = o;
756*b30d1939SAndy Fiddaman 			v.i = u.i;
757*b30d1939SAndy Fiddaman 			v.c[s] = n;
758*b30d1939SAndy Fiddaman 			if (_aso_cas64(&a->i, u.i, v.i) == u.i)
759*b30d1939SAndy Fiddaman 				break;
760*b30d1939SAndy Fiddaman 			for (i = 0;; i++)
761*b30d1939SAndy Fiddaman 				if (i >= elementsof(u.c))
762*b30d1939SAndy Fiddaman 					return a->c[s];
763*b30d1939SAndy Fiddaman 				else if (i != s && u.c[i] != a->c[i])
764*b30d1939SAndy Fiddaman 					break;
765*b30d1939SAndy Fiddaman 		}
766*b30d1939SAndy Fiddaman 		return o;
767*b30d1939SAndy Fiddaman 	}
768*b30d1939SAndy Fiddaman #endif
769*b30d1939SAndy Fiddaman 	k = lock(state.data, 0, p);
770*b30d1939SAndy Fiddaman 	if (*p == o)
771*b30d1939SAndy Fiddaman 		*p = n;
772*b30d1939SAndy Fiddaman 	else
773*b30d1939SAndy Fiddaman 		o = *p;
774*b30d1939SAndy Fiddaman 	lock(state.data, k, p);
775*b30d1939SAndy Fiddaman 	return o;
776*b30d1939SAndy Fiddaman }
777*b30d1939SAndy Fiddaman 
778*b30d1939SAndy Fiddaman uint32_t
779*b30d1939SAndy Fiddaman asocas32(uint32_t volatile* p, uint32_t o, uint32_t n)
780*b30d1939SAndy Fiddaman {
781*b30d1939SAndy Fiddaman 	ssize_t		k;
782*b30d1939SAndy Fiddaman 
783*b30d1939SAndy Fiddaman #if defined(_aso_cas32)
784*b30d1939SAndy Fiddaman 	if (!state.lockf)
785*b30d1939SAndy Fiddaman 		return _aso_cas32(p, o, n);
786*b30d1939SAndy Fiddaman #elif defined(_aso_cas64)
787*b30d1939SAndy Fiddaman 	if (!state.lockf)
788*b30d1939SAndy Fiddaman 	{
789*b30d1939SAndy Fiddaman 		U64_32_t	u;
790*b30d1939SAndy Fiddaman 		U64_32_t	v;
791*b30d1939SAndy Fiddaman 		U64_32_t*	a;
792*b30d1939SAndy Fiddaman 		int		s;
793*b30d1939SAndy Fiddaman 		int		i;
794*b30d1939SAndy Fiddaman 
795*b30d1939SAndy Fiddaman 		s = (int)(integralof(p) & (sizeof(u.i) - 1)) / 4;
796*b30d1939SAndy Fiddaman 		a = (U64_32_t*)((char*)0 + (integralof(p) & ~(sizeof(u.i) - 1)));
797*b30d1939SAndy Fiddaman 		for (;;)
798*b30d1939SAndy Fiddaman 		{
799*b30d1939SAndy Fiddaman 			u.i = a->i;
800*b30d1939SAndy Fiddaman 			u.c[s] = o;
801*b30d1939SAndy Fiddaman 			v.i = u.i;
802*b30d1939SAndy Fiddaman 			v.c[s] = n;
803*b30d1939SAndy Fiddaman 			if (_aso_cas64(&a->i, u.i, v.i) == u.i)
804*b30d1939SAndy Fiddaman 				break;
805*b30d1939SAndy Fiddaman 			for (i = 0;; i++)
806*b30d1939SAndy Fiddaman 				if (i >= elementsof(u.c))
807*b30d1939SAndy Fiddaman 					return a->c[s];
808*b30d1939SAndy Fiddaman 				else if (i != s && u.c[i] != a->c[i])
809*b30d1939SAndy Fiddaman 					break;
810*b30d1939SAndy Fiddaman 		}
811*b30d1939SAndy Fiddaman 		return o;
812*b30d1939SAndy Fiddaman 	}
813*b30d1939SAndy Fiddaman #endif
814*b30d1939SAndy Fiddaman 	k = lock(state.data, 0, p);
815*b30d1939SAndy Fiddaman 	if (*p == o)
816*b30d1939SAndy Fiddaman 		*p = n;
817*b30d1939SAndy Fiddaman 	else
818*b30d1939SAndy Fiddaman 		o = *p;
819*b30d1939SAndy Fiddaman 	lock(state.data, k, p);
820*b30d1939SAndy Fiddaman 	return o;
821*b30d1939SAndy Fiddaman }
822*b30d1939SAndy Fiddaman 
823*b30d1939SAndy Fiddaman #ifdef _ast_int8_t
824*b30d1939SAndy Fiddaman 
825*b30d1939SAndy Fiddaman uint64_t
826*b30d1939SAndy Fiddaman asocas64(uint64_t volatile* p, uint64_t o, uint64_t n)
827*b30d1939SAndy Fiddaman {
828*b30d1939SAndy Fiddaman 	ssize_t		k;
829*b30d1939SAndy Fiddaman 
830*b30d1939SAndy Fiddaman #if defined(_aso_cas64)
831*b30d1939SAndy Fiddaman 	if (!state.lockf)
832*b30d1939SAndy Fiddaman 		return _aso_cas64(p, o, n);
833*b30d1939SAndy Fiddaman #endif
834*b30d1939SAndy Fiddaman 	k = lock(state.data, 0, p);
835*b30d1939SAndy Fiddaman 	if (*p == o)
836*b30d1939SAndy Fiddaman 		*p = n;
837*b30d1939SAndy Fiddaman 	else
838*b30d1939SAndy Fiddaman 		o = *p;
839*b30d1939SAndy Fiddaman 	lock(state.data, k, p);
840*b30d1939SAndy Fiddaman 	return o;
841*b30d1939SAndy Fiddaman }
842*b30d1939SAndy Fiddaman 
843*b30d1939SAndy Fiddaman #endif
844*b30d1939SAndy Fiddaman 
845*b30d1939SAndy Fiddaman /*
846*b30d1939SAndy Fiddaman  * compare with old, swap with new if same, and return old value
847*b30d1939SAndy Fiddaman  */
848*b30d1939SAndy Fiddaman 
849*b30d1939SAndy Fiddaman void*
850*b30d1939SAndy Fiddaman asocasptr(void volatile* p, void* o, void* n)
851*b30d1939SAndy Fiddaman {
852*b30d1939SAndy Fiddaman 	ssize_t		k;
853*b30d1939SAndy Fiddaman 
854*b30d1939SAndy Fiddaman #if defined(_aso_casptr)
855*b30d1939SAndy Fiddaman 	if (!state.lockf)
856*b30d1939SAndy Fiddaman 		return _aso_casptr((void**)p, o, n);
857*b30d1939SAndy Fiddaman #endif
858*b30d1939SAndy Fiddaman 	k = lock(state.data, 0, p);
859*b30d1939SAndy Fiddaman 	if (*(void* volatile*)p == o)
860*b30d1939SAndy Fiddaman 		*(void* volatile*)p = n;
861*b30d1939SAndy Fiddaman 	else
862*b30d1939SAndy Fiddaman 		o = *(void* volatile*)p;
863*b30d1939SAndy Fiddaman 	lock(state.data, k, p);
864*b30d1939SAndy Fiddaman 	return o;
865*b30d1939SAndy Fiddaman }
866*b30d1939SAndy Fiddaman 
867*b30d1939SAndy Fiddaman #endif
868