Changeset 225660 in webkit
- Timestamp:
- Dec 7, 2017 5:26:27 PM (6 years ago)
- Location:
- trunk/Source
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WTF/ChangeLog
r225659 r225660 1 2017-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 1 13 2017-12-07 Mark Lam <mark.lam@apple.com> 2 14 -
trunk/Source/WTF/wtf/ThreadSpecific.h
r223617 r225660 102 102 // needs to access the value, to avoid recursion. 103 103 owner->setInTLS(this); 104 new (NotNull, storagePointer()) T ;104 new (NotNull, storagePointer()) T(); 105 105 } 106 106 -
trunk/Source/WebCore/ChangeLog
r225657 r225660 1 2017-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 1 39 2017-12-07 Alex Christensen <achristensen@webkit.org> 2 40 -
trunk/Source/WebCore/platform/ios/wak/WebCoreThread.mm
r225529 r225660 43 43 #import <wtf/Assertions.h> 44 44 #import <wtf/MainThread.h> 45 #import <wtf/RecursiveLockAdapter.h> 45 46 #import <wtf/RunLoop.h> 46 47 #import <wtf/Threading.h> … … 57 58 58 59 #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 61 static const constexpr Seconds DelegateWaitInterval { 10_s }; 62 63 static void _WebThreadAutoLock(); 64 static void _WebThreadLock(); 65 65 static void _WebThreadLockFromAnyThread(bool shouldLog); 66 static void _WebThreadUnlock( void);66 static void _WebThreadUnlock(); 67 67 68 68 @interface NSObject(ForwardDeclarations) … … 92 92 #endif 93 93 94 static int WebTimedConditionLock(pthread_cond_t* condition, pthread_mutex_t* lock, CFAbsoluteTime interval); 95 96 static pthread_mutex_t webLock; 94 using StaticRecursiveLock = WTF::RecursiveLockAdapter<StaticLock>; 95 96 static StaticRecursiveLock webLock; 97 static StaticLock webThreadReleaseLock; 98 static StaticRecursiveLock webCoreReleaseLock; 99 97 100 static NSAutoreleasePoolMark autoreleasePoolMark; 98 101 static CFRunLoopRef webThreadRunLoop; … … 110 113 } AutoreleasePoolOperation; 111 114 112 static pthread_mutex_t WebThreadReleaseLock = PTHREAD_MUTEX_INITIALIZER;113 115 static CFRunLoopSourceRef WebThreadReleaseSource; 114 116 static CFMutableArrayRef WebThreadReleaseObjArray; … … 116 118 static void MainThreadAdoptAndRelease(id obj); 117 119 118 static pthread_mutex_t delegateLock = PTHREAD_MUTEX_INITIALIZER;119 static pthread_cond_t delegateCondition = PTHREAD_COND_INITIALIZER;120 static StaticLock delegateLock; 121 static StaticCondition delegateCondition; 120 122 static NSInvocation* delegateInvocation; 121 123 static CFRunLoopSourceRef delegateSource = nullptr; … … 131 133 132 134 static WebThreadContext* webThreadContext; 133 static pthread_key_t threadContextKey;134 135 static unsigned mainThreadLockCount; 135 136 static unsigned otherThreadLockCount; … … 138 139 WEBCORE_EXPORT volatile bool webThreadShouldYield; 139 140 140 static pthread_mutex_t WebCoreReleaseLock;141 141 static void WebCoreObjCDeallocOnWebThreadImpl(id self, SEL _cmd); 142 142 static void WebCoreObjCDeallocWithWebThreadLock(Class cls); … … 161 161 _WebThreadAutoLock(); 162 162 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); 165 165 166 166 #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 } 182 180 183 181 #if LOG_MAIN_THREAD_LOCKING … … 194 192 195 193 ASSERT(delegateSource); 196 int result = pthread_mutex_lock(&delegateLock); 197 ASSERT_WITH_MESSAGE(!result, "delegate lock failed with code:%d", result); 194 delegateLock.lock(); 198 195 199 196 delegateInvocation = invocation; … … 218 215 219 216 while (!delegateHandled) { 220 if ( WebTimedConditionLock(&delegateCondition, &delegateLock, DelegateWaitInterval)) {217 if (!delegateCondition.waitFor(delegateLock, DelegateWaitInterval)) { 221 218 id delegateInformation; 222 219 if ([[delegateInvocation target] isKindOfClass:[NSNotificationCenter class]]) … … 226 223 227 224 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); 229 226 if (mode) 230 227 CFRelease(mode); 231 228 } 232 229 } 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(); 237 232 } 238 233 } … … 253 248 Block_release(delegateBlockCopy); 254 249 255 _WebT ryThreadLock(false);250 _WebThreadLock(); 256 251 } 257 252 … … 282 277 #endif 283 278 284 int result = pthread_mutex_lock(&WebThreadReleaseLock); 285 ASSERT_WITH_MESSAGE(!result, "Release lock failed with code:%d", result); 279 auto locker = holdLock(webThreadReleaseLock); 286 280 287 281 if (WebThreadReleaseObjArray == nil) … … 290 284 CFRunLoopSourceSignal(WebThreadReleaseSource); 291 285 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);307 286 } 308 287 … … 366 345 } 367 346 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 } 370 356 // 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()) 381 360 [self _webcore_releaseOnWebThread]; 382 unlockWebCoreReleaseLock();383 }361 else 362 WebThreadAdoptAndRelease(self); 384 363 } 385 364 386 365 void WebCoreObjCDeallocWithWebThreadLockImpl(id self, SEL) 387 366 { 388 lockWebCoreReleaseLock();367 auto locker = holdLock(webCoreReleaseLock); 389 368 if (WebThreadIsLockedOrDisabled() || 1 != [self retainCount]) 390 369 [self _webcore_releaseWithWebThreadLock]; 391 370 else 392 371 WebThreadAdoptAndRelease(self); 393 unlockWebCoreReleaseLock();394 372 } 395 373 … … 398 376 ASSERT(WebThreadIsCurrent()); 399 377 400 int result = pthread_mutex_lock(&WebThreadReleaseLock);401 ASSERT_WITH_MESSAGE(!result, "Release lock failed with code:%d", result);402 403 378 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 } 411 386 412 387 if (!objects) … … 483 458 if (!mainThreadLockCount) { 484 459 CFRunLoopAddObserver(CFRunLoopGetCurrent(), mainRunLoopAutoUnlockObserver, kCFRunLoopCommonModes); 485 _WebT ryThreadLock(false);460 _WebThreadLock(); 486 461 CFRunLoopWakeUp(CFRunLoopGetMain()); 487 462 } … … 490 465 static void WebRunLoopLockInternal(AutoreleasePoolOperation poolOperation) 491 466 { 492 _WebT ryThreadLock(false);467 _WebThreadLock(); 493 468 if (poolOperation == PushOrPopAutoreleasePool) 494 469 autoreleasePoolMark = NSPushAutoreleasePool(0); … … 594 569 } 595 570 596 static WebThreadContext* CurrentThreadContext(void) 571 static ThreadSpecific<WebThreadContext, WTF::CanBeGCThread::True>* threadContext; 572 static WebThreadContext* CurrentThreadContext() 597 573 { 598 574 static std::once_flag flag; 599 575 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>(); 605 577 }); 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; 613 579 } 614 580 … … 682 648 WebCoreObjCDeallocWithWebThreadLock([WAKView class]); 683 649 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 696 650 CFRunLoopRef runLoop = CFRunLoopGetCurrent(); 697 651 CFRunLoopSourceContext delegateSourceContext = {0, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, HandleDelegateSource}; … … 736 690 } 737 691 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 748 692 #if LOG_WEB_LOCK || LOG_MAIN_THREAD_LOCKING 749 693 static unsigned lockCount; 750 694 #endif 751 695 752 static bool _WebTryThreadLock(bool shouldTry)696 static void _WebThreadLock() 753 697 { 754 698 // Suspend the web thread if the main thread is trying to lock. … … 760 704 CRASH(); 761 705 } 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 771 723 } 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(); 797 728 } 798 729 } 799 800 return !busy;801 730 } 802 731 … … 836 765 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()); 837 766 838 pthread_mutex_lock(&webLock);839 767 webLock.lock(); 768 840 769 // This used for any thread other than the web thread. 841 770 otherThreadLockCount++; … … 854 783 ASSERT(otherThreadLockCount); 855 784 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(); 859 787 } 860 788 … … 868 796 } 869 797 870 void _WebThreadUnlock( void)798 void _WebThreadUnlock() 871 799 { 872 800 #if LOG_WEB_LOCK || LOG_MAIN_THREAD_LOCKING … … 884 812 webThreadShouldYield = false; 885 813 } 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(); 889 816 } 890 817
Note: See TracChangeset
for help on using the changeset viewer.