harmony-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ge...@apache.org
Subject svn commit: r452912 - in /incubator/harmony/enhanced/drlvm/trunk/build/patches/win/APR: include/arch/win32/apr_arch_thread_cond.h locks/win32/thread_cond.c
Date Wed, 04 Oct 2006 15:28:27 GMT
Author: geirm
Date: Wed Oct  4 08:28:27 2006
New Revision: 452912

URL: http://svn.apache.org/viewvc?view=rev&rev=452912
Log:
HARMONY-1519

The DRLVM sometimes become VERY slow during Eclipse session, it almost freezes whole system
consuming 99% CPU.

Note that this is a patch for windows, but I wanted to test on linux to be sure all is well.
 All is well.

Will be testing on WinXP now




Modified:
    incubator/harmony/enhanced/drlvm/trunk/build/patches/win/APR/include/arch/win32/apr_arch_thread_cond.h
    incubator/harmony/enhanced/drlvm/trunk/build/patches/win/APR/locks/win32/thread_cond.c

Modified: incubator/harmony/enhanced/drlvm/trunk/build/patches/win/APR/include/arch/win32/apr_arch_thread_cond.h
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/drlvm/trunk/build/patches/win/APR/include/arch/win32/apr_arch_thread_cond.h?view=diff&rev=452912&r1=452911&r2=452912
==============================================================================
--- incubator/harmony/enhanced/drlvm/trunk/build/patches/win/APR/include/arch/win32/apr_arch_thread_cond.h
(original)
+++ incubator/harmony/enhanced/drlvm/trunk/build/patches/win/APR/include/arch/win32/apr_arch_thread_cond.h
Wed Oct  4 08:28:27 2006
@@ -19,14 +19,23 @@
 
 #include "apr_thread_cond.h"
 
+
+struct waiting_node {
+   // notification event
+   HANDLE event;
+   // double-linked queue
+   struct waiting_node *prev;
+   struct waiting_node *next;
+};
+
+// queue based condition implementation
 struct apr_thread_cond_t {
     apr_pool_t *pool;
-    HANDLE event;
-    int signal_all;
-    int num_waiting;
-    int signalled;
-    unsigned wait_level;
-    unsigned notify_level;
+    // the signal, could be called without mutex
+    // so we use internal one to guard the waiting queue
+    apr_thread_mutex_t *queue_mutex;
+    // head-tail marker node
+    struct waiting_node dummy_node;
 };
 
 #endif  /* THREAD_COND_H */

Modified: incubator/harmony/enhanced/drlvm/trunk/build/patches/win/APR/locks/win32/thread_cond.c
URL: http://svn.apache.org/viewvc/incubator/harmony/enhanced/drlvm/trunk/build/patches/win/APR/locks/win32/thread_cond.c?view=diff&rev=452912&r1=452911&r2=452912
==============================================================================
--- incubator/harmony/enhanced/drlvm/trunk/build/patches/win/APR/locks/win32/thread_cond.c
(original)
+++ incubator/harmony/enhanced/drlvm/trunk/build/patches/win/APR/locks/win32/thread_cond.c
Wed Oct  4 08:28:27 2006
@@ -22,81 +22,90 @@
 #include "win32/apr_arch_thread_cond.h"
 #include "apr_portable.h"
 
+// define this constants to synchronized waiting queue access
+// it is neccessery becuase signal() is not requiried to hold mutex
+#define LOCK_QUEUE apr_thread_mutex_lock(cond->queue_mutex)
+#define UNLOCK_QUEUE apr_thread_mutex_unlock(cond->queue_mutex)
+
 static apr_status_t thread_cond_cleanup(void *data)
 {
-    apr_thread_cond_t *cond = data;
-    CloseHandle(cond->event);
+    apr_thread_mutex_destroy(((apr_thread_cond_t *)data)->queue_mutex);
     return APR_SUCCESS;
 }
 
 APR_DECLARE(apr_status_t) apr_thread_cond_create(apr_thread_cond_t **cond,
                                                  apr_pool_t *pool)
 {
-    *cond = apr_palloc(pool, sizeof(**cond));
+    *cond = apr_pcalloc(pool, sizeof(**cond));
     (*cond)->pool = pool;
-    (*cond)->event = CreateEvent(NULL, TRUE, FALSE, NULL);
-    (*cond)->signal_all = 0;
-    (*cond)->num_waiting = 0;
-
-    (*cond)->wait_level = 0;
-    (*cond)->notify_level = 0;
-    
+    (*cond)-> dummy_node.next = (*cond)-> dummy_node.prev =  &((*cond)-> dummy_node);
+    apr_thread_mutex_create(&((*cond)->queue_mutex),  APR_THREAD_MUTEX_NESTED, pool);
     return APR_SUCCESS;
 }
-// this is used to skip staled notifies, 
-// ingnor notify that arrived before wait, V       VVVVV - int overflow check. 
-#define NOT_STALED(wait,notify) (wait<=notify ||  (wait > 0x4fffffff && notify
< 0xffffff))
 
