1 /*
2 * Copyright (C) 2005, 2006, 2007 Apple Inc. All rights reserved.
3 * (C) 2007 Graham Dennis (graham.dennis@gmail.com)
4 * (C) 2007 Eric Seidel <eric@webkit.org>
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
16 * its contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
20 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
23 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
26 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
31 #include "JavaScriptThreading.h"
32
33 #include <CoreFoundation/CoreFoundation.h>
34 #include <JavaScriptCore/JavaScriptCore.h>
35 #include <pthread.h>
36 #include <wtf/Assertions.h>
37 #include <wtf/HashSet.h>
38
39 static pthread_mutex_t javaScriptThreadsMutex = PTHREAD_MUTEX_INITIALIZER;
40 static bool javaScriptThreadsShouldTerminate;
41
42 static const int javaScriptThreadsCount = 4;
43
44 typedef HashSet<pthread_t> ThreadSet;
45
javaScriptThreads()46 static ThreadSet* javaScriptThreads()
47 {
48 ASSERT(pthread_mutex_trylock(&javaScriptThreadsMutex) == EBUSY);
49 static ThreadSet staticJavaScriptThreads;
50 return &staticJavaScriptThreads;
51 }
52
53 // Loops forever, running a script and randomly respawning, until
54 // javaScriptThreadsShouldTerminate becomes true.
runJavaScriptThread(void * arg)55 void* runJavaScriptThread(void* arg)
56 {
57 const char* const script =
58 "var array = [];"
59 "for (var i = 0; i < 10; i++) {"
60 " array.push(String(i));"
61 "}";
62
63 while (1) {
64 JSGlobalContextRef ctx = JSGlobalContextCreate(0);
65 JSStringRef scriptRef = JSStringCreateWithUTF8CString(script);
66
67 JSValueRef exception = 0;
68 JSEvaluateScript(ctx, scriptRef, 0, 0, 1, &exception);
69 ASSERT(!exception);
70
71 JSGarbageCollect(ctx);
72 JSGlobalContextRelease(ctx);
73 JSStringRelease(scriptRef);
74
75 JSGarbageCollect(0);
76
77 pthread_mutex_lock(&javaScriptThreadsMutex);
78
79 // Check for cancellation.
80 if (javaScriptThreadsShouldTerminate) {
81 javaScriptThreads()->remove(pthread_self());
82 pthread_mutex_unlock(&javaScriptThreadsMutex);
83 return 0;
84 }
85
86 // Respawn probabilistically.
87 if (random() % 5 == 0) {
88 pthread_t pthread;
89 pthread_create(&pthread, 0, &runJavaScriptThread, 0);
90 pthread_detach(pthread);
91
92 javaScriptThreads()->remove(pthread_self());
93 javaScriptThreads()->add(pthread);
94
95 pthread_mutex_unlock(&javaScriptThreadsMutex);
96 return 0;
97 }
98
99 pthread_mutex_unlock(&javaScriptThreadsMutex);
100 }
101 }
102
startJavaScriptThreads()103 void startJavaScriptThreads()
104 {
105 pthread_mutex_lock(&javaScriptThreadsMutex);
106
107 for (int i = 0; i < javaScriptThreadsCount; i++) {
108 pthread_t pthread;
109 pthread_create(&pthread, 0, &runJavaScriptThread, 0);
110 pthread_detach(pthread);
111 javaScriptThreads()->add(pthread);
112 }
113
114 pthread_mutex_unlock(&javaScriptThreadsMutex);
115 }
116
stopJavaScriptThreads()117 void stopJavaScriptThreads()
118 {
119 pthread_mutex_lock(&javaScriptThreadsMutex);
120
121 javaScriptThreadsShouldTerminate = true;
122
123 ASSERT(javaScriptThreads()->size() == javaScriptThreadsCount);
124
125 pthread_mutex_unlock(&javaScriptThreadsMutex);
126
127 while (true) {
128 pthread_mutex_lock(&javaScriptThreadsMutex);
129 int threadCount = javaScriptThreads()->size();
130 pthread_mutex_unlock(&javaScriptThreadsMutex);
131
132 if (!threadCount)
133 break;
134
135 usleep(1000);
136 }
137 }
138