diff options
Diffstat (limited to 'Source/WebKit2/Platform/mac')
-rw-r--r-- | Source/WebKit2/Platform/mac/MachUtilities.cpp | 67 | ||||
-rw-r--r-- | Source/WebKit2/Platform/mac/MachUtilities.h | 36 | ||||
-rw-r--r-- | Source/WebKit2/Platform/mac/ModuleMac.mm | 62 | ||||
-rw-r--r-- | Source/WebKit2/Platform/mac/RunLoopMac.mm | 131 | ||||
-rw-r--r-- | Source/WebKit2/Platform/mac/SharedMemoryMac.cpp | 171 | ||||
-rw-r--r-- | Source/WebKit2/Platform/mac/WorkQueueMac.cpp | 202 |
6 files changed, 669 insertions, 0 deletions
diff --git a/Source/WebKit2/Platform/mac/MachUtilities.cpp b/Source/WebKit2/Platform/mac/MachUtilities.cpp new file mode 100644 index 0000000..edb17dc --- /dev/null +++ b/Source/WebKit2/Platform/mac/MachUtilities.cpp @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2010 Apple Inc. 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 APPLE INC. AND ITS CONTRIBUTORS ``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 APPLE INC. OR ITS 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 "MachUtilities.h" + +#include <mach/task.h> + +void setMachPortQueueLength(mach_port_t receivePort, mach_port_msgcount_t queueLength) +{ + mach_port_limits_t portLimits; + portLimits.mpl_qlimit = queueLength; + + mach_port_set_attributes(mach_task_self(), receivePort, MACH_PORT_LIMITS_INFO, reinterpret_cast<mach_port_info_t>(&portLimits), MACH_PORT_LIMITS_INFO_COUNT); +} + +mach_port_t machExceptionPort() +{ + exception_mask_t exceptionMasks[EXC_TYPES_COUNT]; + exception_port_t exceptionHandlers[EXC_TYPES_COUNT]; + exception_behavior_t exceptionBehaviors[EXC_TYPES_COUNT]; + thread_state_flavor_t exceptionFlavors[EXC_TYPES_COUNT]; + mach_msg_type_number_t numExceptionMasks; + + kern_return_t kr = task_get_exception_ports(mach_task_self(), EXC_MASK_CRASH, exceptionMasks, &numExceptionMasks, exceptionHandlers, exceptionBehaviors, exceptionFlavors); + if (kr != KERN_SUCCESS) { + ASSERT_NOT_REACHED(); + return MACH_PORT_NULL; + } + + // We're just interested in the first exception handler. + return exceptionHandlers[0]; +} + +void setMachExceptionPort(mach_port_t exceptionPort) +{ + // Assert that we dont try to call setMachExceptionPort more than once per process. +#if !ASSERT_DISABLED + static mach_port_t taskExceptionPort = MACH_PORT_NULL; + ASSERT(taskExceptionPort == MACH_PORT_NULL); + taskExceptionPort = exceptionPort; +#endif + + if (task_set_exception_ports(mach_task_self(), EXC_MASK_CRASH, exceptionPort, EXCEPTION_STATE_IDENTITY | MACH_EXCEPTION_CODES, MACHINE_THREAD_STATE) != KERN_SUCCESS) + ASSERT_NOT_REACHED(); +} diff --git a/Source/WebKit2/Platform/mac/MachUtilities.h b/Source/WebKit2/Platform/mac/MachUtilities.h new file mode 100644 index 0000000..a8d0d6f --- /dev/null +++ b/Source/WebKit2/Platform/mac/MachUtilities.h @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2010 Apple Inc. 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 APPLE INC. AND ITS CONTRIBUTORS ``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 APPLE INC. OR ITS 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. + */ + +#ifndef MachUtilities_h +#define MachUtilities_h + +#include <mach/mach_port.h> + +void setMachPortQueueLength(mach_port_t, mach_port_msgcount_t queueLength); + +mach_port_t machExceptionPort(); +void setMachExceptionPort(mach_port_t exceptionPort); + +#endif // MachUtilities_h diff --git a/Source/WebKit2/Platform/mac/ModuleMac.mm b/Source/WebKit2/Platform/mac/ModuleMac.mm new file mode 100644 index 0000000..fa38745 --- /dev/null +++ b/Source/WebKit2/Platform/mac/ModuleMac.mm @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2010 Apple Inc. 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 APPLE INC. AND ITS CONTRIBUTORS ``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 APPLE INC. OR ITS 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 "Module.h" + +namespace WebKit { + +bool Module::load() +{ + RetainPtr<CFStringRef> bundlePath(AdoptCF, m_path.createCFString()); + RetainPtr<CFURLRef> bundleURL(AdoptCF, CFURLCreateWithFileSystemPath(kCFAllocatorDefault, bundlePath.get(), kCFURLPOSIXPathStyle, FALSE)); + if (!bundleURL) + return false; + + RetainPtr<CFBundleRef> bundle(AdoptCF, CFBundleCreate(kCFAllocatorDefault, bundleURL.get())); + if (!bundle) + return false; + + if (!CFBundleLoadExecutable(bundle.get())) + return false; + + m_bundle.adoptCF(bundle.releaseRef()); + return true; +} + +void Module::unload() +{ + // See the comment in Module.h for why we leak the bundle here. + m_bundle.releaseRef(); +} + +void* Module::platformFunctionPointer(const char* functionName) const +{ + if (!m_bundle) + return 0; + RetainPtr<CFStringRef> functionNameString(AdoptCF, CFStringCreateWithCStringNoCopy(kCFAllocatorDefault, functionName, kCFStringEncodingASCII, kCFAllocatorNull)); + return CFBundleGetFunctionPointerForName(m_bundle.get(), functionNameString.get()); +} + +} diff --git a/Source/WebKit2/Platform/mac/RunLoopMac.mm b/Source/WebKit2/Platform/mac/RunLoopMac.mm new file mode 100644 index 0000000..ca044f3 --- /dev/null +++ b/Source/WebKit2/Platform/mac/RunLoopMac.mm @@ -0,0 +1,131 @@ +/* + * Copyright (C) 2010 Apple Inc. 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 APPLE INC. AND ITS CONTRIBUTORS ``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 APPLE INC. OR ITS 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 "RunLoop.h" + +#include "WorkItem.h" + +void RunLoop::performWork(void* context) +{ + static_cast<RunLoop*>(context)->performWork(); +} + +RunLoop::RunLoop() +{ + m_runLoop = CFRunLoopGetCurrent(); + + CFRunLoopSourceContext context = { 0, this, 0, 0, 0, 0, 0, 0, 0, performWork }; + m_runLoopSource = CFRunLoopSourceCreate(kCFAllocatorDefault, 0, &context); + CFRunLoopAddSource(m_runLoop, m_runLoopSource, kCFRunLoopCommonModes); +} + +RunLoop::~RunLoop() +{ + // FIXME: Tear down the work item queue here. + CFRunLoopSourceInvalidate(m_runLoopSource); + CFRelease(m_runLoopSource); +} + +void RunLoop::run() +{ + if (current() == main()) { + // Use -[NSApplication run] for the main run loop. + [NSApp run]; + } else { + // Otherwise, use NSRunLoop. We do this because it sets up an autorelease pool for us. + [[NSRunLoop currentRunLoop] run]; + } +} + +void RunLoop::stop() +{ + ASSERT(m_runLoop == CFRunLoopGetCurrent()); + + if (m_runLoop == main()->m_runLoop) { + [NSApp stop:nil]; + NSEvent *event = [NSEvent otherEventWithType:NSApplicationDefined + location:NSMakePoint(0, 0) + modifierFlags:0 + timestamp:0.0 + windowNumber:0 + context:nil + subtype: 0 + data1:0 + data2:0]; + [NSApp postEvent:event atStart:true]; + } else + CFRunLoopStop(m_runLoop); +} + +void RunLoop::wakeUp() +{ + CFRunLoopSourceSignal(m_runLoopSource); + CFRunLoopWakeUp(m_runLoop); +} + +// RunLoop::Timer + +void RunLoop::TimerBase::timerFired(CFRunLoopTimerRef, void* context) +{ + TimerBase* timer = static_cast<TimerBase*>(context); + timer->fired(); +} + +RunLoop::TimerBase::TimerBase(RunLoop* runLoop) + : m_runLoop(runLoop) + , m_timer(0) +{ +} + +RunLoop::TimerBase::~TimerBase() +{ + stop(); +} + +void RunLoop::TimerBase::start(double nextFireInterval, bool repeat) +{ + if (m_timer) + stop(); + + CFRunLoopTimerContext context = { 0, this, 0, 0, 0 }; + CFTimeInterval repeatInterval = repeat ? nextFireInterval : 0; + m_timer = CFRunLoopTimerCreate(kCFAllocatorDefault, CFAbsoluteTimeGetCurrent() + nextFireInterval, repeatInterval, 0, 0, timerFired, &context); + CFRunLoopAddTimer(m_runLoop->m_runLoop, m_timer, kCFRunLoopCommonModes); +} + +void RunLoop::TimerBase::stop() +{ + if (!m_timer) + return; + + CFRunLoopTimerInvalidate(m_timer); + CFRelease(m_timer); + m_timer = 0; +} + +bool RunLoop::TimerBase::isActive() const +{ + return m_timer && CFRunLoopTimerIsValid(m_timer); +} diff --git a/Source/WebKit2/Platform/mac/SharedMemoryMac.cpp b/Source/WebKit2/Platform/mac/SharedMemoryMac.cpp new file mode 100644 index 0000000..07f942c --- /dev/null +++ b/Source/WebKit2/Platform/mac/SharedMemoryMac.cpp @@ -0,0 +1,171 @@ +/* + * Copyright (C) 2010 Apple Inc. 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 APPLE INC. AND ITS CONTRIBUTORS ``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 APPLE INC. OR ITS 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 "SharedMemory.h" + +#include "ArgumentDecoder.h" +#include "ArgumentEncoder.h" +#include "Arguments.h" +#include "MachPort.h" +#include <mach/mach_port.h> +#include <mach/mach_vm.h> +#include <mach/vm_map.h> +#include <wtf/RefPtr.h> + +namespace WebKit { + +SharedMemory::Handle::Handle() + : m_port(MACH_PORT_NULL) + , m_size(0) +{ +} + +SharedMemory::Handle::~Handle() +{ + if (m_port) + mach_port_deallocate(mach_task_self(), m_port); +} + +bool SharedMemory::Handle::isNull() const +{ + return !m_port; +} + +void SharedMemory::Handle::encode(CoreIPC::ArgumentEncoder* encoder) const +{ + encoder->encodeUInt64(m_size); + encoder->encode(CoreIPC::MachPort(m_port, MACH_MSG_TYPE_COPY_SEND)); + m_port = MACH_PORT_NULL; +} + +bool SharedMemory::Handle::decode(CoreIPC::ArgumentDecoder* decoder, Handle& handle) +{ + ASSERT(!handle.m_port); + ASSERT(!handle.m_size); + + uint64_t size; + if (!decoder->decodeUInt64(size)) + return false; + + CoreIPC::MachPort machPort; + if (!decoder->decode(CoreIPC::Out(machPort))) + return false; + + handle.m_size = size; + handle.m_port = machPort.port(); + return true; +} + +static inline void* toPointer(mach_vm_address_t address) +{ + return reinterpret_cast<void*>(static_cast<uintptr_t>(address)); +} + +static inline mach_vm_address_t toVMAddress(void* pointer) +{ + return static_cast<mach_vm_address_t>(reinterpret_cast<uintptr_t>(pointer)); +} + +PassRefPtr<SharedMemory> SharedMemory::create(size_t size) +{ + mach_vm_address_t address; + kern_return_t kr = mach_vm_allocate(mach_task_self(), &address, round_page(size), VM_FLAGS_ANYWHERE); + if (kr != KERN_SUCCESS) + return 0; + + RefPtr<SharedMemory> sharedMemory(adoptRef(new SharedMemory)); + sharedMemory->m_size = size; + sharedMemory->m_data = toPointer(address); + + return sharedMemory.release(); +} + +static inline vm_prot_t machProtection(SharedMemory::Protection protection) +{ + switch (protection) { + case SharedMemory::ReadOnly: + return VM_PROT_READ; + case SharedMemory::ReadWrite: + return VM_PROT_READ | VM_PROT_WRITE; + } + + ASSERT_NOT_REACHED(); + return VM_PROT_NONE; +} + +PassRefPtr<SharedMemory> SharedMemory::create(const Handle& handle, Protection protection) +{ + if (handle.isNull()) + return 0; + + // Map the memory. + vm_prot_t vmProtection = machProtection(protection); + mach_vm_address_t mappedAddress = 0; + kern_return_t kr = mach_vm_map(mach_task_self(), &mappedAddress, handle.m_size, 0, VM_FLAGS_ANYWHERE, handle.m_port, 0, false, vmProtection, vmProtection, VM_INHERIT_NONE); + if (kr != KERN_SUCCESS) + return 0; + + RefPtr<SharedMemory> sharedMemory(adoptRef(new SharedMemory)); + sharedMemory->m_size = handle.m_size; + sharedMemory->m_data = toPointer(mappedAddress); + + return sharedMemory.release(); +} + +SharedMemory::~SharedMemory() +{ + if (!m_data) + return; + + kern_return_t kr = mach_vm_deallocate(mach_task_self(), toVMAddress(m_data), round_page(m_size)); + ASSERT_UNUSED(kr, kr == KERN_SUCCESS); +} + +bool SharedMemory::createHandle(Handle& handle, Protection protection) +{ + ASSERT(!handle.m_port); + ASSERT(!handle.m_size); + + mach_vm_address_t address = toVMAddress(m_data); + memory_object_size_t size = round_page(m_size); + + // Create a mach port that represents the shared memory. + mach_port_t port; + kern_return_t kr = mach_make_memory_entry_64(mach_task_self(), &size, address, machProtection(protection), &port, MACH_PORT_NULL); + if (kr != KERN_SUCCESS) + return false; + + handle.m_port = port; + handle.m_size = size; + + return true; +} + +unsigned SharedMemory::systemPageSize() +{ + return vm_page_size; +} + +} // namespace WebKit diff --git a/Source/WebKit2/Platform/mac/WorkQueueMac.cpp b/Source/WebKit2/Platform/mac/WorkQueueMac.cpp new file mode 100644 index 0000000..3651f8c --- /dev/null +++ b/Source/WebKit2/Platform/mac/WorkQueueMac.cpp @@ -0,0 +1,202 @@ +/* + * Copyright (C) 2010 Apple Inc. 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 APPLE INC. AND ITS CONTRIBUTORS ``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 APPLE INC. OR ITS 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 "WorkQueue.h" + +#include <mach/mach_port.h> +#include <wtf/PassOwnPtr.h> + +#if HAVE(DISPATCH_H) + +void WorkQueue::executeWorkItem(void* item) +{ + WorkQueue* queue = static_cast<WorkQueue*>(dispatch_get_context(dispatch_get_current_queue())); + OwnPtr<WorkItem> workItem(static_cast<WorkItem*>(item)); + + { + MutexLocker locker(queue->m_isValidMutex); + if (!queue->m_isValid) + return; + } + + workItem->execute(); +} + +void WorkQueue::scheduleWork(PassOwnPtr<WorkItem> item) +{ + dispatch_async_f(m_dispatchQueue, item.leakPtr(), executeWorkItem); +} + +void WorkQueue::scheduleWorkAfterDelay(PassOwnPtr<WorkItem> item, double delay) +{ + dispatch_time_t delayTime = dispatch_time(DISPATCH_TIME_NOW, delay * NSEC_PER_SEC); + + dispatch_after_f(delayTime, m_dispatchQueue, item.leakPtr(), executeWorkItem); +} + +class WorkQueue::EventSource { +public: + EventSource(MachPortEventType eventType, dispatch_source_t dispatchSource, PassOwnPtr<WorkItem> workItem) + : m_eventType(eventType) + , m_dispatchSource(dispatchSource) + , m_workItem(workItem) + { + } + + dispatch_source_t dispatchSource() const { return m_dispatchSource; } + + static void eventHandler(void* source) + { + EventSource* eventSource = static_cast<EventSource*>(source); + + eventSource->m_workItem->execute(); + } + + static void cancelHandler(void* source) + { + EventSource* eventSource = static_cast<EventSource*>(source); + + mach_port_t machPort = dispatch_source_get_handle(eventSource->m_dispatchSource); + + switch (eventSource->m_eventType) { + case MachPortDataAvailable: + // Release our receive right. + mach_port_mod_refs(mach_task_self(), machPort, MACH_PORT_RIGHT_RECEIVE, -1); + break; + case MachPortDeadNameNotification: + // Release our send right. + mach_port_deallocate(mach_task_self(), machPort); + break; + } + } + + static void finalizeHandler(void* source) + { + EventSource* eventSource = static_cast<EventSource*>(source); + + delete eventSource; + } + +private: + MachPortEventType m_eventType; + + // This is a weak reference, since m_dispatchSource references the event source. + dispatch_source_t m_dispatchSource; + + OwnPtr<WorkItem> m_workItem; +}; + +void WorkQueue::registerMachPortEventHandler(mach_port_t machPort, MachPortEventType eventType, PassOwnPtr<WorkItem> workItem) +{ + dispatch_source_type_t sourceType = 0; + switch (eventType) { + case MachPortDataAvailable: + sourceType = DISPATCH_SOURCE_TYPE_MACH_RECV; + break; + case MachPortDeadNameNotification: + sourceType = DISPATCH_SOURCE_TYPE_MACH_SEND; + break; + } + + dispatch_source_t dispatchSource = dispatch_source_create(sourceType, machPort, 0, m_dispatchQueue); + + EventSource* eventSource = new EventSource(eventType, dispatchSource, workItem); + dispatch_set_context(dispatchSource, eventSource); + + dispatch_source_set_event_handler_f(dispatchSource, &EventSource::eventHandler); + dispatch_source_set_cancel_handler_f(dispatchSource, &EventSource::cancelHandler); + dispatch_set_finalizer_f(dispatchSource, &EventSource::finalizeHandler); + + // Add the source to our set of sources. + { + MutexLocker locker(m_eventSourcesMutex); + + ASSERT(!m_eventSources.contains(machPort)); + + m_eventSources.set(machPort, eventSource); + + // And start it! + dispatch_resume(dispatchSource); + } +} + +void WorkQueue::unregisterMachPortEventHandler(mach_port_t machPort) +{ + ASSERT(machPort); + + MutexLocker locker(m_eventSourcesMutex); + + HashMap<mach_port_t, EventSource*>::iterator it = m_eventSources.find(machPort); + ASSERT(it != m_eventSources.end()); + + ASSERT(m_eventSources.contains(machPort)); + + EventSource* eventSource = it->second; + // Cancel and release the source. It will be deleted in its finalize handler. + dispatch_source_cancel(eventSource->dispatchSource()); + dispatch_release(eventSource->dispatchSource()); + + m_eventSources.remove(it); +} + +void WorkQueue::platformInitialize(const char* name) +{ + m_dispatchQueue = dispatch_queue_create(name, 0); + dispatch_set_context(m_dispatchQueue, this); +} + +void WorkQueue::platformInvalidate() +{ +#if !ASSERT_DISABLED + MutexLocker locker(m_eventSourcesMutex); + ASSERT(m_eventSources.isEmpty()); +#endif + + dispatch_release(m_dispatchQueue); +} + +#else /* !HAVE(DISPATCH_H) */ + +void WorkQueue::scheduleWork(PassOwnPtr<WorkItem> item) +{ +} + +void WorkQueue::registerMachPortEventHandler(mach_port_t, MachPortEventType, PassOwnPtr<WorkItem>) +{ +} + +void WorkQueue::unregisterMachPortEventHandler(mach_port_t) +{ +} + +void WorkQueue::platformInitialize(const char*) +{ +} + +void WorkQueue::platformInvalidate() +{ +} + +#endif |