summaryrefslogtreecommitdiff
path: root/Source/JavaScriptCore/wtf/ParallelJobsGeneric.cpp
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@nokia.com>2012-01-06 14:44:00 +0100
committerSimon Hausmann <simon.hausmann@nokia.com>2012-01-06 14:44:00 +0100
commit40736c5763bf61337c8c14e16d8587db021a87d4 (patch)
treeb17a9c00042ad89cb1308e2484491799aa14e9f8 /Source/JavaScriptCore/wtf/ParallelJobsGeneric.cpp
downloadqtwebkit-40736c5763bf61337c8c14e16d8587db021a87d4.tar.gz
Imported WebKit commit 2ea9d364d0f6efa8fa64acf19f451504c59be0e4 (http://svn.webkit.org/repository/webkit/trunk@104285)
Diffstat (limited to 'Source/JavaScriptCore/wtf/ParallelJobsGeneric.cpp')
-rw-r--r--Source/JavaScriptCore/wtf/ParallelJobsGeneric.cpp181
1 files changed, 181 insertions, 0 deletions
diff --git a/Source/JavaScriptCore/wtf/ParallelJobsGeneric.cpp b/Source/JavaScriptCore/wtf/ParallelJobsGeneric.cpp
new file mode 100644
index 000000000..b6207dc88
--- /dev/null
+++ b/Source/JavaScriptCore/wtf/ParallelJobsGeneric.cpp
@@ -0,0 +1,181 @@
+/*
+ * Copyright (C) 2011 University of Szeged
+ * Copyright (C) 2011 Gabor Loki <loki@webkit.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY UNIVERSITY OF SZEGED ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL UNIVERSITY OF SZEGED OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if ENABLE(THREADING_GENERIC)
+
+#include "ParallelJobs.h"
+#include "UnusedParam.h"
+
+#if OS(DARWIN) || OS(OPENBSD) || OS(NETBSD)
+#include <sys/sysctl.h>
+#include <sys/types.h>
+#elif OS(LINUX) || OS(AIX) || OS(SOLARIS)
+#include <unistd.h>
+#elif OS(WINDOWS)
+#include <windows.h>
+#endif
+
+namespace WTF {
+
+Vector< RefPtr<ParallelEnvironment::ThreadPrivate> >* ParallelEnvironment::s_threadPool = 0;
+
+int ParallelEnvironment::s_maxNumberOfParallelThreads = -1;
+
+ParallelEnvironment::ParallelEnvironment(ThreadFunction threadFunction, size_t sizeOfParameter, int requestedJobNumber) :
+ m_threadFunction(threadFunction),
+ m_sizeOfParameter(sizeOfParameter)
+{
+ ASSERT_ARG(requestedJobNumber, requestedJobNumber >= 1);
+
+ if (s_maxNumberOfParallelThreads == -1)
+ determineMaxNumberOfParallelThreads();
+
+ if (!requestedJobNumber || requestedJobNumber > s_maxNumberOfParallelThreads)
+ requestedJobNumber = static_cast<unsigned>(s_maxNumberOfParallelThreads);
+
+ if (!s_threadPool)
+ s_threadPool = new Vector< RefPtr<ThreadPrivate> >();
+
+ // The main thread should be also a worker.
+ int maxNumberOfNewThreads = requestedJobNumber - 1;
+
+ for (int i = 0; i < s_maxNumberOfParallelThreads && m_threads.size() < static_cast<unsigned>(maxNumberOfNewThreads); ++i) {
+ if (s_threadPool->size() < static_cast<unsigned>(i) + 1U)
+ s_threadPool->append(ThreadPrivate::create());
+
+ if ((*s_threadPool)[i]->tryLockFor(this))
+ m_threads.append((*s_threadPool)[i]);
+ }
+
+ m_numberOfJobs = m_threads.size() + 1;
+}
+
+void ParallelEnvironment::execute(void* parameters)
+{
+ unsigned char* currentParameter = static_cast<unsigned char*>(parameters);
+ size_t i;
+ for (i = 0; i < m_threads.size(); ++i) {
+ m_threads[i]->execute(m_threadFunction, currentParameter);
+ currentParameter += m_sizeOfParameter;
+ }
+
+ // The work for the main thread.
+ (*m_threadFunction)(currentParameter);
+
+ // Wait until all jobs are done.
+ for (i = 0; i < m_threads.size(); ++i)
+ m_threads[i]->waitForFinish();
+}
+
+void ParallelEnvironment::determineMaxNumberOfParallelThreads()
+{
+ const int defaultIfUnavailable = 2;
+#if OS(DARWIN) || OS(OPENBSD) || OS(NETBSD)
+ unsigned result;
+ size_t length = sizeof(result);
+ int name[] = {
+ CTL_HW,
+ HW_NCPU
+ };
+ int sysctlResult = sysctl(name, sizeof(name) / sizeof(int), &result, &length, 0, 0);
+ s_maxNumberOfParallelThreads = sysctlResult < 0 ? defaultIfUnavailable : result;
+#elif OS(LINUX) || OS(AIX) || OS(SOLARIS)
+ long sysconfResult = sysconf(_SC_NPROCESSORS_ONLN);
+ s_maxNumberOfParallelThreads = sysconfResult < 0 ? defaultIfUnavailable : static_cast<int>(sysconfResult);
+#elif OS(WINDOWS)
+ UNUSED_PARAM(defaultIfUnavailable);
+
+ SYSTEM_INFO sysInfo;
+ GetSystemInfo(&sysInfo);
+ s_maxNumberOfParallelThreads = sysInfo.dwNumberOfProcessors;
+#else
+ s_maxNumberOfParallelThreads = defaultIfUnavailable;
+#endif
+}
+
+bool ParallelEnvironment::ThreadPrivate::tryLockFor(ParallelEnvironment* parent)
+{
+ bool locked = m_mutex.tryLock();
+
+ if (!locked)
+ return false;
+
+ if (m_parent) {
+ m_mutex.unlock();
+ return false;
+ }
+
+ if (!m_threadID)
+ m_threadID = createThread(&ParallelEnvironment::ThreadPrivate::workerThread, this, "Parallel worker");
+
+ if (m_threadID)
+ m_parent = parent;
+
+ m_mutex.unlock();
+ return m_threadID;
+}
+
+void ParallelEnvironment::ThreadPrivate::execute(ThreadFunction threadFunction, void* parameters)
+{
+ MutexLocker lock(m_mutex);
+
+ m_threadFunction = threadFunction;
+ m_parameters = parameters;
+ m_running = true;
+ m_threadCondition.signal();
+}
+
+void ParallelEnvironment::ThreadPrivate::waitForFinish()
+{
+ MutexLocker lock(m_mutex);
+
+ while (m_running)
+ m_threadCondition.wait(m_mutex);
+}
+
+void* ParallelEnvironment::ThreadPrivate::workerThread(void* threadData)
+{
+ ThreadPrivate* sharedThread = reinterpret_cast<ThreadPrivate*>(threadData);
+ MutexLocker lock(sharedThread->m_mutex);
+
+ while (sharedThread->m_threadID) {
+ if (sharedThread->m_running) {
+ (*sharedThread->m_threadFunction)(sharedThread->m_parameters);
+ sharedThread->m_running = false;
+ sharedThread->m_parent = 0;
+ sharedThread->m_threadCondition.signal();
+ }
+
+ sharedThread->m_threadCondition.wait(sharedThread->m_mutex);
+ }
+ return 0;
+}
+
+} // namespace WTF
+#endif // ENABLE(THREADING_GENERIC)