netwerk/sctp/src/user_atomic.h

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rwxr-xr-x

Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

     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  */
    31 #ifndef _USER_ATOMIC_H_
    32 #define _USER_ATOMIC_H_
    34 /* __Userspace__ version of sys/i386/include/atomic.h goes here */
    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  */
    42 #include <stdio.h>
    43 #include <sys/types.h>
    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
    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
    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  */
    93 /*Atomically add V to *P.*/
    94 #define atomic_add_int(P, V)	 (void) __sync_fetch_and_add(P, V)
    96 /*Atomically subtrace V from *P.*/
    97 #define atomic_subtract_int(P, V) (void) __sync_fetch_and_sub(P, V)
    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)
   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  */
   113 #define atomic_cmpset_int(dst, exp, src) __sync_bool_compare_and_swap(dst, exp, src)
   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 static inline void atomic_init() {} /* empty when we are not using atomic_mtx */
   136 #endif
   138 #if 0 /* using libatomic_ops */
   139 #include "user_include/atomic_ops.h"
   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)
   144 #define atomic_subtract_int(P, V) AO_fetch_and_add((AO_t*)P, -(V))
   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)
   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  */
   165 #define atomic_cmpset_int(dst, exp, src) AO_compare_and_swap((AO_t*)dst, exp, src)
   167 static inline void atomic_init() {} /* empty when we are not using atomic_mtx */
   168 #endif /* closing #if for libatomic */
   170 #if 0 /* using atomic_mtx */
   172 #include <pthread.h>
   174 extern userland_mutex_t atomic_mtx;
   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  */
   208 #define	MPLOCKED	"lock ; "
   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();
   228 	return (v);
   229 }
   232 #ifdef CPU_DISABLE_CMPXCHG
   234 static __inline int
   235 atomic_cmpset_int(volatile u_int *dst, u_int exp, u_int src)
   236 {
   237 	u_char res;
   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();
   258 	return (res);
   259 }
   261 #else /* !CPU_DISABLE_CMPXCHG */
   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;
   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();
   283 	return (res);
   284 }
   286 #endif /* CPU_DISABLE_CMPXCHG */
   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)
   299 #endif
   300 #endif

mercurial