fcf8a4beace823272e882453830d17d39efafb0f
[WebKit-https.git] / Tools / TestWebKitAPI / Tests / WTF / Lock.cpp
1 /*
2  * Copyright (C) 2015 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "config.h"
27 #include <wtf/Lock.h>
28 #include <wtf/Threading.h>
29 #include <wtf/ThreadingPrimitives.h>
30 #include <wtf/WordLock.h>
31
32 using namespace WTF;
33
34 namespace TestWebKitAPI {
35
36 struct LockInspector {
37     template<typename LockType>
38     static bool isFullyReset(LockType& lock)
39     {
40         return lock.isFullyReset();
41     }
42 };
43
44 template<typename LockType>
45 void runLockTest(unsigned numThreadGroups, unsigned numThreadsPerGroup, unsigned workPerCriticalSection, unsigned numIterations)
46 {
47     std::unique_ptr<LockType[]> locks = std::make_unique<LockType[]>(numThreadGroups);
48     std::unique_ptr<double[]> words = std::make_unique<double[]>(numThreadGroups);
49     std::unique_ptr<ThreadIdentifier[]> threads = std::make_unique<ThreadIdentifier[]>(numThreadGroups * numThreadsPerGroup);
50
51     for (unsigned threadGroupIndex = numThreadGroups; threadGroupIndex--;) {
52         words[threadGroupIndex] = 0;
53
54         for (unsigned threadIndex = numThreadsPerGroup; threadIndex--;) {
55             threads[threadGroupIndex * numThreadsPerGroup + threadIndex] = createThread(
56                 "Lock test thread",
57                 [threadGroupIndex, &locks, &words, numIterations, workPerCriticalSection] () {
58                     for (unsigned i = numIterations; i--;) {
59                         locks[threadGroupIndex].lock();
60                         for (unsigned j = workPerCriticalSection; j--;)
61                             words[threadGroupIndex]++;
62                         locks[threadGroupIndex].unlock();
63                     }
64                 });
65         }
66     }
67
68     for (unsigned threadIndex = numThreadGroups * numThreadsPerGroup; threadIndex--;)
69         waitForThreadCompletion(threads[threadIndex]);
70
71     double expected = 0;
72     for (uint64_t i = static_cast<uint64_t>(numIterations) * workPerCriticalSection * numThreadsPerGroup; i--;)
73         expected++;
74
75     for (unsigned threadGroupIndex = numThreadGroups; threadGroupIndex--;)
76         EXPECT_EQ(expected, words[threadGroupIndex]);
77
78     // Now test that the locks correctly reset themselves. We expect that if a single thread locks
79     // each of the locks twice in a row, then the lock should be in a pristine state.
80     for (unsigned threadGroupIndex = numThreadGroups; threadGroupIndex--;) {
81         for (unsigned i = 2; i--;) {
82             locks[threadGroupIndex].lock();
83             locks[threadGroupIndex].unlock();
84         }
85
86         EXPECT_EQ(true, LockInspector::isFullyReset(locks[threadGroupIndex]));
87     }
88 }
89
90 TEST(WTF_WordLock, UncontendedShortSection)
91 {
92     runLockTest<WordLock>(1, 1, 1, 10000000);
93 }
94
95 TEST(WTF_WordLock, UncontendedLongSection)
96 {
97     runLockTest<WordLock>(1, 1, 10000, 1000);
98 }
99
100 TEST(WTF_WordLock, ContendedShortSection)
101 {
102     runLockTest<WordLock>(1, 10, 1, 5000000);
103 }
104
105 TEST(WTF_WordLock, ContendedLongSection)
106 {
107     runLockTest<WordLock>(1, 10, 10000, 10000);
108 }
109
110 TEST(WTF_WordLock, ManyContendedShortSections)
111 {
112     runLockTest<WordLock>(10, 10, 1, 500000);
113 }
114
115 TEST(WTF_WordLock, ManyContendedLongSections)
116 {
117     runLockTest<WordLock>(10, 10, 10000, 500);
118 }
119
120 TEST(WTF_Lock, UncontendedShortSection)
121 {
122     runLockTest<Lock>(1, 1, 1, 10000000);
123 }
124
125 TEST(WTF_Lock, UncontendedLongSection)
126 {
127     runLockTest<Lock>(1, 1, 10000, 1000);
128 }
129
130 TEST(WTF_Lock, ContendedShortSection)
131 {
132     runLockTest<Lock>(1, 10, 1, 10000000);
133 }
134
135 TEST(WTF_Lock, ContendedLongSection)
136 {
137     runLockTest<Lock>(1, 10, 10000, 10000);
138 }
139
140 TEST(WTF_Lock, ManyContendedShortSections)
141 {
142     runLockTest<Lock>(10, 10, 1, 500000);
143 }
144
145 TEST(WTF_Lock, ManyContendedLongSections)
146 {
147     runLockTest<Lock>(10, 10, 10000, 1000);
148 }
149
150 TEST(WTF_Lock, ManyContendedLongerSections)
151 {
152     runLockTest<Lock>(10, 10, 100000, 1);
153 }
154
155 TEST(WTF_Lock, SectionAddressCollision)
156 {
157     runLockTest<Lock>(4, 2, 10000, 2000);
158 }
159
160 } // namespace TestWebKitAPI