Index: pjproject/main/pjlib/include/pj/os.h
===================================================================
--- pjproject/main/pjlib/include/pj/os.h	(revision 4)
+++ pjproject/main/pjlib/include/pj/os.h	(revision 5)
@@ -305,9 +305,7 @@
  * @param atomic_var	the atomic variable.
  * @param value		value to be set to the variable.
- *
- * @return the previous value of the variable.
- */
-PJ_DECL(pj_atomic_value_t) pj_atomic_set(pj_atomic_t *atomic_var, 
-					 pj_atomic_value_t value);
+ */
+PJ_DECL(void) pj_atomic_set( pj_atomic_t *atomic_var, 
+			     pj_atomic_value_t value);
 
 /**
@@ -324,8 +322,6 @@
  *
  * @param atomic_var	the atomic variable.
- *
- * @return the result.
- */
-PJ_DECL(pj_atomic_value_t) pj_atomic_inc(pj_atomic_t *atomic_var);
+ */
+PJ_DECL(void) pj_atomic_inc(pj_atomic_t *atomic_var);
 
 /**
@@ -333,8 +329,15 @@
  *
  * @param atomic_var	the atomic variable.
- *
- * @return the result.
- */
-PJ_DECL(pj_atomic_value_t) pj_atomic_dec(pj_atomic_t *atomic_var);
+ */
+PJ_DECL(void) pj_atomic_dec(pj_atomic_t *atomic_var);
+
+/**
+ * Add a value to an atomic type.
+ *
+ * @param atomic_var	The atomic variable.
+ * @param value		Value to be added.
+ */
+PJ_DECL(void) pj_atomic_add( pj_atomic_t *atomic_var,
+			     pj_atomic_value_t value);
 
 /**
Index: pjproject/main/pjlib/src/pj/os_core_linux_kernel.c
===================================================================
--- pjproject/main/pjlib/src/pj/os_core_linux_kernel.c	(revision 4)
+++ pjproject/main/pjlib/src/pj/os_core_linux_kernel.c	(revision 5)
@@ -416,13 +416,10 @@
 PJ_DEF(pj_status_t) pj_atomic_destroy( pj_atomic_t *var )
 {
-    return 0;
-}
-
-PJ_DEF(pj_atomic_value_t) pj_atomic_set(pj_atomic_t *var, 
-				        pj_atomic_value_t value)
-{
-    pj_atomic_value_t oldval = atomic_read(&var->atom);
+    return PJ_SUCCESS;
+}
+
+PJ_DEF(void) pj_atomic_set(pj_atomic_t *var, pj_atomic_value_t value)
+{
     atomic_set(&var->atom, value);
-    return oldval;
 }
 
@@ -432,16 +429,18 @@
 }
 
-PJ_DEF(pj_atomic_value_t) pj_atomic_inc(pj_atomic_t *var)
+PJ_DEF(void) pj_atomic_inc(pj_atomic_t *var)
 {
     atomic_inc(&var->atom);
-    return atomic_read(&var->atom);
-}
-
-PJ_DEF(pj_atomic_value_t) pj_atomic_dec(pj_atomic_t *var)
+}
+
+PJ_DEF(void) pj_atomic_dec(pj_atomic_t *var)
 {
     atomic_dec(&var->atom);
-    return atomic_read(&var->atom);
-}
-
+}
+
+PJ_DEF(void) pj_atomic_add( pj_atomic_t *var, pj_atomic_value_t value )
+{
+    atomic_add(value, &var->atom);
+}
 
 
Index: pjproject/main/pjlib/src/pj/os_core_unix.c
===================================================================
--- pjproject/main/pjlib/src/pj/os_core_unix.c	(revision 4)
+++ pjproject/main/pjlib/src/pj/os_core_unix.c	(revision 5)
@@ -527,81 +527,82 @@
  * pj_atomic_set()
  */
