2 * Copyright (C) the libgit2 contributors. All rights reserved.
4 * This file is part of libgit2, distributed under the GNU GPL v2 with
5 * a Linking Exception. For full terms see the included COPYING file.
7 #ifndef INCLUDE_thread_utils_h__
8 #define INCLUDE_thread_utils_h__
10 #if defined(__GNUC__) && defined(GIT_THREADS)
11 # if (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 1))
12 # error Atomic primitives do not exist on this version of gcc; configure libgit2 with -DTHREADSAFE=OFF
16 /* Common operations even if threading has been disabled */
18 #if defined(GIT_WIN32)
28 #if defined(GIT_WIN32)
35 typedef git_atomic64 git_atomic_ssize
;
37 #define git_atomic_ssize_add git_atomic64_add
41 typedef git_atomic git_atomic_ssize
;
43 #define git_atomic_ssize_add git_atomic_add
50 # include "win32/thread.h"
52 # include "unix/pthread.h"
55 GIT_INLINE(void) git_atomic_set(git_atomic
*a
, int val
)
57 #if defined(GIT_WIN32)
58 InterlockedExchange(&a
->val
, (LONG
)val
);
59 #elif defined(__GNUC__)
60 __sync_lock_test_and_set(&a
->val
, val
);
62 # error "Unsupported architecture for atomic operations"
66 GIT_INLINE(int) git_atomic_inc(git_atomic
*a
)
68 #if defined(GIT_WIN32)
69 return InterlockedIncrement(&a
->val
);
70 #elif defined(__GNUC__)
71 return __sync_add_and_fetch(&a
->val
, 1);
73 # error "Unsupported architecture for atomic operations"
77 GIT_INLINE(int) git_atomic_add(git_atomic
*a
, int32_t addend
)
79 #if defined(GIT_WIN32)
80 return InterlockedExchangeAdd(&a
->val
, addend
);
81 #elif defined(__GNUC__)
82 return __sync_add_and_fetch(&a
->val
, addend
);
84 # error "Unsupported architecture for atomic operations"
88 GIT_INLINE(int) git_atomic_dec(git_atomic
*a
)
90 #if defined(GIT_WIN32)
91 return InterlockedDecrement(&a
->val
);
92 #elif defined(__GNUC__)
93 return __sync_sub_and_fetch(&a
->val
, 1);
95 # error "Unsupported architecture for atomic operations"
99 GIT_INLINE(void *) git___compare_and_swap(
100 void * volatile *ptr
, void *oldval
, void *newval
)
102 volatile void *foundval
;
103 #if defined(GIT_WIN32)
104 foundval
= InterlockedCompareExchangePointer((volatile PVOID
*)ptr
, newval
, oldval
);
105 #elif defined(__GNUC__)
106 foundval
= __sync_val_compare_and_swap(ptr
, oldval
, newval
);
108 # error "Unsupported architecture for atomic operations"
110 return (foundval
== oldval
) ? oldval
: newval
;
113 GIT_INLINE(volatile void *) git___swap(
114 void * volatile *ptr
, void *newval
)
116 #if defined(GIT_WIN32)
117 return InterlockedExchangePointer(ptr
, newval
);
119 return __sync_lock_test_and_set(ptr
, newval
);
125 GIT_INLINE(int64_t) git_atomic64_add(git_atomic64
*a
, int64_t addend
)
127 #if defined(GIT_WIN32)
128 return InterlockedExchangeAdd64(&a
->val
, addend
);
129 #elif defined(__GNUC__)
130 return __sync_add_and_fetch(&a
->val
, addend
);
132 # error "Unsupported architecture for atomic operations"
140 #define git_thread unsigned int
141 #define git_thread_create(thread, start_routine, arg) 0
142 #define git_thread_join(id, status) (void)0
145 #define git_mutex unsigned int
146 GIT_INLINE(int) git_mutex_init(git_mutex
*mutex
) \
147 { GIT_UNUSED(mutex
); return 0; }
148 GIT_INLINE(int) git_mutex_lock(git_mutex
*mutex
) \
149 { GIT_UNUSED(mutex
); return 0; }
150 #define git_mutex_unlock(a) (void)0
151 #define git_mutex_free(a) (void)0
153 /* Pthreads condition vars */
154 #define git_cond unsigned int
155 #define git_cond_init(c, a) (void)0
156 #define git_cond_free(c) (void)0
157 #define git_cond_wait(c, l) (void)0
158 #define git_cond_signal(c) (void)0
159 #define git_cond_broadcast(c) (void)0
161 /* Pthreads rwlock */
162 #define git_rwlock unsigned int
163 #define git_rwlock_init(a) 0
164 #define git_rwlock_rdlock(a) 0
165 #define git_rwlock_rdunlock(a) (void)0
166 #define git_rwlock_wrlock(a) 0
167 #define git_rwlock_wrunlock(a) (void)0
168 #define git_rwlock_free(a) (void)0
169 #define GIT_RWLOCK_STATIC_INIT 0
172 GIT_INLINE(void) git_atomic_set(git_atomic
*a
, int val
)
177 GIT_INLINE(int) git_atomic_inc(git_atomic
*a
)
182 GIT_INLINE(int) git_atomic_add(git_atomic
*a
, int32_t addend
)
188 GIT_INLINE(int) git_atomic_dec(git_atomic
*a
)
193 GIT_INLINE(void *) git___compare_and_swap(
194 void * volatile *ptr
, void *oldval
, void *newval
)
203 GIT_INLINE(volatile void *) git___swap(
204 void * volatile *ptr
, void *newval
)
206 volatile void *old
= *ptr
;
213 GIT_INLINE(int64_t) git_atomic64_add(git_atomic64
*a
, int64_t addend
)
223 GIT_INLINE(int) git_atomic_get(git_atomic
*a
)
228 /* Atomically replace oldval with newval
229 * @return oldval if it was replaced or newval if it was not
231 #define git__compare_and_swap(P,O,N) \
232 git___compare_and_swap((void * volatile *)P, O, N)
234 #define git__swap(ptr, val) (void *)git___swap((void * volatile *)&ptr, val)
236 extern int git_online_cpus(void);
238 #if defined(GIT_THREADS) && defined(_MSC_VER)
239 # define GIT_MEMORY_BARRIER MemoryBarrier()
240 #elif defined(GIT_THREADS)
241 # define GIT_MEMORY_BARRIER __sync_synchronize()
243 # define GIT_MEMORY_BARRIER /* noop */