diff options
Diffstat (limited to 'Source/WTF/wtf/Threading.cpp')
-rw-r--r-- | Source/WTF/wtf/Threading.cpp | 145 |
1 files changed, 75 insertions, 70 deletions
diff --git a/Source/WTF/wtf/Threading.cpp b/Source/WTF/wtf/Threading.cpp index 723a94ee4..c1dc35019 100644 --- a/Source/WTF/wtf/Threading.cpp +++ b/Source/WTF/wtf/Threading.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008, 2009 Apple Inc. All rights reserved. + * Copyright (C) 2008, 2009, 2014 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -25,33 +25,56 @@ #include "config.h" #include "Threading.h" -#include <wtf/OwnPtr.h> -#include <wtf/PassOwnPtr.h> -#include <string.h> +#include <algorithm> +#include <cmath> +#include <cstring> +#include <wtf/text/StringView.h> + +#if HAVE(QOS_CLASSES) +#include <bmalloc/bmalloc.h> +#endif namespace WTF { struct NewThreadContext { WTF_MAKE_FAST_ALLOCATED; public: - NewThreadContext(ThreadFunction entryPoint, void* data, const char* name) - : entryPoint(entryPoint) - , data(data) - , name(name) - { - } - - ThreadFunction entryPoint; - void* data; const char* name; - + std::function<void()> entryPoint; Mutex creationMutex; }; +const char* normalizeThreadName(const char* threadName) +{ +#if HAVE(PTHREAD_SETNAME_NP) + return threadName; +#else + // This name can be com.apple.WebKit.ProcessLauncher or com.apple.CoreIPC.ReceiveQueue. + // We are using those names for the thread name, but both are longer than the limit of + // the platform thread name length, 32 for Windows and 16 for Linux. + StringView result(threadName); + size_t size = result.reverseFind('.'); + if (size != notFound) + result = result.substring(size + 1); + +#if OS(WINDOWS) + constexpr const size_t kVisualStudioThreadNameLimit = 32 - 1; + if (result.length() > kVisualStudioThreadNameLimit) + result = result.right(kVisualStudioThreadNameLimit); +#elif OS(LINUX) + constexpr const size_t kLinuxThreadNameLimit = 16 - 1; + if (result.length() > kLinuxThreadNameLimit) + result = result.right(kLinuxThreadNameLimit); +#endif + ASSERT(result.characters8()[result.length()] == '\0'); + return reinterpret_cast<const char*>(result.characters8()); +#endif +} + static void threadEntryPoint(void* contextData) { - NewThreadContext* context = reinterpret_cast<NewThreadContext*>(contextData); + NewThreadContext* context = static_cast<NewThreadContext*>(contextData); // Block until our creating thread has completed any extra setup work, including // establishing ThreadIdentifier. @@ -61,24 +84,17 @@ static void threadEntryPoint(void* contextData) initializeCurrentThreadInternal(context->name); - // Grab the info that we need out of the context, then deallocate it. - ThreadFunction entryPoint = context->entryPoint; - void* data = context->data; + auto entryPoint = WTFMove(context->entryPoint); + + // Delete the context before starting the thread. delete context; - entryPoint(data); + entryPoint(); } -ThreadIdentifier createThread(ThreadFunction entryPoint, void* data, const char* name) +ThreadIdentifier createThread(const char* name, std::function<void()> entryPoint) { - // Visual Studio has a 31-character limit on thread names. Longer names will - // be truncated silently, but we'd like callers to know about the limit. -#if !LOG_DISABLED && PLATFORM(WIN) - if (name && strlen(name) > 31) - LOG_ERROR("Thread name \"%s\" is longer than 31 characters and will be truncated by Visual Studio", name); -#endif - - NewThreadContext* context = new NewThreadContext(entryPoint, data, name); + NewThreadContext* context = new NewThreadContext { name, WTFMove(entryPoint), { } }; // Prevent the thread body from executing until we've established the thread identifier. MutexLocker locker(context->creationMutex); @@ -86,60 +102,49 @@ ThreadIdentifier createThread(ThreadFunction entryPoint, void* data, const char* return createThreadInternal(threadEntryPoint, context, name); } -#if PLATFORM(MAC) || PLATFORM(WIN) - -// For ABI compatibility with Safari on Mac / Windows: Safari uses the private -// createThread() and waitForThreadCompletion() functions directly and we need -// to keep the old ABI compatibility until it's been rebuilt. - -typedef void* (*ThreadFunctionWithReturnValue)(void* argument); - -WTF_EXPORT_PRIVATE ThreadIdentifier createThread(ThreadFunctionWithReturnValue entryPoint, void* data, const char* name); - -struct ThreadFunctionWithReturnValueInvocation { - ThreadFunctionWithReturnValueInvocation(ThreadFunctionWithReturnValue function, void* data) - : function(function) - , data(data) - { - } - - ThreadFunctionWithReturnValue function; - void* data; -}; - -static void compatEntryPoint(void* param) +ThreadIdentifier createThread(ThreadFunction entryPoint, void* data, const char* name) { - // Balanced by .release() in createThread. - auto invocation = std::unique_ptr<ThreadFunctionWithReturnValueInvocation>(static_cast<ThreadFunctionWithReturnValueInvocation*>(param)); - invocation->function(invocation->data); + return createThread(name, [entryPoint, data] { + entryPoint(data); + }); } -ThreadIdentifier createThread(ThreadFunctionWithReturnValue entryPoint, void* data, const char* name) +void setCurrentThreadIsUserInteractive(int relativePriority) { - auto invocation = std::make_unique<ThreadFunctionWithReturnValueInvocation>(entryPoint, data); - - // Balanced by std::unique_ptr constructor in compatEntryPoint. - return createThread(compatEntryPoint, invocation.release(), name); +#if HAVE(QOS_CLASSES) + ASSERT(relativePriority <= 0); + ASSERT(relativePriority >= QOS_MIN_RELATIVE_PRIORITY); + pthread_set_qos_class_self_np(adjustedQOSClass(QOS_CLASS_USER_INTERACTIVE), relativePriority); +#else + UNUSED_PARAM(relativePriority); +#endif } -WTF_EXPORT_PRIVATE int waitForThreadCompletion(ThreadIdentifier, void**); - -int waitForThreadCompletion(ThreadIdentifier threadID, void**) +void setCurrentThreadIsUserInitiated(int relativePriority) { - return waitForThreadCompletion(threadID); +#if HAVE(QOS_CLASSES) + ASSERT(relativePriority <= 0); + ASSERT(relativePriority >= QOS_MIN_RELATIVE_PRIORITY); + pthread_set_qos_class_self_np(adjustedQOSClass(QOS_CLASS_USER_INITIATED), relativePriority); +#else + UNUSED_PARAM(relativePriority); +#endif } -// This function is deprecated but needs to be kept around for backward -// compatibility. Use the 3-argument version of createThread above. - -WTF_EXPORT_PRIVATE ThreadIdentifier createThread(ThreadFunctionWithReturnValue entryPoint, void* data); +#if HAVE(QOS_CLASSES) +static qos_class_t globalMaxQOSclass { QOS_CLASS_UNSPECIFIED }; -ThreadIdentifier createThread(ThreadFunctionWithReturnValue entryPoint, void* data) +void setGlobalMaxQOSClass(qos_class_t maxClass) { - auto invocation = std::make_unique<ThreadFunctionWithReturnValueInvocation>(entryPoint, data); + bmalloc::api::setScavengerThreadQOSClass(maxClass); + globalMaxQOSclass = maxClass; +} - // Balanced by adoptPtr() in compatEntryPoint. - return createThread(compatEntryPoint, invocation.release(), 0); +qos_class_t adjustedQOSClass(qos_class_t originalClass) +{ + if (globalMaxQOSclass != QOS_CLASS_UNSPECIFIED) + return std::min(originalClass, globalMaxQOSclass); + return originalClass; } #endif |