diff options
author | Luo Jinghua <sunmoon1997@gmail.com> | 2009-10-29 00:09:34 +0800 |
---|---|---|
committer | Luo Jinghua <sunmoon1997@gmail.com> | 2009-10-29 00:09:34 +0800 |
commit | e322403dda7ab50ff4713cdcbb2988278245ffe8 (patch) | |
tree | 2356da4de3d912a8666786865c0855b6f782f424 | |
parent | b10d18dbdee8f8762a79e8e7b6706d7326217798 (diff) |
milkway: add a atomic implemantation
-rw-r--r-- | milkway/Makefile.am | 35 | ||||
-rw-r--r-- | milkway/milkway.h | 1 | ||||
-rw-r--r-- | milkway/mw-atomic-pthread.c | 132 | ||||
-rw-r--r-- | milkway/mw-atomic-win32.c | 117 | ||||
-rw-r--r-- | milkway/mw-atomic-x86-gcc.c | 109 | ||||
-rw-r--r-- | milkway/mw-atomic.c | 52 | ||||
-rw-r--r-- | milkway/mw-atomic.h | 141 | ||||
-rw-r--r-- | milkway/mw-types.h | 2 |
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 |