Title: [128289] trunk/Source/WebKit2
Revision
128289
Author
commit-qu...@webkit.org
Date
2012-09-12 03:20:00 -0700 (Wed, 12 Sep 2012)

Log Message

[EFL][WK2] WorkQueue::dispatchAfterDelay() doesn't work properly.
https://bugs.webkit.org/show_bug.cgi?id=91179

Patch by Byungwoo Lee <bw80....@samsung.com> on 2012-09-12
Reviewed by Gyuyoung Kim.

When UI Process is crashed and WebProcess's ecore main loop is very
busy or lockup also, watchdocCallback() function in the
ChildProcess.cpp doesn't triggered. And this is because of that
WorkQueue::dispatchAfterDelay() function uses ecore timer for getting
timer event.

For removing the dependency between the dispatchAfterDelay() and ecore
main loop, new timer event mechanism is added to WorkQueue main loop.

* Platform/WorkQueue.h:
(TimerWorkItem):
(WorkQueue::TimerWorkItem::dispatch):
(WorkQueue::TimerWorkItem::expireTime):
(WorkQueue::TimerWorkItem::expired):
(WorkQueue):
* Platform/efl/WorkQueueEfl.cpp:
(WorkQueue::TimerWorkItem::create):
(WorkQueue::TimerWorkItem::TimerWorkItem):
(WorkQueue::performFileDescriptorWork):
(WorkQueue::getCurrentTime):
(WorkQueue::getNextTimeOut):
(WorkQueue::performTimerWork):
(WorkQueue::workQueueThread):
(WorkQueue::dispatchAfterDelay):

Modified Paths

Diff

Modified: trunk/Source/WebKit2/ChangeLog (128288 => 128289)


--- trunk/Source/WebKit2/ChangeLog	2012-09-12 10:17:00 UTC (rev 128288)
+++ trunk/Source/WebKit2/ChangeLog	2012-09-12 10:20:00 UTC (rev 128289)
@@ -1,3 +1,35 @@
+2012-09-12  Byungwoo Lee  <bw80....@samsung.com>
+
+        [EFL][WK2] WorkQueue::dispatchAfterDelay() doesn't work properly.
+        https://bugs.webkit.org/show_bug.cgi?id=91179
+
+        Reviewed by Gyuyoung Kim.
+
+        When UI Process is crashed and WebProcess's ecore main loop is very
+        busy or lockup also, watchdocCallback() function in the
+        ChildProcess.cpp doesn't triggered. And this is because of that
+        WorkQueue::dispatchAfterDelay() function uses ecore timer for getting
+        timer event.
+
+        For removing the dependency between the dispatchAfterDelay() and ecore
+        main loop, new timer event mechanism is added to WorkQueue main loop.
+
+        * Platform/WorkQueue.h:
+        (TimerWorkItem):
+        (WorkQueue::TimerWorkItem::dispatch):
+        (WorkQueue::TimerWorkItem::expireTime):
+        (WorkQueue::TimerWorkItem::expired):
+        (WorkQueue):
+        * Platform/efl/WorkQueueEfl.cpp:
+        (WorkQueue::TimerWorkItem::create):
+        (WorkQueue::TimerWorkItem::TimerWorkItem):
+        (WorkQueue::performFileDescriptorWork):
+        (WorkQueue::getCurrentTime):
+        (WorkQueue::getNextTimeOut):
+        (WorkQueue::performTimerWork):
+        (WorkQueue::workQueueThread):
+        (WorkQueue::dispatchAfterDelay):
+
 2012-09-12  Christophe Dumez  <christophe.du...@intel.com>
 
         [WK2][WKTR] TestRunner needs to implement dumpApplicationCacheDelegateCallbacks

Modified: trunk/Source/WebKit2/Platform/WorkQueue.h (128288 => 128289)


--- trunk/Source/WebKit2/Platform/WorkQueue.h	2012-09-12 10:17:00 UTC (rev 128288)
+++ trunk/Source/WebKit2/Platform/WorkQueue.h	2012-09-12 10:20:00 UTC (rev 128289)
@@ -187,6 +187,21 @@
     HashMap<int, Vector<EventSource*> > m_eventSources;
     typedef HashMap<int, Vector<EventSource*> >::iterator EventSourceIterator; 
 #elif PLATFORM(EFL)
