drm_atomic.h revision 152909
1/** 2 * \file drm_atomic.h 3 * Atomic operations used in the DRM which may or may not be provided by the OS. 4 * 5 * \author Eric Anholt <anholt@FreeBSD.org> 6 */ 7 8/*- 9 * Copyright 2004 Eric Anholt 10 * All Rights Reserved. 11 * 12 * Permission is hereby granted, free of charge, to any person obtaining a 13 * copy of this software and associated documentation files (the "Software"), 14 * to deal in the Software without restriction, including without limitation 15 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 16 * and/or sell copies of the Software, and to permit persons to whom the 17 * Software is furnished to do so, subject to the following conditions: 18 * 19 * The above copyright notice and this permission notice (including the next 20 * paragraph) shall be included in all copies or substantial portions of the 21 * Software. 22 * 23 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 24 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 25 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 26 * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 27 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 28 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 29 * OTHER DEALINGS IN THE SOFTWARE. 30 */ 31 32#include <sys/cdefs.h> 33__FBSDID("$FreeBSD: head/sys/dev/drm/drm_atomic.h 152909 2005-11-28 23:13:57Z anholt $"); 34 35/* Many of these implementations are rather fake, but good enough. */ 36 37typedef u_int32_t atomic_t; 38 39#ifdef __FreeBSD__ 40#define atomic_set(p, v) (*(p) = (v)) 41#define atomic_read(p) (*(p)) 42#define atomic_inc(p) atomic_add_int(p, 1) 43#define atomic_dec(p) atomic_subtract_int(p, 1) 44#define atomic_add(n, p) atomic_add_int(p, n) 45#define atomic_sub(n, p) atomic_subtract_int(p, n) 46#else /* __FreeBSD__ */ 47/* FIXME */ 48#define atomic_set(p, v) (*(p) = (v)) 49#define atomic_read(p) (*(p)) 50#define atomic_inc(p) (*(p) += 1) 51#define atomic_dec(p) (*(p) -= 1) 52#define atomic_add(n, p) (*(p) += (n)) 53#define atomic_sub(n, p) (*(p) -= (n)) 54/* FIXME */ 55#define atomic_add_int(p, v) *(p) += v 56#define atomic_subtract_int(p, v) *(p) -= v 57#define atomic_set_int(p, bits) *(p) |= (bits) 58#define atomic_clear_int(p, bits) *(p) &= ~(bits) 59#endif /* !__FreeBSD__ */ 60 61#if !defined(__FreeBSD_version) || (__FreeBSD_version < 500000) 62#if defined(__i386__) 63/* The extra atomic functions from 5.0 haven't been merged to 4.x */ 64static __inline int 65atomic_cmpset_int(volatile u_int *dst, u_int exp, u_int src) 66{ 67 int res = exp; 68 69 __asm __volatile ( 70 " lock ; " 71 " cmpxchgl %1,%2 ; " 72 " setz %%al ; " 73 " movzbl %%al,%0 ; " 74 "1: " 75 "# atomic_cmpset_int" 76 : "+a" (res) /* 0 (result) */ 77 : "r" (src), /* 1 */ 78 "m" (*(dst)) /* 2 */ 79 : "memory"); 80 81 return (res); 82} 83#else /* __i386__ */ 84static __inline int 85atomic_cmpset_int(__volatile__ int *dst, int old, int new) 86{ 87 int s = splhigh(); 88 if (*dst==old) { 89 *dst = new; 90 splx(s); 91 return 1; 92 } 93 splx(s); 94 return 0; 95} 96#endif /* !__i386__ */ 97#endif /* !__FreeBSD_version || __FreeBSD_version < 500000 */ 98 99static __inline atomic_t 100test_and_set_bit(int b, volatile void *p) 101{ 102 int s = splhigh(); 103 unsigned int m = 1<<b; 104 unsigned int r = *(volatile int *)p & m; 105 *(volatile int *)p |= m; 106 splx(s); 107 return r; 108} 109 110static __inline void 111clear_bit(int b, volatile void *p) 112{ 113 atomic_clear_int(((volatile int *)p) + (b >> 5), 1 << (b & 0x1f)); 114} 115 116static __inline void 117set_bit(int b, volatile void *p) 118{ 119 atomic_set_int(((volatile int *)p) + (b >> 5), 1 << (b & 0x1f)); 120} 121 122static __inline int 123test_bit(int b, volatile void *p) 124{ 125 return ((volatile int *)p)[b >> 5] & (1 << (b & 0x1f)); 126} 127 128static __inline int 129find_first_zero_bit(volatile void *p, int max) 130{ 131 int b; 132 volatile int *ptr = (volatile int *)p; 133 134 for (b = 0; b < max; b += 32) { 135 if (ptr[b >> 5] != ~0) { 136 for (;;) { 137 if ((ptr[b >> 5] & (1 << (b & 0x1f))) == 0) 138 return b; 139 b++; 140 } 141 } 142 } 143 return max; 144} 145