LCOV - code coverage report
Current view: top level - netwerk/sctp/src - user_atomic.h (source / functions) Hit Total Coverage
Test: output.info Lines: 0 1 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 1 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*-
       2             :  * Copyright (c) 2009-2010 Brad Penoff
       3             :  * Copyright (c) 2009-2010 Humaira Kamal
       4             :  * Copyright (c) 2011-2012 Irene Ruengeler
       5             :  * Copyright (c) 2011-2012 Michael Tuexen
       6             :  *
       7             :  * All rights reserved.
       8             :  *
       9             :  * Redistribution and use in source and binary forms, with or without
      10             :  * modification, are permitted provided that the following conditions
      11             :  * are met:
      12             :  * 1. Redistributions of source code must retain the above copyright
      13             :  *    notice, this list of conditions and the following disclaimer.
      14             :  * 2. Redistributions in binary form must reproduce the above copyright
      15             :  *    notice, this list of conditions and the following disclaimer in the
      16             :  *    documentation and/or other materials provided with the distribution.
      17             :  *
      18             :  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
      19             :  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
      20             :  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
      21             :  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
      22             :  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
      23             :  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
      24             :  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
      25             :  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
      26             :  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
      27             :  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
      28             :  * SUCH DAMAGE.
      29             :  */
      30             : 
      31             : #ifndef _USER_ATOMIC_H_
      32             : #define _USER_ATOMIC_H_
      33             : 
      34             : /* __Userspace__ version of sys/i386/include/atomic.h goes here */
      35             : 
      36             : /* TODO In the future, might want to not use i386 specific assembly.
      37             :  *    The options include:
      38             :  *       - implement them generically (but maybe not truly atomic?) in userspace
      39             :  *       - have ifdef's for __Userspace_arch_ perhaps (OS isn't enough...)
      40             :  */
      41             : 
      42             : #include <stdio.h>
      43             : #include <sys/types.h>
      44             : 
      45             : #if defined(__Userspace_os_Darwin) || defined (__Userspace_os_Windows)
      46             : #if defined (__Userspace_os_Windows)
      47             : #define atomic_add_int(addr, val) InterlockedExchangeAdd((LPLONG)addr, (LONG)val)
      48             : #define atomic_fetchadd_int(addr, val) InterlockedExchangeAdd((LPLONG)addr, (LONG)val)
      49             : #define atomic_subtract_int(addr, val)   InterlockedExchangeAdd((LPLONG)addr,-((LONG)val))
      50             : #define atomic_cmpset_int(dst, exp, src) InterlockedCompareExchange((LPLONG)dst, src, exp)
      51             : #define SCTP_DECREMENT_AND_CHECK_REFCOUNT(addr) (InterlockedExchangeAdd((LPLONG)addr, (-1L)) == 1)
      52             : #else
      53             : #include <libkern/OSAtomic.h>
      54             : #define atomic_add_int(addr, val) OSAtomicAdd32Barrier(val, (int32_t *)addr)
      55             : #define atomic_fetchadd_int(addr, val) OSAtomicAdd32Barrier(val, (int32_t *)addr)
      56             : #define atomic_subtract_int(addr, val) OSAtomicAdd32Barrier(-val, (int32_t *)addr)
      57             : #define atomic_cmpset_int(dst, exp, src) OSAtomicCompareAndSwapIntBarrier(exp, src, (int *)dst)
      58             : #define SCTP_DECREMENT_AND_CHECK_REFCOUNT(addr) (atomic_fetchadd_int(addr, -1) == 0)
      59             : #endif
      60             : 
      61             : #if defined(INVARIANTS)
      62             : #define SCTP_SAVE_ATOMIC_DECREMENT(addr, val) \
      63             : { \
      64             :         int32_t newval; \
      65             :         newval = atomic_fetchadd_int(addr, -val); \
      66             :         if (newval < 0) { \
      67             :                 panic("Counter goes negative"); \
      68             :         } \
      69             : }
      70             : #else
      71             : #define SCTP_SAVE_ATOMIC_DECREMENT(addr, val) \
      72             : { \
      73             :         int32_t newval; \
      74             :         newval = atomic_fetchadd_int(addr, -val); \
      75             :         if (newval < 0) { \
      76             :                 *addr = 0; \
      77             :         } \
      78             : }
      79             : #if defined(__Userspace_os_Windows)
      80             : static void atomic_init() {} /* empty when we are not using atomic_mtx */
      81             : #else
      82             : static inline void atomic_init() {} /* empty when we are not using atomic_mtx */
      83             : #endif
      84             : #endif
      85             : 
      86             : #else
      87             : /* Using gcc built-in functions for atomic memory operations
      88             :    Reference: http://gcc.gnu.org/onlinedocs/gcc-4.1.0/gcc/Atomic-Builtins.html
      89             :    Requires gcc version 4.1.0
      90             :    compile with -march=i486
      91             :  */
      92             : 
      93             : /*Atomically add V to *P.*/
      94             : #define atomic_add_int(P, V)     (void) __sync_fetch_and_add(P, V)
      95             : 
      96             : /*Atomically subtrace V from *P.*/
      97             : #define atomic_subtract_int(P, V) (void) __sync_fetch_and_sub(P, V)
      98             : 
      99             : /*
     100             :  * Atomically add the value of v to the integer pointed to by p and return
     101             :  * the previous value of *p.
     102             :  */
     103             : #define atomic_fetchadd_int(p, v) __sync_fetch_and_add(p, v)
     104             : 
     105             : /* Following explanation from src/sys/i386/include/atomic.h,
     106             :  * for atomic compare and set
     107             :  *
     108             :  * if (*dst == exp) *dst = src (all 32 bit words)
     109             :  *
     110             :  * Returns 0 on failure, non-zero on success
     111             :  */
     112             : 
     113             : #define atomic_cmpset_int(dst, exp, src) __sync_bool_compare_and_swap(dst, exp, src)
     114             : 
     115             : #define SCTP_DECREMENT_AND_CHECK_REFCOUNT(addr) (atomic_fetchadd_int(addr, -1) == 1)
     116             : #if defined(INVARIANTS)
     117             : #define SCTP_SAVE_ATOMIC_DECREMENT(addr, val) \
     118             : { \
     119             :         int32_t oldval; \
     120             :         oldval = atomic_fetchadd_int(addr, -val); \
     121             :         if (oldval < val) { \
     122             :                 panic("Counter goes negative"); \
     123             :         } \
     124             : }
     125             : #else
     126             : #define SCTP_SAVE_ATOMIC_DECREMENT(addr, val) \
     127             : { \
     128             :         int32_t oldval; \
     129             :         oldval = atomic_fetchadd_int(addr, -val); \
     130             :         if (oldval < val) { \
     131             :                 *addr = 0; \
     132             :         } \
     133             : }
     134             : #endif
     135           0 : static inline void atomic_init() {} /* empty when we are not using atomic_mtx */
     136             : #endif
     137             : 
     138             : #if 0 /* using libatomic_ops */
     139             : #include "user_include/atomic_ops.h"
     140             : 
     141             : /*Atomically add incr to *P, and return the original value of *P.*/
     142             : #define atomic_add_int(P, V)     AO_fetch_and_add((AO_t*)P, V)
     143             : 
     144             : #define atomic_subtract_int(P, V) AO_fetch_and_add((AO_t*)P, -(V))
     145             : 
     146             : /*
     147             :  * Atomically add the value of v to the integer pointed to by p and return
     148             :  * the previous value of *p.
     149             :  */
     150             : #define atomic_fetchadd_int(p, v) AO_fetch_and_add((AO_t*)p, v)
     151             : 
     152             : /* Atomically compare *addr to old_val, and replace *addr by new_val
     153             :    if the first comparison succeeds.  Returns nonzero if the comparison
     154             :    succeeded and *addr was updated.
     155             : */
     156             : /* Following Explanation from src/sys/i386/include/atomic.h, which
     157             :    matches that of AO_compare_and_swap above.
     158             :  * Atomic compare and set, used by the mutex functions
     159             :  *
     160             :  * if (*dst == exp) *dst = src (all 32 bit words)
     161             :  *
     162             :  * Returns 0 on failure, non-zero on success
     163             :  */
     164             : 
     165             : #define atomic_cmpset_int(dst, exp, src) AO_compare_and_swap((AO_t*)dst, exp, src)
     166             : 
     167             : static inline void atomic_init() {} /* empty when we are not using atomic_mtx */
     168             : #endif /* closing #if for libatomic */
     169             : 
     170             : #if 0 /* using atomic_mtx */
     171             : 
     172             : #include <pthread.h>
     173             : 
     174             : extern userland_mutex_t atomic_mtx;
     175             : 
     176             : #if defined (__Userspace_os_Windows)
     177             : static inline void atomic_init() {
     178             :         InitializeCriticalSection(&atomic_mtx);
     179             : }
     180             : static inline void atomic_destroy() {
     181             :         DeleteCriticalSection(&atomic_mtx);
     182             : }
     183             : static inline void atomic_lock() {
     184             :         EnterCriticalSection(&atomic_mtx);
     185             : }
     186             : static inline void atomic_unlock() {
     187             :         LeaveCriticalSection(&atomic_mtx);
     188             : }
     189             : #else
     190             : static inline void atomic_init() {
     191             :         (void)pthread_mutex_init(&atomic_mtx, NULL);
     192             : }
     193             : static inline void atomic_destroy() {
     194             :         (void)pthread_mutex_destroy(&atomic_mtx);
     195             : }
     196             : static inline void atomic_lock() {
     197             :         (void)pthread_mutex_lock(&atomic_mtx);
     198             : }
     199             : static inline void atomic_unlock() {
     200             :         (void)pthread_mutex_unlock(&atomic_mtx);
     201             : }
     202             : #endif
     203             : /*
     204             :  * For userland, always use lock prefixes so that the binaries will run
     205             :  * on both SMP and !SMP systems.
     206             :  */
     207             : 
     208             : #define MPLOCKED        "lock ; "
     209             : 
     210             : /*
     211             :  * Atomically add the value of v to the integer pointed to by p and return
     212             :  * the previous value of *p.
     213             :  */
     214             : static __inline u_int
     215             : atomic_fetchadd_int(volatile void *n, u_int v)
     216             : {
     217             :         int *p = (int *) n;
     218             :         atomic_lock();
     219             :         __asm __volatile(
     220             :         "  " MPLOCKED "          "
     221             :         "  xaddl   %0, %1 ;        "
     222             :         "# atomic_fetchadd_int"
     223             :         : "+r" (v),                   /* 0 (result) */
     224             :           "=m" (*p)                   /* 1 */
     225             :         : "m" (*p));                  /* 2 */
     226             :         atomic_unlock();
     227             : 
     228             :         return (v);
     229             : }
     230             : 
     231             : 
     232             : #ifdef CPU_DISABLE_CMPXCHG
     233             : 
     234             : static __inline int
     235             : atomic_cmpset_int(volatile u_int *dst, u_int exp, u_int src)
     236             : {
     237             :         u_char res;
     238             : 
     239             :         atomic_lock();
     240             :         __asm __volatile(
     241             :         "  pushfl ;                "
     242             :         "  cli ;                   "
     243             :         "  cmpl    %3,%4 ;         "
     244             :         "  jne     1f ;            "
     245             :         "  movl    %2,%1 ;         "
     246             :         "1:                                "
     247             :         "       sete       %0 ;            "
     248             :         "  popfl ;                 "
     249             :         "# atomic_cmpset_int"
     250             :         : "=q" (res),                 /* 0 */
     251             :           "=m" (*dst)                 /* 1 */
     252             :         : "r" (src),                  /* 2 */
     253             :           "r" (exp),                  /* 3 */
     254             :           "m" (*dst)                  /* 4 */
     255             :         : "memory");
     256             :         atomic_unlock();
     257             : 
     258             :         return (res);
     259             : }
     260             : 
     261             : #else /* !CPU_DISABLE_CMPXCHG */
     262             : 
     263             : static __inline int
     264             : atomic_cmpset_int(volatile u_int *dst, u_int exp, u_int src)
     265             : {
     266             :         atomic_lock();
     267             :         u_char res;
     268             : 
     269             :         __asm __volatile(
     270             :         "  " MPLOCKED "          "
     271             :         "  cmpxchgl %2,%1 ;        "
     272             :         "  sete    %0 ;            "
     273             :         "1:                                "
     274             :         "# atomic_cmpset_int"
     275             :         : "=a" (res),                 /* 0 */
     276             :           "=m" (*dst)                 /* 1 */
     277             :         : "r" (src),                  /* 2 */
     278             :           "a" (exp),                  /* 3 */
     279             :           "m" (*dst)                  /* 4 */
     280             :         : "memory");
     281             :         atomic_unlock();
     282             : 
     283             :         return (res);
     284             : }
     285             : 
     286             : #endif /* CPU_DISABLE_CMPXCHG */
     287             : 
     288             : #define atomic_add_int(P, V)     do {   \
     289             :                 atomic_lock();          \
     290             :                 (*(u_int *)(P) += (V)); \
     291             :                 atomic_unlock();        \
     292             : } while(0)
     293             : #define atomic_subtract_int(P, V)  do {   \
     294             :                 atomic_lock();            \
     295             :                 (*(u_int *)(P) -= (V));   \
     296             :                 atomic_unlock();          \
     297             : } while(0)
     298             : 
     299             : #endif
     300             : #endif

Generated by: LCOV version 1.13