root/src/utils/noit_atomic.h

Revision 3b3b432b41dd3bfb80c144aa7ba28e75daa2337f, 2.9 kB (checked in by Theo Schlossnagle <jesus@omniti.com>, 10 years ago)

asynchronous job queues

  • Property mode set to 100644
Line 
1 /*
2  * Copyright (c) 2007, OmniTI Computer Consulting, Inc.
3  * All rights reserved.
4  */
5
6 #ifndef UTILS_NOIT_ATOMIC_H
7 #define UTILS_NOIT_ATOMIC_H
8
9 #include "noit_config.h"
10
11 typedef int32_t noit_atomic32_t;
12 typedef int64_t noit_atomic64_t;
13
14 #ifdef HAVE_LIBKERN_OSATOMIC_H
15 /*
16  * This secion is for Darwin.
17  * And we simply don't run on 32bit PPC.  Life's a bitch.
18  */
19 #include <libkern/OSAtomic.h>
20 typedef OSSpinLock noit_spinlock_t;
21 #define noit_atomic_cas32(ref,new,old) (OSAtomicCompareAndSwap32(old,new,ref) ? old : new)
22 #define noit_atomic_cas64(ref,new,old) (OSAtomicCompareAndSwap64(old,new,ref) ? old : new)
23 #define noit_atomic_inc32(ref) OSAtomicIncrement32(ref)
24 #define noit_atomic_inc64(ref) OSAtomicIncrement64(ref)
25 #define noit_atomic_dec32(ref) OSAtomicDecrement32(ref)
26 #define noit_atomic_dec64(ref) OSAtomicDecrement64(ref)
27 #define noit_spinlock_lock OSSpinLockLock
28 #define noit_spinlock_unlock OSSpinLockUnlock
29 #define noit_spinlock_trylock OSSpinLockTry
30 #elif defined(__GNUC__)
31
32 #if (SIZEOF_VOID_P == 4)
33 #define noit_atomic_casptr(a,b,c) noit_atomic_cas32((a),(void *)(b),(void *)(c))
34 #elif (SIZEOF_VOID_P == 8)
35 #define noit_atomic_casptr(a,b,c) noit_atomic_cas64((a),(void *)(b),(void *)(c))
36 #else
37 #error unsupported pointer width
38 #endif
39
40 typedef noit_atomic32_t noit_spinlock_t;
41
42 static inline noit_atomic32_t
43 noit_atomic_cas32(volatile noit_atomic32_t *ptr,
44                   volatile noit_atomic32_t rpl,
45                   volatile noit_atomic32_t curr) {
46   noit_atomic32_t prev;
47   __asm__ volatile (
48       "lock; cmpxchgl %1, %2"
49     : "=a" (prev)
50     : "r"  (rpl), "m" (*(ptr)), "0" (curr)
51     : "memory");
52   return prev;
53 }
54
55 #ifdef __x86_64__
56 static inline noit_atomic64_t
57 noit_atomic_cas64(volatile noit_atomic64_t *ptr,
58                   volatile noit_atomic64_t rpl,
59                   volatile noit_atomic64_t curr) {
60   noit_atomic64_t prev;
61   __asm__ volatile (
62       "lock; cmpxchgq %1, %2"
63     : "=a" (prev)
64     : "r"  (rpl), "m" (*(ptr)), "0" (curr)
65     : "memory");
66   return prev;
67 }
68 #else
69 static inline noit_atomic64_t
70 noit_atomic_cas64(volatile noit_atomic64_t *ptr,
71                   volatile noit_atomic64_t rpl,
72                   volatile noit_atomic64_t curr) {
73   noit_atomic64_t prev;
74   __asm__ volatile (
75       "pushl %%ebx;"
76       "mov 4+%1,%%ecx;"
77       "mov %1,%%ebx;"
78       "lock;"
79       "cmpxchg8b (%3);"
80       "popl %%ebx"
81     : "=A" (prev)
82     : "m" (rpl), "A" (curr), "r" (ptr)
83     : "%ebx", "%ecx", "memory");
84   return prev;
85 };
86 #endif
87
88 static inline void noit_spinlock_lock(volatile noit_spinlock_t *lock) {
89   while(noit_atomic_cas32(lock, 1, 0) != 0);
90 }
91 static inline void noit_spinlock_unlock(volatile noit_spinlock_t *lock) {
92   while(noit_atomic_cas32(lock, 0, 1) != 1);
93 }
94 static inline noit_spinlock_trylock(volatile noit_spinlock_t *lock) {
95   return (noit_atomic_cas32(lock, 1, 0) == 0);
96 }
97
98 #else
99 #error Please stub out the atomics section for your platform
100 #endif
101
102 #endif
Note: See TracBrowser for help on using the browser.