Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(248)

Side by Side Diff: Source/platform/heap/HeapTest.cpp

Issue 415083002: [oilpan]: fix deadlock when leaving a safepoint and sweeping. (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Created 6 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2013 Google Inc. All rights reserved. 2 * Copyright (C) 2013 Google Inc. All rights reserved.
3 * 3 *
4 * Redistribution and use in source and binary forms, with or without 4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are 5 * modification, are permitted provided that the following conditions are
6 * met: 6 * met:
7 * 7 *
8 * * Redistributions of source code must retain the above copyright 8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer. 9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above 10 * * Redistributions in binary form must reproduce the above
(...skipping 4854 matching lines...) Expand 10 before | Expand all | Expand 10 after
4865 4865
4866 // Regression test for out of bounds call through vtable. 4866 // Regression test for out of bounds call through vtable.
4867 // Passes if it doesn't crash. 4867 // Passes if it doesn't crash.
4868 TEST(HeapTest, GarbageCollectionDuringMixinConstruction) 4868 TEST(HeapTest, GarbageCollectionDuringMixinConstruction)
4869 { 4869 {
4870 ClassWithGarbageCollectingMixinConstructor* a = 4870 ClassWithGarbageCollectingMixinConstructor* a =
4871 new ClassWithGarbageCollectingMixinConstructor(); 4871 new ClassWithGarbageCollectingMixinConstructor();
4872 a->verify(); 4872 a->verify();
4873 } 4873 }
4874 4874
4875 static RecursiveMutex& recursiveMutex()
4876 {
4877 AtomicallyInitializedStatic(RecursiveMutex&, recursiveMutex = *new Recursive Mutex);
4878 return recursiveMutex;
4879 }
4880
4881 class DestructorLockingObject : public GarbageCollectedFinalized<DestructorLocki ngObject> {
4882 public:
4883 static DestructorLockingObject* create()
4884 {
4885 return new DestructorLockingObject();
4886 }
4887
4888 virtual ~DestructorLockingObject()
4889 {
4890 SafePointAwareMutexLocker lock(recursiveMutex());
4891 ++s_destructorCalls;
4892 }
4893
4894 static int s_destructorCalls;
4895 void trace(Visitor* visitor) { }
4896
4897 private:
4898 DestructorLockingObject() { }
4899 };
4900
4901 int DestructorLockingObject::s_destructorCalls = 0;
4902
4903 class RecursiveLockingTester {
4904 public:
4905 static void test()
4906 {
4907 DestructorLockingObject::s_destructorCalls = 0;
4908
4909 MutexLocker locker(mainThreadMutex());
4910 createThread(&workerThreadMain, 0, "Worker Thread");
4911
4912 // Park the main thread until the worker thread has initialized.
4913 parkMainThread();
4914
4915 {
4916 SafePointAwareMutexLocker recursiveLocker(recursiveMutex());
4917
4918 // Let the worker try to acquire the above mutex. It won't get it
4919 // until the main thread has done its GC.
4920 wakeWorkerThread();
4921
4922 Heap::collectGarbage(ThreadState::NoHeapPointersOnStack);
4923
4924 // The worker thread should not have swept yet since it is waiting
4925 // to get the global mutex.
4926 EXPECT_EQ(0, DestructorLockingObject::s_destructorCalls);
4927 }
4928 // At this point the main thread releases the global lock and the worker
4929 // can acquire it and do its sweep of its heaps. Just wait for the worke r
4930 // to complete its sweep and check the result.
4931 parkMainThread();
4932 EXPECT_EQ(1, DestructorLockingObject::s_destructorCalls);
4933 }
4934
4935 private:
4936 static void workerThreadMain(void* data)
4937 {
4938 MutexLocker locker(workerThreadMutex());
4939 ThreadState::attach();
4940
4941 DestructorLockingObject* dlo = DestructorLockingObject::create();
4942 ASSERT_UNUSED(dlo, dlo);
4943
4944 // Wake up the main thread which is waiting for the worker to do its
4945 // allocation.
4946 wakeMainThread();
4947
4948 // Wait for the main thread to get the global lock to ensure it has
4949 // it before the worker tries to acquire it. We want the worker to
4950 // block in the SafePointAwareMutexLocker until the main thread
4951 // has done a GC. The GC will not mark the "dlo" object since the worker
4952 // is entering the safepoint with NoHeapPointersOnStack. When the worker
4953 // subsequently gets the global lock and leaves the safepoint it will
4954 // sweep its heap and finalize "dlo". The destructor of "dlo" will try
4955 // to acquire the same global lock that the thread just got and deadlock
4956 // unless the global lock is recursive.
4957 parkWorkerThread();
4958 SafePointAwareMutexLocker recursiveLocker(recursiveMutex(), ThreadState: :NoHeapPointersOnStack);
4959
4960 // We won't get here unless the lock is recursive since the sweep done
4961 // in the constructor of SafePointAwareMutexLocker after
4962 // getting the lock will not complete given the "dlo" destructor is
4963 // waiting to get the same lock.
4964 // Tell the main thread the worker has done its sweep.
4965 wakeMainThread();
4966
4967 ThreadState::detach();
4968 }
4969
4970 static volatile IntWrapper* s_workerObjectPointer;
4971 };
4972
4973 TEST(HeapTest, RecursiveMutex)
4974 {
4975 RecursiveLockingTester::test();
4976 }
4977
4875 } // WebCore namespace 4978 } // WebCore namespace
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698