Changeset 128289 in webkit


Ignore:
Timestamp:
Sep 12, 2012 3:20:00 AM (12 years ago)
Author:
commit-queue@webkit.org
Message:

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

Patch by Byungwoo Lee <bw80.lee@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):

Location:
trunk/Source/WebKit2
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebKit2/ChangeLog

    r128280 r128289  
     12012-09-12  Byungwoo Lee  <bw80.lee@samsung.com>
     2
     3        [EFL][WK2] WorkQueue::dispatchAfterDelay() doesn't work properly.
     4        https://bugs.webkit.org/show_bug.cgi?id=91179
     5
     6        Reviewed by Gyuyoung Kim.
     7
     8        When UI Process is crashed and WebProcess's ecore main loop is very
     9        busy or lockup also, watchdocCallback() function in the
     10        ChildProcess.cpp doesn't triggered. And this is because of that
     11        WorkQueue::dispatchAfterDelay() function uses ecore timer for getting
     12        timer event.
     13
     14        For removing the dependency between the dispatchAfterDelay() and ecore
     15        main loop, new timer event mechanism is added to WorkQueue main loop.
     16
     17        * Platform/WorkQueue.h:
     18        (TimerWorkItem):
     19        (WorkQueue::TimerWorkItem::dispatch):
     20        (WorkQueue::TimerWorkItem::expireTime):
     21        (WorkQueue::TimerWorkItem::expired):
     22        (WorkQueue):
     23        * Platform/efl/WorkQueueEfl.cpp:
     24        (WorkQueue::TimerWorkItem::create):
     25        (WorkQueue::TimerWorkItem::TimerWorkItem):
     26        (WorkQueue::performFileDescriptorWork):
     27        (WorkQueue::getCurrentTime):
     28        (WorkQueue::getNextTimeOut):
     29        (WorkQueue::performTimerWork):
     30        (WorkQueue::workQueueThread):
     31        (WorkQueue::dispatchAfterDelay):
     32
    1332012-09-12  Christophe Dumez  <christophe.dumez@intel.com>
    234
  • trunk/Source/WebKit2/Platform/WorkQueue.h

    r127983 r128289  
    188188    typedef HashMap<int, Vector<EventSource*> >::iterator EventSourceIterator;
    189189#elif PLATFORM(EFL)
     190    class TimerWorkItem {
     191    public:
     192        static PassOwnPtr<TimerWorkItem> create(Function<void()>, double expireTime);
     193        void dispatch() { m_function(); }
     194        double expireTime() const { return m_expireTime; }
     195        bool expired(double currentTime) const { return currentTime >= m_expireTime; }
     196
     197    protected:
     198        TimerWorkItem(Function<void()>, double expireTime);
     199
     200    private:
     201        Function<void()> m_function;
     202        double m_expireTime;
     203    };
     204
    190205    fd_set m_fileDescriptorSet;
    191206    int m_maxFileDescriptor;
     
    200215    Function<void()> m_socketEventHandler;
    201216
    202     HashMap<int, OwnPtr<Ecore_Timer> > m_timers;
     217    Vector<OwnPtr<TimerWorkItem> > m_timerWorkItems;
     218    Mutex m_timerWorkItemsLock;
    203219
    204220    void sendMessageToThread(const char*);
     
    206222    void performWork();
    207223    void performFileDescriptorWork();
    208     static bool timerFired(void*);
     224    static double getCurrentTime();
     225    struct timeval* getNextTimeOut();
     226    void performTimerWork();
     227    void insertTimerWorkItem(PassOwnPtr<TimerWorkItem>);
    209228#endif
    210229};
  • trunk/Source/WebKit2/Platform/efl/WorkQueueEfl.cpp

    r122136 r128289  
    2121#include "WorkQueue.h"
    2222
     23#include <sys/timerfd.h>
    2324#include <wtf/Assertions.h>
    24 
    25 class TimerWorkItem {
    26 public:
    27     TimerWorkItem(int timerID, const Function<void()>& function, WorkQueue* queue)
    28         : m_function(function)
    29         , m_queue(queue)
    30         , m_timerID(timerID)
    31     {
    32     }
    33     ~TimerWorkItem() { }
    34 
    35     Function<void()> function() const { return m_function; }
    36     WorkQueue* queue() const { return m_queue; }
    37 
    38     int timerID() const { return m_timerID; }
    39 
    40 private:
    41     Function<void()> m_function;
    42     WorkQueue* m_queue;
    43     int m_timerID;
    44 };
     25#include <wtf/CurrentTime.h>
    4526
    4627static const int invalidSocketDescriptor = -1;
     
    4829static const char finishThreadMessage[] = "F";
    4930static const char wakupThreadMessage[] = "W";
     31
     32PassOwnPtr<WorkQueue::TimerWorkItem> WorkQueue::TimerWorkItem::create(Function<void()> function, double expireTime)
     33{
     34    if (expireTime < 0)
     35        return nullptr;
     36
     37    return adoptPtr(new TimerWorkItem(function, expireTime));
     38}
     39
     40WorkQueue::TimerWorkItem::TimerWorkItem(Function<void()> function, double expireTime)
     41    : m_function(function)
     42    , m_expireTime(expireTime)
     43{
     44}
    5045
    5146void WorkQueue::platformInitialize(const char* name)
     
    9287    fd_set readFileDescriptorSet = m_fileDescriptorSet;
    9388
    94     if (select(m_maxFileDescriptor + 1, &readFileDescriptorSet, 0, 0, 0) >= 0) {
     89    if (select(m_maxFileDescriptor + 1, &readFileDescriptorSet, 0, 0, getNextTimeOut()) >= 0) {
    9590        if (FD_ISSET(m_readFromPipeDescriptor, &readFileDescriptorSet)) {
    9691            char readBuf[threadMessageSize];
     
    106101}
    107102
     103struct timeval* WorkQueue::getNextTimeOut()
     104{
     105    MutexLocker locker(m_timerWorkItemsLock);
     106    if (m_timerWorkItems.isEmpty())
     107        return 0;
     108
     109    static struct timeval timeValue;
     110    timeValue.tv_sec = 0;
     111    timeValue.tv_usec = 0;
     112    double timeOut = m_timerWorkItems[0]->expireTime() - currentTime();
     113    if (timeOut > 0) {
     114        timeValue.tv_sec = static_cast<long>(timeOut);
     115        timeValue.tv_usec = static_cast<long>((timeOut - timeValue.tv_sec) * 1000000);
     116    }
     117
     118    return &timeValue;
     119}
     120
     121void WorkQueue::insertTimerWorkItem(PassOwnPtr<TimerWorkItem> item)
     122{
     123    if (!item)
     124        return;
     125
     126    size_t position = 0;
     127
     128    // m_timerWorkItems should be ordered by expire time.
     129    for (; position < m_timerWorkItems.size(); ++position)
     130        if (item->expireTime() < m_timerWorkItems[position]->expireTime())
     131            break;
     132
     133    m_timerWorkItems.insert(position, item);
     134}
     135
     136void WorkQueue::performTimerWork()
     137{
     138    // Protects m_timerWorkItems.
     139    m_timerWorkItemsLock.lock();
     140
     141    if (m_timerWorkItems.isEmpty()) {
     142        m_timerWorkItemsLock.unlock();
     143        return;
     144    }
     145
     146    double current = currentTime();
     147    Vector<OwnPtr<TimerWorkItem> > timerWorkItems;
     148
     149    // Copies all the timer work items in m_timerWorkItems to local vector.
     150    m_timerWorkItems.swap(timerWorkItems);
     151
     152    for (size_t i = 0; i < timerWorkItems.size(); ++i) {
     153        if (!timerWorkItems[i]->expired(current)) {
     154            // If a timer work item does not expired, keep it to the m_timerWorkItems.
     155            // m_timerWorkItems should be ordered by expire time.
     156            insertTimerWorkItem(timerWorkItems[i].release());
     157            continue;
     158        }
     159
     160        // If a timer work item expired, dispatch the function of the work item.
     161        // Before dispatching, m_timerWorkItemsLock should unlock for preventing deadlock,
     162        // because it can be accessed inside the function of the timer work item dispatched.
     163        m_timerWorkItemsLock.unlock();
     164        timerWorkItems[i]->dispatch();
     165        m_timerWorkItemsLock.lock();
     166    }
     167
     168    m_timerWorkItemsLock.unlock();
     169}
     170
    108171void WorkQueue::sendMessageToThread(const char* message)
    109172{
     
    116179    while (workQueue->m_threadLoop) {
    117180        workQueue->performWork();
     181        workQueue->performTimerWork();
    118182        workQueue->performFileDescriptorWork();
    119183    }
     
    154218}
    155219
    156 bool WorkQueue::timerFired(void* data)
    157 {
    158     TimerWorkItem* item = static_cast<TimerWorkItem*>(data);
    159     if (item && item->queue()->m_isValid) {
    160         item->queue()->dispatch(item->function());
    161         item->queue()->m_timers.take(item->timerID());
    162         delete item;
    163     }
    164 
    165     return ECORE_CALLBACK_CANCEL;
    166 }
    167 
    168220void WorkQueue::dispatchAfterDelay(const Function<void()>& function, double delay)
    169221{
    170     static int timerId = 1;
    171     m_timers.set(timerId, adoptPtr(ecore_timer_add(delay, reinterpret_cast<Ecore_Task_Cb>(timerFired), new TimerWorkItem(timerId, function, this))));
    172     timerId++;
    173 }
     222    if (delay < 0)
     223        return;
     224
     225    MutexLocker locker(m_timerWorkItemsLock);
     226    OwnPtr<TimerWorkItem> timerWorkItem = TimerWorkItem::create(function, currentTime() + delay);
     227    if (!timerWorkItem)
     228        return;
     229
     230    insertTimerWorkItem(timerWorkItem.release());
     231    sendMessageToThread(wakupThreadMessage);
     232}
Note: See TracChangeset for help on using the changeset viewer.