Changeset 225660 in webkit


Ignore:
Timestamp:
Dec 7, 2017 5:26:27 PM (6 years ago)
Author:
Yusuke Suzuki
Message:

Use WTF Locking primitives in WebThread and drop pthread_xxx use
https://bugs.webkit.org/show_bug.cgi?id=180445

Reviewed by Saam Barati.

Source/WebCore:

We remove use of pthread locking primitives from WebThread implementation,
and use WTF Lock and Condition instead.

No behavior change.

  • platform/ios/wak/WebCoreThread.mm:

(HandleDelegateSource):
(SendDelegateMessage):
(WebThreadRunOnMainThread):
(WebThreadAdoptAndRelease):
(WebCoreObjCDeallocOnWebThreadImpl):
(WebCoreObjCDeallocWithWebThreadLockImpl):
(HandleWebThreadReleaseSource):
(_WebThreadAutoLock):
(WebRunLoopLockInternal):
(CurrentThreadContext):
Use WTF::ThreadSpecific.

(StartWebThread):
(_WebThreadLock):
Remove shouldTry parameter since it is always false. We clean up code based on shouldTry = false,
and rename it from _WebTryThreadLock to _WebThreadLock since it does not try now.

(_WebThreadLockFromAnyThread):
(WebThreadUnlockFromAnyThread):
(_WebThreadUnlock):
(lockWebCoreReleaseLock): Deleted.
(unlockWebCoreReleaseLock): Deleted.
(WebTimedConditionLock): Deleted.
(_WebTryThreadLock): Deleted.

Source/WTF:

Add initializer form to fill struct with zero if struct does not have any default initializers.

  • wtf/ThreadSpecific.h:

(WTF::ThreadSpecific::Data::Data):

