drm_atomic.h revision 145132
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 * $FreeBSD: head/sys/dev/drm/drm_atomic.h 145132 2005-04-16 03:44:47Z anholt $ 32 */ 33 34/* Many of these implementations are rather fake, but good enough. */ 35 36typedef u_int32_t atomic_t; 37 38#ifdef __FreeBSD__ 39#define atomic_set(p, v) (*(p) = (v)) 40#define atomic_read(p) (*(p)) 41#define atomic_inc(p) atomic_add_int(p, 1) 42#define atomic_dec(p) atomic_subtract_int(p, 1) 43#define atomic_add(n, p) atomic_add_int(p, n) 44#define atomic_sub(n, p) atomic_subtract_int(p, n) 45#else /* __FreeBSD__ */ 46/* FIXME */ 47#define atomic_set(p, v) (*(p) = (v)) 48#define atomic_read(p) (*(p)) 49#define atomic_inc(p) (*(p) += 1) 50#define atomic_dec(p) (*(p) -= 1) 51#define atomic_add(n, p) (*(p) += (n)) 52#define atomic_sub(n, p) (*(p) -= (n)) 53/* FIXME */ 54#define atomic_add_int(p, v) *(p) += v 55#define atomic_subtract_int(p, v) *(p) -= v 56#define atomic_set_int(p, bits) *(p) |= (bits) 57#define atomic_clear_int(p, bits) *(p) &= ~(bits) 58#endif /* !__FreeBSD__ */ 59 60#if !defined(__FreeBSD_version) || (__FreeBSD_version < 500000) 61#if defined(__i386__) 62/* The extra atomic functions from 5.0 haven't been merged to 4.x */ 63static __inline int 64atomic_cmpset_int(volatile u_int *dst, u_int exp, u_int src) 65{ 66 int res = exp; 67 68 __asm __volatile ( 69 " lock ; " 70 " cmpxchgl %1,%2 ; " 71 " setz %%al ; " 72 " movzbl %%al,%0 ; " 73 "1: " 74 "# atomic_cmpset_int" 75 : "+a" (res) /* 0 (result) */ 76 : "r" (src), /* 1 */ 77 "m" (*(dst)) /* 2 */ 78 : "memory"); 79 80 return (res); 81} 82#else /* __i386__ */ 83static __inline int 84atomic_cmpset_int(__volatile__ int *dst, int old, int new) 85{ 86 int s = splhigh(); 87 if (*dst==old) { 88 *dst = new; 89 splx(s); 90 return 1; 91 } 92 splx(s); 93 return 0; 94} 95#endif /* !__i386__ */ 96#endif /* !__FreeBSD_version || __FreeBSD_version < 500000 */ 97 98static __inline atomic_t 99test_and_set_bit(int b, volatile void *p) 100{ 101 int s = splhigh(); 102 unsigned int m = 1<<b; 103 unsigned int r = *(volatile int *)p & m; 104 *(volatile int *)p |= m; 105 splx(s); 106 return r; 107} 108 109static __inline void 110clear_bit(int b, volatile void *p) 111{ 112 atomic_clear_int(((volatile int *)p) + (b >> 5), 1 << (b & 0x1f)); 113} 114 115static __inline void 116set_bit(int b, volatile void *p) 117{ 118 atomic_set_int(((volatile int *)p) + (b >> 5), 1 << (b & 0x1f)); 119} 120 121static __inline int 122test_bit(int b, volatile void *p) 123{ 124 return ((volatile int *)p)[b >> 5] & (1 << (b & 0x1f)); 125} 126 127static __inline int 128find_first_zero_bit(volatile void *p, int max) 129{ 130 int b; 131 volatile int *ptr = (volatile int *)p; 132 133 for (b = 0; b < max; b += 32) { 134 if (ptr[b >> 5] != ~0) { 135 for (;;) { 136 if ((ptr[b >> 5] & (1 << (b & 0x1f))) == 0) 137 return b; 138 b++; 139 } 140 } 141 } 142 return max; 143} 144