ianh 02/02/16 08:34:32
Modified: atomic/unix apr_atomic.c
include apr_atomic.h
test testatomic.c
Log:
remove CAS option as linux doesn't support it out of the box
(needs to be there, but getting native versions working on the add/dec is
more
important)
get a 'linux-only' version running
newtype apr_atomic_t
test program can switch between mutex/atomic (so you can see the
speed difference easily)
Revision Changes Path
1.3 +13 -6 apr/atomic/unix/apr_atomic.c
Index: apr_atomic.c
===================================================================
RCS file: /home/cvs/apr/atomic/unix/apr_atomic.c,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- apr_atomic.c 13 Feb 2002 01:22:18 -0000 1.2
+++ apr_atomic.c 16 Feb 2002 16:34:32 -0000 1.3
@@ -5,6 +5,8 @@
#ifdef WIN32
/* win32 implementation is all macros */
+#elif defined(__linux)
+/* linux implementation is all macros */
#else
#if APR_HAS_THREADS
@@ -26,7 +28,7 @@
}
return APR_SUCCESS;
}
-long apr_atomic_add(volatile long*mem, long val)
+apr_uint32_t apr_atomic_add(volatile apr_atomic_t *mem, long val)
{
apr_thread_mutex_t *lock = hash_mutex[ATOMIC_HASH(mem)];
long prev;
@@ -39,7 +41,7 @@
}
return *mem;
}
-long apr_atomic_set(volatile long*mem, long val)
+apr_uint32_t apr_atomic_set(volatile apr_atomic_t *mem, long val)
{
apr_thread_mutex_t *lock = hash_mutex[ATOMIC_HASH(mem)];
long prev;
@@ -53,7 +55,7 @@
return *mem;
}
-long apr_atomic_inc( volatile long *mem)
+apr_uint32_t apr_atomic_inc( volatile apr_uint32_t *mem)
{
apr_thread_mutex_t *lock = hash_mutex[ATOMIC_HASH(mem)];
long prev;
@@ -66,7 +68,7 @@
}
return *mem;
}
-long apr_atomic_dec(volatile long *mem)
+apr_uint32_t apr_atomic_dec(volatile apr_atomic_t *mem)
{
apr_thread_mutex_t *lock = hash_mutex[ATOMIC_HASH(mem)];
long prev;
@@ -79,7 +81,12 @@
}
return *mem;
}
-long apr_atomic_cas(volatile long *mem,long with,long cmp)
+#if 0
+/*
+ * linux doesn't have a easy to do this
+ * so comment it out for the moment
+ */
+apr_uint32_t apr_atomic_cas(volatile apr_atomic_t *mem,apr_uint32_t with,
apr_uint32_t cmp)
{
apr_thread_mutex_t *lock = hash_mutex[ATOMIC_HASH(mem)];
long prev;
@@ -94,7 +101,7 @@
}
return *mem;
}
-
+#endif
#endif /* APR_HAS_THREADS */
#endif /* default implementation */
1.3 +20 -6 apr/include/apr_atomic.h
Index: apr_atomic.h
===================================================================
RCS file: /home/cvs/apr/include/apr_atomic.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -r1.2 -r1.3
--- apr_atomic.h 13 Feb 2002 01:22:18 -0000 1.2
+++ apr_atomic.h 16 Feb 2002 16:34:32 -0000 1.3
@@ -63,26 +63,40 @@
extern "C" {
#endif
#ifdef WIN32
+#define apr_atomic_t LONG;
#define apr_atomic_add(mem, val) InterlockedExchangeAdd(mem,val)
#define apr_atomic_dec(mem) InterlockedDecrement(mem)
#define apr_atomic_inc(mem) InterlockedIncrement(mem)
#define apr_atomic_set(mem, val) InterlockedExchange(mem, val)
#define apr_atomic_read(mem) *mem
-#define apr_atomic_cas(mem,with,cmp) InterlockedCompareExchange(mem,with,cmp)
+/* #define apr_atomic_cas(mem,with,cmp)
InterlockedCompareExchange(mem,with,cmp)*/
#define apr_atomic_init(pool) APR_SUCCESS
+#elif defined(__linux)
+#include <asm/atomic.h>
+#define apr_atomic_t atomic_t
+
+#define apr_atomic_add(mem, val) atomic_add(val,mem)
+#define apr_atomic_dec(mem) atomic_dec(mem)
+#define apr_atomic_inc(mem) atomic_inc(mem)
+#define apr_atomic_set(mem, val) atomic_set(mem, val)
+#define apr_atomic_read(mem) atomic_read(mem)
+#define apr_atomic_init(pool) APR_SUCCESS
+
+
#else
#if APR_HAS_THREADS
+#define apr_atomic_t apr_uint32_t
#define apr_atomic_read(p) *p
apr_status_t apr_atomic_init(apr_pool_t *p);
-long apr_atomic_set(volatile long*mem, long val);
-long apr_atomic_add(volatile long*mem, long val);
-long apr_atomic_inc( volatile long *mem);
-long apr_atomic_dec(volatile long *mem);
-long apr_atomic_cas(volatile long *mem,long with,long cmp);
+apr_uint32_t apr_atomic_set(volatile apr_atomic_t *mem, long val);
+apr_uint32_t apr_atomic_add(volatile apr_atomic_t *mem, long val);
+apr_uint32_t apr_atomic_inc(volatile apr_atomic_t *mem);
+apr_uint32_t apr_atomic_dec(volatile apr_atomic_t *mem);
+/*long apr_atomic_cas(volatile apr_atomic_t *mem,long with,long cmp);*/
#endif /* APR_HAS_THREADS */
1.2 +47 -34 apr/test/testatomic.c
Index: testatomic.c
===================================================================
RCS file: /home/cvs/apr/test/testatomic.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- testatomic.c 12 Feb 2002 21:49:32 -0000 1.1
+++ testatomic.c 16 Feb 2002 16:34:32 -0000 1.2
@@ -78,27 +78,27 @@
}
#else /* !APR_HAS_THREADS */
-void * APR_THREAD_FUNC thread_func_traditional(apr_thread_t *thd, void
*data);
+void * APR_THREAD_FUNC thread_func_mutex(apr_thread_t *thd, void *data);
void * APR_THREAD_FUNC thread_func_atomic(apr_thread_t *thd, void *data);
void * APR_THREAD_FUNC thread_func_none(apr_thread_t *thd, void *data);
apr_lock_t *thread_lock;
apr_pool_t *context;
apr_thread_once_t *control = NULL;
-volatile long x = 0; /* traditional locks */
-volatile long y = 0; /* atomic locks */
+volatile long x = 0; /* mutex locks */
+apr_atomic_t y; /* atomic locks */
volatile long z = 0; /* no locks */
int value = 0;
apr_status_t exit_ret_val = 123; /* just some made up number to check on
later */
-#define NUM_THREADS 10
+#define NUM_THREADS 50
#define NUM_ITERATIONS 20000
static void init_func(void)
{
value++;
}
-void * APR_THREAD_FUNC thread_func_traditional(apr_thread_t *thd, void *data)
+void * APR_THREAD_FUNC thread_func_mutex(apr_thread_t *thd, void *data)
{
int i;
@@ -112,6 +112,7 @@
apr_thread_exit(thd, exit_ret_val);
return NULL;
}
+
void * APR_THREAD_FUNC thread_func_atomic(apr_thread_t *thd, void *data)
{
int i;
@@ -136,22 +137,23 @@
apr_thread_exit(thd, exit_ret_val);
return NULL;
}
-int main(void)
+int main(int argc, char**argv)
{
apr_thread_t *t1[NUM_THREADS];
apr_thread_t *t2[NUM_THREADS];
- apr_thread_t *t3[NUM_THREADS];
apr_status_t r1[NUM_THREADS];
apr_status_t r2[NUM_THREADS];
- apr_status_t r3[NUM_THREADS];
apr_status_t s1[NUM_THREADS];
apr_status_t s2[NUM_THREADS];
- apr_status_t s3[NUM_THREADS];
apr_status_t rv;
int i;
+ int mutex=0;
apr_initialize();
+ if (argc==2 && argv[1][0]=='m')
+ mutex=1;
+
printf("APR Simple Thread Test\n======================\n\n");
#ifndef WIN32
@@ -176,16 +178,18 @@
exit(-1);
}
rv = apr_atomic_init( context);
+ apr_atomic_set(&y,0);
printf("OK\n");
printf("%-60s", "Starting all the threads");
for (i=0;i<NUM_THREADS;i++) {
- r1[i] = apr_thread_create(&t1[i], NULL, thread_func_traditional,
NULL, context);
- r2[i] = apr_thread_create(&t2[i], NULL, thread_func_atomic,
NULL, context);
- r3[i] = apr_thread_create(&t3[i], NULL, thread_func_none,
NULL, context);
- if (r1[i] != APR_SUCCESS || r2[i] != APR_SUCCESS ||
- r3[i] != APR_SUCCESS ) {
+ if (mutex ==1)
+ r1[i] = apr_thread_create(&t1[i], NULL, thread_func_mutex, NULL,
context);
+ else
+ r1[i] = apr_thread_create(&t1[i], NULL, thread_func_atomic,
NULL, context);
+ r2[i] = apr_thread_create(&t2[i], NULL, thread_func_none, NULL,
context);
+ if (r1[i] != APR_SUCCESS || r2[i] != APR_SUCCESS ) {
fflush(stdout);
fprintf(stderr, "Failed\nError starting thread in group %d\n",i);
exit(-1);
@@ -198,36 +202,45 @@
for (i=0;i<NUM_THREADS;i++) {
apr_thread_join(&s1[i], t1[i]);
apr_thread_join(&s2[i], t2[i]);
- apr_thread_join(&s3[i], t3[i]);
- if (s1[i] != exit_ret_val || s2[i] != exit_ret_val ||
- s3[i] != exit_ret_val ) {
+ if (s1[i] != exit_ret_val || s2[i] != exit_ret_val ) {
fprintf(stderr,
- "Invalid return value\nGot %d/%d/%d, but expected %d
for all \n",
- s1[i], s2[i], s3[i], exit_ret_val);
-
+ "Invalid return value\nGot %d/%d, but expected %d
for all \n",
+ s1[i], s2[i], exit_ret_val);
}
-
}
printf("OK\n");
- printf("%-60s", "Checking if locks worked");
- if (x != NUM_THREADS*NUM_ITERATIONS) {
- fflush(stdout);
- fprintf(stderr, "No!\nThe locks didn't work???? x = %ld instead of
%ld\n", x,NUM_THREADS*NUM_ITERATIONS);
+ if (mutex ==1) {
+ printf("%-60s", "Checking if mutex locks worked");
+ if (x != NUM_THREADS*NUM_ITERATIONS) {
+ fflush(stdout);
+ fprintf(stderr,
+ "No!\nThe locks didn't work?? x = %ld instead of %ld\n",
+ x,
+ (long)NUM_THREADS*NUM_ITERATIONS);
+ }
+ else
+ printf("OK\n");
}
- else
- printf("OK\n");
- printf("%-60s", "Checking if atomic worked");
- if (apr_atomic_read(&y) != NUM_THREADS*NUM_ITERATIONS) {
- fflush(stdout);
- fprintf(stderr, "No!\nThe atomics didn't work???? y = %ld instead
of %ld\n", y,NUM_THREADS*NUM_ITERATIONS);
+ else {
+ printf("%-60s", "Checking if atomic worked");
+ if (apr_atomic_read(&y) != NUM_THREADS*NUM_ITERATIONS) {
+ fflush(stdout);
+ fprintf(stderr,
+ "No!\nThe atomics didn't work?? y = %ld instead of
%ld\n",
+ apr_atomic_read(&y),
+ (long)NUM_THREADS*NUM_ITERATIONS);
+ }
+ else
+ printf("OK\n");
}
- else
- printf("OK\n");
printf("%-60s", "Checking if nolock worked");
if ( z != NUM_THREADS*NUM_ITERATIONS) {
fflush(stdout);
- fprintf(stderr, "no suprise\nThe no-locks didn't work???? z = %ld
instead of %ld\n", z, NUM_THREADS*NUM_ITERATIONS);
+ fprintf(stderr,
+ "no suprise\nThe no-locks didn't work. z = %ld instead of
%ld\n",
+ z,
+ (long)NUM_THREADS*NUM_ITERATIONS);
}
else
printf("OK\n");