summaryrefslogtreecommitdiffstats
path: root/Source/WebKit2/Platform/mac
diff options
context:
space:
mode:
Diffstat (limited to 'Source/WebKit2/Platform/mac')
-rw-r--r--Source/WebKit2/Platform/mac/MachUtilities.cpp67
-rw-r--r--Source/WebKit2/Platform/mac/MachUtilities.h36
-rw-r--r--Source/WebKit2/Platform/mac/ModuleMac.mm62
-rw-r--r--Source/WebKit2/Platform/mac/RunLoopMac.mm131
-rw-r--r--Source/WebKit2/Platform/mac/SharedMemoryMac.cpp171
-rw-r--r--Source/WebKit2/Platform/mac/WorkQueueMac.cpp202
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