+    class TimerWorkItem {
+    public:
+        static PassOwnPtr<TimerWorkItem> create(Function<void()>, double expireTime);
+        void dispatch() { m_function(); }
+        double expireTime() const { return m_expireTime; }
+        bool expired(double currentTime) const { return currentTime >= m_expireTime; }
+
+    protected:
+        TimerWorkItem(Function<void()>, double expireTime);
+
+    private:
+        Function<void()> m_function;
+        double m_expireTime;
+    };
+
     fd_set m_fileDescriptorSet;
     int m_maxFileDescriptor;
     int m_readFromPipeDescriptor;
@@ -199,13 +214,17 @@
     int m_socketDescriptor;
     Function<void()> m_socketEventHandler;
 
-    HashMap<int, OwnPtr<Ecore_Timer> > m_timers;
+    Vector<OwnPtr<TimerWorkItem> > m_timerWorkItems;
+    Mutex m_timerWorkItemsLock;
 
     void sendMessageToThread(const char*);
     static void* workQueueThread(WorkQueue*);
     void performWork();
     void performFileDescriptorWork();
-    static bool timerFired(void*);
+    static double getCurrentTime();
+    struct timeval* getNextTimeOut();
+    void performTimerWork();
+    void insertTimerWorkItem(PassOwnPtr<TimerWorkItem>);
 #endif
 };
 

Modified: trunk/Source/WebKit2/Platform/efl/WorkQueueEfl.cpp (128288 => 128289)


--- trunk/Source/WebKit2/Platform/efl/WorkQueueEfl.cpp	2012-09-12 10:17:00 UTC (rev 128288)
+++ trunk/Source/WebKit2/Platform/efl/WorkQueueEfl.cpp	2012-09-12 10:20:00 UTC (rev 128289)
@@ -20,34 +20,29 @@
 #include "config.h"
 #include "WorkQueue.h"
 
+#include <sys/timerfd.h>
 #include <wtf/Assertions.h>
+#include <wtf/CurrentTime.h>
 
-class TimerWorkItem {
-public:
-    TimerWorkItem(int timerID, const Function<void()>& function, WorkQueue* queue)
-        : m_function(function)
-        , m_queue(queue)
-        , m_timerID(timerID)
-    {
-    }
-    ~TimerWorkItem() { }
-
-    Function<void()> function() const { return m_function; }
-    WorkQueue* queue() const { return m_queue; }
-
-    int timerID() const { return m_timerID; }
-
-private:
-    Function<void()> m_function;
-    WorkQueue* m_queue;
-    int m_timerID;
-};
-
 static const int invalidSocketDescriptor = -1;
 static const int threadMessageSize = 1;
 static const char finishThreadMessage[] = "F";
 static const char wakupThreadMessage[] = "W";
 
