summaryrefslogtreecommitdiff
path: root/src/thread-utils.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/thread-utils.h')
-rw-r--r--src/thread-utils.h104
1 files changed, 104 insertions, 0 deletions
diff --git a/src/thread-utils.h b/src/thread-utils.h
index 2ca290adf..49b5f3b5e 100644
--- a/src/thread-utils.h
+++ b/src/thread-utils.h
@@ -18,6 +18,28 @@ typedef struct {
#endif
} git_atomic;
+#ifdef GIT_ARCH_64
+
+typedef struct {
+#if defined(GIT_WIN32)
+ __int64 val;
+#else
+ int64_t val;
+#endif
+} git_atomic64;
+
+typedef git_atomic64 git_atomic_ssize;
+
+#define git_atomic_ssize_add git_atomic64_add
+
+#else
+
+typedef git_atomic git_atomic_ssize;
+
+#define git_atomic_ssize_add git_atomic_add
+
+#endif
+
GIT_INLINE(void) git_atomic_set(git_atomic *a, int val)
{
a->val = val;
@@ -57,6 +79,17 @@ GIT_INLINE(int) git_atomic_inc(git_atomic *a)
#endif
}
+GIT_INLINE(int) git_atomic_add(git_atomic *a, int32_t addend)
+{
+#if defined(GIT_WIN32)
+ return InterlockedExchangeAdd(&a->val, addend);
+#elif defined(__GNUC__)
+ return __sync_add_and_fetch(&a->val, addend);
+#else
+# error "Unsupported architecture for atomic operations"
+#endif
+}
+
GIT_INLINE(int) git_atomic_dec(git_atomic *a)
{
#if defined(GIT_WIN32)
@@ -68,6 +101,35 @@ GIT_INLINE(int) git_atomic_dec(git_atomic *a)
#endif
}
+GIT_INLINE(void *) git___compare_and_swap(
+ volatile void **ptr, void *oldval, void *newval)
+{
+ volatile void *foundval;
+#if defined(GIT_WIN32)
+ foundval = InterlockedCompareExchangePointer(ptr, newval, oldval);
+#elif defined(__GNUC__)
+ foundval = __sync_val_compare_and_swap(ptr, oldval, newval);
+#else
+# error "Unsupported architecture for atomic operations"
+#endif
+ return (foundval == oldval) ? oldval : newval;
+}
+
+#ifdef GIT_ARCH_64
+
+GIT_INLINE(int64_t) git_atomic64_add(git_atomic64 *a, int64_t addend)
+{
+#if defined(GIT_WIN32)
+ return InterlockedExchangeAdd64(&a->val, addend);
+#elif defined(__GNUC__)
+ return __sync_add_and_fetch(&a->val, addend);
+#else
+# error "Unsupported architecture for atomic operations"
+#endif
+}
+
+#endif
+
#else
#define git_thread unsigned int
@@ -96,13 +158,55 @@ GIT_INLINE(int) git_atomic_inc(git_atomic *a)
return ++a->val;
}
+GIT_INLINE(int) git_atomic_add(git_atomic *a, int32_t addend)
+{
+ a->val += addend;
+ return a->val;
+}
+
GIT_INLINE(int) git_atomic_dec(git_atomic *a)
{
return --a->val;
}
+GIT_INLINE(void *) git___compare_and_swap(
+ volatile void **ptr, void *oldval, void *newval)
+{
+ if (*ptr == oldval)
+ *ptr = newval;
+ else
+ oldval = newval;
+ return oldval;
+}
+
+#ifdef GIT_ARCH_64
+
+GIT_INLINE(int64_t) git_atomic64_add(git_atomic64 *a, int64_t addend)
+{
+ a->val += addend;
+ return a->val;
+}
+
+#endif
+
#endif
+/* Atomically replace oldval with newval
+ * @return oldval if it was replaced or newval if it was not
+ */
+#define git__compare_and_swap(P,O,N) \
+ git___compare_and_swap((volatile void **)P, O, N)
+
+#define git__swap(ptr, val) git__compare_and_swap(&ptr, ptr, val)
+
extern int git_online_cpus(void);
+#if defined(GIT_THREADS) && defined(GIT_WIN32)
+# define GIT_MEMORY_BARRIER MemoryBarrier()
+#elif defined(GIT_THREADS)
+# define GIT_MEMORY_BARRIER __sync_synchronize()
+#else
+# define GIT_MEMORY_BARRIER /* noop */
+#endif
+
#endif /* INCLUDE_thread_utils_h__ */