summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuo Jinghua <sunmoon1997@gmail.com>2009-10-29 00:09:34 +0800
committerLuo Jinghua <sunmoon1997@gmail.com>2009-10-29 00:09:34 +0800
commite322403dda7ab50ff4713cdcbb2988278245ffe8 (patch)
tree2356da4de3d912a8666786865c0855b6f782f424
parentb10d18dbdee8f8762a79e8e7b6706d7326217798 (diff)
milkway: add a atomic implemantation
-rw-r--r--milkway/Makefile.am35
-rw-r--r--milkway/milkway.h1
-rw-r--r--milkway/mw-atomic-pthread.c132
-rw-r--r--milkway/mw-atomic-win32.c117
-rw-r--r--milkway/mw-atomic-x86-gcc.c109
-rw-r--r--milkway/mw-atomic.c52
-rw-r--r--milkway/mw-atomic.h141
-rw-r--r--milkway/mw-types.h2
8 files changed, 579 insertions, 10 deletions
diff --git a/milkway/Makefile.am b/milkway/Makefile.am
index 11265ba..3bbf21d 100644
--- a/milkway/Makefile.am
+++ b/milkway/Makefile.am
@@ -1,9 +1,26 @@
SUBDIRS = test
+EXTRA_DIST =
lib_LTLIBRARIES = libmilkway.la
+
+milkway_headers = \
+ milkway.h \
+ mw-assert.h \
+ mw-atomic.h \
+ mw-byteorder.h \
+ mw-config.h \
+ mw-checksum.h \
+ mw-error.h \
+ mw-types.h \
+ mw-compiler.h \
+ mw-crypt.h \
+ mw-hexlify.h
+
libmilkway_la_LDFLAGS = -version-info $(LT_VERSION_INFO) -no-undefined
libmilkway_la_LIBADD = @DEP_LIBS@
-libmilkway_la_CFLAGS = -I$(top_srcdir)/lib/milkway $(MILKWAY_CFLAGS)
+libmilkway_la_CFLAGS = -I$(top_srcdir)/milkway -I$(top_srcdir) $(MILKWAY_CFLAGS)
libmilkway_la_SOURCES = \
+ $(milkway_headers) \
+ milkwayint.h \
blowfish.c \
blowfish.h \
base32.c \
@@ -13,17 +30,15 @@ libmilkway_la_SOURCES = \
sha1.c \
sha1.h \
mw-assert.c \
+ mw-atomic.c \
mw-crypt.c \
mw-checksum.c \
mw-hexlify.c
-libmilkwayincludedir = $(includedir)/milkway/milkway
-libmilkwayinclude_HEADER = \
- milkway.h \
- mw-assert.h \
- mw-byteorder.h \
- mw-config.h \
- mw-types.h \
- mw-compiler.h \
- mw-crypt.h
+milkwayincludedir = $(includedir)/milkway/milkway
+milkwayinclude_HEADERS = $(milkway_headers)
+EXTRA_DIST += \
+ mw-atomic-x86-gcc.c \
+ mw-atomic-pthread.c \
+ mw-atomic-win32.c \ No newline at end of file
diff --git a/milkway/milkway.h b/milkway/milkway.h
index e384937..ef58d7d 100644
--- a/milkway/milkway.h
+++ b/milkway/milkway.h
@@ -25,6 +25,7 @@
#include <milkway/mw-error.h>
#include <milkway/mw-assert.h>
#include <milkway/mw-byteorder.h>
+#include <milkway/mw-atomic.h>
#include <milkway/mw-crypt.h>
#include <milkway/mw-checksum.h>
#include <milkway/mw-hexlify.h>
diff --git a/milkway/mw-atomic-pthread.c b/milkway/mw-atomic-pthread.c
new file mode 100644
index 0000000..57cc5d4
--- /dev/null
+++ b/milkway/mw-atomic-pthread.c
@@ -0,0 +1,132 @@
+/* Milkway
+ *
+ * Copyright (C) 2008- Luo Jinghua <sunmoon1997@gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+#ifdef MW_ATOMIC_IMPLEMENTATION_GENERIC_PTHREAD
+
+static pthread_mutex_t atomic_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+#define LOCK() pthread_mutex_lock (&atomic_mutex)
+#define UNLOCK() pthread_mutex_unlock (&atomic_mutex)
+
+int
+mw_atomic_get (const volatile int * atomic)
+{
+ int val;
+
+ LOCK ();
+ val = *atomic;
+ UNLOCK ();
+
+ return val;
+}
+
+void
+mw_atomic_set (volatile int * atomic, int val)
+{
+ LOCK ();
+
+ *atomic = val;
+
+ UNLOCK ();
+}
+
+int
+mw_atomic_add (volatile int * atomic, int count)
+{
+ LOCK ();
+ *atomic = *atomic + count;
+ UNLOCK ();
+
+ return mw_atomic_get (atomic);
+}
+
+int
+mw_atomic_sub (volatile int * atomic, int count)
+{
+ LOCK ();
+ *atomic = *atomic - count;
+ UNLOCK ();
+
+ return mw_atomic_get (atomic);
+}
+
+mw_bool_t
+mw_atomic_sub_and_test (volatile int * atomic, int count)
+{
+ unsigned char c;
+
+ LOCK ();
+ *atomic = *atomic - count;
+ c = (*atomic == 0);
+ UNLOCK ();
+
+ return c;
+}
+
+mw_bool_t
+mw_atomic_cmpxchg (volatile int * atomic,
+ int oldval, int newval)
+{
+ int result;
+
+ LOCK ();
+ result = *atomic;
+ if (result == oldval)
+ *atomic = newval;
+ UNLOCK ();
+
+ return result == oldval;
+}
+
+void
+mw_atomic_pointer_set (volatile mw_pointer_t * atomic, mw_pointer_t ptr)
+{
+ LOCK ();
+ *atomic = ptr;
+ UNLOCK ();
+}
+
+mw_pointer_t
+mw_atomic_pointer_get (volatile mw_pointer_t * atomic)
+{
+ mw_pointer_t ptr;
+
+ LOCK ();
+ ptr = *atomic;
+ UNLOCK ();
+
+ return ptr;
+}
+
+mw_bool_t
+mw_atomic_pointer_cmpxchg (volatile mw_pointer_t * atomic, mw_pointer_t oldval,
+ mw_pointer_t newval)
+{
+ mw_pointer_t result;
+
+ LOCK ();
+ result = *atomic;
+ if (result == oldval)
+ *atomic = newval;
+ UNLOCK ();
+
+ return result == oldval;
+}
+
+#endif
diff --git a/milkway/mw-atomic-win32.c b/milkway/mw-atomic-win32.c
new file mode 100644
index 0000000..3e70e16
--- /dev/null
+++ b/milkway/mw-atomic-win32.c
@@ -0,0 +1,117 @@
+/* Milkway
+ *
+ * Copyright (C) 2008- Luo Jinghua <sunmoon1997@gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+#ifdef MW_ATOMIC_IMPLEMENTATION_WIN32
+
+#include <windows.h>
+
+#if !(defined(_M_IX86) || defined(_M_AMD64) || defined(_M_IA64) || \
+ defined(__i386__) || defined(__x86_64__) || defined(__ia64__))
+#define NEED_BARRIER
+#endif
+
+#if defined(MW_COMPILER_MSVC) && defined(NEED_BARRIER) && defined(MW_HAVE_MEMORYBARRIER)
+#define BARRIER() MemoryBarrier()
+#else
+#define BARRIER() do {} while (0)
+#endif
+
+int
+mw_atomic_get (const volatile int * atomic)
+{
+ int val;
+
+ BARRIER ();
+ val = *atomic;
+ return val;
+}
+
+void
+mw_atomic_set (volatile int * atomic, int val)
+{
+ *atomic = val;
+ BARRIER ();
+}
+
+int
+mw_atomic_add (volatile int * atomic, int count)
+{
+ int result;
+
+ do {
+ result = *atomic;
+ } while (!mw_atomic_cmpxchg (atomic, result, result + count));
+
+ return result + count;
+}
+
+int
+mw_atomic_sub (volatile int * atomic, int count)
+{
+ int result;
+
+ do {
+ result = *atomic;
+ } while (!mw_atomic_cmpxchg (atomic, result, result - count));
+
+ return result - count;
+}
+
+mw_bool_t
+mw_atomic_sub_and_test (volatile int * atomic, int count)
+{
+ return !mw_atomic_sub (atomic, count);
+}
+
+mw_bool_t
+mw_atomic_cmpxchg (volatile int * atomic,
+ int oldval, int newval)
+{
+ int result;
+
+ result = InterlockedCompareExchange ((volatile LONG *)atomic, newval, oldval);
+ return result == oldval;
+}
+
+void
+mw_atomic_pointer_set (volatile mw_pointer_t * atomic, mw_pointer_t ptr)
+{
+ *atomic = ptr;
+}
+
+mw_pointer_t
+mw_atomic_pointer_get (volatile mw_pointer_t * atomic)
+{
+ mw_pointer_t ptr;
+
+ ptr = *atomic;
+ return ptr;
+}
+
+mw_bool_t
+mw_atomic_pointer_cmpxchg (volatile mw_pointer_t * atomic, mw_pointer_t oldval,
+ mw_pointer_t newval)
+{
+ mw_pointer_t result;
+
+ result = InterlockedCompareExchangePointer (atomic, newval, oldval);
+ return result == oldval;
+}
+
+#endif
diff --git a/milkway/mw-atomic-x86-gcc.c b/milkway/mw-atomic-x86-gcc.c
new file mode 100644
index 0000000..36991e7
--- /dev/null
+++ b/milkway/mw-atomic-x86-gcc.c
@@ -0,0 +1,109 @@
+/* Milkway
+ *
+ * Copyright (C) 2008- Luo Jinghua <sunmoon1997@gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+#ifdef MW_ATOMIC_IMPLEMENTATION_X86_GCC
+
+int
+mw_atomic_get (const volatile int * atomic)
+{
+ return *atomic;
+}
+
+void
+mw_atomic_set (volatile int * atomic, int val)
+{
+ *atomic = val;
+}
+
+int
+mw_atomic_add (volatile int * atomic, int count)
+{
+ __asm__ __volatile__ ("lock; addl %1, %0"
+ :"=m" (*atomic)
+ :"ir" (count), "m" (*atomic));
+
+ return mw_atomic_get (atomic);
+}
+
+int
+mw_atomic_sub (volatile int * atomic, int count)
+{
+ __asm__ __volatile__ ("lock; subl %1, %0"
+ :"=m" (*atomic)
+ :"ir" (count), "m" (*atomic));
+
+ return mw_atomic_get (atomic);
+}
+
+mw_bool_t
+mw_atomic_sub_and_test (volatile int * atomic, int count)
+{
+ unsigned char c;
+
+ __asm__ __volatile__ ("lock; subl %2, %0; sete %1"
+ : "=m" (*atomic), "=qm" (c)
+ : "ir" (count), "m" (*atomic) : "memory");
+ return c;
+}
+
+mw_bool_t
+mw_atomic_cmpxchg (volatile int * atomic,
+ int oldval, int newval)
+{
+ int result;
+
+ __asm__ __volatile__ ("lock; cmpxchgl %2, %1"
+ : "=a" (result), "=m" (*atomic)
+ : "r" (newval), "m" (*atomic), "0" (oldval));
+
+ return result == oldval;
+}
+
+void
+mw_atomic_pointer_set (volatile mw_pointer_t * atomic, mw_pointer_t ptr)
+{
+ *atomic = ptr;
+}
+
+mw_pointer_t
+mw_atomic_pointer_get (volatile mw_pointer_t * atomic)
+{
+ return (mw_pointer_t)*atomic;
+}
+
+mw_bool_t
+mw_atomic_pointer_cmpxchg (volatile mw_pointer_t * atomic, mw_pointer_t oldval,
+ mw_pointer_t newval)
+{
+ mw_pointer_t result;
+
+#if defined(__x86_64__) || defined(__amd64__)
+ __asm__ __volatile__ ("lock; cmpxchgq %2, %1"
+ : "=a" (result), "=m" (*atomic)
+ : "r" (newval), "m" (*atomic), "0" (oldval));
+#else
+ __asm__ __volatile__ ("lock; cmpxchgl %2, %1"
+ : "=a" (result), "=m" (*atomic)
+ : "r" (newval), "m" (*atomic), "0" (oldval));
+#endif
+
+ return result == oldval;
+}
+
+#endif
diff --git a/milkway/mw-atomic.c b/milkway/mw-atomic.c
new file mode 100644
index 0000000..847eb54
--- /dev/null
+++ b/milkway/mw-atomic.c
@@ -0,0 +1,52 @@
+/* flib - fundamental c library.
+ *
+ * Copyright (C) 2008- Luo Jinghua <sunmoon1997@gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "milkwayint.h"
+
+#undef MW_ATOMIC_IMPLEMENTED
+
+#if defined(__GNUC__)
+
+#if defined(__i386__) || defined(__x86_64__) || defined(__amd64__)
+#define MW_ATOMIC_IMPLEMENTATION_X86_GCC
+#define MW_ATOMIC_IMPLEMENTED
+#include "mw-atomic-x86-gcc.c"
+#endif
+
+#endif
+
+#ifndef MW_ATOMIC_IMPLEMENTED
+#ifdef MW_PLATFORM_WIN32
+#define MW_ATOMIC_IMPLEMENTATION_WIN32
+#define MW_ATOMIC_IMPLEMENTED
+#include "mw-atomic-win32.c"
+#endif
+#endif
+
+#ifndef MW_ATOMIC_IMPLEMENTED
+#ifdef MW_HAVE_PTHREAD_H
+#define MW_ATOMIC_IMPLEMENTATION_POSIX
+#define MW_ATOMIC_IMPLEMENTED
+#include "mw-atomic-generic-pthread.c"
+#endif
+#endif
diff --git a/milkway/mw-atomic.h b/milkway/mw-atomic.h
new file mode 100644
index 0000000..dac3f78
--- /dev/null
+++ b/milkway/mw-atomic.h
@@ -0,0 +1,141 @@
+/* flib - fundamental c library.
+ *
+ * Copyright (C) 2008- Luo Jinghua <sunmoon1997@gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+#ifndef F_ATOMIC_H
+#define F_ATOMIC_H
+
+#include <milkway/mw-types.h>
+
+/**
+ * @file mw-atomic.h
+ * @brief Basic atomic integer and pointer operations
+ * @defgroup atomic Basic atomic integer and pointer operations
+ * @ingroup fcore
+ * @{
+ */
+
+MW_BEGIN_DECLS
+
+/**
+ * @brief Reads the value of a integer by atomic.
+ *
+ * Reads the value of the integer pointed to by atomic. Issues
+ * memory barrier as needed.
+ *
+ * @param atomic a pointer to a integer.
+ */
+mw_public int
+mw_atomic_get (const volatile int * atomic);
+
+/**
+ * @brief Sets the value of a integer by atomic.
+ *
+ * Sets the value of the integer pointed to by atomic. Issues
+ * memory barrier as needed.
+ *
+ * @param atomic a pointer to a integer.
+ * @param val the value to set.
+ */
+mw_public void
+mw_atomic_set (volatile int * atomic, int val);
+
+/**
+ * @brief Adds a value to a integer by atomic.
+ *
+ * @param atomic a pointer to a integer.
+ * @param count the value
+ */
+mw_public int
+mw_atomic_add (volatile int * atomic, int count);
+
+/**
+ * @brief Subs a value to a integer by atomic.
+ *
+ * @param atomic a pointer to a integer.
+ * @param count the value
+ */
+mw_public int
+mw_atomic_sub (volatile int * atomic, int count);
+
+/**
+ * @brief Subs a value to a integer by atomic and returns MW_TRUE if
+ * result is zero.
+ *
+ * @param atomic a pointer to a integer.
+ * @param count the value
+ * @return MW_TRUE if result is zero
+ */
+mw_public mw_bool_t
+mw_atomic_sub_and_test (volatile int * atomic, int count);
+
+/**
+ * @brief Compares oldval with the integer pointed to by atomic and if
+ * they are equal, atomically exchanges atomic with newval. Issues
+ * memory barrier as needed.
+ *
+ * @param atomic a pointer to a integer.
+ * @param oldval the old value
+ * @param newval the new value
+ * @return MW_TRUE if oldval is equal to *atomic
+ */
+mw_public mw_bool_t
+mw_atomic_cmpxchg (volatile int * atomic,
+ int oldval, int newval);
+
+/**
+ * @brief Sets the value of a pointer by atomic.
+ *
+ * @param atomic a pointer to a pointer
+ * @param ptr the value to set
+ */
+mw_public void
+mw_atomic_pointer_set (volatile mw_pointer_t * atomic,
+ mw_pointer_t ptr);
+
+/**
+ * @brief Reads the value of a pointer by atomic.
+ *
+ * @param atomic a pointer to a pointer
+ * @return returns the value of *atomic
+ */
+mw_public mw_pointer_t
+mw_atomic_pointer_get (volatile mw_pointer_t * atomic);
+
+/**
+ * @brief Compares oldval with the pointer pointed to by atomic and if
+ * they are equal, atomically exchanges atomic with newval. Issues
+ * memory barrier as needed.
+ *
+ * @param atomic a pointer to a pointer.
+ * @param oldval the old value
+ * @param newval the new value
+ * @return MW_TRUE if oldval is equal to *atomic
+ */
+mw_public mw_bool_t
+mw_atomic_pointer_cmpxchg (volatile mw_pointer_t * atomic,
+ mw_pointer_t oldval,
+ mw_pointer_t newval);
+
+MW_END_DECLS
+
+/**
+ * @}
+ */
+
+#endif
diff --git a/milkway/mw-types.h b/milkway/mw-types.h
index dd85f20..3da517c 100644
--- a/milkway/mw-types.h
+++ b/milkway/mw-types.h
@@ -53,4 +53,6 @@ typedef int mw_bool_t;
#define MW_TRUE (1)
#define MW_FALSE (0)
+typedef void* mw_pointer_t;
+
#endif