1132400Sgrehan/*
2132400Sgrehan * Copyright 2004 by Peter Grehan. All rights reserved.
3132400Sgrehan *
4132400Sgrehan * Redistribution and use in source and binary forms, with or without
5132400Sgrehan * modification, are permitted provided that the following conditions
6132400Sgrehan * are met:
7132400Sgrehan * 1. Redistributions of source code must retain the above copyright
8132400Sgrehan *    notice, this list of conditions and the following disclaimer.
9132400Sgrehan * 2. Redistributions in binary form must reproduce the above copyright
10132400Sgrehan *    notice, this list of conditions and the following disclaimer in the
11132400Sgrehan *    documentation and/or other materials provided with the distribution.
12132400Sgrehan * 3. The name of the author may not be used to endorse or promote products
13132400Sgrehan *    derived from this software without specific prior written permission.
14132400Sgrehan *
15132400Sgrehan * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16132400Sgrehan * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17132400Sgrehan * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18132400Sgrehan * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19132400Sgrehan * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
20132400Sgrehan * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21132400Sgrehan * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
22132400Sgrehan * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23132400Sgrehan * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24132400Sgrehan * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25132400Sgrehan * SUCH DAMAGE.
26132400Sgrehan *
27132400Sgrehan * $FreeBSD$
28132400Sgrehan */
29132400Sgrehan
30132400Sgrehan#ifndef	_ATOMIC_OPS_H_
31132400Sgrehan#define	_ATOMIC_OPS_H_
32132400Sgrehan
33132400Sgrehan/*
34132400Sgrehan * Atomic swap:
35132400Sgrehan *   Atomic (tmp = *dst, *dst = val), then *res = tmp
36132400Sgrehan *
37132400Sgrehan * void atomic_swap32(intptr_t *dst, intptr_t val, intptr_t *res);
38132400Sgrehan */
39132400Sgrehanstatic inline void
40174112Sdeischenatomic_swap32(volatile intptr_t *dst, intptr_t val, intptr_t *res)
41132400Sgrehan{
42132400Sgrehan	int tmp;
43132400Sgrehan
44132400Sgrehan	tmp = 0;	/* should be a better way to quieten cc1... */
45132400Sgrehan#ifdef __GNUC__
46132400Sgrehan	__asm __volatile(
47132400Sgrehan		"1:	lwarx	%0, 0, %4\n"	/* load with reservation */
48132400Sgrehan		"	stwcx.	%3, 0, %4\n"	/* attempt to store val */
49132400Sgrehan		"	bne- 1b\n"		/* interrupted? retry */
50132400Sgrehan		"	stw	%0, %1\n"	/* else, *dst -> *res */
51132400Sgrehan		: "=&r" (tmp), "=m" (*res), "+m" (*dst)
52132400Sgrehan		: "r" (val), "r" (dst)
53132400Sgrehan		: "cc", "memory");
54132400Sgrehan#endif
55132400Sgrehan}
56132400Sgrehan
57132400Sgrehan#define	atomic_swap_ptr(d, v, r) \
58174112Sdeischen	atomic_swap32((volatile intptr_t *)d, (intptr_t)v, (intptr_t *)r)
59132400Sgrehan
60132400Sgrehan#define	atomic_swap_int(d, v, r) \
61174112Sdeischen	atomic_swap32((volatile intptr_t *)d, (intptr_t)v, (intptr_t *)r)
62132400Sgrehan#endif
63