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 /* Many of these implementations are rather fake, but good enough. */ 33 34 typedef u_int32_t atomic_t; 35 36 #if defined(__FreeBSD__) 37 #define atomic_set(p, v) (*(p) = (v)) 38 #define atomic_read(p) (*(p)) 39 #define atomic_inc(p) atomic_add_int(p, 1) 40 #define atomic_dec(p) atomic_subtract_int(p, 1) 41 #define atomic_add(n, p) atomic_add_int(p, n) 42 #define atomic_sub(n, p) atomic_subtract_int(p, n) 43 44 static __inline atomic_t 45 test_and_set_bit(int b, volatile void *p) 46 { 47 int s = splhigh(); 48 unsigned int m = 1<<b; 49 unsigned int r = *(volatile int *)p & m; 50 *(volatile int *)p |= m; 51 splx(s); 52 return r; 53 } 54 55 static __inline void 56 clear_bit(int b, volatile void *p) 57 { 58 atomic_clear_int(((volatile int *)p) + (b >> 5), 1 << (b & 0x1f)); 59 } 60 61 static __inline void 62 set_bit(int b, volatile void *p) 63 { 64 atomic_set_int(((volatile int *)p) + (b >> 5), 1 << (b & 0x1f)); 65 } 66 67 static __inline int 68 test_bit(int b, volatile void *p) 69 { 70 return ((volatile int *)p)[b >> 5] & (1 << (b & 0x1f)); 71 } 72 73 #elif defined(__NetBSD__) 74 75 #include <sys/atomic.h> 76 77 #define atomic_set(p, v) (*((volatile uint32_t *)p) = (v)) 78 #define atomic_read(p) (*(p)) 79 #define atomic_inc(p) atomic_inc_uint(p) 80 #define atomic_dec(p) atomic_dec_uint(p) 81 #define atomic_add(n, p) atomic_add_int(p, n) 82 #define atomic_sub(n, p) atomic_add_int(p, -(n)) 83 84 #define atomic_add_acq_int(p, v) atomic_add(v, p) 85 #define atomic_subtract_acq_int(p, v) atomic_sub(v, p) 86 #define atomic_set_int(p, bits) atomic_or_uint(p, bits) 87 #define atomic_clear_int(p, bits) atomic_and_uint(p, ~(bits)) 88 89 #define atomic_cmpset_int(p, o, n) \ 90 ((old == atomic_cas_uint(p, o, n)) ? 1 : 0) 91 92 #define set_bit(b, p) \ 93 atomic_set_int(((volatile uint32_t *)(volatile void *)p) + (b >> 5),\ 94 (1 << (b & 0x1f))) 95 96 #define clear_bit(b, p) \ 97 atomic_clear_int(((volatile uint32_t *)(volatile void *)p) + (b >> 5), \ 98 (1 << (b & 0x1f))) 99 100 #define test_bit(b, p) \ 101 (((volatile uint32_t *)(volatile void *)p)[b >> 5] & (1 << (b & 0x1f))) 102 103 static __inline uint32_t 104 test_and_set_bit(int b, volatile void *p) 105 { 106 volatile uint32_t *val; 107 uint32_t mask, old; 108 109 val = (volatile uint32_t *)p; 110 mask = 1 << b; 111 112 do { 113 old = *val; 114 if ((old & mask) != 0) 115 break; 116 } while (atomic_cas_uint(val, old, old | mask) != old); 117 118 return old & mask; 119 } 120 121 #endif 122 static __inline int 123 find_first_zero_bit(volatile void *p, int max_) 124 { 125 int b; 126 volatile int *ptr = (volatile int *)p; 127 128 for (b = 0; b < max_; b += 32) { 129 if (ptr[b >> 5] != ~0) { 130 for (;;) { 131 if ((ptr[b >> 5] & (1 << (b & 0x1f))) == 0) 132 return b; 133 b++; 134 } 135 } 136 } 137 return max_; 138 } 139