-PJ_DEF(pj_atomic_value_t) pj_atomic_set(pj_atomic_t *atomic_var, 
-					pj_atomic_value_t value)
-{
-    pj_atomic_value_t oldval;
-    
-    PJ_CHECK_STACK();
-    PJ_ASSERT_RETURN(atomic_var, 0);
+PJ_DEF(void) pj_atomic_set(pj_atomic_t *atomic_var, pj_atomic_value_t value)
+{
+    PJ_CHECK_STACK();
 
 #if PJ_HAS_THREADS
     pj_mutex_lock( atomic_var->mutex );
 #endif
-    oldval = atomic_var->value;
     atomic_var->value = value;
 #if PJ_HAS_THREADS
     pj_mutex_unlock( atomic_var->mutex);
 #endif 
+}
+
+/*
+ * pj_atomic_get()
+ */
+PJ_DEF(pj_atomic_value_t) pj_atomic_get(pj_atomic_t *atomic_var)
+{
+    pj_atomic_value_t oldval;
+    
+    PJ_CHECK_STACK();
+
+#if PJ_HAS_THREADS
+    pj_mutex_lock( atomic_var->mutex );
+#endif
+    oldval = atomic_var->value;
+#if PJ_HAS_THREADS
+    pj_mutex_unlock( atomic_var->mutex);
+#endif
     return oldval;
 }
 
 /*
- * pj_atomic_get()
- */
-PJ_DEF(pj_atomic_value_t) pj_atomic_get(pj_atomic_t *atomic_var)
-{
-    pj_atomic_value_t oldval;
-    
-    PJ_CHECK_STACK();
-    PJ_ASSERT_RETURN(atomic_var, 0);
+ * pj_atomic_inc()
+ */
+PJ_DEF(void) pj_atomic_inc(pj_atomic_t *atomic_var)
+{
+    PJ_CHECK_STACK();
 
 #if PJ_HAS_THREADS
     pj_mutex_lock( atomic_var->mutex );
 #endif
-    oldval = atomic_var->value;
+    ++atomic_var->value;
 #if PJ_HAS_THREADS
     pj_mutex_unlock( atomic_var->mutex);
 #endif
-    return oldval;
-}
-
-/*
- * pj_atomic_inc()
- */
-PJ_DEF(pj_atomic_value_t) pj_atomic_inc(pj_atomic_t *atomic_var)
-{
-    pj_atomic_value_t newval;
-
-    PJ_CHECK_STACK();
-    PJ_ASSERT_RETURN(atomic_var, 0);
+}
+
+/*
+ * pj_atomic_dec()
+ */
+PJ_DEF(void) pj_atomic_dec(pj_atomic_t *atomic_var)
+{
+    PJ_CHECK_STACK();
 
 #if PJ_HAS_THREADS
     pj_mutex_lock( atomic_var->mutex );
 #endif
-    newval = ++atomic_var->value;
+    --atomic_var->value;
 #if PJ_HAS_THREADS
     pj_mutex_unlock( atomic_var->mutex);
 #endif
-    return newval;
-}
-
-/*
- * pj_atomic_dec()
- */
-PJ_DEF(pj_atomic_value_t) pj_atomic_dec(pj_atomic_t *atomic_var)
-{
-    pj_atomic_value_t newval;
-
-    PJ_CHECK_STACK();
-    PJ_ASSERT_RETURN(atomic_var, 0);
-
-#if PJ_HAS_THREADS
-    pj_mutex_lock( atomic_var->mutex );
-#endif
-    newval = --atomic_var->value;
-#if PJ_HAS_THREADS
-    pj_mutex_unlock( atomic_var->mutex);
-#endif
-    return newval;
+}
+
+/*
+ * pj_atomic_add()
+ */ 
+PJ_DEF(void) pj_atomic_add( pj_atomic_t *atomic_var, pj_atomic_value_t value )
+{
+#if PJ_HAS_THREADS
+    pj_mutex_lock(atomic_var->mutex);
+#endif
+    
+    atomic_var->value += value;
+
+#if PJ_HAS_THREADS
+    pj_mutex_unlock(atomic_var->mutex);
+#endif
 }
 
Index: pjproject/main/pjlib/src/pj/os_core_win32.c
===================================================================
--- pjproject/main/pjlib/src/pj/os_core_win32.c	(revision 4)
+++ pjproject/main/pjlib/src/pj/os_core_win32.c	(revision 5)
@@ -496,20 +496,19 @@
  * pj_atomic_set()
  */
-PJ_DEF(long) pj_atomic_set(pj_atomic_t *atomic_var, long value)
+PJ_DEF(void) pj_atomic_set( pj_atomic_t *atomic_var, pj_atomic_value_t value)
+{
+    PJ_CHECK_STACK();
+
+    InterlockedExchange(&atomic_var->value, value);
+}
+
+/*
+ * pj_atomic_get()
+ */
+PJ_DEF(pj_atomic_value_t) pj_atomic_get(pj_atomic_t *atomic_var)
 {
     PJ_CHECK_STACK();
     PJ_ASSERT_RETURN(atomic_var, 0);
 
-    return InterlockedExchange(&atomic_var->value, value);
-}
-
-/*
- * pj_atomic_get()
- */
-PJ_DEF(long) pj_atomic_get(pj_atomic_t *atomic_var)
-{
-    PJ_CHECK_STACK();
-    PJ_ASSERT_RETURN(atomic_var, 0);
-
     return atomic_var->value;
 }
@@ -518,11 +517,10 @@
  * pj_atomic_inc()
  */
-PJ_DEF(long) pj_atomic_inc(pj_atomic_t *atomic_var)
-{
-    PJ_CHECK_STACK();
-    PJ_ASSERT_RETURN(atomic_var, 0);
+PJ_DEF(void) pj_atomic_inc(pj_atomic_t *atomic_var)
+{
+    PJ_CHECK_STACK();
 
 #if defined(PJ_WIN32_WINNT) && PJ_WIN32_WINNT >= 0x0400
-    return InterlockedIncrement(&atomic_var->value);
+    InterlockedIncrement(&atomic_var->value);
 #else
 #   error Fix Me
@@ -533,11 +531,10 @@
  * pj_atomic_dec()
  */
-PJ_DEF(long) pj_atomic_dec(pj_atomic_t *atomic_var)
-{
-    PJ_CHECK_STACK();
-    PJ_ASSERT_RETURN(atomic_var, 0);
+PJ_DEF(void) pj_atomic_dec(pj_atomic_t *atomic_var)
+{
+    PJ_CHECK_STACK();
 
 #if defined(PJ_WIN32_WINNT) && PJ_WIN32_WINNT >= 0x0400
-    return InterlockedDecrement(&atomic_var->value);
+    InterlockedDecrement(&atomic_var->value);
 #else
 #   error Fix me
@@ -545,5 +542,14 @@
 }
 
-
+/*
+ * pj_atomic_add()
+ */
+PJ_DEF(void) pj_atomic_add( pj_atomic_t *atomic_var,
+			    pj_atomic_value_t value )
+{
+    InterlockedExchangeAdd( &atomic_var->value, value );
+}
+
+	
 ///////////////////////////////////////////////////////////////////////////////
 /*
Index: pjproject/main/pjlib/src/pjlib-test/echo_clt.c
===================================================================
--- pjproject/main/pjlib/src/pjlib-test/echo_clt.c	(revision 4)
+++ pjproject/main/pjlib/src/pjlib-test/echo_clt.c	(revision 5)
@@ -29,9 +29,5 @@
 };
 
-static pj_sem_t *sem;
-static pj_mutex_t *mutex;
-static pj_size_t total_bw;
-static unsigned total_poster;
-static pj_time_val first_report;
+static pj_atomic_t *totalBytes;
 
 #define MSEC_PRINT_DURATION 1000
@@ -62,7 +58,5 @@
     struct client *client = arg;
     pj_status_t last_recv_err = PJ_SUCCESS, last_send_err = PJ_SUCCESS;
-
-    pj_time_val last_report, next_report;
-    pj_size_t thread_total;
+    unsigned counter = 0;
 
     rc = app_socket(PJ_AF_INET, client->sock_type, 0, -1, &sock);
@@ -90,12 +84,9 @@
 		  pj_ntohs(addr.sin_port)));
 
-    pj_create_random_string(send_buf, BUF_SIZE);
-    thread_total = 0;
+    pj_memset(send_buf, 'A', BUF_SIZE);
+    send_buf[BUF_SIZE-1]='\0';
 
     /* Give other thread chance to initialize themselves! */
-    pj_thread_sleep(500);
-
-    pj_gettimeofday(&last_report);
-    next_report = first_report;
+    pj_thread_sleep(200);
 
     //PJ_LOG(3,("", "...thread %p running", pj_thread_this()));
@@ -104,5 +95,6 @@
         int rc;
         pj_ssize_t bytes;
-        pj_time_val now;
+
+	++counter;
 
         /* Send a packet. */
@@ -148,49 +140,18 @@
         }
 
-        /* Accumulate total received. */
-        thread_total = thread_total + bytes;
-
-        /* Report current bandwidth on due. */
-        pj_gettimeofday(&now);
-
-        if (PJ_TIME_VAL_GTE(now, next_report)) {
-            pj_uint32_t bw;
-            pj_bool_t signal_parent = 0;
-            pj_time_val duration;
-            pj_uint32_t msec;
-
-            duration = now;
-            PJ_TIME_VAL_SUB(duration, last_report);
-            msec = PJ_TIME_VAL_MSEC(duration);
-
-            bw = thread_total * 1000 / msec;
-
-            /* Post result to parent */
-            pj_mutex_lock(mutex);
-            total_bw += bw;
-            total_poster++;
-            //PJ_LOG(3,("", "...thread %p posting result", pj_thread_this()));
-            if (total_poster >= ECHO_CLIENT_MAX_THREADS)
-                signal_parent = 1;
-            pj_mutex_unlock(mutex);
-
-            thread_total = 0;
-            last_report = now;
-            next_report.sec++;
-
-            if (signal_parent) {
-                pj_sem_post(sem);
-            }
-
-            pj_thread_sleep(0);
-        }
-
         if (bytes == 0)
             continue;
 
         if (pj_memcmp(send_buf, recv_buf, BUF_SIZE) != 0) {
-            //PJ_LOG(3,("", "...error: buffer has changed!"));
-            break;
-        }
+	    recv_buf[BUF_SIZE-1] = '\0';
+            PJ_LOG(3,("", "...error: buffer %u has changed!\n"
+			  "send_buf=%s\n"
+			  "recv_buf=%s\n", 
+			  counter, send_buf, recv_buf));
+            //break;
+        }
+
+        /* Accumulate total received. */
+	pj_atomic_add(totalBytes, bytes);
     }
 
@@ -206,4 +167,6 @@
     struct client client;
     int i;
+    pj_atomic_value_t last_received;
+    pj_timestamp last_report;
 
     client.sock_type = sock_type;
@@ -213,23 +176,9 @@
     pool = pj_pool_create( mem, NULL, 4000, 4000, NULL );
 
-    rc = pj_sem_create(pool, NULL, 0, ECHO_CLIENT_MAX_THREADS+1, &sem);
-    if (rc != PJ_SUCCESS) {
-        PJ_LOG(3,("", "...error: unable to create semaphore", rc));
-        return -10;
-    }
-
-    rc = pj_mutex_create_simple(pool, NULL, &mutex);
-    if (rc != PJ_SUCCESS) {
-        PJ_LOG(3,("", "...error: unable to create mutex", rc));
-        return -20;
-    }
-
-    /*
-    rc = pj_atomic_create(pool, 0, &atom);
+    rc = pj_atomic_create(pool, 0, &totalBytes);
     if (rc != PJ_SUCCESS) {
         PJ_LOG(3,("", "...error: unable to create atomic variable", rc));
         return -30;
     }
-    */
 
     PJ_LOG(3,("", "Echo client started"));
@@ -237,7 +186,4 @@
                   ECHO_SERVER_ADDRESS, ECHO_SERVER_START_PORT));
     PJ_LOG(3,("", "  Press Ctrl-C to exit"));
