On Mon, Nov 25, 2013 at 2:59 PM, <j...@apache.org> wrote:

> Author: jim
> Date: Mon Nov 25 13:59:06 2013
> New Revision: 1545286
>
> URL: http://svn.apache.org/r1545286
> Log:
> Use a normalized offset point for idlers... still need to worry
> that atomics work as "expected", in this case that a add32 of a -1
> is the "same" as dec32 (as far as effect on idlers)
>
> Modified:
>     httpd/httpd/trunk/server/mpm/event/event.c
>     httpd/httpd/trunk/server/mpm/event/fdqueue.c
>
>
> @@ -131,7 +128,7 @@ apr_status_t ap_queue_info_set_idle(fd_q
>  apr_status_t ap_queue_info_try_get_idler(fd_queue_info_t * queue_info)
>  {
>      int prev_idlers;
> -    prev_idlers = apr_atomic_dec32((apr_uint32_t *)&(queue_info->idlers));
> +    prev_idlers = apr_atomic_add32((apr_uint32_t *)&(queue_info->idlers),
> -1) - zero_pt;
>      if (prev_idlers <= 0) {
>          apr_atomic_inc32((apr_uint32_t *)&(queue_info->idlers));    /*
> back out dec */
>          return APR_EAGAIN;
>

As Jeff said in the other thread, I think the test here should be :
   if (prev_idlers <= 1)
that's because dec32 was returning the new value while add32 now returns
the old one (fetch_and_sub vs sub_and_fetch).

Also, couldn't 
"
queue_info->idlers
"
 and "
zero_pt
"
 become apr_uint32_t now, like in the following patch?
(Note the "int prev_idlers" => "apr_int32_t prev_idlers" too in the patch,
should int be larger than int32_t, eg. with 64bits int, prev_idlers would
not become negative is this case...).

Regards,
Yann.


Index: server/mpm/event/fdqueue.c
===================================================================
--- server/mpm/event/fdqueue.c    (revision 1545301)
+++ server/mpm/event/fdqueue.c    (working copy)
@@ -17,7 +17,7 @@
 #include "fdqueue.h"
 #include "apr_atomic.h"

-static zero_pt = (APR_INT32_MAX-1)>>2;
+static const apr_uint32_t zero_pt = ((apr_uint32_t)1 << 31);

 struct recycled_pool
 {
@@ -27,10 +27,12 @@ struct recycled_pool

 struct fd_queue_info_t
 {
-    apr_int32_t idlers;      /**
-                              * 0 or positive: number of idle worker
threads
-                              * negative: number of threads blocked waiting
-                              *           for an idle worker
+    apr_uint32_t idlers;     /**
+                              * >= zero_pt: (zero_pt - idlers) is the
number
+                              *             of idle worker threads
+                              *  < zero_pt: (idlers - zero_pt) is the
number
+                              *             of threads blocked waiting for
+                              *             an idle worker
                               */
     apr_thread_mutex_t *idlers_mutex;
     apr_thread_cond_t *wait_for_idler;
@@ -97,12 +99,12 @@ apr_status_t ap_queue_info_set_idle(fd_queue_info_
                                     apr_pool_t * pool_to_recycle)
 {
     apr_status_t rv;
-    int prev_idlers;
+    apr_int32_t prev_idlers;

     ap_push_pool(queue_info, pool_to_recycle);

     /* Atomically increment the count of idle workers */
-    prev_idlers = apr_atomic_inc32((apr_uint32_t *)&(queue_info->idlers))
- zero_pt;
+    prev_idlers = apr_atomic_inc32(&queue_info->idlers) - zero_pt;

     /* If other threads are waiting on a worker, wake one up */
     if (prev_idlers < 0) {
@@ -127,10 +129,10 @@ apr_status_t ap_queue_info_set_idle(fd_queue_info_

 apr_status_t ap_queue_info_try_get_idler(fd_queue_info_t * queue_info)
 {
-    int prev_idlers;
-    prev_idlers = apr_atomic_add32((apr_uint32_t *)&(queue_info->idlers),
-1) - zero_pt;
-    if (prev_idlers <= 0) {
-        apr_atomic_inc32((apr_uint32_t *)&(queue_info->idlers));    /*
back out dec */
+    apr_int32_t prev_idlers;
+    prev_idlers = apr_atomic_add32(&queue_info->idlers, -1) - zero_pt;
+    if (prev_idlers <= 1) {
+        apr_atomic_inc32(&queue_info->idlers);    /* back out dec */
         return APR_EAGAIN;
     }
     return APR_SUCCESS;
@@ -140,11 +142,11 @@ apr_status_t ap_queue_info_wait_for_idler(fd_queue
                                           int *had_to_block)
 {
     apr_status_t rv;
-    int prev_idlers;
+    apr_int32_t prev_idlers;

     /* Atomically decrement the idle worker count, saving the old value */
     /* See TODO in ap_queue_info_set_idle() */
-    prev_idlers = apr_atomic_add32((apr_uint32_t *)&(queue_info->idlers),
-1) - zero_pt;
+    prev_idlers = apr_atomic_add32(&queue_info->idlers, -1) - zero_pt;

     /* Block if there weren't any idle workers */
     if (prev_idlers <= 0) {
@@ -152,7 +154,7 @@ apr_status_t ap_queue_info_wait_for_idler(fd_queue
         if (rv != APR_SUCCESS) {
             AP_DEBUG_ASSERT(0);
             /* See TODO in ap_queue_info_set_idle() */
-            apr_atomic_inc32((apr_uint32_t *)&(queue_info->idlers));    /*
back out dec */
+            apr_atomic_inc32(&queue_info->idlers);    /* back out dec */
             return rv;
         }
         /* Re-check the idle worker count to guard against a
@@ -206,8 +208,8 @@ apr_status_t ap_queue_info_wait_for_idler(fd_queue
 apr_uint32_t ap_queue_info_get_idlers(fd_queue_info_t * queue_info)
 {
     apr_int32_t val;
-    val = (apr_int32_t)apr_atomic_read32((apr_uint32_t
*)&queue_info->idlers) - zero_pt;
-    if (val < 0)
+    val = apr_atomic_read32(&queue_info->idlers) - zero_pt;
+    if (val <= 0)
         return 0;
     return val;
 }
Index: server/mpm/eventopt/fdqueue.c
===================================================================
--- server/mpm/eventopt/fdqueue.c    (revision 1545301)
+++ server/mpm/eventopt/fdqueue.c    (working copy)
@@ -17,6 +17,8 @@
 #include "fdqueue.h"
 #include "apr_atomic.h"

+static const apr_uint32_t zero_pt = ((apr_uint32_t)1 << 31);
+
 typedef struct recycled_pool
 {
     apr_pool_t *pool;
@@ -25,10 +27,12 @@ typedef struct recycled_pool

 struct fd_queue_info_t
 {
-    apr_int32_t idlers;      /**
-                              * 0 or positive: number of idle worker
threads
-                              * negative: number of threads blocked waiting
-                              *           for an idle worker
+    apr_uint32_t idlers;     /**
+                              * >= zero_pt: (zero_pt - idlers) is the
number
+                              *             of idle worker threads
+                              *  < zero_pt: (idlers - zero_pt) is the
number
+                              *             of threads blocked waiting for
+                              *             an idle worker
                               */
     apr_thread_mutex_t *idlers_mutex;
     apr_thread_cond_t *wait_for_idler;
@@ -95,12 +99,12 @@ apr_status_t ap_queue_info_set_idle(fd_queue_info_
                                     apr_pool_t * pool_to_recycle)
 {
     apr_status_t rv;
-    int prev_idlers;
+    apr_int32_t prev_idlers;

     ap_push_pool(queue_info, pool_to_recycle);

     /* Atomically increment the count of idle workers */
-    prev_idlers = apr_atomic_inc32((apr_uint32_t *)&(queue_info->idlers))
- zero_pt;
+    prev_idlers = apr_atomic_inc32(&queue_info->idlers) - zero_pt;

     /* If other threads are waiting on a worker, wake one up */
     if (prev_idlers < 0) {
@@ -125,10 +129,10 @@ apr_status_t ap_queue_info_set_idle(fd_queue_info_

 apr_status_t ap_queue_info_try_get_idler(fd_queue_info_t * queue_info)
 {
-    int prev_idlers;
-    prev_idlers = apr_atomic_add32((apr_uint32_t *)&(queue_info->idlers),
-1) - zero_pt;
-    if (prev_idlers <= 0) {
-        apr_atomic_inc32((apr_uint32_t *)&(queue_info->idlers));    /*
back out dec */
+    apr_int32_t prev_idlers;
+    prev_idlers = apr_atomic_add32(&queue_info->idlers, -1) - zero_pt;
+    if (prev_idlers <= 1) {
+        apr_atomic_inc32(&queue_info->idlers);    /* back out dec */
         return APR_EAGAIN;
     }
     return APR_SUCCESS;
@@ -138,11 +142,11 @@ apr_status_t ap_queue_info_wait_for_idler(fd_queue
                                           int *had_to_block)
 {
     apr_status_t rv;
-    int prev_idlers;
+    apr_int32_t prev_idlers;

     /* Atomically decrement the idle worker count, saving the old value */
     /* See TODO in ap_queue_info_set_idle() */
-    prev_idlers = apr_atomic_add32((apr_uint32_t *)&(queue_info->idlers),
-1) - zero_pt;
+    prev_idlers = apr_atomic_add32(&queue_info->idlers, -1) - zero_pt;

     /* Block if there weren't any idle workers */
     if (prev_idlers <= 0) {
@@ -150,7 +154,7 @@ apr_status_t ap_queue_info_wait_for_idler(fd_queue
         if (rv != APR_SUCCESS) {
             AP_DEBUG_ASSERT(0);
             /* See TODO in ap_queue_info_set_idle() */
-            apr_atomic_inc32((apr_uint32_t *)&(queue_info->idlers));    /*
back out dec */
+            apr_atomic_inc32(&queue_info->idlers);    /* back out dec */
             return rv;
         }
         /* Re-check the idle worker count to guard against a
@@ -204,8 +208,8 @@ apr_status_t ap_queue_info_wait_for_idler(fd_queue
 apr_uint32_t ap_queue_info_get_idlers(fd_queue_info_t * queue_info)
 {
     apr_int32_t val;
-    val = (apr_int32_t)apr_atomic_read32((apr_uint32_t
*)&queue_info->idlers) - zero_pt;
-    if (val < 0)
+    val = apr_atomic_read32(&queue_info->idlers) - zero_pt;
+    if (val <= 0)
         return 0;
     return val;
 }
[END]
Index: server/mpm/event/fdqueue.c
===================================================================
--- server/mpm/event/fdqueue.c	(revision 1545301)
+++ server/mpm/event/fdqueue.c	(working copy)
@@ -17,7 +17,7 @@
 #include "fdqueue.h"
 #include "apr_atomic.h"
 
-static zero_pt = (APR_INT32_MAX-1)>>2;
+static const apr_uint32_t zero_pt = ((apr_uint32_t)1 << 31);
 
 struct recycled_pool
 {
@@ -27,10 +27,12 @@ struct recycled_pool
 
 struct fd_queue_info_t
 {
-    apr_int32_t idlers;      /**
-                              * 0 or positive: number of idle worker threads
-                              * negative: number of threads blocked waiting
-                              *           for an idle worker
+    apr_uint32_t idlers;     /**
+                              * >= zero_pt: (zero_pt - idlers) is the number
+                              *             of idle worker threads
+                              *  < zero_pt: (idlers - zero_pt) is the number
+                              *             of threads blocked waiting for
+                              *             an idle worker
                               */
     apr_thread_mutex_t *idlers_mutex;
     apr_thread_cond_t *wait_for_idler;
@@ -97,12 +99,12 @@ apr_status_t ap_queue_info_set_idle(fd_queue_info_
                                     apr_pool_t * pool_to_recycle)
 {
     apr_status_t rv;
-    int prev_idlers;
+    apr_int32_t prev_idlers;
 
     ap_push_pool(queue_info, pool_to_recycle);
 
     /* Atomically increment the count of idle workers */
-    prev_idlers = apr_atomic_inc32((apr_uint32_t *)&(queue_info->idlers)) - zero_pt;
+    prev_idlers = apr_atomic_inc32(&queue_info->idlers) - zero_pt;
 
     /* If other threads are waiting on a worker, wake one up */
     if (prev_idlers < 0) {
@@ -127,10 +129,10 @@ apr_status_t ap_queue_info_set_idle(fd_queue_info_
 
 apr_status_t ap_queue_info_try_get_idler(fd_queue_info_t * queue_info)
 {
-    int prev_idlers;
-    prev_idlers = apr_atomic_add32((apr_uint32_t *)&(queue_info->idlers), -1) - zero_pt;
-    if (prev_idlers <= 0) {
-        apr_atomic_inc32((apr_uint32_t *)&(queue_info->idlers));    /* back out dec */
+    apr_int32_t prev_idlers;
+    prev_idlers = apr_atomic_add32(&queue_info->idlers, -1) - zero_pt;
+    if (prev_idlers <= 1) {
+        apr_atomic_inc32(&queue_info->idlers);    /* back out dec */
         return APR_EAGAIN;
     }
     return APR_SUCCESS;
@@ -140,11 +142,11 @@ apr_status_t ap_queue_info_wait_for_idler(fd_queue
                                           int *had_to_block)
 {
     apr_status_t rv;
-    int prev_idlers;
+    apr_int32_t prev_idlers;
 
     /* Atomically decrement the idle worker count, saving the old value */
     /* See TODO in ap_queue_info_set_idle() */
-    prev_idlers = apr_atomic_add32((apr_uint32_t *)&(queue_info->idlers), -1) - zero_pt;
+    prev_idlers = apr_atomic_add32(&queue_info->idlers, -1) - zero_pt;
 
     /* Block if there weren't any idle workers */
     if (prev_idlers <= 0) {
@@ -152,7 +154,7 @@ apr_status_t ap_queue_info_wait_for_idler(fd_queue
         if (rv != APR_SUCCESS) {
             AP_DEBUG_ASSERT(0);
             /* See TODO in ap_queue_info_set_idle() */
-            apr_atomic_inc32((apr_uint32_t *)&(queue_info->idlers));    /* back out dec */
+            apr_atomic_inc32(&queue_info->idlers);    /* back out dec */
             return rv;
         }
         /* Re-check the idle worker count to guard against a
@@ -206,8 +208,8 @@ apr_status_t ap_queue_info_wait_for_idler(fd_queue
 apr_uint32_t ap_queue_info_get_idlers(fd_queue_info_t * queue_info)
 {
     apr_int32_t val;
-    val = (apr_int32_t)apr_atomic_read32((apr_uint32_t *)&queue_info->idlers) - zero_pt;
-    if (val < 0)
+    val = apr_atomic_read32(&queue_info->idlers) - zero_pt;
+    if (val <= 0)
         return 0;
     return val;
 }
Index: server/mpm/eventopt/fdqueue.c
===================================================================
--- server/mpm/eventopt/fdqueue.c	(revision 1545301)
+++ server/mpm/eventopt/fdqueue.c	(working copy)
@@ -17,6 +17,8 @@
 #include "fdqueue.h"
 #include "apr_atomic.h"
 
+static const apr_uint32_t zero_pt = ((apr_uint32_t)1 << 31);
+
 typedef struct recycled_pool
 {
     apr_pool_t *pool;
@@ -25,10 +27,12 @@ typedef struct recycled_pool
 
 struct fd_queue_info_t
 {
-    apr_int32_t idlers;      /**
-                              * 0 or positive: number of idle worker threads
-                              * negative: number of threads blocked waiting
-                              *           for an idle worker
+    apr_uint32_t idlers;     /**
+                              * >= zero_pt: (zero_pt - idlers) is the number
+                              *             of idle worker threads
+                              *  < zero_pt: (idlers - zero_pt) is the number
+                              *             of threads blocked waiting for
+                              *             an idle worker
                               */
     apr_thread_mutex_t *idlers_mutex;
     apr_thread_cond_t *wait_for_idler;
@@ -95,12 +99,12 @@ apr_status_t ap_queue_info_set_idle(fd_queue_info_
                                     apr_pool_t * pool_to_recycle)
 {
     apr_status_t rv;
-    int prev_idlers;
+    apr_int32_t prev_idlers;
 
     ap_push_pool(queue_info, pool_to_recycle);
 
     /* Atomically increment the count of idle workers */
-    prev_idlers = apr_atomic_inc32((apr_uint32_t *)&(queue_info->idlers)) - zero_pt;
+    prev_idlers = apr_atomic_inc32(&queue_info->idlers) - zero_pt;
 
     /* If other threads are waiting on a worker, wake one up */
     if (prev_idlers < 0) {
@@ -125,10 +129,10 @@ apr_status_t ap_queue_info_set_idle(fd_queue_info_
 
 apr_status_t ap_queue_info_try_get_idler(fd_queue_info_t * queue_info)
 {
-    int prev_idlers;
-    prev_idlers = apr_atomic_add32((apr_uint32_t *)&(queue_info->idlers), -1) - zero_pt;
-    if (prev_idlers <= 0) {
-        apr_atomic_inc32((apr_uint32_t *)&(queue_info->idlers));    /* back out dec */
+    apr_int32_t prev_idlers;
+    prev_idlers = apr_atomic_add32(&queue_info->idlers, -1) - zero_pt;
+    if (prev_idlers <= 1) {
+        apr_atomic_inc32(&queue_info->idlers);    /* back out dec */
         return APR_EAGAIN;
     }
     return APR_SUCCESS;
@@ -138,11 +142,11 @@ apr_status_t ap_queue_info_wait_for_idler(fd_queue
                                           int *had_to_block)
 {
     apr_status_t rv;
-    int prev_idlers;
+    apr_int32_t prev_idlers;
 
     /* Atomically decrement the idle worker count, saving the old value */
     /* See TODO in ap_queue_info_set_idle() */
-    prev_idlers = apr_atomic_add32((apr_uint32_t *)&(queue_info->idlers), -1) - zero_pt;
+    prev_idlers = apr_atomic_add32(&queue_info->idlers, -1) - zero_pt;
 
     /* Block if there weren't any idle workers */
     if (prev_idlers <= 0) {
@@ -150,7 +154,7 @@ apr_status_t ap_queue_info_wait_for_idler(fd_queue
         if (rv != APR_SUCCESS) {
             AP_DEBUG_ASSERT(0);
             /* See TODO in ap_queue_info_set_idle() */
-            apr_atomic_inc32((apr_uint32_t *)&(queue_info->idlers));    /* back out dec */
+            apr_atomic_inc32(&queue_info->idlers);    /* back out dec */
             return rv;
         }
         /* Re-check the idle worker count to guard against a
@@ -204,8 +208,8 @@ apr_status_t ap_queue_info_wait_for_idler(fd_queue
 apr_uint32_t ap_queue_info_get_idlers(fd_queue_info_t * queue_info)
 {
     apr_int32_t val;
-    val = (apr_int32_t)apr_atomic_read32((apr_uint32_t *)&queue_info->idlers) - zero_pt;
-    if (val < 0)
+    val = apr_atomic_read32(&queue_info->idlers) - zero_pt;
+    if (val <= 0)
         return 0;
     return val;
 }

Reply via email to