+static void _enqueue (apr_thread_cond_t *cond, struct waiting_node *node) {
+     node->next = &(cond->dummy_node);
+     node->prev = cond->dummy_node.prev;
+     node->prev->next = node;
+     cond->dummy_node.prev = node;
+
+}
+
+static int _remove_from_queue (apr_thread_cond_t *cond, struct waiting_node *node) {
+    if (node->next == NULL || node->prev == NULL) {
+        // already dequeued (by signal)
+        return -1;
+    }
+    node->prev->next = node->next;
+    node->next->prev = node->prev;
+    node->next = NULL; 
+    node->prev = NULL;
+    return 0;
+}
+
+//dequeue 
+// return NULL if queue is empty
+static struct waiting_node* _dequeue (apr_thread_cond_t *cond) {
+    struct waiting_node* node;
+    if (cond->dummy_node.next == &(cond->dummy_node)) {
+        // the queue is empty
+        return NULL;
+    }
+    node=cond->dummy_node.next;
+    _remove_from_queue (cond,node);
+    return node;
+}
 static APR_INLINE apr_status_t _thread_cond_timedwait(apr_thread_cond_t *cond,
                                                       apr_thread_mutex_t *mutex,
                                                       DWORD timeout_ms )
 {
     DWORD res;
-    unsigned this_wait_level;
-
-    cond->wait_level++;
-    this_wait_level=cond->wait_level;
-   
-    while (1) {
-        cond->num_waiting++;
-        apr_thread_mutex_unlock(mutex);
-        res = WaitForSingleObject(cond->event, timeout_ms);
-        apr_thread_mutex_lock(mutex);
-        cond->num_waiting--;
-        if (res != WAIT_OBJECT_0) {
-            apr_status_t rv = apr_get_os_error();
-            if (res == WAIT_TIMEOUT) {
-                return APR_TIMEUP;
-            }
-            return apr_get_os_error();
-        }
-        if (cond->signal_all) {
-            if (cond->num_waiting == 0) {
-                cond->signal_all = 0;
-                cond->signalled = 0;
-                ResetEvent(cond->event);
-            }
-
-            // wait till all NOT_STALLED wait procceed and reset the event
-           // then continue waiting
-            while (!NOT_STALED(this_wait_level, cond->notify_level) && cond->num_waiting
!= 0)  {
-                   apr_thread_mutex_unlock(mutex);
-                   apr_thread_yield();
-                   apr_thread_mutex_lock(mutex);
-            }
-
-            if(NOT_STALED(this_wait_level, cond->notify_level)) {
-                break;
-            }
+    apr_status_t rv = APR_SUCCESS;
+    struct waiting_node node;
 
-        }
-        else if (cond->signalled && NOT_STALED(this_wait_level, cond->notify_level))
{
-            cond->signalled = 0;
-            ResetEvent(cond->event);
-            break;
+    // add waiting
+    node.event = CreateEvent(NULL, TRUE, FALSE, NULL);
+    LOCK_QUEUE;
+    _enqueue (cond, &node);
+    UNLOCK_QUEUE;
+
+    // release mutex and wait for signal 
+    apr_thread_mutex_unlock(mutex);
+    res = WaitForSingleObject(node.event, timeout_ms);
+    if (res != WAIT_OBJECT_0) {
+        if (res == WAIT_TIMEOUT) {
+            rv = APR_TIMEUP;
+        } else {
+            rv = apr_get_os_error();
         }
     }
-    return APR_SUCCESS;
+    apr_thread_mutex_lock(mutex);
+    LOCK_QUEUE;
+    _remove_from_queue (cond, &node);
+    CloseHandle(node.event);
+    UNLOCK_QUEUE;
+
+    return rv;
 }
 
 APR_DECLARE(apr_status_t) apr_thread_cond_wait(apr_thread_cond_t *cond,
@@ -118,13 +127,17 @@
 {
     apr_status_t rv = APR_SUCCESS;
     DWORD res;
+    struct waiting_node* node;
 
-    cond->signalled = 1;
-    cond->notify_level = cond->wait_level;
-    res = SetEvent(cond->event);
-    if (res == 0) {
-        rv = apr_get_os_error();
+    LOCK_QUEUE;
+    node = _dequeue (cond);
+    if (node != NULL) {
+        res = SetEvent(node->event);
+        if (res == 0) {
+             rv = apr_get_os_error();
+        }
     }
+    UNLOCK_QUEUE;
     return rv;
 }
 
@@ -132,14 +145,16 @@
 {
     apr_status_t rv = APR_SUCCESS;
     DWORD res;
+    struct waiting_node* node;
 
-    cond->signalled = 1;
-    cond->signal_all = 1;
-    cond->notify_level = cond->wait_level;
-    res = SetEvent(cond->event);
-    if (res == 0) {
-        rv = apr_get_os_error();
+    LOCK_QUEUE;
+    for (node = _dequeue (cond); node != NULL; node = _dequeue (cond)) {
+        res = SetEvent(node->event);
+        if (res == 0) {
+              rv = apr_get_os_error();
+        }
     }
+    UNLOCK_QUEUE;
     return rv;
 }
 



Mime
View raw message