Location:
trunk/Source
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WTF/ChangeLog

    r225659 r225660  
     12017-12-07  Yusuke Suzuki  <utatane.tea@gmail.com>
     2
     3        Use WTF Locking primitives in WebThread and drop pthread_xxx use
     4        https://bugs.webkit.org/show_bug.cgi?id=180445
     5
     6        Reviewed by Saam Barati.
     7
     8        Add initializer form to fill struct with zero if struct does not have any default initializers.
     9
     10        * wtf/ThreadSpecific.h:
     11        (WTF::ThreadSpecific::Data::Data):
     12
    1132017-12-07  Mark Lam  <mark.lam@apple.com>
    214
  • trunk/Source/WTF/wtf/ThreadSpecific.h

    r223617 r225660  
    102102            // needs to access the value, to avoid recursion.
    103103            owner->setInTLS(this);
    104             new (NotNull, storagePointer()) T;
     104            new (NotNull, storagePointer()) T();
    105105        }
    106106
  • trunk/Source/WebCore/ChangeLog

    r225657 r225660  
     12017-12-07  Yusuke Suzuki  <utatane.tea@gmail.com>
     2
     3        Use WTF Locking primitives in WebThread and drop pthread_xxx use
     4        https://bugs.webkit.org/show_bug.cgi?id=180445
     5
     6        Reviewed by Saam Barati.
     7
     8        We remove use of pthread locking primitives from WebThread implementation,
     9        and use WTF Lock and Condition instead.
     10
     11        No behavior change.
     12
     13        * platform/ios/wak/WebCoreThread.mm:
     14        (HandleDelegateSource):
     15        (SendDelegateMessage):
     16        (WebThreadRunOnMainThread):
     17        (WebThreadAdoptAndRelease):
     18        (WebCoreObjCDeallocOnWebThreadImpl):
     19        (WebCoreObjCDeallocWithWebThreadLockImpl):
     20        (HandleWebThreadReleaseSource):
     21        (_WebThreadAutoLock):
     22        (WebRunLoopLockInternal):
     23        (CurrentThreadContext):
     24        Use WTF::ThreadSpecific.
     25
     26        (StartWebThread):
     27        (_WebThreadLock):
     28        Remove `shouldTry` parameter since it is always `false`. We clean up code based on `shouldTry = false`,
     29        and rename it from _WebTryThreadLock to _WebThreadLock since it does not try now.
     30
     31        (_WebThreadLockFromAnyThread):
     32        (WebThreadUnlockFromAnyThread):
     33        (_WebThreadUnlock):
     34        (lockWebCoreReleaseLock): Deleted.
     35        (unlockWebCoreReleaseLock): Deleted.
     36        (WebTimedConditionLock): Deleted.
     37        (_WebTryThreadLock): Deleted.
     38
    1392017-12-07  Alex Christensen  <achristensen@webkit.org>
    240
  • trunk/Source/WebCore/platform/ios/wak/WebCoreThread.mm

    r225529 r225660  
    4343#import <wtf/Assertions.h>
    4444#import <wtf/MainThread.h>
     45#import <wtf/RecursiveLockAdapter.h>
    4546#import <wtf/RunLoop.h>
    4647#import <wtf/Threading.h>
     
    5758
    5859#define DistantFuture   (86400.0 * 2000 * 365.2425 + 86400.0)   // same as +[NSDate distantFuture]
    59 #define MaxArgCount         5
    60 #define DrawWaitInterval     10
    61 #define DelegateWaitInterval 10
    62 
    63 static void _WebThreadAutoLock(void);
    64 static bool _WebTryThreadLock(bool shouldTry);
     60
     61static const constexpr Seconds DelegateWaitInterval { 10_s };
     62
     63static void _WebThreadAutoLock();
     64static void _WebThreadLock();
    6565static void _WebThreadLockFromAnyThread(bool shouldLog);
    66 static void _WebThreadUnlock(void);
     66static void _WebThreadUnlock();
    6767
    6868@interface NSObject(ForwardDeclarations)
     
    9292#endif
    9393
    94 static int WebTimedConditionLock(pthread_cond_t* condition, pthread_mutex_t* lock, CFAbsoluteTime interval);
    95 
    96 static pthread_mutex_t webLock;
     94using StaticRecursiveLock = WTF::RecursiveLockAdapter<StaticLock>;
     95
     96static StaticRecursiveLock webLock;
     97static StaticLock webThreadReleaseLock;
     98static StaticRecursiveLock webCoreReleaseLock;
     99
    97100static NSAutoreleasePoolMark autoreleasePoolMark;
    98101static CFRunLoopRef webThreadRunLoop;
     
    110113} AutoreleasePoolOperation;
    111114
    112 static pthread_mutex_t WebThreadReleaseLock = PTHREAD_MUTEX_INITIALIZER;
    113115static CFRunLoopSourceRef WebThreadReleaseSource;
    114116static CFMutableArrayRef WebThreadReleaseObjArray;
     
    116118static void MainThreadAdoptAndRelease(id obj);
    117119
    118 static pthread_mutex_t delegateLock = PTHREAD_MUTEX_INITIALIZER;
    119 static pthread_cond_t delegateCondition = PTHREAD_COND_INITIALIZER;
     120static StaticLock delegateLock;
     121static StaticCondition delegateCondition;
    120122static NSInvocation* delegateInvocation;
    121123static CFRunLoopSourceRef delegateSource = nullptr;
     
    131133
    132134static WebThreadContext* webThreadContext;
    133 static pthread_key_t threadContextKey;
    134135static unsigned mainThreadLockCount;
    135136static unsigned otherThreadLockCount;
     
    138139WEBCORE_EXPORT volatile bool webThreadShouldYield;
    139140
    140 static pthread_mutex_t WebCoreReleaseLock;
    141141static void WebCoreObjCDeallocOnWebThreadImpl(id self, SEL _cmd);
    142142static void WebCoreObjCDeallocWithWebThreadLock(Class cls);
     
    161161    _WebThreadAutoLock();
    162162
    163     int result = pthread_mutex_lock(&delegateLock);
    164     ASSERT_WITH_MESSAGE(!result, "delegate lock failed with code:%d", result);
     163    {
     164        auto locker = holdLock(delegateLock);
    165165
    166166#if LOG_MESSAGES
    167     if ([[delegateInvocation target] isKindOfClass:[NSNotificationCenter class]]) {
    168         id argument0;
    169         [delegateInvocation getArgument:&argument0 atIndex:0];
    170         NSLog(@"notification receive: %@", argument0);
    171     } else
    172         NSLog(@"delegate receive: %@", NSStringFromSelector([delegateInvocation selector]));
    173 #endif
    174 
    175     SendMessage(delegateInvocation);
    176 
    177     delegateHandled = YES;
    178     pthread_cond_signal(&delegateCondition);
    179 
    180     result = pthread_mutex_unlock(&delegateLock);
    181     ASSERT_WITH_MESSAGE(!result, "delegate unlock failed with code:%d", result);
     167        if ([[delegateInvocation target] isKindOfClass:[NSNotificationCenter class]]) {
     168            id argument0;
     169            [delegateInvocation getArgument:&argument0 atIndex:0];
     170            NSLog(@"notification receive: %@", argument0);
     171        } else
     172            NSLog(@"delegate receive: %@", NSStringFromSelector([delegateInvocation selector]));
     173#endif
     174
     175        SendMessage(delegateInvocation);
     176
     177        delegateHandled = YES;
     178        delegateCondition.notifyOne();
     179    }
    182180
    183181#if LOG_MAIN_THREAD_LOCKING
     
    194192
    195193    ASSERT(delegateSource);
    196     int result = pthread_mutex_lock(&delegateLock);
    197     ASSERT_WITH_MESSAGE(!result, "delegate lock failed with code:%d", result);
     194    delegateLock.lock();
    198195
    199196    delegateInvocation = invocation;
     
    218215
    219216        while (!delegateHandled) {
    220             if (WebTimedConditionLock(&delegateCondition, &delegateLock, DelegateWaitInterval)) {
     217            if (!delegateCondition.waitFor(delegateLock, DelegateWaitInterval)) {
    221218                id delegateInformation;
    222219                if ([[delegateInvocation target] isKindOfClass:[NSNotificationCenter class]])
     
    226223   
    227224                CFStringRef mode = CFRunLoopCopyCurrentMode(CFRunLoopGetMain());
    228                 NSLog(@"%s: delegate (%@) failed to return after waiting %d seconds. main run loop mode: %@", __PRETTY_FUNCTION__, delegateInformation, DelegateWaitInterval, mode);
     225                NSLog(@"%s: delegate (%@) failed to return after waiting %f seconds. main run loop mode: %@", __PRETTY_FUNCTION__, delegateInformation, DelegateWaitInterval.seconds(), mode);
    229226                if (mode)
    230227                    CFRelease(mode);
    231228            }
    232229        }
    233         result = pthread_mutex_unlock(&delegateLock);
    234 
    235         ASSERT_WITH_MESSAGE(!result, "delegate unlock failed with code:%d", result);
    236         _WebTryThreadLock(false);
     230        delegateLock.unlock();
     231        _WebThreadLock();
    237232    }
    238233}
     
    253248    Block_release(delegateBlockCopy);
    254249
    255     _WebTryThreadLock(false);
     250    _WebThreadLock();
    256251}
    257252
     
    282277#endif       
    283278
    284     int result = pthread_mutex_lock(&WebThreadReleaseLock);
    285     ASSERT_WITH_MESSAGE(!result, "Release lock failed with code:%d", result);
     279    auto locker = holdLock(webThreadReleaseLock);
    286280
    287281    if (WebThreadReleaseObjArray == nil)
     
    290284    CFRunLoopSourceSignal(WebThreadReleaseSource);
    291285    CFRunLoopWakeUp(webThreadRunLoop);
    292 
    293     result = pthread_mutex_unlock(&WebThreadReleaseLock);   
    294     ASSERT_WITH_MESSAGE(!result, "Release unlock failed with code:%d", result);
    295 }
    296 
    297 static inline void lockWebCoreReleaseLock()
    298 {
    299     int lockcode = pthread_mutex_lock(&WebCoreReleaseLock);
    300     ASSERT_WITH_MESSAGE_UNUSED(lockcode, !lockcode, "WebCoreReleaseLock lock failed with code:%d", lockcode);
    301 }
    302 
    303 static inline void unlockWebCoreReleaseLock()
    304 {
    305     int lockcode = pthread_mutex_unlock(&WebCoreReleaseLock);
    306     ASSERT_WITH_MESSAGE_UNUSED(lockcode, !lockcode, "WebCoreReleaseLock unlock failed with code:%d", lockcode);
    307286}
    308287
     
    366345    }
    367346
    368     lockWebCoreReleaseLock();
    369     if ([self retainCount] == 1) {
     347    {
     348        auto locker = holdLock(webCoreReleaseLock);
     349        if ([self retainCount] != 1) {
     350            // This is not the only reference retaining the object, so another
     351            // thread could also call release - hold the lock whilst calling
     352            // release to avoid a race condition.
     353            [self _webcore_releaseOnWebThread];
     354            return;
     355        }
    370356        // This is the only reference retaining the object, so we can
    371         // safely release the WebCoreReleaseLock now.
    372         unlockWebCoreReleaseLock();
    373         if (WebThreadIsCurrent())
    374             [self _webcore_releaseOnWebThread];
    375         else
    376             WebThreadAdoptAndRelease(self);
    377     } else {
    378         // This is not the only reference retaining the object, so another
    379         // thread could also call release - hold the lock whilst calling
    380         // release to avoid a race condition.
     357        // safely release the webCoreReleaseLock now.
     358    }
     359    if (WebThreadIsCurrent())
    381360        [self _webcore_releaseOnWebThread];
    382         unlockWebCoreReleaseLock();
    383     }
     361    else
     362        WebThreadAdoptAndRelease(self);
    384363}
    385364
    386365void WebCoreObjCDeallocWithWebThreadLockImpl(id self, SEL)
    387366{
    388     lockWebCoreReleaseLock();
     367    auto locker = holdLock(webCoreReleaseLock);
    389368    if (WebThreadIsLockedOrDisabled() || 1 != [self retainCount])
    390369        [self _webcore_releaseWithWebThreadLock];
    391370    else
    392371        WebThreadAdoptAndRelease(self);
    393     unlockWebCoreReleaseLock();
    394372}
    395373
     
    398376    ASSERT(WebThreadIsCurrent());
    399377
    400     int result = pthread_mutex_lock(&WebThreadReleaseLock);
    401     ASSERT_WITH_MESSAGE(!result, "Release lock failed with code:%d", result);
    402 
    403378    CFMutableArrayRef objects = nullptr;
    404     if (CFArrayGetCount(WebThreadReleaseObjArray)) {
    405         objects = CFArrayCreateMutableCopy(nullptr, 0, WebThreadReleaseObjArray);
    406         CFArrayRemoveAllValues(WebThreadReleaseObjArray);
    407     }
    408 
    409     result = pthread_mutex_unlock(&WebThreadReleaseLock);
    410     ASSERT_WITH_MESSAGE(!result, "Release unlock failed with code:%d", result);
     379    {
     380        auto locker = holdLock(webThreadReleaseLock);
     381        if (CFArrayGetCount(WebThreadReleaseObjArray)) {
     382            objects = CFArrayCreateMutableCopy(nullptr, 0, WebThreadReleaseObjArray);
     383            CFArrayRemoveAllValues(WebThreadReleaseObjArray);
     384        }
     385    }
    411386
    412387    if (!objects)
     
    483458    if (!mainThreadLockCount) {
    484459        CFRunLoopAddObserver(CFRunLoopGetCurrent(), mainRunLoopAutoUnlockObserver, kCFRunLoopCommonModes);   
    485         _WebTryThreadLock(false);
     460        _WebThreadLock();
    486461        CFRunLoopWakeUp(CFRunLoopGetMain());
    487462    }
     
    490465static void WebRunLoopLockInternal(AutoreleasePoolOperation poolOperation)
    491466{
    492     _WebTryThreadLock(false);
     467    _WebThreadLock();
    493468    if (poolOperation == PushOrPopAutoreleasePool)
    494469        autoreleasePoolMark = NSPushAutoreleasePool(0);
     
    594569}
    595570
    596 static WebThreadContext* CurrentThreadContext(void)
     571static ThreadSpecific<WebThreadContext, WTF::CanBeGCThread::True>* threadContext;
     572static WebThreadContext* CurrentThreadContext()
    597573{
    598574    static std::once_flag flag;
    599575    std::call_once(flag, [] {
    600         int error = pthread_key_create(&threadContextKey, [] (void* threadContext) {
    601             if (threadContext)
    602                 free(threadContext);
    603         });
    604         RELEASE_ASSERT(!error);
     576        threadContext = new ThreadSpecific<WebThreadContext, WTF::CanBeGCThread::True>();
    605577    });
    606 
    607     WebThreadContext* threadContext = (WebThreadContext*)pthread_getspecific(threadContextKey);
    608     if (!threadContext) {
    609         threadContext = static_cast<WebThreadContext*>(calloc(sizeof(WebThreadContext), 1));
    610         pthread_setspecific(threadContextKey, threadContext);
    611     }       
    612     return threadContext;
     578    return *threadContext;
    613579}
    614580
     
    682648    WebCoreObjCDeallocWithWebThreadLock([WAKView class]);
    683649
    684     pthread_mutexattr_t mattr;
    685     pthread_mutexattr_init(&mattr);
    686     pthread_mutexattr_settype(&mattr, PTHREAD_MUTEX_RECURSIVE);
    687     pthread_mutex_init(&webLock, &mattr);
    688     pthread_mutexattr_destroy(&mattr);           
    689 
    690     pthread_mutexattr_t mutex_attr;
    691     pthread_mutexattr_init(&mutex_attr);
    692     pthread_mutexattr_settype(&mutex_attr, PTHREAD_MUTEX_RECURSIVE);   
    693     pthread_mutex_init(&WebCoreReleaseLock, &mutex_attr);
    694     pthread_mutexattr_destroy(&mutex_attr);
    695 
    696650    CFRunLoopRef runLoop = CFRunLoopGetCurrent();
    697651    CFRunLoopSourceContext delegateSourceContext = {0, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, HandleDelegateSource};
     
    736690}
    737691
    738 static int WebTimedConditionLock(pthread_cond_t* condition, pthread_mutex_t* lock, CFAbsoluteTime interval)
    739 {
    740     struct timespec time;
    741     CFAbsoluteTime at = CFAbsoluteTimeGetCurrent() + interval;
    742     time.tv_sec = (time_t)(floor(at) + kCFAbsoluteTimeIntervalSince1970);
    743     time.tv_nsec = (int32_t)((at - floor(at)) * 1000000000.0);       
    744     return pthread_cond_timedwait(condition, lock, &time);
    745 }
    746 
    747 
    748692#if LOG_WEB_LOCK || LOG_MAIN_THREAD_LOCKING
    749693static unsigned lockCount;
    750694#endif
    751695
    752 static bool _WebTryThreadLock(bool shouldTry)
     696static void _WebThreadLock()
    753697{
    754698    // Suspend the web thread if the main thread is trying to lock.
     
    760704        CRASH();
    761705    }
    762        
    763            
    764     bool busy = false;
    765     if (shouldTry) {
    766         int result = pthread_mutex_trylock(&webLock);
    767         if (result == EBUSY)
    768             busy = true;
    769         else
    770             ASSERT_WITH_MESSAGE(!result, "try web lock failed with code:%d", result);
     706
     707    webLock.lock();
     708
     709#if LOG_WEB_LOCK || LOG_MAIN_THREAD_LOCKING
     710    lockCount++;
     711#if LOG_WEB_LOCK
     712    NSLog(@"lock   %d, web-thread: %d", lockCount, WebThreadIsCurrent());
     713#endif
     714#endif
     715    if (onMainThread) {
     716        ASSERT(CFRunLoopGetCurrent() == CFRunLoopGetMain());
     717        webThreadShouldYield = false;
     718        mainThreadLockCount++;
     719#if LOG_MAIN_THREAD_LOCKING
     720        if (!sendingDelegateMessage && lockCount == 1)
     721            NSLog(@"Main thread locking outside of delegate messages.");
     722#endif
    771723    } else {
    772         int result = pthread_mutex_lock(&webLock);
    773         ASSERT_WITH_MESSAGE_UNUSED(result, !result, "web lock failed with code:%d", result);
    774     }
    775    
    776     if (!busy) {
    777 #if LOG_WEB_LOCK || LOG_MAIN_THREAD_LOCKING
    778         lockCount++;
    779 #if LOG_WEB_LOCK
    780         NSLog(@"lock   %d, web-thread: %d", lockCount, WebThreadIsCurrent());
    781 #endif
    782 #endif
    783         if (onMainThread) {
    784             ASSERT(CFRunLoopGetCurrent() == CFRunLoopGetMain());
    785             webThreadShouldYield = false;
    786             mainThreadLockCount++;
    787 #if LOG_MAIN_THREAD_LOCKING
    788             if (!sendingDelegateMessage && lockCount == 1)
    789                 NSLog(@"Main thread locking outside of delegate messages.");
    790 #endif
    791         } else {
    792             webThreadLockCount++;
    793             if (webThreadLockCount > 1) {
    794                 NSLog(@"%s, %p: Multiple locks on web thread not allowed! Please file a bug. Crashing now...", __PRETTY_FUNCTION__, CurrentThreadContext());
    795                 CRASH();
    796             }
     724        webThreadLockCount++;
     725        if (webThreadLockCount > 1) {
     726            NSLog(@"%s, %p: Multiple locks on web thread not allowed! Please file a bug. Crashing now...", __PRETTY_FUNCTION__, CurrentThreadContext());
     727            CRASH();
    797728        }
    798729    }
    799    
    800     return !busy;
    801730}
    802731
     
    836765        NSLog(@"%s, %p: Obtaining the web lock from a thread other than the main thread or the web thread. UIKit should not be called from a secondary thread.", __PRETTY_FUNCTION__, CurrentThreadContext());
    837766
    838     pthread_mutex_lock(&webLock);
    839    
     767    webLock.lock();
     768
    840769    // This used for any thread other than the web thread.
    841770    otherThreadLockCount++;
     
    854783    ASSERT(otherThreadLockCount);
    855784    otherThreadLockCount--;
    856    
    857     int result = pthread_mutex_unlock(&webLock);
    858     ASSERT_WITH_MESSAGE_UNUSED(result, !result, "web unlock failed with code:%d", result);
     785
     786    webLock.unlock();
    859787}
    860788
     
    868796}
    869797
    870 void _WebThreadUnlock(void)
     798void _WebThreadUnlock()
    871799{
    872800#if LOG_WEB_LOCK || LOG_MAIN_THREAD_LOCKING
     
    884812        webThreadShouldYield = false;
    885813    }
    886    
    887     int result = pthread_mutex_unlock(&webLock);
    888     ASSERT_WITH_MESSAGE_UNUSED(result, !result, "web unlock failed with code:%d", result);   
     814
     815    webLock.unlock();
    889816}
    890817
Note: See TracChangeset for help on using the changeset viewer.