LCOV - code coverage report
Current view: top level - dev/pci/drm - drm_linux_atomic.h (source / functions) Hit Total Coverage
Test: 6.4 Lines: 0 79 0.0 %
Date: 2018-10-19 03:25:38 Functions: 0 14 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* $OpenBSD: drm_linux_atomic.h,v 1.2 2018/01/30 08:15:17 jsg Exp $ */
       2             : /**
       3             :  * \file drm_atomic.h
       4             :  * Atomic operations used in the DRM which may or may not be provided by the OS.
       5             :  * 
       6             :  * \author Eric Anholt <anholt@FreeBSD.org>
       7             :  */
       8             : 
       9             : /*-
      10             :  * Copyright 2004 Eric Anholt
      11             :  * All Rights Reserved.
      12             :  *
      13             :  * Permission is hereby granted, free of charge, to any person obtaining a
      14             :  * copy of this software and associated documentation files (the "Software"),
      15             :  * to deal in the Software without restriction, including without limitation
      16             :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      17             :  * and/or sell copies of the Software, and to permit persons to whom the
      18             :  * Software is furnished to do so, subject to the following conditions:
      19             :  *
      20             :  * The above copyright notice and this permission notice (including the next
      21             :  * paragraph) shall be included in all copies or substantial portions of the
      22             :  * Software.
      23             :  *
      24             :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      25             :  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      26             :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
      27             :  * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
      28             :  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
      29             :  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
      30             :  * OTHER DEALINGS IN THE SOFTWARE.
      31             :  */
      32             : 
      33             : #ifndef _DRM_LINUX_ATOMIC_H_
      34             : #define _DRM_LINUX_ATOMIC_H_
      35             : 
      36             : #include <machine/atomic.h>
      37             : 
      38             : typedef uint32_t atomic_t;
      39             : 
      40             : #define atomic_set(p, v)        (*(p) = (v))
      41             : #define atomic_read(p)          (*(p))
      42             : #define atomic_inc(p)           __sync_fetch_and_add(p, 1)
      43             : #define atomic_dec(p)           __sync_fetch_and_sub(p, 1)
      44             : #define atomic_add(n, p)        __sync_fetch_and_add(p, n)
      45             : #define atomic_sub(n, p)        __sync_fetch_and_sub(p, n)
      46             : #define atomic_add_return(n, p) __sync_add_and_fetch(p, n)
      47             : #define atomic_sub_return(n, p) __sync_sub_and_fetch(p, n)
      48             : #define atomic_inc_return(v)    atomic_add_return(1, (v))
      49             : #define atomic_dec_return(v)    atomic_sub_return(1, (v))
      50             : #define atomic_dec_and_test(v)  (atomic_dec_return(v) == 0)
      51             : #define atomic_inc_and_test(v)  (atomic_inc_return(v) == 0)
      52             : #define atomic_or(n, p)         atomic_setbits_int(p, n)
      53             : #define atomic_cmpxchg(p, o, n) __sync_val_compare_and_swap(p, o, n)
      54             : 
      55             : static __inline int
      56           0 : atomic_xchg(volatile int *v, int n)
      57             : {
      58           0 :         __sync_synchronize();
      59           0 :         return __sync_lock_test_and_set(v, n);
      60             : }
      61             : 
      62             : static __inline int
      63           0 : atomic_add_unless(volatile int *v, int n, int u)
      64             : {
      65           0 :         int o = *v;
      66             : 
      67           0 :         do {
      68           0 :                 o = *v;
      69           0 :                 if (o == u)
      70           0 :                         return 0;
      71           0 :         } while (__sync_val_compare_and_swap(v, o, o +n) != o);
      72             : 
      73           0 :         return 1;
      74           0 : }
      75             : 
      76             : #define atomic_long_read(p)     (*(p))
      77             : 
      78             : #ifdef __LP64__
      79             : typedef uint64_t atomic64_t;
      80             : 
      81             : #define atomic64_set(p, v)      (*(p) = (v))
      82             : #define atomic64_read(p)        (*(p))
      83             : 
      84             : static __inline int64_t
      85           0 : atomic64_xchg(volatile int64_t *v, int64_t n)
      86             : {
      87           0 :         __sync_synchronize();
      88           0 :         return __sync_lock_test_and_set(v, n);
      89             : }
      90             : 
      91             : #define atomic64_add(n, p)      __sync_fetch_and_add_8(p, n)
      92             : #define atomic64_sub(n, p)      __sync_fetch_and_sub_8(p, n)
      93             : 
      94             : #else
      95             : 
      96             : typedef struct {
      97             :         volatile uint64_t val;
      98             :         struct mutex lock;
      99             : } atomic64_t;
     100             : 
     101             : static __inline void
     102             : atomic64_set(atomic64_t *v, int64_t i)
     103             : {
     104             :         mtx_init(&v->lock, IPL_HIGH);
     105             :         v->val = i;
     106             : }
     107             : 
     108             : static __inline int64_t
     109             : atomic64_read(atomic64_t *v)
     110             : {
     111             :         int64_t val;
     112             : 
     113             :         mtx_enter(&v->lock);
     114             :         val = v->val;
     115             :         mtx_leave(&v->lock);
     116             : 
     117             :         return val;
     118             : }
     119             : 
     120             : static __inline int64_t
     121             : atomic64_xchg(atomic64_t *v, int64_t n)
     122             : {
     123             :         int64_t val;
     124             : 
     125             :         mtx_enter(&v->lock);
     126             :         val = v->val;
     127             :         v->val = n;
     128             :         mtx_leave(&v->lock);
     129             : 
     130             :         return val;
     131             : }
     132             : 
     133             : static __inline void
     134             : atomic64_add(int i, atomic64_t *v)
     135             : {
     136             :         mtx_enter(&v->lock);
     137             :         v->val += i;
     138             :         mtx_leave(&v->lock);
     139             : }
     140             : 
     141             : static __inline void
     142             : atomic64_sub(int i, atomic64_t *v)
     143             : {
     144             :         mtx_enter(&v->lock);
     145             :         v->val -= i;
     146             :         mtx_leave(&v->lock);
     147             : }
     148             : #endif
     149             : 
     150             : static inline int
     151           0 : atomic_inc_not_zero(atomic_t *p)
     152             : {
     153           0 :         if (*p == 0)
     154           0 :                 return (0);
     155             : 
     156           0 :         *(p) += 1;
     157           0 :         return (*p);
     158           0 : }
     159             : 
     160             : /* FIXME */
     161             : #define atomic_set_int(p, bits)         atomic_setbits_int(p,bits)
     162             : #define atomic_set_mask(bits, p)        atomic_setbits_int(p,bits)
     163             : #define atomic_clear_int(p, bits)       atomic_clearbits_int(p,bits)
     164             : #define atomic_clear_mask(bits, p)      atomic_clearbits_int(p,bits)
     165             : #define atomic_fetchadd_int(p, n) __sync_fetch_and_add(p, n)
     166             : #define atomic_fetchsub_int(p, n) __sync_fetch_and_sub(p, n)
     167             : 
     168             : #if defined(__i386__) || defined(__amd64__)
     169             : static __inline int
     170             : atomic_cmpset_int(volatile u_int *dst, u_int exp, u_int src)
     171             : {
     172             :         int res = exp;
     173             : 
     174             :         __asm __volatile (
     175             :         "  lock ;                  "
     176             :         "  cmpxchgl %1,%2 ;        "
     177             :         "       setz       %%al ;          "
     178             :         "  movzbl  %%al,%0 ;       "
     179             :         "1:                                "
     180             :         "# atomic_cmpset_int"
     181             :         : "+a" (res)                  /* 0 (result) */
     182             :         : "r" (src),                  /* 1 */
     183             :           "m" (*(dst))                        /* 2 */
     184             :         : "memory");                           
     185             : 
     186             :         return (res);
     187             : }
     188             : #else /* __i386__ */
     189             : static __inline int
     190             : atomic_cmpset_int(__volatile__ u_int *dst, u_int old, u_int new)
     191             : {
     192             :         int s = splhigh();
     193             :         if (*dst==old) {
     194             :                 *dst = new;
     195             :                 splx(s);
     196             :                 return 1;
     197             :         }
     198             :         splx(s);
     199             :         return 0;
     200             : }
     201             : #endif /* !__i386__ */
     202             : 
     203             : static __inline atomic_t
     204           0 : test_and_set_bit(u_int b, volatile void *p)
     205             : {
     206           0 :         int s = splhigh();
     207           0 :         unsigned int m = 1<<b;
     208           0 :         unsigned int r = *(volatile int *)p & m;
     209           0 :         *(volatile int *)p |= m;
     210           0 :         splx(s);
     211           0 :         return r;
     212             : }
     213             : 
     214             : static __inline void
     215           0 : clear_bit(u_int b, volatile void *p)
     216             : {
     217           0 :         atomic_clear_int(((volatile u_int *)p) + (b >> 5), 1 << (b & 0x1f));
     218           0 : }
     219             : 
     220             : static __inline void
     221           0 : set_bit(u_int b, volatile void *p)
     222             : {
     223           0 :         atomic_set_int(((volatile u_int *)p) + (b >> 5), 1 << (b & 0x1f));
     224           0 : }
     225             : 
     226             : static __inline void
     227           0 : __clear_bit(u_int b, volatile void *p)
     228             : {
     229           0 :         volatile u_int *ptr = (volatile u_int *)p;
     230           0 :         ptr[b >> 5] &= ~(1 << (b & 0x1f));
     231           0 : }
     232             : 
     233             : static __inline void
     234           0 : __set_bit(u_int b, volatile void *p)
     235             : {
     236           0 :         volatile u_int *ptr = (volatile u_int *)p;
     237           0 :         ptr[b >> 5] |= (1 << (b & 0x1f));
     238           0 : }
     239             : 
     240             : static __inline int
     241           0 : test_bit(u_int b, volatile void *p)
     242             : {
     243           0 :         return !!(((volatile u_int *)p)[b >> 5] & (1 << (b & 0x1f)));
     244             : }
     245             : 
     246             : static __inline int
     247           0 : __test_and_clear_bit(u_int b, volatile void *p)
     248             : {
     249           0 :         volatile u_int *ptr = (volatile u_int *)p;
     250           0 :         int rv = !!(ptr[b >> 5] & (1 << (b & 0x1f)));
     251           0 :         ptr[b >> 5] &= ~(1 << (b & 0x1f));
     252           0 :         return rv;
     253             : }
     254             : 
     255             : static __inline int
     256           0 : find_first_zero_bit(volatile void *p, int max)
     257             : {
     258             :         int b;
     259           0 :         volatile u_int *ptr = (volatile u_int *)p;
     260             : 
     261           0 :         for (b = 0; b < max; b += 32) {
     262           0 :                 if (ptr[b >> 5] != ~0) {
     263           0 :                         for (;;) {
     264           0 :                                 if ((ptr[b >> 5] & (1 << (b & 0x1f))) == 0)
     265           0 :                                         return b;
     266           0 :                                 b++;
     267             :                         }
     268             :                 }
     269             :         }
     270           0 :         return max;
     271           0 : }
     272             : 
     273             : static __inline int
     274           0 : find_first_bit(volatile void *p, int max)
     275             : {
     276             :         int b;
     277           0 :         volatile u_int *ptr = (volatile u_int *)p;
     278             : 
     279           0 :         for (b = 0; b < max; b += 32) {
     280           0 :                 if (ptr[b >> 5] != 0) {
     281           0 :                         for (;;) {
     282           0 :                                 if (ptr[b >> 5] & (1 << (b & 0x1f)))
     283           0 :                                         return b;
     284           0 :                                 b++;
     285             :                         }
     286             :                 }
     287             :         }
     288           0 :         return max;
     289           0 : }
     290             : 
     291             : static __inline int
     292           0 : find_next_bit(volatile void *p, int max, int b)
     293             : {
     294           0 :         volatile u_int *ptr = (volatile u_int *)p;
     295             : 
     296           0 :         for (; b < max; b+= 32) {
     297           0 :                 if (ptr[b >> 5] != 0) {
     298           0 :                         for (;;) {
     299           0 :                                 if (ptr[b >> 5] & (1 << (b & 0x1f)))
     300           0 :                                         return b;
     301           0 :                                 b++;
     302             :                         }
     303             :                 }
     304             :         }
     305           0 :         return max;
     306           0 : }
     307             : 
     308             : #define for_each_set_bit(b, p, max) \
     309             :         for ((b) = find_first_bit((p), (max));                  \
     310             :              (b) < (max);                                    \
     311             :              (b) = find_next_bit((p), (max), (b) + 1))
     312             : 
     313             : #endif

Generated by: LCOV version 1.13