ianh 02/02/19 15:15:40
Modified: test testatomic.c
atomic/unix apr_atomic.c
include apr_atomic.h
Log:
re-introduce the CAS apr call.
doxygenize the header
testing is now harder
Revision Changes Path
1.4 +84 -20 apr/test/testatomic.c
Index: testatomic.c
===================================================================
RCS file: /home/cvs/apr/test/testatomic.c,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- testatomic.c 18 Feb 2002 06:23:40 -0000 1.3
+++ testatomic.c 19 Feb 2002 23:15:39 -0000 1.4
@@ -71,12 +71,72 @@
apr_pool_t *context;
apr_atomic_t y; /* atomic locks */
-#if !APR_HAS_HREADS
+
+static apr_status_t check_basic_atomics(volatile apr_atomic_t*p)
+{
+ apr_uint32_t oldval;
+ apr_atomic_set(&y,0);
+ printf("%-60s", "testing CAS");
+ oldval = apr_atomic_cas(&y,12,0);
+ if (oldval != 0) {
+ fprintf(stderr, "Failed\noldval =%d should be zero\n",oldval);
+ return APR_EGENERAL;
+ }
+ printf("OK\n");
+ printf("debug\n y=%d\n",y);
+ printf("%-60s", "testing CAS - match non-null");
+ oldval = apr_atomic_cas(&y,23,12);
+ if (oldval != 12) {
+ fprintf(stderr, "Failed\noldval =%d should be 12 y=%d\n",
+ oldval,
+ apr_atomic_read(&y));
+ return APR_EGENERAL;
+ }
+ printf("OK\n");
+ printf("%-60s", "testing CAS - no match");
+ oldval = apr_atomic_cas(&y,23,12);
+ if (oldval != 23 ) {
+ fprintf(stderr, "Failed\noldval =%d should be 23 y=%d\n",
+ oldval,
+ apr_atomic_read(&y));
+ return APR_EGENERAL;
+ }
+ printf("OK\n");
+
+ printf("%-60s", "testing add");
+ oldval = apr_atomic_add(&y,4);
+ if (oldval != 23) {
+ fprintf(stderr, "Failed\nAtomic Add should return the old value
expecting 23 got %d\n",
+ oldval);
+ exit(-1);
+ }
+ if (apr_atomic_read(&y) != 27) {
+ fprintf(stderr, "Failed\nAtomic Add doesn't add up ;( expected 27
got %d\n",
+ oldval);
+ exit(-1);
+ }
+
+ printf("OK\n");
+ printf("%-60s", "testing add/inc");
+ apr_atomic_set(&y,0);
+ apr_atomic_add(&y,20);
+ apr_atomic_inc(&y);
+ if (apr_atomic_read(&y) != 21) {
+ fprintf(stderr, "Failed.\natomics do not add up\n");
+ return APR_EGENERAL;
+ }
+ fprintf(stdout, "OK\n");
+
+ return APR_SUCCESS;
+}
+
+#if !APR_HAS_THREADS
int main(void)
{
apr_status_t rv;
+
fprintf(stderr,
- "This program won't work on this platform because there is no "
+ "This program won't work fully on this platform because there is
no "
"support for threads.\n");
if (apr_pool_create(&context, NULL) != APR_SUCCESS) {
fflush(stdout);
@@ -86,17 +146,13 @@
rv = apr_atomic_init(context);
if (rv != APR_SUCCESS) {
fprintf(stderr, "Failed.\nCould not initialize atomics\n");
+ exit(-1);
}
- apr_atomic_set(&y,0);
- apr_atomic_add(&y,20);
- apr_atomic_inc(&y);
- if (apr_atomic_read(&y) != 21) {
- fprintf(stderr, "Failed.\natomics do not add up\n");
- }
- else {
- fprintf(stdout, "no threads .. OK\n");
+ rv = check_basic_atomics(&y);
+ if (rv != APR_SUCCESS) {
+ fprintf(stderr, "Failed.\n");
+ exit(-1);
}
-
return 0;
}
#else /* !APR_HAS_THREADS */
@@ -158,6 +214,7 @@
apr_thread_exit(thd, exit_ret_val);
return NULL;
}
+
int main(int argc, char**argv)
{
apr_thread_t *t1[NUM_THREADS];
@@ -190,19 +247,26 @@
apr_thread_once_init(&control, context);
- printf("%-60s", "Initializing the lock");
- rv = apr_lock_create(&thread_lock, APR_MUTEX, APR_INTRAPROCESS,
- APR_LOCK_DEFAULT, "lock.file", context);
+ if (mutex==1) {
+ printf("%-60s", "Initializing the lock");
+ rv = apr_lock_create(&thread_lock, APR_MUTEX, APR_INTRAPROCESS,
+ APR_LOCK_DEFAULT, "lock.file", context);
+ if (rv != APR_SUCCESS) {
+ fflush(stdout);
+ fprintf(stderr, "Failed\nCould not create lock\n");
+ exit(-1);
+ }
+ printf("OK\n");
+ }
+ rv = apr_atomic_init( context);
+
+ rv = check_basic_atomics(&y);
if (rv != APR_SUCCESS) {
- fflush(stdout);
- fprintf(stderr, "Failed\nCould not create lock\n");
+ fprintf(stderr, "Failed.\n");
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++) {
if (mutex ==1)
@@ -249,7 +313,7 @@
fflush(stdout);
fprintf(stderr,
"No!\nThe atomics didn't work?? y = %ld instead of
%ld\n",
- apr_atomic_read(&y),
+ (long)apr_atomic_read(&y),
(long)NUM_THREADS*NUM_ITERATIONS);
}
else
1.6 +17 -17 apr/atomic/unix/apr_atomic.c
Index: apr_atomic.c
===================================================================
RCS file: /home/cvs/apr/atomic/unix/apr_atomic.c,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -r1.5 -r1.6
--- apr_atomic.c 17 Feb 2002 20:17:54 -0000 1.5
+++ apr_atomic.c 19 Feb 2002 23:15:39 -0000 1.6
@@ -58,10 +58,10 @@
#include "apr_thread_mutex.h"
#include "apr_atomic.h"
-#if defined(APR_ATOMIC_NEED_DEFAULT)
-
#if APR_HAS_THREADS
+#if defined(APR_ATOMIC_NEED_DEFAULT)
+
#define NUM_ATOMIC_HASH 7
/* shift by 2 to get rid of alignment issues */
#define ATOMIC_HASH(x) (int)(((long)x>>2)%NUM_ATOMIC_HASH)
@@ -79,10 +79,10 @@
}
return APR_SUCCESS;
}
-apr_uint32_t apr_atomic_add(volatile apr_atomic_t *mem, long val)
+apr_uint32_t apr_atomic_add(volatile apr_atomic_t *mem, apr_uint32_t val)
{
apr_thread_mutex_t *lock = hash_mutex[ATOMIC_HASH(mem)];
- long prev;
+ apr_uint32_t prev;
if (apr_thread_mutex_lock(lock) == APR_SUCCESS) {
prev = *mem;
@@ -90,12 +90,13 @@
apr_thread_mutex_unlock(lock);
return prev;
}
+ printf("debug no workee\n");
return *mem;
}
-apr_uint32_t apr_atomic_set(volatile apr_atomic_t *mem, long val)
+apr_uint32_t apr_atomic_set(volatile apr_atomic_t *mem, apr_uint32_t val)
{
apr_thread_mutex_t *lock = hash_mutex[ATOMIC_HASH(mem)];
- long prev;
+ apr_uint32_t prev;
if (apr_thread_mutex_lock(lock) == APR_SUCCESS) {
prev = *mem;
@@ -109,7 +110,7 @@
apr_uint32_t apr_atomic_inc( volatile apr_uint32_t *mem)
{
apr_thread_mutex_t *lock = hash_mutex[ATOMIC_HASH(mem)];
- long prev;
+ apr_uint32_t prev;
if (apr_thread_mutex_lock(lock) == APR_SUCCESS) {
prev = *mem;
@@ -122,7 +123,7 @@
apr_uint32_t apr_atomic_dec(volatile apr_atomic_t *mem)
{
apr_thread_mutex_t *lock = hash_mutex[ATOMIC_HASH(mem)];
- long prev;
+ apr_uint32_t prev;
if (apr_thread_mutex_lock(lock) == APR_SUCCESS) {
prev = *mem;
@@ -132,15 +133,13 @@
}
return *mem;
}
-#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)
+
+#if defined(APR_ATOMIC_NEED_CAS_DEFAULT)
+
+long apr_atomic_cas(volatile apr_atomic_t *mem,long with, long cmp)
{
apr_thread_mutex_t *lock = hash_mutex[ATOMIC_HASH(mem)];
- long prev;
+ apr_uint32_t prev;
if (apr_thread_mutex_lock(lock) == APR_SUCCESS) {
prev = *mem;
@@ -152,7 +151,8 @@
}
return *mem;
}
-#endif
-#endif /* APR_HAS_THREADS */
+#endif /* APR_ATOMIC_NEED_CAS_DEFAULT */
#endif /* APR_ATOMIC_NEED_DEFAULT */
+
+#endif /* APR_HAS_THREADS */
1.7 +89 -5 apr/include/apr_atomic.h
Index: apr_atomic.h
===================================================================
RCS file: /home/cvs/apr/include/apr_atomic.h,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -r1.6 -r1.7
--- apr_atomic.h 18 Feb 2002 06:24:13 -0000 1.6
+++ apr_atomic.h 19 Feb 2002 23:15:40 -0000 1.7
@@ -63,6 +63,78 @@
extern "C" {
#endif
+/**
+ * @file apr_atomic.h
+ * @brief APR Atomic Operations
+ */
+/**
+ * @defgroup APR_Atomic Atomic operations
+ * @ingroup APR
+ * @{
+ */
+
+/* easiest way to get these documented for the moment */
+#if defined(DOXYGEN)
+/**
+ * structure for holding a atomic value.
+ * this number >only< has a 24 bit size on some platforms
+ */
+typedef apr_atomic_t;
+
+/**
+ * @param pool
+ * this function is required on some platforms to initiliaze the
+ * atomic operation's internal structures
+ * returns APR_SUCCESS on successfull completion
+ */
+apr_status_t apr_atomic_init(apr_pool_t *p);
+/**
+ * read the value stored in a atomic variable
+ * @param the pointer
+ * @warning on certain platforms (linux) this number is not
+ * stored directly in the pointer. in others it is
+ */
+apr_uint32_t apr_atomic_read(volatile apr_atomic_t *mem);
+/**
+ * set the value for atomic.
+ * @param the pointer
+ * @param the value
+ * @warning the return value is undefined at the moment
+ */
+apr_uint32_t apr_atomic_set(volatile apr_atomic_t *mem, apr_uint32_t val);
+/**
+ * Add 'val' to the atomic variable
+ * @param mem pointer to the atomic value
+ * @param val the addition
+ * @return the old value of the atomic
+ */
+apr_uint32_t apr_atomic_add(volatile apr_atomic_t *mem, apr_uint32_t val);
+
+/**
+ * increment the atomic variable by 1
+ * @param mem pointer to the atomic value
+ * @return the old value of the atomic
+ */
+apr_uint32_t apr_atomic_inc(volatile apr_atomic_t *mem);
+
+/**
+ * decrement the atomic variable by 1
+ * @param mem pointer to the atomic value
+ * @return the old value of the atomic
+ */
+apr_uint32_t apr_atomic_dec(volatile apr_atomic_t *mem);
+
+/**
+ * compare the atomic's value with cmp.
+ * If they are the same swap the value with 'with'
+ * @param mem pointer to the atomic value
+ * @param with what to swap it with
+ * @param the value to compare it to
+ * @return the old value of the atomic
+ */
+long apr_atomic_cas(volatile apr_atomic_t *mem,long with,long cmp);
+#else /* !DOXYGEN */
+
#ifdef WIN32
#define apr_atomic_t LONG;
@@ -72,7 +144,7 @@
#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)
@@ -86,6 +158,7 @@
#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
+#define APR_ATOMIC_NEED_CAS_DEFAULT 1
#elif defined(__FreeBSD__) && (__FreeBSD__ >= 4)
#include <machine/atomic.h>
@@ -98,36 +171,47 @@
#define apr_atomic_read(mem) *mem
#define apr_atomic_init(pool) APR_SUCCESS
+#define APR_ATOMIC_NEED_CAS_DEFAULT 1
-#elif defined(__sparc__not_ready_yet)
+#elif defined(__sparc__not_yet)
#define apr_atomic_t apr_uint32_t
#define apr_atomic_read(p) *p
#define apr_atomic_add(mem, val) apr_atomic_add_sparc(mem,val)
#define apr_atomic_dec(mem) apr_atomic_sub_sparc(mem,1)
#define apr_atomic_inc(mem) apr_atomic_add_sparc(mem,1)
+#define apr_atomic_cas(mem,val,cond) apr_atomic_cas_sparc(mem,val,cond)
+#define apr_atomic_casptr(mem,val,cond) apr_atomic_casptr_sparc(mem,val,cond)
#define apr_atomic_set(mem, val) *mem= val
#define apr_atomic_init(pool) APR_SUCCESS
apr_uint32_t apr_atomic_add_sparc( volatile apr_atomic_t* mem, apr_uint32_t
add);
apr_uint32_t apr_atomic_sub_sparc( volatile apr_atomic_t* mem, apr_uint32_t
sub);
+long apr_atomic_cas_sparc(volatile apr_atomic_t *mem,long with,long cmp);
+
#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);
-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_set(volatile apr_atomic_t *mem, apr_uint32_t val);
+apr_uint32_t apr_atomic_add(volatile apr_atomic_t *mem, apr_uint32_t 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);*/
#define APR_ATOMIC_NEED_DEFAULT 1
+#define APR_ATOMIC_NEED_CAS_DEFAULT 1
+
#endif /* APR_HAS_THREADS */
#endif /* !defined(WIN32) && !defined(__linux) */
+#if defined(APR_ATOMIC_NEED_CAS_DEFAULT)
+long apr_atomic_cas(volatile apr_atomic_t *mem,long with,long cmp);
+#endif
+
+#endif /* DOXYGEN */
#ifdef __cplusplus
}
#endif