+PassOwnPtr<WorkQueue::TimerWorkItem> WorkQueue::TimerWorkItem::create(Function<void()> function, double expireTime)
+{
+    if (expireTime < 0)
+        return nullptr;
+
+    return adoptPtr(new TimerWorkItem(function, expireTime));
+}
+
+WorkQueue::TimerWorkItem::TimerWorkItem(Function<void()> function, double expireTime)
+    : m_function(function)
+    , m_expireTime(expireTime)
+{
+}
+
 void WorkQueue::platformInitialize(const char* name)
 {
     int fds[2];
@@ -91,7 +86,7 @@
 {
     fd_set readFileDescriptorSet = m_fileDescriptorSet;
 
-    if (select(m_maxFileDescriptor + 1, &readFileDescriptorSet, 0, 0, 0) >= 0) {
+    if (select(m_maxFileDescriptor + 1, &readFileDescriptorSet, 0, 0, getNextTimeOut()) >= 0) {
         if (FD_ISSET(m_readFromPipeDescriptor, &readFileDescriptorSet)) {
             char readBuf[threadMessageSize];
             if (read(m_readFromPipeDescriptor, readBuf, threadMessageSize) == -1)
@@ -105,6 +100,74 @@
     }
 }
 
+struct timeval* WorkQueue::getNextTimeOut()
+{
+    MutexLocker locker(m_timerWorkItemsLock);
+    if (m_timerWorkItems.isEmpty())
+        return 0;
+
+    static struct timeval timeValue;
+    timeValue.tv_sec = 0;
+    timeValue.tv_usec = 0;
+    double timeOut = m_timerWorkItems[0]->expireTime() - currentTime();
+    if (timeOut > 0) {
+        timeValue.tv_sec = static_cast<long>(timeOut);
+        timeValue.tv_usec = static_cast<long>((timeOut - timeValue.tv_sec) * 1000000);
+    }
+
+    return &timeValue;
+}
+
+void WorkQueue::insertTimerWorkItem(PassOwnPtr<TimerWorkItem> item)
+{
+    if (!item)
+        return;
+
+    size_t position = 0;
+
+    // m_timerWorkItems should be ordered by expire time.
+    for (; position < m_timerWorkItems.size(); ++position)
+        if (item->expireTime() < m_timerWorkItems[position]->expireTime())
+            break;
+
+    m_timerWorkItems.insert(position, item);
+}
+
+void WorkQueue::performTimerWork()
+{
+    // Protects m_timerWorkItems.
+    m_timerWorkItemsLock.lock();
+
+    if (m_timerWorkItems.isEmpty()) {
+        m_timerWorkItemsLock.unlock();
+        return;
+    }
+
+    double current = currentTime();
+    Vector<OwnPtr<TimerWorkItem> > timerWorkItems;
+
+    // Copies all the timer work items in m_timerWorkItems to local vector.
+    m_timerWorkItems.swap(timerWorkItems);
+
+    for (size_t i = 0; i < timerWorkItems.size(); ++i) {
+        if (!timerWorkItems[i]->expired(current)) {
+            // If a timer work item does not expired, keep it to the m_timerWorkItems.
+            // m_timerWorkItems should be ordered by expire time.
+            insertTimerWorkItem(timerWorkItems[i].release());
+            continue;
+        }
+
+        // If a timer work item expired, dispatch the function of the work item.
+        // Before dispatching, m_timerWorkItemsLock should unlock for preventing deadlock,
+        // because it can be accessed inside the function of the timer work item dispatched.
+        m_timerWorkItemsLock.unlock();
+        timerWorkItems[i]->dispatch();
+        m_timerWorkItemsLock.lock();
+    }
+
+    m_timerWorkItemsLock.unlock();
+}
+
 void WorkQueue::sendMessageToThread(const char* message)
 {
     if (write(m_writeToPipeDescriptor, message, threadMessageSize) == -1)
@@ -115,6 +178,7 @@
 {
     while (workQueue->m_threadLoop) {
         workQueue->performWork();
+        workQueue->performTimerWork();
         workQueue->performFileDescriptorWork();
     }
 
@@ -153,21 +217,16 @@
     sendMessageToThread(wakupThreadMessage);
 }
 
-bool WorkQueue::timerFired(void* data)
+void WorkQueue::dispatchAfterDelay(const Function<void()>& function, double delay)
 {
-    TimerWorkItem* item = static_cast<TimerWorkItem*>(data);
-    if (item && item->queue()->m_isValid) {
-        item->queue()->dispatch(item->function());
-        item->queue()->m_timers.take(item->timerID());
-        delete item;
-    }
+    if (delay < 0)
+        return;
 
-    return ECORE_CALLBACK_CANCEL;
-}
+    MutexLocker locker(m_timerWorkItemsLock);
+    OwnPtr<TimerWorkItem> timerWorkItem = TimerWorkItem::create(function, currentTime() + delay);
+    if (!timerWorkItem)
+        return;
 
-void WorkQueue::dispatchAfterDelay(const Function<void()>& function, double delay)
-{
-    static int timerId = 1;
-    m_timers.set(timerId, adoptPtr(ecore_timer_add(delay, reinterpret_cast<Ecore_Task_Cb>(timerFired), new TimerWorkItem(timerId, function, this))));
-    timerId++;
+    insertTimerWorkItem(timerWorkItem.release());
+    sendMessageToThread(wakupThreadMessage);
 }
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
http://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to