-
-    pj_gettimeofday(&first_report);
-    first_report.sec += 2;
 
     for (i=0; i<ECHO_CLIENT_MAX_THREADS; ++i) {
@@ -251,17 +197,35 @@
     }
 
+    last_received = 0;
+    pj_get_timestamp(&last_report);
+
     for (;;) {
-        pj_uint32_t bw;
-
-        pj_sem_wait(sem);
-
-        pj_mutex_lock(mutex);
-        bw = total_bw;
-        total_bw = 0;
-        total_poster = 0;
-        pj_mutex_unlock(mutex);
+	pj_timestamp now;
+	unsigned long received, cur_received;
+	unsigned msec;
+	pj_highprec_t bw;
+	pj_time_val elapsed;
+	unsigned bw32;
+
+	pj_thread_sleep(1000);
+
+	pj_get_timestamp(&now);
+	elapsed = pj_elapsed_time(&last_report, &now);
+	msec = PJ_TIME_VAL_MSEC(elapsed);
+
+	received = pj_atomic_get(totalBytes);
+	cur_received = received - last_received;
+	
+	bw = cur_received;
+	pj_highprec_mul(bw, 1000);
+	pj_highprec_div(bw, msec);
+
+	bw32 = (unsigned)bw;
+	
+	last_report = now;
+	last_received = received;
 
         PJ_LOG(3,("", "...%d threads, total bandwidth: %d KB/s", 
-                  ECHO_CLIENT_MAX_THREADS, bw/1000));
+                  ECHO_CLIENT_MAX_THREADS, bw32/1000));
     }
 
Index: pjproject/main/pjlib/src/pjlib-test/test.h
===================================================================
--- pjproject/main/pjlib/src/pjlib-test/test.h	(revision 4)
+++ pjproject/main/pjlib/src/pjlib-test/test.h	(revision 5)
@@ -45,5 +45,5 @@
 #define ECHO_SERVER_DURATION_MSEC   (60*60*1000)
 
-#define ECHO_CLIENT_MAX_THREADS     2
+#define ECHO_CLIENT_MAX_THREADS     6
 
 PJ_BEGIN_DECL
