[Libdispatch-changes] [2] trunk

source_changes at macosforge.org source_changes at macosforge.org
Thu Sep 10 16:26:17 PDT 2009


Revision: 2
          http://trac.macosforge.org/projects/libdispatch/changeset/2
Author:   kvv at apple.com
Date:     2009-08-29 18:07:28 -0700 (Sat, 29 Aug 2009)
Log Message:
-----------
initial import

Added Paths:
-----------
    trunk/LICENSE
    trunk/libdispatch.xcodeproj/
    trunk/libdispatch.xcodeproj/project.pbxproj
    trunk/man/
    trunk/man/dispatch.3
    trunk/man/dispatch_after.3
    trunk/man/dispatch_api.3
    trunk/man/dispatch_apply.3
    trunk/man/dispatch_async.3
    trunk/man/dispatch_benchmark.3
    trunk/man/dispatch_group_create.3
    trunk/man/dispatch_object.3
    trunk/man/dispatch_once.3
    trunk/man/dispatch_queue_create.3
    trunk/man/dispatch_semaphore_create.3
    trunk/man/dispatch_source_create.3
    trunk/man/dispatch_time.3
    trunk/src/
    trunk/src/apply.c
    trunk/src/base.h
    trunk/src/benchmark.c
    trunk/src/benchmark.h
    trunk/src/dispatch.h
    trunk/src/group.h
    trunk/src/hw_shims.h
    trunk/src/internal.h
    trunk/src/legacy.c
    trunk/src/legacy.h
    trunk/src/object.c
    trunk/src/object.h
    trunk/src/object_internal.h
    trunk/src/once.c
    trunk/src/once.h
    trunk/src/os_shims.h
    trunk/src/private.h
    trunk/src/protocol.defs
    trunk/src/queue.c
    trunk/src/queue.h
    trunk/src/queue_internal.h
    trunk/src/queue_private.h
    trunk/src/semaphore.c
    trunk/src/semaphore.h
    trunk/src/semaphore_internal.h
    trunk/src/shims.c
    trunk/src/source.c
    trunk/src/source.h
    trunk/src/source_internal.h
    trunk/src/source_private.h
    trunk/src/time.c
    trunk/src/time.h

Property Changed:
----------------
    trunk/


Property changes on: trunk
___________________________________________________________________
Added: svn:ignore
   + build


Added: trunk/LICENSE
===================================================================
--- trunk/LICENSE	                        (rev 0)
+++ trunk/LICENSE	2009-08-30 01:07:28 UTC (rev 2)
@@ -0,0 +1,202 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.


Property changes on: trunk/libdispatch.xcodeproj
___________________________________________________________________
Added: svn:ignore
   + *.mode1v3
*.pbxuser


Added: trunk/libdispatch.xcodeproj/project.pbxproj
===================================================================
--- trunk/libdispatch.xcodeproj/project.pbxproj	                        (rev 0)
+++ trunk/libdispatch.xcodeproj/project.pbxproj	2009-08-30 01:07:28 UTC (rev 2)
@@ -0,0 +1,497 @@
+// !$*UTF8*$!
+{
+	archiveVersion = 1;
+	classes = {
+	};
+	objectVersion = 45;
+	objects = {
+
+/* Begin PBXBuildFile section */
+		2EC9C9B80E8809EF00E2499A /* legacy.c in Sources */ = {isa = PBXBuildFile; fileRef = 2EC9C9B70E8809EF00E2499A /* legacy.c */; };
+		5A5D13AC0F6B280500197CC3 /* semaphore_internal.h in Headers */ = {isa = PBXBuildFile; fileRef = 5A5D13AB0F6B280500197CC3 /* semaphore_internal.h */; };
+		721F5C5D0F15520500FF03A6 /* semaphore.h in Headers */ = {isa = PBXBuildFile; fileRef = 721F5C5C0F15520500FF03A6 /* semaphore.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		721F5CCF0F15553500FF03A6 /* semaphore.c in Sources */ = {isa = PBXBuildFile; fileRef = 721F5CCE0F15553500FF03A6 /* semaphore.c */; };
+		72CC94300ECCD8750031B751 /* base.h in Headers */ = {isa = PBXBuildFile; fileRef = 72CC942F0ECCD8750031B751 /* base.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		96032E4B0F5CC8C700241C5F /* time.c in Sources */ = {isa = PBXBuildFile; fileRef = 96032E4A0F5CC8C700241C5F /* time.c */; };
+		96032E4D0F5CC8D100241C5F /* time.h in Headers */ = {isa = PBXBuildFile; fileRef = 96032E4C0F5CC8D100241C5F /* time.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		961B99360F3E83980006BC96 /* benchmark.h in Headers */ = {isa = PBXBuildFile; fileRef = 961B99350F3E83980006BC96 /* benchmark.h */; settings = {ATTRIBUTES = (Private, ); }; };
+		961B99500F3E85C30006BC96 /* object.h in Headers */ = {isa = PBXBuildFile; fileRef = 961B994F0F3E85C30006BC96 /* object.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		965CD6350F3E806200D4E28D /* benchmark.c in Sources */ = {isa = PBXBuildFile; fileRef = 965CD6340F3E806200D4E28D /* benchmark.c */; };
+		965ECC210F3EAB71004DDD89 /* object_internal.h in Headers */ = {isa = PBXBuildFile; fileRef = 965ECC200F3EAB71004DDD89 /* object_internal.h */; };
+		9661E56B0F3E7DDF00749F3E /* object.c in Sources */ = {isa = PBXBuildFile; fileRef = 9661E56A0F3E7DDF00749F3E /* object.c */; };
+		9676A0E10F3E755D00713ADB /* apply.c in Sources */ = {isa = PBXBuildFile; fileRef = 9676A0E00F3E755D00713ADB /* apply.c */; };
+		96929D840F3EA1020041FF5D /* hw_shims.h in Headers */ = {isa = PBXBuildFile; fileRef = 96929D820F3EA1020041FF5D /* hw_shims.h */; };
+		96929D850F3EA1020041FF5D /* os_shims.h in Headers */ = {isa = PBXBuildFile; fileRef = 96929D830F3EA1020041FF5D /* os_shims.h */; };
+		96929D960F3EA2170041FF5D /* queue_internal.h in Headers */ = {isa = PBXBuildFile; fileRef = 96929D950F3EA2170041FF5D /* queue_internal.h */; };
+		96A8AA870F41E7A400CD570B /* source.c in Sources */ = {isa = PBXBuildFile; fileRef = 96A8AA860F41E7A400CD570B /* source.c */; };
+		96BC39BD0F3EBAB100C59689 /* queue_private.h in Headers */ = {isa = PBXBuildFile; fileRef = 96BC39BC0F3EBAB100C59689 /* queue_private.h */; settings = {ATTRIBUTES = (Private, ); }; };
+		96C9553B0F3EAEDD000D2CA4 /* once.h in Headers */ = {isa = PBXBuildFile; fileRef = 96C9553A0F3EAEDD000D2CA4 /* once.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		96DF70BE0F38FE3C0074BD99 /* once.c in Sources */ = {isa = PBXBuildFile; fileRef = 96DF70BD0F38FE3C0074BD99 /* once.c */; };
+		FC0B34790FA2851C0080FFA0 /* source_internal.h in Headers */ = {isa = PBXBuildFile; fileRef = FC0B34780FA2851C0080FFA0 /* source_internal.h */; };
+		FC5C9C1E0EADABE3006E462D /* group.h in Headers */ = {isa = PBXBuildFile; fileRef = FC5C9C1D0EADABE3006E462D /* group.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		FC7BED990E8361E600161930 /* queue.c in Sources */ = {isa = PBXBuildFile; fileRef = FC7BED8A0E8361E600161930 /* queue.c */; };
+		FC7BED9A0E8361E600161930 /* queue.h in Headers */ = {isa = PBXBuildFile; fileRef = FC7BED8B0E8361E600161930 /* queue.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		FC7BED9C0E8361E600161930 /* source.h in Headers */ = {isa = PBXBuildFile; fileRef = FC7BED8D0E8361E600161930 /* source.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		FC7BED9E0E8361E600161930 /* internal.h in Headers */ = {isa = PBXBuildFile; fileRef = FC7BED8F0E8361E600161930 /* internal.h */; settings = {ATTRIBUTES = (); }; };
+		FC7BED9F0E8361E600161930 /* legacy.h in Headers */ = {isa = PBXBuildFile; fileRef = FC7BED900E8361E600161930 /* legacy.h */; settings = {ATTRIBUTES = (Private, ); }; };
+		FC7BEDA20E8361E600161930 /* private.h in Headers */ = {isa = PBXBuildFile; fileRef = FC7BED930E8361E600161930 /* private.h */; settings = {ATTRIBUTES = (Private, ); }; };
+		FC7BEDA40E8361E600161930 /* protocol.defs in Sources */ = {isa = PBXBuildFile; fileRef = FC7BED950E8361E600161930 /* protocol.defs */; settings = {ATTRIBUTES = (Client, Server, ); }; };
+		FC7BEDA50E8361E600161930 /* dispatch.h in Headers */ = {isa = PBXBuildFile; fileRef = FC7BED960E8361E600161930 /* dispatch.h */; settings = {ATTRIBUTES = (Public, ); }; };
+		FC7BEDA60E8361E600161930 /* shims.c in Sources */ = {isa = PBXBuildFile; fileRef = FC7BED970E8361E600161930 /* shims.c */; };
+		FCEF04800F5661960067401F /* source_private.h in Headers */ = {isa = PBXBuildFile; fileRef = FCEF047F0F5661960067401F /* source_private.h */; settings = {ATTRIBUTES = (Private, ); }; };
+/* End PBXBuildFile section */
+
+/* Begin PBXFileReference section */
+		2EC9C9B70E8809EF00E2499A /* legacy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = legacy.c; path = src/legacy.c; sourceTree = "<group>"; };
+		5A5D13AB0F6B280500197CC3 /* semaphore_internal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = semaphore_internal.h; path = src/semaphore_internal.h; sourceTree = "<group>"; };
+		721F5C5C0F15520500FF03A6 /* semaphore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = semaphore.h; path = src/semaphore.h; sourceTree = "<group>"; };
+		721F5CCE0F15553500FF03A6 /* semaphore.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = semaphore.c; path = src/semaphore.c; sourceTree = "<group>"; };
+		72B54F690EB169EB00DBECBA /* dispatch_source_create.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; name = dispatch_source_create.3; path = man/dispatch_source_create.3; sourceTree = "<group>"; };
+		72CC940C0ECCD5720031B751 /* dispatch_object.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; name = dispatch_object.3; path = man/dispatch_object.3; sourceTree = "<group>"; };
+		72CC940D0ECCD5720031B751 /* dispatch.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; name = dispatch.3; path = man/dispatch.3; sourceTree = "<group>"; };
+		72CC942F0ECCD8750031B751 /* base.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = base.h; path = src/base.h; sourceTree = "<group>"; };
+		96032E4A0F5CC8C700241C5F /* time.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = time.c; path = src/time.c; sourceTree = "<group>"; };
+		96032E4C0F5CC8D100241C5F /* time.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = time.h; path = src/time.h; sourceTree = "<group>"; };
+		960F0E7D0F3FB232000D88BF /* dispatch_apply.3 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = dispatch_apply.3; path = man/dispatch_apply.3; sourceTree = "<group>"; };
+		960F0E7E0F3FB232000D88BF /* dispatch_once.3 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = dispatch_once.3; path = man/dispatch_once.3; sourceTree = "<group>"; };
+		961B99350F3E83980006BC96 /* benchmark.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = benchmark.h; path = src/benchmark.h; sourceTree = "<group>"; };
+		961B994F0F3E85C30006BC96 /* object.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = object.h; path = src/object.h; sourceTree = "<group>"; };
+		963FDDE50F3FB6BD00BF2D00 /* dispatch_semaphore_create.3 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = dispatch_semaphore_create.3; path = man/dispatch_semaphore_create.3; sourceTree = "<group>"; };
+		965CD6340F3E806200D4E28D /* benchmark.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = benchmark.c; path = src/benchmark.c; sourceTree = "<group>"; };
+		965ECC200F3EAB71004DDD89 /* object_internal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = object_internal.h; path = src/object_internal.h; sourceTree = "<group>"; };
+		9661E56A0F3E7DDF00749F3E /* object.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = object.c; path = src/object.c; sourceTree = "<group>"; };
+		9676A0E00F3E755D00713ADB /* apply.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = apply.c; path = src/apply.c; sourceTree = "<group>"; };
+		96859A3D0EF71BAD003EB3FB /* dispatch_benchmark.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; name = dispatch_benchmark.3; path = man/dispatch_benchmark.3; sourceTree = "<group>"; };
+		96929D820F3EA1020041FF5D /* hw_shims.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = hw_shims.h; path = src/hw_shims.h; sourceTree = "<group>"; };
+		96929D830F3EA1020041FF5D /* os_shims.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = os_shims.h; path = src/os_shims.h; sourceTree = "<group>"; };
+		96929D950F3EA2170041FF5D /* queue_internal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = queue_internal.h; path = src/queue_internal.h; sourceTree = "<group>"; };
+		96A8AA860F41E7A400CD570B /* source.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = source.c; path = src/source.c; sourceTree = "<group>"; };
+		96BC39BC0F3EBAB100C59689 /* queue_private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = queue_private.h; path = src/queue_private.h; sourceTree = "<group>"; };
+		96C9553A0F3EAEDD000D2CA4 /* once.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = once.h; path = src/once.h; sourceTree = "<group>"; };
+		96DF70BD0F38FE3C0074BD99 /* once.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = once.c; path = src/once.c; sourceTree = "<group>"; };
+		D2AAC046055464E500DB518D /* libdispatch.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libdispatch.a; sourceTree = BUILT_PRODUCTS_DIR; };
+		FC0B34780FA2851C0080FFA0 /* source_internal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = source_internal.h; path = src/source_internal.h; sourceTree = "<group>"; };
+		FC36279C0E933ED80054F1A3 /* dispatch_queue_create.3 */ = {isa = PBXFileReference; explicitFileType = text.man; fileEncoding = 4; name = dispatch_queue_create.3; path = man/dispatch_queue_create.3; sourceTree = "<group>"; };
+		FC5C9C1D0EADABE3006E462D /* group.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = group.h; path = src/group.h; sourceTree = "<group>"; };
+		FC678DE80F97E0C300AB5993 /* dispatch_after.3 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = dispatch_after.3; path = man/dispatch_after.3; sourceTree = "<group>"; };
+		FC678DE90F97E0C300AB5993 /* dispatch_api.3 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = dispatch_api.3; path = man/dispatch_api.3; sourceTree = "<group>"; };
+		FC678DEA0F97E0C300AB5993 /* dispatch_async.3 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = dispatch_async.3; path = man/dispatch_async.3; sourceTree = "<group>"; };
+		FC678DEB0F97E0C300AB5993 /* dispatch_group_create.3 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = dispatch_group_create.3; path = man/dispatch_group_create.3; sourceTree = "<group>"; };
+		FC678DEC0F97E0C300AB5993 /* dispatch_time.3 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = dispatch_time.3; path = man/dispatch_time.3; sourceTree = "<group>"; };
+		FC7BED8A0E8361E600161930 /* queue.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = queue.c; path = src/queue.c; sourceTree = "<group>"; };
+		FC7BED8B0E8361E600161930 /* queue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = queue.h; path = src/queue.h; sourceTree = "<group>"; };
+		FC7BED8D0E8361E600161930 /* source.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = source.h; path = src/source.h; sourceTree = "<group>"; };
+		FC7BED8F0E8361E600161930 /* internal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = internal.h; path = src/internal.h; sourceTree = "<group>"; };
+		FC7BED900E8361E600161930 /* legacy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = legacy.h; path = src/legacy.h; sourceTree = "<group>"; };
+		FC7BED930E8361E600161930 /* private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = private.h; path = src/private.h; sourceTree = "<group>"; };
+		FC7BED950E8361E600161930 /* protocol.defs */ = {isa = PBXFileReference; explicitFileType = sourcecode.mig; fileEncoding = 4; name = protocol.defs; path = src/protocol.defs; sourceTree = "<group>"; };
+		FC7BED960E8361E600161930 /* dispatch.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = dispatch.h; path = src/dispatch.h; sourceTree = "<group>"; };
+		FC7BED970E8361E600161930 /* shims.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = shims.c; path = src/shims.c; sourceTree = "<group>"; };
+		FCEF047F0F5661960067401F /* source_private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = source_private.h; path = src/source_private.h; sourceTree = "<group>"; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+		D289987405E68DCB004EDB86 /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+		08FB7794FE84155DC02AAC07 /* libdispatch */ = {
+			isa = PBXGroup;
+			children = (
+				FC7BEDAA0E83625200161930 /* Public Headers */,
+				FC7BEDAF0E83626100161930 /* Private Headers */,
+				FC7BEDB60E8363DC00161930 /* Project Headers */,
+				08FB7795FE84155DC02AAC07 /* Source */,
+				C6A0FF2B0290797F04C91782 /* Documentation */,
+				1AB674ADFE9D54B511CA2CBB /* Products */,
+			);
+			name = libdispatch;
+			sourceTree = "<group>";
+		};
+		08FB7795FE84155DC02AAC07 /* Source */ = {
+			isa = PBXGroup;
+			children = (
+				965CD6340F3E806200D4E28D /* benchmark.c */,
+				9661E56A0F3E7DDF00749F3E /* object.c */,
+				9676A0E00F3E755D00713ADB /* apply.c */,
+				FC7BED8A0E8361E600161930 /* queue.c */,
+				96DF70BD0F38FE3C0074BD99 /* once.c */,
+				96032E4A0F5CC8C700241C5F /* time.c */,
+				721F5CCE0F15553500FF03A6 /* semaphore.c */,
+				96A8AA860F41E7A400CD570B /* source.c */,
+				FC7BED970E8361E600161930 /* shims.c */,
+				2EC9C9B70E8809EF00E2499A /* legacy.c */,
+				FC7BED950E8361E600161930 /* protocol.defs */,
+			);
+			name = Source;
+			sourceTree = "<group>";
+		};
+		1AB674ADFE9D54B511CA2CBB /* Products */ = {
+			isa = PBXGroup;
+			children = (
+				D2AAC046055464E500DB518D /* libdispatch.a */,
+			);
+			name = Products;
+			sourceTree = "<group>";
+		};
+		C6A0FF2B0290797F04C91782 /* Documentation */ = {
+			isa = PBXGroup;
+			children = (
+				FC678DE80F97E0C300AB5993 /* dispatch_after.3 */,
+				FC678DE90F97E0C300AB5993 /* dispatch_api.3 */,
+				FC678DEA0F97E0C300AB5993 /* dispatch_async.3 */,
+				FC678DEB0F97E0C300AB5993 /* dispatch_group_create.3 */,
+				FC678DEC0F97E0C300AB5993 /* dispatch_time.3 */,
+				72CC940D0ECCD5720031B751 /* dispatch.3 */,
+				960F0E7D0F3FB232000D88BF /* dispatch_apply.3 */,
+				96859A3D0EF71BAD003EB3FB /* dispatch_benchmark.3 */,
+				72CC940C0ECCD5720031B751 /* dispatch_object.3 */,
+				960F0E7E0F3FB232000D88BF /* dispatch_once.3 */,
+				963FDDE50F3FB6BD00BF2D00 /* dispatch_semaphore_create.3 */,
+				72B54F690EB169EB00DBECBA /* dispatch_source_create.3 */,
+				FC36279C0E933ED80054F1A3 /* dispatch_queue_create.3 */,
+			);
+			name = Documentation;
+			sourceTree = "<group>";
+		};
+		FC7BEDAA0E83625200161930 /* Public Headers */ = {
+			isa = PBXGroup;
+			children = (
+				96032E4C0F5CC8D100241C5F /* time.h */,
+				721F5C5C0F15520500FF03A6 /* semaphore.h */,
+				961B994F0F3E85C30006BC96 /* object.h */,
+				96C9553A0F3EAEDD000D2CA4 /* once.h */,
+				961B99350F3E83980006BC96 /* benchmark.h */,
+				72CC942F0ECCD8750031B751 /* base.h */,
+				FC7BED960E8361E600161930 /* dispatch.h */,
+				FC7BED8B0E8361E600161930 /* queue.h */,
+				FC7BED8D0E8361E600161930 /* source.h */,
+				FC5C9C1D0EADABE3006E462D /* group.h */,
+			);
+			name = "Public Headers";
+			sourceTree = "<group>";
+		};
+		FC7BEDAF0E83626100161930 /* Private Headers */ = {
+			isa = PBXGroup;
+			children = (
+				FC7BED930E8361E600161930 /* private.h */,
+				96BC39BC0F3EBAB100C59689 /* queue_private.h */,
+				FC7BED900E8361E600161930 /* legacy.h */,
+			);
+			name = "Private Headers";
+			sourceTree = "<group>";
+		};
+		FC7BEDB60E8363DC00161930 /* Project Headers */ = {
+			isa = PBXGroup;
+			children = (
+				965ECC200F3EAB71004DDD89 /* object_internal.h */,
+				96929D950F3EA2170041FF5D /* queue_internal.h */,
+				5A5D13AB0F6B280500197CC3 /* semaphore_internal.h */,
+				FC0B34780FA2851C0080FFA0 /* source_internal.h */,
+				FCEF047F0F5661960067401F /* source_private.h */,
+				96929D820F3EA1020041FF5D /* hw_shims.h */,
+				96929D830F3EA1020041FF5D /* os_shims.h */,
+				FC7BED8F0E8361E600161930 /* internal.h */,
+			);
+			name = "Project Headers";
+			sourceTree = "<group>";
+		};
+/* End PBXGroup section */
+
+/* Begin PBXHeadersBuildPhase section */
+		D2AAC043055464E500DB518D /* Headers */ = {
+			isa = PBXHeadersBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				72CC94300ECCD8750031B751 /* base.h in Headers */,
+				FC7BEDA50E8361E600161930 /* dispatch.h in Headers */,
+				FC7BED9A0E8361E600161930 /* queue.h in Headers */,
+				FC7BED9C0E8361E600161930 /* source.h in Headers */,
+				FC5C9C1E0EADABE3006E462D /* group.h in Headers */,
+				FC7BEDA20E8361E600161930 /* private.h in Headers */,
+				FC7BED9F0E8361E600161930 /* legacy.h in Headers */,
+				FC7BED9E0E8361E600161930 /* internal.h in Headers */,
+				721F5C5D0F15520500FF03A6 /* semaphore.h in Headers */,
+				961B99360F3E83980006BC96 /* benchmark.h in Headers */,
+				961B99500F3E85C30006BC96 /* object.h in Headers */,
+				96929D840F3EA1020041FF5D /* hw_shims.h in Headers */,
+				96929D850F3EA1020041FF5D /* os_shims.h in Headers */,
+				96929D960F3EA2170041FF5D /* queue_internal.h in Headers */,
+				965ECC210F3EAB71004DDD89 /* object_internal.h in Headers */,
+				96C9553B0F3EAEDD000D2CA4 /* once.h in Headers */,
+				96BC39BD0F3EBAB100C59689 /* queue_private.h in Headers */,
+				FCEF04800F5661960067401F /* source_private.h in Headers */,
+				96032E4D0F5CC8D100241C5F /* time.h in Headers */,
+				5A5D13AC0F6B280500197CC3 /* semaphore_internal.h in Headers */,
+				FC0B34790FA2851C0080FFA0 /* source_internal.h in Headers */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXHeadersBuildPhase section */
+
+/* Begin PBXLegacyTarget section */
+		721EB4790F69D26F00845379 /* testbots */ = {
+			isa = PBXLegacyTarget;
+			buildArgumentsString = testbots;
+			buildConfigurationList = 721EB4850F69D2A600845379 /* Build configuration list for PBXLegacyTarget "testbots" */;
+			buildPhases = (
+			);
+			buildToolPath = /usr/bin/make;
+			buildWorkingDirectory = testing;
+			dependencies = (
+			);
+			name = testbots;
+			passBuildSettingsInEnvironment = 0;
+			productName = testbots;
+		};
+		7276FCBA0EB10E0F00F7F487 /* test */ = {
+			isa = PBXLegacyTarget;
+			buildArgumentsString = test;
+			buildConfigurationList = 7276FCC80EB10E2300F7F487 /* Build configuration list for PBXLegacyTarget "test" */;
+			buildPhases = (
+			);
+			buildToolPath = /usr/bin/make;
+			buildWorkingDirectory = testing;
+			dependencies = (
+			);
+			name = test;
+			passBuildSettingsInEnvironment = 0;
+			productName = test;
+		};
+/* End PBXLegacyTarget section */
+
+/* Begin PBXNativeTarget section */
+		D2AAC045055464E500DB518D /* libdispatch */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = 1DEB91EB08733DB70010E9CD /* Build configuration list for PBXNativeTarget "libdispatch" */;
+			buildPhases = (
+				D2AAC043055464E500DB518D /* Headers */,
+				D2AAC044055464E500DB518D /* Sources */,
+				D289987405E68DCB004EDB86 /* Frameworks */,
+				2EC9C9800E846B5200E2499A /* ShellScript */,
+				4CED8B9D0EEDF8B600AF99AB /* ShellScript */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+			);
+			name = libdispatch;
+			productName = libdispatch;
+			productReference = D2AAC046055464E500DB518D /* libdispatch.a */;
+			productType = "com.apple.product-type.library.static";
+		};
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+		08FB7793FE84155DC02AAC07 /* Project object */ = {
+			isa = PBXProject;
+			buildConfigurationList = 1DEB91EF08733DB70010E9CD /* Build configuration list for PBXProject "libdispatch" */;
+			compatibilityVersion = "Xcode 3.1";
+			hasScannedForEncodings = 1;
+			mainGroup = 08FB7794FE84155DC02AAC07 /* libdispatch */;
+			projectDirPath = "";
+			projectRoot = "";
+			targets = (
+				D2AAC045055464E500DB518D /* libdispatch */,
+				7276FCBA0EB10E0F00F7F487 /* test */,
+				721EB4790F69D26F00845379 /* testbots */,
+			);
+		};
+/* End PBXProject section */
+
+/* Begin PBXShellScriptBuildPhase section */
+		2EC9C9800E846B5200E2499A /* ShellScript */ = {
+			isa = PBXShellScriptBuildPhase;
+			buildActionMask = 8;
+			files = (
+			);
+			inputPaths = (
+			);
+			outputPaths = (
+			);
+			runOnlyForDeploymentPostprocessing = 1;
+			shellPath = /bin/sh;
+			shellScript = "# private.h supersedes dispatch.h where available\nmv \"$DSTROOT\"/usr/local/include/dispatch/private.h \"$DSTROOT\"/usr/local/include/dispatch/dispatch.h\nln -sf dispatch.h \"$DSTROOT\"/usr/local/include/dispatch/private.h\n\n# keep events.h around for a little while\nln -sf ../../../include/dispatch/source.h \"$DSTROOT\"/usr/local/include/dispatch/events.h";
+		};
+		4CED8B9D0EEDF8B600AF99AB /* ShellScript */ = {
+			isa = PBXShellScriptBuildPhase;
+			buildActionMask = 8;
+			files = (
+			);
+			inputPaths = (
+			);
+			outputPaths = (
+			);
+			runOnlyForDeploymentPostprocessing = 1;
+			shellPath = /bin/sh;
+			shellScript = "#!/bin/sh\n\nmkdir -p $DSTROOT/usr/share/man/man3 || true\nmkdir -p $DSTROOT/usr/local/share/man/man3 || true\n\n# Copy man pages\ncd $SRCROOT/man\nBASE_PAGES=\"dispatch.3 dispatch_after.3 dispatch_api.3 dispatch_apply.3 dispatch_async.3 dispatch_group_create.3 dispatch_object.3 dispatch_once.3 dispatch_queue_create.3 dispatch_semaphore_create.3 dispatch_source_create.3 dispatch_time.3\"\n\nPRIVATE_PAGES=\"dispatch_benchmark.3\"\n\ncp ${BASE_PAGES} $DSTROOT/usr/share/man/man3\ncp ${PRIVATE_PAGES} $DSTROOT/usr/local/share/man/man3\n\n# Make hard links (lots of hard links)\n\ncd $DSTROOT/usr/local/share/man/man3\nln -f dispatch_benchmark.3 dispatch_benchmark_f.3\nchown ${INSTALL_OWNER}:${INSTALL_GROUP} $PRIVATE_PAGES\nchmod $INSTALL_MODE_FLAG $PRIVATE_PAGES\n\n\ncd $DSTROOT/usr/share/man/man3\n\nchown ${INSTALL_OWNER}:${INSTALL_GROUP} $BASE_PAGES\nchmod $INSTALL_MODE_FLAG $BASE_PAGES\n\nln -f dispatch_after.3 dispatch_after_f.3\nln -f dispatch_apply.3 dispatch_apply_f.3\nln -f dispatch_once.3 dispatch_once_f.3\n\nfor m in dispatch_async_f dispatch_sync dispatch_sync_f; do\n\tln -f dispatch_async.3 ${m}.3\ndone\n\nfor m in dispatch_group_enter dispatch_group_leave dispatch_group_wait dispatch_group_async dispatch_group_async_f dispatch_group_notify dispatch_group_notify_f; do\n\tln -f dispatch_group_create.3 ${m}.3\ndone\n\nfor m in dispatch_retain dispatch_release dispatch_suspend dispatch_resume dispatch_get_context dispatch_set_context dispatch_set_finalizer_f; do\n\tln -f dispatch_object.3 ${m}.3\ndone\n\nfor m in dispatch_semaphore_signal dispatch_semaphore_wait; do\n\tln -f dispatch_semaphore_create.3 ${m}.3\ndone\n\nfor m in dispatch_get_current_queue dispatch_main dispatch_get_main_queue dispatch_get_global_queue dispatch_queue_get_label dispatch_set_target_queue; do\n\tln -f dispatch_queue_create.3 ${m}.3\ndone\n\nfor m in dispatch_source_set_event_handler dispatch_source_set_event_handler_f dispatch_source_set_cancel_handler dispatch_source_set_cancel_handler_f dispatch_source_cancel dispatch_source_testcancel dispatch_source_get_handle dispatch_source_get_mask dispatch_source_get_data dispatch_source_merge_data dispatch_source_set_timer; do\n\tln -f dispatch_source_create.3 ${m}.3\ndone\n\nln -f dispatch_time.3 dispatch_walltime.3";
+		};
+/* End PBXShellScriptBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+		D2AAC044055464E500DB518D /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				FC7BEDA40E8361E600161930 /* protocol.defs in Sources */,
+				FC7BED990E8361E600161930 /* queue.c in Sources */,
+				FC7BEDA60E8361E600161930 /* shims.c in Sources */,
+				2EC9C9B80E8809EF00E2499A /* legacy.c in Sources */,
+				721F5CCF0F15553500FF03A6 /* semaphore.c in Sources */,
+				96DF70BE0F38FE3C0074BD99 /* once.c in Sources */,
+				9676A0E10F3E755D00713ADB /* apply.c in Sources */,
+				9661E56B0F3E7DDF00749F3E /* object.c in Sources */,
+				965CD6350F3E806200D4E28D /* benchmark.c in Sources */,
+				96A8AA870F41E7A400CD570B /* source.c in Sources */,
+				96032E4B0F5CC8C700241C5F /* time.c in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXSourcesBuildPhase section */
+
+/* Begin XCBuildConfiguration section */
+		1DEB91ED08733DB70010E9CD /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				COPY_PHASE_STRIP = NO;
+				CURRENT_PROJECT_VERSION = "$(RC_ProjectSourceVersion)";
+				EXECUTABLE_PREFIX = "";
+				GCC_CW_ASM_SYNTAX = NO;
+				GCC_ENABLE_CPP_EXCEPTIONS = NO;
+				GCC_ENABLE_CPP_RTTI = NO;
+				GCC_ENABLE_OBJC_EXCEPTIONS = NO;
+				GCC_OPTIMIZATION_LEVEL = s;
+				GCC_PREPROCESSOR_DEFINITIONS = "__DARWIN_NON_CANCELABLE=1";
+				GENERATE_MASTER_OBJECT_FILE = NO;
+				INSTALL_PATH = /usr/local/lib/system;
+				LINK_WITH_STANDARD_LIBRARIES = NO;
+				OTHER_CFLAGS = (
+					"-fno-unwind-tables",
+					"-fno-exceptions",
+					"-I$(SDKROOT)/System/Library/Frameworks/System.framework/PrivateHeaders",
+					"-fdiagnostics-show-option",
+					"-fsched-interblock",
+					"-freorder-blocks",
+					"-Xarch_x86_64",
+					"-momit-leaf-frame-pointer",
+					"-Xarch_i386",
+					"-momit-leaf-frame-pointer",
+				);
+				OTHER_CFLAGS_debug = "-O0 -fstack-protector -fno-inline -DDISPATCH_DEBUG=1";
+				PRIVATE_HEADERS_FOLDER_PATH = /usr/local/include/dispatch;
+				PRODUCT_NAME = libdispatch;
+				PUBLIC_HEADERS_FOLDER_PATH = /usr/include/dispatch;
+				SEPARATE_STRIP = NO;
+				VERSIONING_SYSTEM = "apple-generic";
+				VERSION_INFO_PREFIX = __;
+			};
+			name = Release;
+		};
+		1DEB91F108733DB70010E9CD /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = NO;
+				ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
+				BUILD_VARIANTS = (
+					normal,
+					debug,
+					profile,
+				);
+				COPY_PHASE_STRIP = NO;
+				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+				GCC_ENABLE_PASCAL_STRINGS = NO;
+				GCC_OPTIMIZATION_LEVEL = s;
+				GCC_STRICT_ALIASING = YES;
+				GCC_SYMBOLS_PRIVATE_EXTERN = YES;
+				GCC_TREAT_WARNINGS_AS_ERRORS = YES;
+				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+				GCC_WARN_ABOUT_MISSING_NEWLINE = YES;
+				GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;
+				GCC_WARN_ABOUT_RETURN_TYPE = YES;
+				GCC_WARN_SHADOW = YES;
+				GCC_WARN_UNUSED_VARIABLE = YES;
+				LINK_WITH_STANDARD_LIBRARIES = YES;
+				ONLY_ACTIVE_ARCH = NO;
+				OTHER_CFLAGS = (
+					"-I$(SDKROOT)/System/Library/Frameworks/System.framework/PrivateHeaders",
+					"-fdiagnostics-show-option",
+					"-fsched-interblock",
+					"-freorder-blocks",
+					"-Xarch_x86_64",
+					"-momit-leaf-frame-pointer",
+					"-Xarch_i386",
+					"-momit-leaf-frame-pointer",
+				);
+				OTHER_CFLAGS_debug = "-O0 -fstack-protector -fno-inline -DDISPATCH_DEBUG=1";
+				PREBINDING = NO;
+				STRIP_INSTALLED_PRODUCT = NO;
+				WARNING_CFLAGS = (
+					"-Wall",
+					"-Wextra",
+					"-Waggregate-return",
+					"-Wfloat-equal",
+					"-Wpacked",
+					"-Wmissing-declarations",
+					"-Wstrict-overflow=4",
+					"-Wstrict-aliasing=2",
+				);
+			};
+			name = Release;
+		};
+		721EB47A0F69D26F00845379 /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+			};
+			name = Release;
+		};
+		7276FCBB0EB10E0F00F7F487 /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+			};
+			name = Release;
+		};
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+		1DEB91EB08733DB70010E9CD /* Build configuration list for PBXNativeTarget "libdispatch" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				1DEB91ED08733DB70010E9CD /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		1DEB91EF08733DB70010E9CD /* Build configuration list for PBXProject "libdispatch" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				1DEB91F108733DB70010E9CD /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		721EB4850F69D2A600845379 /* Build configuration list for PBXLegacyTarget "testbots" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				721EB47A0F69D26F00845379 /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		7276FCC80EB10E2300F7F487 /* Build configuration list for PBXLegacyTarget "test" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				7276FCBB0EB10E0F00F7F487 /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+/* End XCConfigurationList section */
+	};
+	rootObject = 08FB7793FE84155DC02AAC07 /* Project object */;
+}

Added: trunk/man/dispatch.3
===================================================================
--- trunk/man/dispatch.3	                        (rev 0)
+++ trunk/man/dispatch.3	2009-08-30 01:07:28 UTC (rev 2)
@@ -0,0 +1,38 @@
+.\" Copyright (c) 2008-2009 Apple Inc. All rights reserved.
+.Dd May 1, 2009
+.Dt dispatch 3
+.Os Darwin
+.Sh NAME
+.Nm dispatch
+.Nd the dispatch framework
+.Sh SYNOPSIS
+.Fd #include <dispatch/dispatch.h>
+.Sh DESCRIPTION
+The dispatch framework allows blocks to be scheduled for asynchronous and
+concurrent execution via the core functions described in
+.Xr dispatch_async 3 and
+.Xr dispatch_apply 3 .
+.Pp
+Dispatch queues are the basic units of organization of blocks. Several queues
+are created by default, and applications may create additional queues for their
+own use. See
+.Xr dispatch_queue_create 3
+for more information.
+.Pp
+Dispatch groups allow applications to track the progress of blocks submitted to
+queues and take action when the blocks complete. See
+.Xr dispatch_group_create 3
+for more information.
+.Pp
+The dispatch framework also provides functions to monitor underlying system
+events and automatically submit event handler blocks to dispatch queues.
+.Sh SEE ALSO
+.Xr dispatch_async 3 ,
+.Xr dispatch_object 3 ,
+.Xr dispatch_queue_create 3 ,
+.Xr dispatch_group_create 3 ,
+.Xr dispatch_source_create 3 ,
+.Xr dispatch_benchmark 3 ,
+.Xr dispatch_time 3 ,
+.Xr dispatch_apply 3 ,
+.Xr dispatch_once 3 .

Added: trunk/man/dispatch_after.3
===================================================================
--- trunk/man/dispatch_after.3	                        (rev 0)
+++ trunk/man/dispatch_after.3	2009-08-30 01:07:28 UTC (rev 2)
@@ -0,0 +1,57 @@
+.\" Copyright (c) 2008-2009 Apple Inc. All rights reserved.
+.Dd May 1, 2009
+.Dt dispatch_after 3
+.Os Darwin
+.Sh NAME
+.Nm dispatch_after
+.Nd schedule blocks for deferred execution
+.Sh SYNOPSIS
+.Fd #include <dispatch/dispatch.h>
+.Ft void
+.Fo dispatch_after
+.Fa "dispatch_time_t when" "dispatch_queue_t queue" "void (^block)(void)"
+.Fc
+.Ft void
+.Fo dispatch_after_f
+.Fa "dispatch_time_t when" "dispatch_queue_t queue" "void *context" "void (^function)(void *)"
+.Fc
+.Sh DESCRIPTION
+The
+.Fn dispatch_after
+function submits the
+.Fa block
+to the given
+.Fa queue
+at the time specified by the
+.Fa when
+parameter.
+The
+.Fa when
+parameter is a value created by
+.Fn dispatch_time
+or
+.Fn dispatch_walltime .
+.Pp
+For a more detailed description about submitting blocks to queues, see
+.Xr dispatch_async 3 .
+.Sh CAVEATS
+Specifying
+.Vt DISPATCH_TIME_NOW
+as the
+.Fa when
+parameter
+is supported, but is not as efficient as calling
+.Fn dispatch_async .
+The result of passing
+.Vt DISPATCH_TIME_FOREVER
+as the
+.Fa when
+parameter is undefined.
+.Sh FUNDAMENTALS
+The
+.Fn dispatch_after
+function is a wrapper around
+.Fn dispatch_after_f .
+.Sh SEE ALSO
+.Xr dispatch_async 3 ,
+.Xr dispatch_time 3

Added: trunk/man/dispatch_api.3
===================================================================
--- trunk/man/dispatch_api.3	                        (rev 0)
+++ trunk/man/dispatch_api.3	2009-08-30 01:07:28 UTC (rev 2)
@@ -0,0 +1,44 @@
+.\" Copyright (c) 2008-2009 Apple Inc. All rights reserved.
+.Dd May 1, 2009
+.Dt dispatch_api 3
+.Os Darwin
+.Sh NAME
+.Nm dispatch_api
+.Nd Designing API using dispatch
+.Sh DESCRIPTION
+The following is a brief summary of some of the common design patterns to
+consider when designing and implementing API in terms of dispatch queues
+and blocks.
+.Pp
+A general recommendation is to allow both a callback block and target dispatch
+queue to be specified. This gives the application the greatest flexibility in
+handling asynchronous events.
+.Pp
+It's also recommended that interfaces take only a single block as the last
+parameter. This is both for consistency across projects, as well as the visual
+aesthetics of multiline blocks that are declared inline. The dispatch queue to
+which the block will be submitted should immediately precede the block argument
+(second-to-last argument). For example:
+.Pp
+.Bd -literal -offset indent
+read_async(file, callback_queue, ^{
+	printf("received callback.\n");
+});
+.Ed
+.Pp
+When function pointer alternatives to interfaces that take blocks are provided,
+the argument order of the function signature should be identical to the block
+variant; with the exception that the block argument is replaced with a context
+pointer, and a new last parameter is added, which is the function to call.
+.Pp
+The function based callback should pass the context pointer as the first
+argument, and the subsequent arguments should be identical to the block based
+variant (albeit offset by one in order).
+.Pp
+It is also important to use consistent naming. The dispatch API, for example,
+uses the suffix "_f" for function based variants.
+.Pp
+.Sh SEE ALSO
+.Xr dispatch 3 ,
+.Xr dispatch_async 3 ,
+.Xr dispatch_queue_create 3

Added: trunk/man/dispatch_apply.3
===================================================================
--- trunk/man/dispatch_apply.3	                        (rev 0)
+++ trunk/man/dispatch_apply.3	2009-08-30 01:07:28 UTC (rev 2)
@@ -0,0 +1,80 @@
+.\" Copyright (c) 2008-2009 Apple Inc. All rights reserved.
+.Dd May 1, 2009
+.Dt dispatch_apply 3
+.Os Darwin
+.Sh NAME
+.Nm dispatch_apply
+.Nd schedule blocks for iterative execution
+.Sh SYNOPSIS
+.Fd #include <dispatch/dispatch.h>
+.Ft void
+.Fo dispatch_apply
+.Fa "size_t iterations" "dispatch_queue_t queue" "void (^block)(size_t)"
+.Fc
+.Ft void
+.Fo dispatch_apply_f
+.Fa "size_t iterations" "dispatch_queue_t queue" "void *context" "void (*function)(void *, size_t)"
+.Fc
+.Sh DESCRIPTION
+The
+.Fn dispatch_apply
+function provides data-level concurrency through a "for (;;)" loop like primitive:
+.Bd -literal
+dispatch_queue_t the_queue = dispatch_get_concurrent_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT);
+size_t iterations = 10;
+
+// 'idx' is zero indexed, just like:
+// for (idx = 0; idx < iterations; idx++)
+
+dispatch_apply(iterations, the_queue, ^(size_t idx) {
+	printf("%zu\\n", idx);
+});
+.Ed
+.Pp
+Like a "for (;;)" loop, the
+.Fn dispatch_apply
+function is synchronous.
+If asynchronous behavior is desired, please wrap the call to
+.Fn dispatch_apply
+with a call to
+.Fn dispatch_async
+against another queue.
+.Pp
+Sometimes, when the block passed to
+.Fn dispatch_apply
+is simple, the use of striding can tune performance.
+Calculating the optimal stride is best left to experimentation.
+Start with a stride of one and work upwards until the desired performance is
+achieved (perhaps using a power of two search):
+.Bd -literal
+#define	STRIDE	3
+
+dispatch_apply(count / STRIDE, queue, ^(size_t idx) {
+	size_t j = idx * STRIDE;
+	size_t j_stop = j + STRIDE;
+	do {
+		printf("%zu\\n", j++);
+	} while (j < j_stop);
+});
+
+size_t i;
+for (i = count - (count % STRIDE); i < count; i++) {
+	printf("%zu\\n", i);
+}
+.Ed
+.Sh FUNDAMENTALS
+Conceptually,
+.Fn dispatch_apply
+is a convenient wrapper around
+.Fn dispatch_async
+and a semaphore to wait for completion.
+In practice, the dispatch library optimizes this function.
+.Pp
+The
+.Fn dispatch_apply
+function is a wrapper around
+.Fn dispatch_apply_f .
+.Sh SEE ALSO
+.Xr dispatch_async 3 ,
+.Xr dispatch_semaphore_create 3 ,
+.Xr dispatch_queue_create 3

Added: trunk/man/dispatch_async.3
===================================================================
--- trunk/man/dispatch_async.3	                        (rev 0)
+++ trunk/man/dispatch_async.3	2009-08-30 01:07:28 UTC (rev 2)
@@ -0,0 +1,234 @@
+.\" Copyright (c) 2008-2009 Apple Inc. All rights reserved.
+.Dd May 1, 2009
+.Dt dispatch_async 3
+.Os Darwin
+.Sh NAME
+.Nm dispatch_async ,
+.Nm dispatch_sync
+.Nd schedule blocks for execution
+.Sh SYNOPSIS
+.Fd #include <dispatch/dispatch.h>
+.Ft void
+.Fo dispatch_async
+.Fa "dispatch_queue_t queue" "void (^block)(void)"
+.Fc
+.Ft void
+.Fo dispatch_sync
+.Fa "dispatch_queue_t queue" "void (^block)(void)"
+.Fc
+.Ft void
+.Fo dispatch_async_f
+.Fa "dispatch_queue_t queue" "void *context" "void (*function)(void *)"
+.Fc
+.Ft void
+.Fo dispatch_sync_f
+.Fa "dispatch_queue_t queue" "void *context" "void (*function)(void *)"
+.Fc
+.Sh DESCRIPTION
+The
+.Fn dispatch_async
+and
+.Fn dispatch_sync
+functions schedule blocks for concurrent execution within the
+.Xr dispatch 3
+framework. Blocks are submitted to a queue which dictates the policy for their
+execution. See
+.Xr dispatch_queue_create 3
+for more information about creating dispatch queues.
+.Pp
+These functions support efficient temporal synchronization, background
+concurrency and data-level concurrency. These same functions can also be used
+for efficient notification of the completion of asynchronous blocks (a.k.a.
+callbacks).
+.Sh TEMPORAL SYNCHRONIZATION
+Synchronization is often required when multiple threads of execution access
+shared data concurrently. The simplest form of synchronization is
+mutual-exclusion (a lock), whereby different subsystems execute concurrently
+until a shared critical section is entered. In the
+.Xr pthread 3
+family of procedures, temporal synchronization is accomplished like so:
+.Bd -literal -offset indent
+int r = pthread_mutex_lock(&my_lock);
+assert(r == 0);
+
+// critical section
+
+r = pthread_mutex_unlock(&my_lock);
+assert(r == 0);
+.Ed
+.Pp
+The
+.Fn dispatch_sync
+function may be used with a serial queue to accomplish the same style of
+synchronization. For example:
+.Bd -literal -offset indent
+dispatch_sync(my_queue, ^{
+	// critical section
+});
+.Ed
+.Pp
+In addition to providing a more concise expression of synchronization, this
+approach is less error prone as the critical section cannot be accidentally
+left without restoring the queue to a reentrant state.
+.Pp
+The
+.Fn dispatch_async
+function may be used to implement deferred critical sections when the result
+of the block is not needed locally. Deferred critical sections have the same
+synchronization properties as the above code, but are non-blocking and
+therefore more efficient to perform. For example:
+.Bd -literal
+dispatch_async(my_queue, ^{
+	// critical section
+});
+.Ed
+.Sh BACKGROUND CONCURRENCY
+.The
+.Fn dispatch_async
+function may be used to execute trivial backgound tasks on a global concurrent
+queue. For example:
+.Bd -literal
+dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0), ^{
+	// background operation
+});
+.Ed
+.Pp
+This approach is an efficient replacement for
+.Xr pthread_create 3 .
+.Sh COMPLETION CALLBACKS
+Completion callbacks can be accomplished via nested calls to the
+.Fn dispatch_async
+function. It is important to remember to retain the destination queue before the
+first call to
+.Fn dispatch_async ,
+and to release that queue at the end of the completion callback to ensure the
+destination queue is not deallocated while the completion callback is pending.
+For example:
+.Bd -literal
+void
+async_read(object_t obj,
+	void *where, size_t bytes,
+	dispatch_queue_t destination_queue,
+	void (^reply_block)(ssize_t r, int err))
+{
+	// There are better ways of doing async I/O.
+	// This is just an example of nested blocks.
+
+	dispatch_retain(destination_queue);
+	
+	dispatch_async(obj->queue, ^{
+		ssize_t r = read(obj->fd, where, bytes);
+		int err = errno;
+
+		dispatch_async(destination_queue, ^{
+			reply_block(r, err);
+		}); 
+		dispatch_release(destination_queue);
+	});
+}
+.Ed
+.Sh RECURSIVE LOCKS
+While
+.Fn dispatch_sync
+can replace a lock, it cannot replace a recursive lock. Unlike locks, queues
+support both asynchronous and synchrnous operations, and those operations are
+ordered by definition. A recursive call to
+.Fn dispatch_sync
+causes a simple deadlock as the currently executing block waits for the next
+block to complete, but the next block will not start until the currently
+running block completes.
+.Pp
+As the dispatch framework was designed, we studied recursive locks. We found
+that the vast majority of recursive locks are deployed retroactively when
+ill-defined lock hierarchies are discovered. As a consequence, the adoption of
+recursive locks often mutates obvious bugs into obscure ones. This study also
+revealed an insight: if reentrancy is unavoidable, then reader/writer locks are
+preferable to recursive locks. Disciplined use of reader/writer locks enable
+reentrancy only when reentrancy is safe (the "read" side of the lock).
+.Pp
+Nevertheless, if it is absolutely necessary, what follows is an imperfect way of
+implementing recursive locks using the dispatch framework:
+.Bd -literal
+void
+sloppy_lock(object_t object, void (^block)(void))
+{
+	if (object->owner == pthread_self()) {
+		return block();
+	}
+	dispatch_sync(object->queue, ^{
+		object->owner = pthread_self();
+		block();
+		object->owner = NULL;
+	});
+}
+.Ed
+.Pp
+The above example does not solve the case where queue A runs on thread X which
+calls
+.Fn dispatch_sync
+against queue B which runs on thread Y which recursively calls
+.Fn dispatch_sync
+against queue A, which deadlocks both examples. This is bug-for-bug compatible
+with nontrivial pthread usage. In fact, nontrivial reentrancy is impossible to
+support in recursive locks once the ultimate level of reentrancy is deployed
+(IPC or RPC). 
+.Sh IMPLIED REFERENCES
+Synchronous functions within the dispatch framework hold an implied reference
+on the target queue. In other words, the synchronous function borrows the
+reference of the calling function (this is valid because the calling function
+is blocked waiting for the result of the synchronous function, and therefore
+cannot modify the reference count of the target queue until after the
+synchronous function has returned).
+For example:
+.Bd -literal
+queue = dispatch_queue_create("com.example.queue", NULL);
+assert(queue);
+dispatch_sync(queue, ^{
+	do_something();
+	//dispatch_release(queue); // NOT SAFE -- dispatch_sync() is still using 'queue'
+});
+dispatch_release(queue); // SAFELY balanced outside of the block provided to dispatch_sync()
+.Ed
+.Pp
+This is in contrast to asynchronous functions which must retain both the block
+and target queue for the duration of the asynchronous operation (as the calling
+function may immediately release its interest in these objects).
+.Sh FUNDAMENTALS
+Conceptually,
+.Fn dispatch_sync
+is a convenient wrapper around
+.Fn dispatch_async
+with the addition of a semaphore to wait for completion of the block, and a
+wrapper around the block to signal its completion. See
+.Xr dispatch_semaphore_create 3
+for more information about dispatch semaphores. The actual implementation of the
+.Fn dispatch_sync
+function may be optimized and differ from the above description.
+.Pp
+The
+.Fn dispatch_async
+function is a wrapper around
+.Fn dispatch_async_f .
+The application-defined
+.Fa context
+parameter is passed to the
+.Fa function
+when it is invoked on the target
+.Fa queue .
+.Pp
+The
+.Fn dispatch_sync
+function is a wrapper around
+.Fn dispatch_sync_f .
+The application-defined
+.Fa context
+parameter is passed to the
+.Fa function
+when it is invoked on the target
+.Fa queue .
+.Pp
+.Sh SEE ALSO
+.Xr dispatch_once 3 ,
+.Xr dispatch_queue_create 3 ,
+.Xr dispatch_semaphore_create 3 ,
+.Xr dispatch_apply 3

Added: trunk/man/dispatch_benchmark.3
===================================================================
--- trunk/man/dispatch_benchmark.3	                        (rev 0)
+++ trunk/man/dispatch_benchmark.3	2009-08-30 01:07:28 UTC (rev 2)
@@ -0,0 +1,55 @@
+.\" Copyright (c) 2008-2009 Apple Inc. All rights reserved.
+.Dd May 1, 2009
+.Dt dispatch_benchmark 3
+.Os Darwin
+.Sh NAME
+.Nm dispatch_benchmark
+.Nd Measures block execution time
+.Sh SYNOPSIS
+.Fd #include <dispatch/dispatch.h>
+.Ft uint64_t
+.Fo dispatch_benchmark
+.Fa "size_t count" "void (^block)(void)"
+.Fc
+.Sh DESCRIPTION
+The
+.Fn dispatch_benchmark
+function executes the given
+.Fa block
+multiple times according to the
+.Fa count
+variable and then returns the average number of nanoseconds per execution.
+This function is for debugging and performance analysis work.
+For the best
+results, pass a high count value to
+.Fn dispatch_benchmark .
+When benchmarking concurrent code, please compare the
+serial version of the code against the concurrent version, and compare the
+concurrent version on different classes of hardware.
+Please look for inflection
+points with various data sets and keep the following facts in mind:
+.Pp
+.Bl -bullet -offset indent -compact
+.It
+Code bound by computational bandwidth may be inferred by proportional
+changes in performance as concurrency is increased.
+.It
+Code bound by memory bandwidth may be inferred by negligible changes in
+performance as concurrency is increased.
+.It
+Code bound by critical sections may be inferred by retrograde changes in
+performance as concurrency is increased.
+.Bl -bullet -offset indent -compact
+.It
+Intentional: locks, mutexes, and condition variables.
+.It
+Accidental: unrelated and frequently modified data on the same cache-line.
+.El
+.El
+.Sh RETURN VALUE
+The
+.Fn dispatch_benchmark
+function returns the average number of nanoseconds the given block takes to
+execute.
+.Sh SEE ALSO
+.Xr dispatch 3

Added: trunk/man/dispatch_group_create.3
===================================================================
--- trunk/man/dispatch_group_create.3	                        (rev 0)
+++ trunk/man/dispatch_group_create.3	2009-08-30 01:07:28 UTC (rev 2)
@@ -0,0 +1,149 @@
+.\" Copyright (c) 2008-2009 Apple Inc. All rights reserved.
+.Dd May 1, 2009
+.Dt dispatch_group_create 3
+.Os Darwin
+.Sh NAME
+.Nm dispatch_group_create ,
+.Nm dispatch_group_async ,
+.Nm dispatch_group_wait ,
+.Nm dispatch_group_notify
+.Nd group blocks submitted to queues
+.Sh SYNOPSIS
+.Fd #include <dispatch/dispatch.h>
+.Ft dispatch_group_t
+.Fo dispatch_group_create
+.Fa void
+.Fc
+.Ft void
+.Fo dispatch_group_enter
+.Fa "dispatch_group_t group"
+.Fc
+.Ft void
+.Fo dispatch_group_leave
+.Fa "dispatch_group_t group"
+.Fc
+.Ft long
+.Fo dispatch_group_wait
+.Fa "dispatch_group_t group" "dispatch_time_t timeout"
+.Fc
+.Ft void
+.Fo dispatch_group_notify
+.Fa "dispatch_group_t group" "dispatch_queue_t queue" "void (^block)(void)"
+.Fc
+.Ft void
+.Fo dispatch_group_notify_f
+.Fa "dispatch_group_t group" "dispatch_queue_t queue" "void *context" "void (*function)(void *)"
+.Fc
+.Ft void
+.Fo dispatch_group_async
+.Fa "dispatch_group_t group" "dispatch_queue_t queue" "void (^block)(void)"
+.Fc
+.Ft void
+.Fo dispatch_group_async_f
+.Fa "dispatch_group_t group" "dispatch_queue_t queue" "void *context" "void (*function)(void *)"
+.Fc
+.Sh DESCRIPTION
+A dispatch group is an association of one or more blocks submitted to dispatch
+queues for asynchronous invocation.
+Applications may use dispatch groups to
+wait for the completion of blocks associated with the group.
+.Pp
+The
+.Fn dispatch_group_create
+function returns a new and empty dispatch group.
+.Pp
+The
+.Fn dispatch_group_enter
+and
+.Fn dispatch_group_leave
+functions update the number of blocks running within a group.
+.Pp
+The
+.Fn dispatch_group_wait
+function waits until all blocks associated with the
+.Fa group
+have completed, or until the specified
+.Fa timeout
+has elapsed.
+If the
+.Fa group
+becomes empty within the specified amount of time, the function will return zero
+indicating success. Otherwise, a non-zero return code will be returned.
+When
+.Va DISPATCH_TIME_FOREVER
+is passed as the
+.Fa timeout ,
+calls to this function will wait an unlimited amount of time until the group
+becomes empty and the return value is always zero.
+.Pp
+The
+.Fn dispatch_group_notify
+function provides asynchronous notification of the completion of the blocks
+associated with the
+.Fa group
+by submitting the
+.Fa block
+to the specified
+.Fa queue 
+once all blocks associated with the
+.Fa group
+have completed.
+The system holds a reference to the dispatch group while an asynchronous
+notification is pending, therefore it is valid to release the
+.Fa group
+after setting a notification block.
+The group will be empty at the time the notification block is submitted to the
+target queue. The group may either be released with
+.Fn dispatch_release
+or reused for additional operations.
+.Pp
+The
+.Fn dispatch_group_async
+convenience function behaves like so:
+.Bd -literal
+void
+dispatch_group_async(dispatch_group_t group, dispatch_queue_t queue, dispatch_block_t block)
+{
+	dispatch_retain(group);
+	dispatch_group_enter(group);
+	dispatch_async(queue, ^{
+		block();
+		dispatch_group_leave(group);
+		dispatch_release(group);
+	});
+}
+.Ed
+.Sh RETURN VALUE
+The
+.Fn dispatch_group_create
+function returns NULL on failure and non-NULL on success.
+.Pp
+The
+.Fn dispatch_group_wait
+function returns zero upon success and non-zero after the timeout expires.
+If the timeout is
+.Va DISPATCH_TIME_FOREVER ,
+then
+.Fn dispatch_group_wait
+waits forever and always returns zero.
+.Sh MEMORY MODEL
+Dispatch groups are retained and released via calls to
+.Fn dispatch_retain
+and
+.Fn dispatch_release .
+.Sh FUNDAMENTALS
+The
+.Fn dispatch_group_async
+and
+.Fn dispatch_group_notify
+functions are wrappers around
+.Fn dispatch_group_async_f
+and
+.Fn dispatch_group_notify_f
+respectively.
+.Sh SEE ALSO
+.Xr dispatch_object 3 ,
+.Xr dispatch_async 3 ,
+.Xr dispatch_time 3 ,
+.Xr dispatch_queue_create 3 ,
+.Xr dispatch_semaphore_create 3

Added: trunk/man/dispatch_object.3
===================================================================
--- trunk/man/dispatch_object.3	                        (rev 0)
+++ trunk/man/dispatch_object.3	2009-08-30 01:07:28 UTC (rev 2)
@@ -0,0 +1,99 @@
+.\" Copyright (c) 2008-2009 Apple Inc. All rights reserved.
+.Dd May 1, 2009
+.Dt dispatch_object 3
+.Os Darwin
+.Sh NAME
+.Nm dispatch_object
+.Nd General manipulation of dispatch objects
+.Sh SYNOPSIS
+.Fd #include <dispatch/dispatch.h>
+.Ft void
+.Fo dispatch_retain
+.Fa "dispatch_object_t object"
+.Fc
+.Ft void
+.Fo dispatch_release
+.Fa "dispatch_object_t object"
+.Fc
+.Ft void
+.Fo dispatch_suspend
+.Fa "dispatch_object_t object"
+.Fc
+.Ft void
+.Fo dispatch_resume
+.Fa "dispatch_object_t object"
+.Fc
+.Ft "void *"
+.Fo dispatch_get_context
+.Fa "dispatch_object_t object"
+.Fc
+.Ft void
+.Fo dispatch_set_context
+.Fa "dispatch_object_t object"
+.Fa "void *context"
+.Fc
+.Ft void
+.Fo dispatch_set_finalizer_f
+.Fa "dispatch_object_t object"
+.Fa "dispatch_function_t finalizer"
+.Fc
+.Sh DESCRIPTION
+Dispatch objects share functions for coordinating memory management, suspension,
+cancellation and context pointers. While all dispatch objects are retainable,
+not all objects support suspension, context pointers or finalizers (currently
+only queues and sources support these additional interfaces).
+.Sh MEMORY MANGEMENT
+Objects returned by creation functions in the dispatch framework may be
+uniformly retained and released with the functions
+.Fn dispatch_retain
+and
+.Fn dispatch_release
+respectively.
+.Pp
+The dispatch framework does not guarantee that any given client has the last or
+only reference to a given object. Objects may be retained internally by the
+system.
+.Sh SUSPENSION
+The invocation of blocks on dispatch queues or dispatch sources may be suspended
+or resumed with the functions
+.Fn dispatch_suspend
+and
+.Fn dispatch_resume 
+respectively.
+The dispatch framework always checks the suspension status before executing a
+block, but such changes never affect a block during execution (non-preemptive).
+Therefore the suspension of an object is asynchronous, unless it is performed
+from the context of the target queue for the given object.
+The result of suspending or resuming an object that is not a dispatch queue or
+a dispatch source is undefined.
+.Pp
+.Em Important :
+suspension applies to all aspects of the dispatch object life cycle, including
+the finalizer function and cancellation handler. Therefore it is important to
+balance calls to
+.Fn dispatch_suspend
+and
+.Fn dispatch_resume
+such that the dispatch object is fully resumed when the last reference is
+released. The result of releasing all references to a dispatch object while in
+a suspended state is undefined.
+.Sh CONTEXT POINTERS
+Dispatch queues and sources support supplemental context pointers. The value of
+the context point may be retrieved and updated with
+.Fn dispatch_get_context
+and
+.Fn dispatch_set_context
+respectively.
+The
+.Fn dispatch_set_finalizer_f
+specifies an optional per-object finalizer function to that is invoked
+asynchronously when the last reference to the object is released. This gives the
+application an opportunity to free the context data associated with the object.
+.Pp
+The result of getting or setting the context of an object that is not a
+dispatch queue or a dispatch source is undefined.
+.Sh SEE ALSO
+.Xr dispatch_group_create 3 ,
+.Xr dispatch_queue_create 3 ,
+.Xr dispatch_semaphore_create 3 ,
+.Xr dispatch_source_create 3

Added: trunk/man/dispatch_once.3
===================================================================
--- trunk/man/dispatch_once.3	                        (rev 0)
+++ trunk/man/dispatch_once.3	2009-08-30 01:07:28 UTC (rev 2)
@@ -0,0 +1,44 @@
+.\" Copyright (c) 2008-2009 Apple Inc. All rights reserved.
+.Dd May 1, 2009
+.Dt dispatch_once 3
+.Os Darwin
+.Sh NAME
+.Nm dispatch_once
+.Nd execute a block only once
+.Sh SYNOPSIS
+.Fd #include <dispatch/dispatch.h>
+.Ft void
+.Fo dispatch_once
+.Fa "dispatch_once_t *predicate" "void (^block)(void)"
+.Fc
+.Ft void
+.Fo dispatch_once_f
+.Fa "dispatch_once_t *predicate" "void *context" "void (*function)(void *)"
+.Fc
+.Sh DESCRIPTION
+The
+.Fn dispatch_once
+function provides a simple and efficient mechanism to run an initializer
+exactly once, similar to
+.Xr pthread_once 3 .
+Well designed code hides the use of lazy initialization.
+For example:
+.Bd -literal
+FILE *getlogfile(void)
+{
+	static dispatch_once_t pred;
+	static FILE *logfile;
+
+	dispatch_once(&pred, ^{
+		logfile = fopen(MY_LOG_FILE, "a");
+	});
+
+	return logfile;
+}
+.Ed
+.Pp
+.Sh FUNDAMENTALS
+The
+.Fn dispatch_once
+function is a wrapper around
+.Fn dispatch_once_f .

Added: trunk/man/dispatch_queue_create.3
===================================================================
--- trunk/man/dispatch_queue_create.3	                        (rev 0)
+++ trunk/man/dispatch_queue_create.3	2009-08-30 01:07:28 UTC (rev 2)
@@ -0,0 +1,318 @@
+.\" Copyright (c) 2008-2009 Apple Inc. All rights reserved.
+.Dd May 1, 2008
+.Dt dispatch_queue_create 3
+.Os Darwin
+.Sh NAME
+.Nm dispatch_queue_create ,
+.Nm dispatch_queue_get_label ,
+.Nm dispatch_get_current_queue ,
+.Nm dispatch_get_global_queue ,
+.Nm dispatch_get_main_queue ,
+.Nm dispatch_main ,
+.Nm dispatch_set_target_queue
+.Nd where blocks are scheduled for execution
+.Sh SYNOPSIS
+.Fd #include <dispatch/dispatch.h>
+.Ft dispatch_queue_t
+.Fo dispatch_queue_create
+.Fa "const char *label" "dispatch_queue_attr_t attr"
+.Fc
+.Ft "const char *"
+.Fo dispatch_queue_get_label
+.Fa "dispatch_queue_t queue"
+.Fc
+.Ft dispatch_queue_t
+.Fo dispatch_get_current_queue
+.Fa void
+.Fc
+.Ft dispatch_queue_t
+.Fo dispatch_get_global_queue
+.Fa "long priority"
+.Fa "unsigned long flags"
+.Fc
+.Ft dispatch_queue_t
+.Fo dispatch_get_main_queue
+.Fa void
+.Fc
+.Ft void
+.Fo dispatch_main
+.Fa void
+.Fc
+.Ft void
+.Fo dispatch_set_target_queue
+.Fa "dispatch_object_t object"
+.Fa "dispatch_queue_t target"
+.Fc
+.Sh DESCRIPTION
+Queues are the fundamental mechanism for scheduling blocks for execution within
+the
+.Xr dispatch 3
+framework.
+.Pp
+All blocks submitted to dispatch queues are dequeued in FIFO order.
+By default, queues created with
+.Fn dispatch_queue_create
+wait for the previously dequeued block to complete before dequeuing the next
+block. This FIFO completion behavior is sometimes simply described as a "serial queue."
+Queues are not bound to any specific thread of execution and blocks submitted
+to independent queues may execute concurrently.
+Queues, like all dispatch objects, are reference counted and newly created
+queues have a reference count of one.
+.Pp
+The optional
+.Fa label
+argument is used to describe the purpose of the queue and is useful during
+debugging and performance analysis. By convention, clients should pass a
+reverse DNS style label.
+If a label is provided, it is copied. If a label is not provided, then
+.Fn dispatch_queue_get_label
+returns an empty C string.
+For example:
+.Pp
+.Bd -literal
+my_queue = dispatch_queue_create("com.example.subsystem.taskXYZ", NULL);
+.Ed
+.Pp
+The
+.Fa attr
+argument is reserved for future use and must be NULL.
+.Pp
+Queues may be temporarily suspended and resumed with the functions
+.Fn dispatch_suspend
+and
+.Fn dispatch_resume 
+respectively. Suspension is checked prior to block execution and is
+.Em not
+preemptive.
+.Sh MAIN QUEUE
+The dispatch framework provides a default serial queue for the application to use.
+This queue is accessed via
+.Fn dispatch_get_main_queue .
+Programs must call
+.Fn dispatch_main
+at the end of
+.Fn main
+in order to process blocks submitted to the main queue. (See the compatibility
+section for exceptions.)
+.Sh GLOBAL CONCURRENT QUEUES
+Unlike the main queue or queues allocated with
+.Fn dispatch_queue_create ,
+the global concurrent queues schedule blocks as soon as threads become
+available (non-FIFO completion order). The global concurrent queues represent
+three priority bands:
+.Bl -bullet -compact -offset indent
+.It
+DISPATCH_QUEUE_PRIORITY_HIGH
+.It
+DISPATCH_QUEUE_PRIORITY_DEFAULT
+.It
+DISPATCH_QUEUE_PRIORITY_LOW
+.El
+.Pp
+Blocks submitted to the high priority global queue will be invoked before those
+submitted to the default or low priority global queues. Blocks submitted to the
+low priority global queue will only be invoked if no blocks are pending on the
+default or high priority queues.
+.Pp
+.Sh RETURN VALUES
+The
+.Fn dispatch_queue_create
+function returns NULL on failure.
+.Pp
+The
+.Fn dispatch_queue_get_label
+function always returns a valid C string. An empty C string is returned if the
+.Fa label
+was NULL creation time.
+.Pp
+The
+.Fn dispatch_get_main_queue
+function returns the default main queue.
+.Pp
+The
+.Fn dispatch_get_current_queue
+function always returns a valid queue. When called from within a block submitted
+to a dispatch queue, that queue will be returned. If this function is called from
+the main thread before
+.Fn dispatch_main
+is called, then the result of
+.Fn dispatch_get_main_queue
+is returned.  Otherwise, the result of
+.Fo dispatch_get_global_queue
+.Fa DISPATCH_QUEUE_PRIORITY_DEFAULT
+.Fa 0
+.Fc
+will be returned in all other cases.
+.Pp
+The
+.Fn dispatch_main
+function never returns.
+.Sh TARGET QUEUE
+The
+.Fn dispatch_set_target_queue
+function updates the target queue of the given dispatch object. The target
+queue of an object is responsible for processing the object. Currently only
+dispatch queues and dispatch sources are supported by this function. The result
+of using
+.Fn dispatch_set_target_queue
+with any other dispatch object type is undefined.
+.Pp
+The new target queue is retained by the given object before the previous target
+queue is released. The new target queue will take effect between block
+executions, but not in the middle of any existing block executions
+(non-preemptive).
+.Pp
+The priority of a dispatch queue is inherited by its target queue. 
+In order to change the priority of a queue created with
+.Fn dispatch_queue_create ,
+use the
+.Fn dispatch_get_global_queue
+function to obtain a target queue of the desired priority. The
+.Fa flags
+argument is reserved for future use and must be zero. Passing any value other
+than zero may result in a
+.Vt NULL
+return value.
+.Pp
+The target queue of a dispatch source specifies where its event handler and
+cancellation handler blocks will be submitted. See
+.Xr dispatch_source_create 3
+for more information about dispatch sources.
+.Pp
+The result of passing the main queue or a global concurrent queue to the first
+argument of
+.Fn dispatch_set_target_queue
+is undefined.
+.Pp
+Directly or indirectly setting the target queue of a dispatch queue to itself is undefined.
+.Sh CAVEATS
+Code cannot make any assumptions about the queue returned by
+.Fn dispatch_get_current_queue .
+The returned queue may have arbitrary policies that may surprise code that tries
+to schedule work with the queue. The list of policies includes, but is not
+limited to, queue width (i.e. serial vs. concurrent), scheduling priority,
+security credential or filesystem configuration. Therefore,
+.Fn dispatch_get_current_queue
+.Em MUST
+only be used for identity tests or debugging.
+.Sh COMPATIBILITY
+Cocoa applications need not call
+.Fn dispatch_main .
+Blocks submitted to the main queue will be executed as part of the "common modes"
+of the application's main NSRunLoop or CFRunLoop.
+.Pp
+The dispatch framework is a pure C level API. As a result, it does not catch
+exceptions generated by higher level languages such as Objective-C or C++.
+Applications
+.Em MUST
+catch all exceptions before returning from a block submitted to a dispatch
+queue; otherwise the internal data structures of the dispatch framework will be
+left in an inconsistent state.
+.Pp
+The dispatch framework manages the relationship between dispatch queues and
+threads of execution. As a result, applications
+.Em MUST NOT
+delete or mutate objects that they did not create. The following interfaces
+.Em MUST NOT
+be called by blocks submitted to a dispatch queue:
+.Bl -bullet -offset indent
+.It
+.Fn pthread_cancel
+.It
+.Fn pthread_detach
+.It
+.Fn pthread_join
+.It
+.Fn pthread_kill
+.It
+.Fn pthread_exit
+.El
+.Pp
+Applications
+.Em MAY
+call the following interfaces from a block submitted to a dispatch queue if
+and only if they restore the thread to its original state before returning:
+.Bl -bullet -offset indent
+.It
+.Fn pthread_setcancelstate
+.It
+.Fn pthread_setcanceltype
+.It
+.Fn pthread_setschedparam
+.It
+.Fn pthread_sigmask
+.It
+.Fn pthread_setugid_np
+.It
+.Fn pthread_chdir
+.It
+.Fn pthread_fchdir
+.El
+.Pp
+Applications
+.Em MUST NOT
+rely on the following interfaces returning predictable results between
+invocations of blocks submitted to a dispatch queue:
+.Bl -bullet -offset indent
+.It
+.Fn pthread_self
+.It
+.Fn pthread_getschedparam
+.It
+.Fn pthread_get_stacksize_np
+.It
+.Fn pthread_get_stackaddr_np
+.It
+.Fn pthread_mach_thread_np
+.It
+.Fn pthread_from_mach_thread_np
+.El
+.Pp
+While the result of
+.Fn pthread_self
+may change between invocations of blocks, the value will not change during the
+execution of any single block. Because the underlying thread may change beteween
+block invocations on a single queue, using per-thread data as an out-of-band
+return value is error prone. In other words, the result of calling
+.Fn pthread_setspecific
+and
+.Fn pthread_getspecific
+is well defined within a signle block, but not across multiple blocks. Also,
+one cannot make any assumptions about when the destructor passed to
+.Fn pthread_key_create
+is called. The destructor may be called between the invocation of blocks on
+the same queue, or during the idle state of a process.
+.Pp
+The following example code correctly handles per-thread return values:
+.Bd -literal -offset indent
+__block int r;
+__block int e;
+dispatch_sync(queue, ^{
+	r = kill(1, 0);
+	// Copy the per-thread return value to the callee thread
+	e = errno;
+});
+printf("kill(1,0) returned %d and errno %d\n", r, e);
+.Ed
+.Pp
+Note that in the above example
+.Va errno
+is a per-thread variable and must be copied out explicitly as the block may be
+invoked on different thread of execution than the caller. Another example of
+per-thread data that would need to be copied is the use of 
+.Fn getpwnam
+instead of
+.Fn getpwnam_r .
+.Pp
+As an optimization,
+.Fn dispatch_sync
+invokes the block on the current thread when possible. In this case, the thread
+specific data such as
+.Va errno
+may persist from the block until back to the caller. Great care should be taken
+not to accidentally rely on this side-effect.
+.Pp
+.Sh SEE ALSO
+.Xr dispatch_object 3 ,
+.Xr dispatch_async 3 ,
+.Xr dispatch_source_create 3

Added: trunk/man/dispatch_semaphore_create.3
===================================================================
--- trunk/man/dispatch_semaphore_create.3	                        (rev 0)
+++ trunk/man/dispatch_semaphore_create.3	2009-08-30 01:07:28 UTC (rev 2)
@@ -0,0 +1,114 @@
+.\" Copyright (c) 2008-2009 Apple Inc. All rights reserved.
+.Dd May 1, 2009
+.Dt dispatch_semaphore_create 3
+.Os Darwin
+.Sh NAME
+.Nm dispatch_semaphore_create ,
+.Nm dispatch_semaphore_signal ,
+.Nm dispatch_semaphore_wait
+.Nd synchronized counting semaphore
+.Sh SYNOPSIS
+.Fd #include <dispatch/dispatch.h>
+.Ft dispatch_semaphore_t
+.Fo dispatch_semaphore_create
+.Fa "long count"
+.Fc
+.Ft long
+.Fo dispatch_semaphore_signal
+.Fa "dispatch_semaphore_t semaphore"
+.Fc
+.Ft long
+.Fo dispatch_semaphore_wait
+.Fa "dispatch_semaphore_t semaphore" "dispatch_time_t timeout"
+.Fc
+.Sh DESCRIPTION
+Dispatch semaphores are used to synchronize threads.
+The
+.Fa timeout
+parameter is creatable with the
+.Xr dispatch_time 3
+or
+.Xr dispatch_walltime 3
+functions.
+.Sh COMPLETION SYNCHRONIZATION
+If the
+.Fa count
+parameter is equal to zero, then the semaphore is useful for synchronizing completion of work.
+For example:
+.Bd -literal -offset indent
+sema = dispatch_semaphore_create(0);
+
+dispatch_async(queue, ^{
+	foo();
+	dispatch_semaphore_signal(sema);
+});
+
+bar();
+
+dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
+.Ed
+.Sh FINITE RESOURCE POOL
+If the
+.Fa count
+parameter is greater than zero, then the semaphore is useful for managing a finite pool of resources.
+For example, a library that wants to limit Unix descriptor usage:
+.Bd -literal -offset indent
+sema = dispatch_semaphore_create(getdtablesize() / 4);
+.Ed
+.Pp
+At each Unix FD allocation:
+.Bd -literal -offset indent
+dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
+fd = open("/etc/services", O_RDONLY);
+.Ed
+.Pp
+When each FD is closed:
+.Bd -literal -offset indent
+close(fd);
+dispatch_semaphore_signal(sema);
+.Ed
+.Sh RETURN VALUES
+The
+.Fn dispatch_semaphore_create
+function returns NULL if no memory is available or if the
+.Fa count
+parameter is less than zero.
+.Pp
+The
+.Fn dispatch_semaphore_signal
+function returns non-zero when a thread is woken.
+Otherwise, zero is returned.
+.Pp
+The
+.Fn dispatch_semaphore_wait
+function returns zero upon success and non-zero after the timeout expires. If the timeout is DISPATCH_TIME_FOREVER, then
+.Fn dispatch_semaphore_wait
+waits forever and always returns zero.
+.Sh MEMORY MODEL
+Dispatch semaphores are retained and released via calls to
+.Fn dispatch_retain
+and
+.Fn dispatch_release .
+.Sh CAVEATS
+Dispatch semaphores are strict counting semaphores.
+In other words, dispatch semaphores do not saturate at any particular value.
+Saturation can be achieved through atomic compare-and-swap logic.
+What follows is a saturating binary semaphore:
+.Bd -literal
+void
+saturating_semaphore_signal(dispatch_semaphore_t dsema, int *sent)
+{
+	if (__sync_bool_compare_and_swap(sent, 0, 1)) {
+		dispatch_semaphore_signal(dsema);
+	}
+}
+
+void
+saturating_semaphore_wait(dispatch_semaphore_t dsema, int *sent)
+{
+	*sent = 0;
+	dispatch_semaphore_wait(dsema, DISPATCH_TIME_FOREVER);
+}
+.Ed
+.Sh SEE ALSO
+.Xr dispatch_object 3

Added: trunk/man/dispatch_source_create.3
===================================================================
--- trunk/man/dispatch_source_create.3	                        (rev 0)
+++ trunk/man/dispatch_source_create.3	2009-08-30 01:07:28 UTC (rev 2)
@@ -0,0 +1,456 @@
+.\" Copyright (c) 2008-2009 Apple Inc. All rights reserved.
+.Dd May 1, 2009
+.Dt dispatch_source_create 3
+.Os Darwin
+.Sh NAME
+.Nm dispatch_source_create
+.Nd dispatch event sources
+.Sh SYNOPSIS
+.Fd #include <dispatch/dispatch.h>
+.Ft dispatch_source_t
+.Fo dispatch_source_create
+.Fa "dispatch_source_type_t type"
+.Fa "uintptr_t handle"
+.Fa "unsigned long mask"
+.Fa "dispatch_queue_t queue"
+.Fc
+.Ft void
+.Fo dispatch_source_set_event_handler
+.Fa "dispatch_source_t source"
+.Fa "void (^block)(void)"
+.Fc
+.Ft void
+.Fo dispatch_source_set_event_handler_f
+.Fa "dispatch_source_t source"
+.Fa "void (*function)(void *)"
+.Fc
+.Ft void
+.Fo dispatch_source_set_cancel_handler
+.Fa "dispatch_source_t source"
+.Fa "void (^block)(void)"
+.Fc
+.Ft void
+.Fo dispatch_source_set_cancel_handler_f
+.Fa "dispatch_source_t source"
+.Fa "void (*function)(void *)"
+.Fc
+.Ft void
+.Fo dispatch_source_cancel
+.Fa "dispatch_source_t source"
+.Fc
+.Ft void
+.Fo dispatch_source_testcancel
+.Fa "dispatch_source_t source"
+.Fc
+.Ft uintptr_t
+.Fo dispatch_source_get_handle
+.Fa "dispatch_source_t source"
+.Fc
+.Ft "unsigned long"
+.Fo dispatch_source_get_mask
+.Fa "dispatch_source_t source"
+.Fc
+.Ft "unsigned long"
+.Fo dispatch_source_get_data
+.Fa "dispatch_source_t source"
+.Fc
+.Ft void
+.Fo dispatch_source_merge_data
+.Fa "dispatch_source_t source"
+.Fa "unsigned long data"
+.Fc
+.Ft void
+.Fo dispatch_source_set_timer
+.Fa "dispatch_source_t source"
+.Fa "dispatch_time_t start"
+.Fa "uint64_t interval"
+.Fa "uint64_t leeway"
+.Fc
+.Sh DESCRIPTION
+Dispatch event sources may be used to monitor a variety of system objects and 
+events including file descriptors, mach ports, processes, virtual filesystem
+nodes, signal delivery and timers.
+.Pp
+When a state change occurs, the dispatch source will submit its event handler
+block to its target queue.
+.Pp
+The
+.Fn dispatch_source_create
+function creates a new dispatch source object that may be retained and released
+with calls to
+.Fn dispatch_retain
+and
+.Fn dispatch_release
+respectively. Newly created sources are created in a suspended state. After the
+source has been configured by setting an event handler, cancellation handler,
+context, etc., the source must be activated by a call to
+.Fn dispatch_resume
+before any events will be delivered.
+.Pp
+Dispatch sources may be one of the following types:
+.Bl -bullet -compact -offset indent
+.It
+DISPATCH_SOURCE_TYPE_DATA_ADD
+.It
+DISPATCH_SOURCE_TYPE_DATA_OR
+.It
+DISPATCH_SOURCE_TYPE_MACH_SEND
+.It
+DISPATCH_SOURCE_TYPE_MACH_RECV
+.It
+DISPATCH_SOURCE_TYPE_PROC
+.It
+DISPATCH_SOURCE_TYPE_READ
+.It
+DISPATCH_SOURCE_TYPE_SIGNAL
+.It
+DISPATCH_SOURCE_TYPE_TIMER
+.It
+DISPATCH_SOURCE_TYPE_VNODE
+.It
+DISPATCH_SOURCE_TYPE_WRITE
+.El
+.Pp
+The
+.Fa handle
+and
+.Fa mask
+arguments to
+.Fn dispatch_source_create
+and the return values of the 
+.Fn dispatch_source_get_handle ,
+.Fn dispatch_source_get_mask ,
+and
+.Fn dispatch_source_get_data 
+functions should be interpreted according to the type of the dispatch source.
+.Pp
+The 
+.Fn dispatch_source_get_handle
+function
+returns the underlying handle to the dispatch source (i.e. file descriptor,
+mach port, process identifer, etc.). The result of this function may be cast
+directly to the underlying type.
+.Pp
+The 
+.Fn dispatch_source_get_mask
+function
+returns the set of flags that were specified at source creation time via the
+.Fa mask
+argument.
+.Pp
+The
+.Fn dispatch_source_get_data
+function returns the currently pending data for the dispatch source.
+This function should only be called from within the source's event handler.
+The result of calling this function from any other context is undefined.
+.Pp
+The
+.Fn dispatch_source_merge_data
+function is intended for use with the
+.Vt DISPATCH_SOURCE_TYPE_DATA_ADD
+and
+.Vt DISPATCH_SOURCE_TYPE_DATA_OR
+source types. The result of using this function with any other source type is
+undefined. Calling this function will atomically add or logical OR the data
+into the source's data, and trigger the delivery of the source's event handler.
+.Pp
+.Sh SOURCE EVENT HANDLERS
+In order to receive events from the dispatch source, an event handler should be
+specified via
+.Fn dispatch_source_set_event_handler .
+The event handler block is submitted to the source's target queue when the state
+of the underlying system handle changes, or when an event occurs.
+.Pp
+Dispatch sources may be suspended or resumed independently of their target
+queues using
+.Fn dispatch_suspend
+and
+.Fn dispatch_resume
+on the dispatch source directly. The data describing events which occur while a
+source is suspended are coalesced and delivered once the source is resumed.
+.Pp
+The
+.Fa handler
+block
+need not be reentrant safe, as it is not resubmitted to the target
+.Fa queue
+until any prior invocation for that dispatch source has completed.
+When the hander is set, the dispatch source will perform a
+.Fn Block_copy
+on the
+.Fa handler
+block.
+.Pp
+.Sh CANCELLATION
+The
+.Fn dispatch_source_cancel
+function asynchronously cancels the dispatch source, preventing any further
+invocation of its event handler block. Cancellation does not interrupt a
+currently executing handler block (non-preemptive).
+.Pp
+The
+.Fn dispatch_source_testcancel
+function may be used to determine whether the specified source has been
+canceled. A non-zero value will be returned if the source is canceled.
+.Pp
+When a dispatch source is canceled its optional cancellation handler will be
+submitted to its target queue. The cancellation handler may be specified via
+.Fn dispatch_source_set_cancel_handler .
+This cancellation handler is invoked only once, and only as a direct consequence
+of calling
+.Fn dispatch_source_cancel .
+.Pp
+.Em Important:
+a cancellation handler is required for file descriptor and mach port based
+sources in order to safely close the descriptor or destroy the port. Closing the
+descriptor or port before the cancellation handler has run may result in a race
+condition: if a new descriptor is allocated with the same value as the recently
+cosed descriptor while the source's event handler is still running, the event
+handler may read/write data to the wrong descriptor.
+.Pp
+.Sh DISPATCH SOURCE TYPES
+The following section contains a summary of supported dispatch event types and
+the interpretation of their parameters and returned data.
+.Pp
+.Vt DISPATCH_SOURCE_TYPE_DATA_ADD ,
+.Vt DISPATCH_SOURCE_TYPE_DATA_OR
+.Pp
+Sources of this type allow applications to manually trigger the source's event
+handler via a call to 
+.Fn dispatch_source_merge_data .
+The data will be merged with the source's pending data via an atomic add or
+logic OR (based on the source's type), and the event handler block will be
+submitted to the source's target queue. The
+.Fa mask
+and
+.Fa data
+are application defined. These sources have no
+.Fa handle
+and zero should be used.
+.Pp
+.Vt DISPATCH_SOURCE_TYPE_MACH_SEND
+.Pp
+Sources of this type monitor a mach port with a send right for state changes.
+The
+.Fa handle
+is the mach port (mach_port_t) to monitor and the
+.Fa mask
+may be:
+.Bl -tag -width "XXDISPATCH_PROC_SIGNAL" -compact -offset indent
+.It \(bu DISPATCH_MACH_SEND_DEAD
+The port's corresponding receive right has been destroyed
+.El
+.Pp
+The data returned by
+.Fn dispatch_source_get_data
+indicates which of the events in the
+.Fa mask
+were observed.
+.Pp
+.Vt DISPATCH_SOURCE_TYPE_MACH_RECV
+.Pp
+Sources of this type monitor a mach port with a receive right for state changes.
+The
+.Fa handle
+is the mach port (mach_port_t) to monitor and the
+.Fa mask
+is unused and should be zero.
+The event handler block will be submitted to the target queue when a message
+on the mach port is waiting to be received.
+.Pp
+.Vt DISPATCH_SOURCE_TYPE_PROC
+.Pp
+Sources of this type monitor processes for state changes.
+The
+.Fa handle
+is the process identifier (pid_t) of the process to monitor and the
+.Fa mask
+may be one or more of the following:
+.Bl -tag -width "XXDISPATCH_PROC_SIGNAL" -compact -offset indent
+.It \(bu DISPATCH_PROC_EXIT
+The process has exited and is available to 
+.Xr wait 2 .
+.It \(bu DISPATCH_PROC_FORK
+The process has created one or more child processes.
+.It \(bu DISPATCH_PROC_EXEC
+The process has become another executable image via a call to
+.Xr execve 2
+or
+.Xr posix_spawn 2 .
+.It \(bu  DISPATCH_PROC_REAP
+The process status has been collected by its parent process via
+.Xr wait 2 .
+.It \(bu DISPATCH_PROC_SIGNAL
+A signal was delivered to the process.
+.El
+.Pp
+The data returned by
+.Fn dispatch_source_get_data
+indicates which of the events in the
+.Fa mask
+were observed.
+.Pp
+.Vt DISPATCH_SOURCE_TYPE_READ
+.Pp
+Sources of this type monitor file descriptors for pending data.
+The
+.Fa handle
+is the file descriptor (int) to monitor and the
+.Fa mask
+is unused and should be zero.
+.Pp
+The data returned by
+.Fn dispatch_source_get_data
+is an estimated number of bytes available to be read from the descriptor. This
+estimate should be treated as a suggested
+.Em minimum
+read buffer size. There are no guarantees that a complete read of this size
+will be performed.
+.Pp
+Users of this source type are strongly encouraged to perform non-blocking I/O
+and handle any truncated reads or error conditions that may occur. See
+.Xr fnctl 2
+for additional information about setting the
+.Vt O_NONBLOCK
+flag on a file descriptor.
+.Pp
+.Vt DISPATCH_SOURCE_TYPE_SIGNAL
+.Pp
+Sources of this type monitor signals delivered to the current process. The
+.Fa handle
+is the signal number to monitor (int) and the
+.Fa mask
+is unused and should be zero.
+.Pp
+The data returned by
+.Fn dispatch_source_get_data
+is the number of signals received since the last invocation of the event handler
+block.
+.Pp
+Unlike signal handlers specified via
+.Fn sigaction ,
+the execution of the event handler block does not interrupt the current thread
+of execution; therefore the handler block is not limited to the use of signal
+safe interfaces defined in
+.Xr sigaction 2 .
+Furthermore, multiple observers of a given signal are supported; thus allowing
+applications and libraries to cooperate safely. However, a dispatch source
+.Em does not
+install a signal handler or otherwise alter the behavior of signal delivery.
+Therefore, applications must ignore or at least catch any signal that terminates
+a process by default. For example, near the top of
+.Fn main :
+.Bd -literal -offset ident
+signal(SIGTERM, SIG_IGN);
+.Ed
+.Pp
+.Vt DISPATCH_SOURCE_TYPE_TIMER
+.Pp
+Sources of this type periodically submit the event handler block to the target
+queue on an interval specified by
+.Fn dispatch_source_set_timer .
+The
+.Fa handle
+and
+.Fa mask
+arguments are unused and should be zero.
+.Pp
+A best effort attempt is made to submit the event handler block to the target
+queue at the specified time; however, actual invocation may occur at a later
+time.
+.Pp
+The data returned by
+.Fn dispatch_source_get_data
+is the number of times the timer has fired since the last invocation of the
+event handler block.
+.Pp
+The function
+.Fn dispatch_source_set_timer
+takes as an argument the
+.Fa start
+time of the timer (initial fire time) represented as a
+.Vt dispatch_time_t .
+The timer dispatch source will use the same clock as the function used to
+create this value. (See
+.Xr dispatch_time 3
+for more information.) The
+.Fa interval ,
+in nanoseconds, specifies the period at which the timer should repeat. All
+timers will repeat indefinitely until
+.Fn dispatch_source_cancel
+is called. The 
+.Fa leeway ,
+in nanoseconds, is a hint to the system that it may defer the timer in order to
+align with other system activity for improved system performance or reduced
+power consumption. (For example, an application might perform a periodic task
+every 5 minutes with a leeway of up to 30 seconds.) Note that some latency is
+to be expected for all timers even when a value of zero is used.
+.Pp
+.Em Note :
+Under the C language, untyped numbers default to the 
+.Vt int
+type. This can lead to truncation bugs when arithmetic operations with other
+numbers are expected to generate a
+.Vt uint64_t
+sized result. When in doubt, use
+.Vt ull
+as a suffix. For example:
+.Bd -literal -offset indent
+3ull * NSEC_PER_SEC
+.Ed
+.Pp
+.Vt DISPATCH_SOURCE_TYPE_VNODE
+.Pp
+Sources of this type monitor the virtual filesystem nodes for state changes.
+The
+.Fa handle
+is a file descriptor (int) referencing the node to monitor, and 
+the
+.Fa mask
+may be one or more of the following:
+.Bl -tag -width "XXDISPATCH_VNODE_ATTRIB" -compact -offset indent
+.It \(bu DISPATCH_VNODE_DELETE
+The referenced node was removed from the filesystem namespace via
+.Xr unlink 2 .
+.It \(bu DISPATCH_VNODE_WRITE
+A write to the referenced file occurred
+.It \(bu DISPATCH_VNODE_EXTEND
+The referenced file was extended
+.It \(bu DISPATCH_VNODE_ATTRIB
+The metadata attributes of the referenced node have changed
+.It \(bu DISPATCH_VNODE_LINK
+The link count on the referenced node has changed
+.It \(bu DISPATCH_VNODE_RENAME
+The referenced node was renamed
+.It \(bu DISPATCH_VNODE_REVOKE
+Access to the referenced node was revoked via 
+.Xr revoke 2
+or the underlying fileystem was unmounted.
+.El
+.Pp
+The data returned by
+.Fn dispatch_source_get_data
+indicates which of the events in the
+.Fa mask
+were observed.
+.Pp
+.Vt DISPATCH_SOURCE_TYPE_WRITE
+.Pp
+Sources of this type monitor file descriptors for available write buffer space.
+The
+.Fa handle
+is the file descriptor (int) to monitor and the
+.Fa mask
+is unused and should be zero.
+.Pp
+Users of this source type are strongly encouraged to perform non-blocking I/O
+and handle any truncated reads or error conditions that may occur. See
+.Xr fnctl 2
+for additional information about setting the
+.Vt O_NONBLOCK
+flag on a file descriptor.
+.Pp
+.Sh SEE ALSO
+.Xr dispatch 3 ,
+.Xr dispatch_object 3 ,
+.Xr dispatch_queue_create 3

Added: trunk/man/dispatch_time.3
===================================================================
--- trunk/man/dispatch_time.3	                        (rev 0)
+++ trunk/man/dispatch_time.3	2009-08-30 01:07:28 UTC (rev 2)
@@ -0,0 +1,110 @@
+.\" Copyright (c) 2008-2009 Apple Inc. All rights reserved.
+.Dd May 1, 2009
+.Dt dispatch_time 3
+.Os Darwin
+.Sh NAME
+.Nm dispatch_time ,
+.Nm dispatch_walltime
+.Nd Calculate temporal milestones
+.Sh SYNOPSIS
+.Fd #include <dispatch/dispatch.h>
+.Vt static const dispatch_time_t DISPATCH_TIME_NOW = 0 ;
+.Vt static const dispatch_time_t DISPATCH_TIME_FOREVER = ~0ull ;
+.Ft dispatch_time_t
+.Fo dispatch_time
+.Fa "dispatch_time_t base" "int64_t offset"
+.Fc
+.Ft dispatch_time_t
+.Fo dispatch_walltime
+.Fa "struct timespec *base" "int64_t offset"
+.Fc
+.Sh DESCRIPTION
+The
+.Fn dispatch_time
+and
+.Fn dispatch_walltime
+functions provide a simple mechanism for expressing temporal milestones for use
+with dispatch functions that need timeouts or operate on a schedule.
+.Pp
+The
+.Fa dispatch_time_t
+type is a semi-opaque integer, with only the special values
+.Vt DISPATCH_TIME_NOW
+and
+.Vt DISPATCH_TIME_FOREVER
+being externally defined. All other values are represented using an internal
+format that is not safe for integer arithmetic or comparison.
+The internal format is subject to change.
+.Pp
+The
+.Fn dispatch_time
+function returns a milestone relative to an existing milestone after adding
+.Fa offset
+nanoseconds.
+If the
+.Fa base
+parameter maps internally to a wall clock, then the returned value is
+relative to the wall clock.
+Otherwise, if
+.Fa base
+is
+.Vt DISPATCH_TIME_NOW ,
+then the the current time of the default host clock is used.
+.Pp
+The
+.Fn dispatch_walltime
+function is useful for creating a milestone relative to a fixed point in time
+using the wall clock, as specified by the optional
+.Fa base
+parameter. If
+.Fa base
+is NULL, then the current time of the wall clock is used.
+.Sh EDGE CONDITIONS
+The
+.Fn dispatch_time
+and
+.Fn dispatch_walltime
+functions detect overflow and underflow conditions when applying the
+.Fa offset
+parameter.
+.Pp
+Overflow causes
+.Vt DISPATCH_TIME_FOREVER
+to be returned. When
+.Fa base
+is
+.Vt DISPATCH_TIME_FOREVER ,
+then the
+.Fa offset
+parameter is ignored.
+.Pp
+Underflow causes the smallest representable value to be
+returned for a given clock.
+.Sh EXAMPLES
+Create a milestone two seconds in the future:
+.Bd -literal -offset indent
+milestone = dispatch_time(DISPATCH_TIME_NOW, 2LL * NSEC_PER_SEC);
+.Ed
+.Pp
+Create a milestone for use as an infinite timeout:
+.Bd -literal -offset indent
+milestone = DISPATCH_TIME_FOREVER;
+.Ed
+.Pp
+Create a milestone on Tuesday, January 19, 2038:
+.Bd -literal -offset indent
+struct timespec ts;
+ts.tv_sec = 0x7FFFFFFF;
+ts.tv_nsec = 0;
+milestone = dispatch_walltime(&ts, 0);
+.Ed
+.Sh RETURN VALUE
+These functions return an abstract value for use with
+.Fn dispatch_after ,
+.Fn dispatch_group_wait ,
+or
+.Fn dispatch_semaphore_wait .
+.Sh SEE ALSO
+.Xr dispatch_after 3 ,
+.Xr dispatch_group_create 3 ,
+.Xr dispatch_semaphore_create 3

Added: trunk/src/apply.c
===================================================================
--- trunk/src/apply.c	                        (rev 0)
+++ trunk/src/apply.c	2009-08-30 01:07:28 UTC (rev 2)
@@ -0,0 +1,178 @@
+/*
+ * Copyright (c) 2008-2009 Apple Inc. All rights reserved.
+ *
+ * @APPLE_APACHE_LICENSE_HEADER_START@
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * 
+ * @APPLE_APACHE_LICENSE_HEADER_END@
+ */
+#include "internal.h"
+
+// We'd use __attribute__((aligned(x))), but it does not atually increase the
+// alignment of stack variables. All we really need is the stack usage of the
+// local thread to be sufficiently away to avoid cache-line contention with the
+// busy 'da_index' variable.
+//
+// NOTE: 'char' arrays cause GCC to insert buffer overflow detection logic 
+struct dispatch_apply_s {
+	long	_da_pad0[DISPATCH_CACHELINE_SIZE / sizeof(long)];
+	void	(*da_func)(void *, size_t);
+	void	*da_ctxt;
+	size_t	da_iterations;
+	size_t	da_index;
+	uint32_t	da_thr_cnt;
+	dispatch_semaphore_t da_sema;
+	long	_da_pad1[DISPATCH_CACHELINE_SIZE / sizeof(long)];
+};
+
+static void
+_dispatch_apply2(void *_ctxt)
+{
+	struct dispatch_apply_s *da = _ctxt;
+	size_t const iter = da->da_iterations;
+	typeof(da->da_func) const func = da->da_func;
+	void *const ctxt = da->da_ctxt;
+	size_t idx;
+
+	_dispatch_workitem_dec(); // this unit executes many items
+
+	// Striding is the responsibility of the caller.
+	while (fastpath((idx = dispatch_atomic_inc(&da->da_index) - 1) < iter)) {
+		func(ctxt, idx);
+		_dispatch_workitem_inc();
+	}
+
+	if (dispatch_atomic_dec(&da->da_thr_cnt) == 0) {
+		dispatch_semaphore_signal(da->da_sema);
+	}
+}
+
+static void
+_dispatch_apply_serial(void *context)
+{
+	struct dispatch_apply_s *da = context;
+	size_t idx = 0;
+
+	_dispatch_workitem_dec(); // this unit executes many items
+	do {
+		da->da_func(da->da_ctxt, idx);
+		_dispatch_workitem_inc();
+	} while (++idx < da->da_iterations);
+}
+
+#ifdef __BLOCKS__
+void
+dispatch_apply(size_t iterations, dispatch_queue_t dq, void (^work)(size_t))
+{
+	struct Block_basic *bb = (void *)work;
+
+	dispatch_apply_f(iterations, dq, bb, (void *)bb->Block_invoke);
+}
+#endif
+
+// 256 threads should be good enough for the short to mid term
+#define DISPATCH_APPLY_MAX_CPUS	256
+
+DISPATCH_NOINLINE
+void
+dispatch_apply_f(size_t iterations, dispatch_queue_t dq, void *ctxt, void (*func)(void *, size_t))
+{
+	struct dispatch_apply_dc_s {
+		DISPATCH_CONTINUATION_HEADER(dispatch_apply_dc_s);
+	} da_dc[DISPATCH_APPLY_MAX_CPUS];
+	struct dispatch_apply_s da;
+	size_t i;
+
+	da.da_func = func;
+	da.da_ctxt = ctxt;
+	da.da_iterations = iterations;
+	da.da_index = 0;
+	da.da_thr_cnt = _dispatch_hw_config.cc_max_active;
+
+	if (da.da_thr_cnt > DISPATCH_APPLY_MAX_CPUS) {
+		da.da_thr_cnt = DISPATCH_APPLY_MAX_CPUS;
+	}
+	if (slowpath(iterations == 0)) {
+		return;
+	}
+	if (iterations < da.da_thr_cnt) {
+		da.da_thr_cnt = (uint32_t)iterations;
+	}
+	if (slowpath(dq->dq_width <= 2 || da.da_thr_cnt <= 1)) {
+		return dispatch_sync_f(dq, &da, _dispatch_apply_serial);
+	}
+
+	for (i = 0; i < da.da_thr_cnt; i++) {
+		da_dc[i].do_vtable = NULL;
+		da_dc[i].do_next = &da_dc[i + 1];
+		da_dc[i].dc_func = _dispatch_apply2;
+		da_dc[i].dc_ctxt = &da;
+	}
+
+	da.da_sema = _dispatch_get_thread_semaphore();
+
+	// some queues are easy to borrow and some are not
+	if (slowpath(dq->do_targetq)) {
+		_dispatch_queue_push_list(dq, (void *)&da_dc[0], (void *)&da_dc[da.da_thr_cnt - 1]);
+	} else {
+		dispatch_queue_t old_dq = _dispatch_thread_getspecific(dispatch_queue_key);
+		// root queues are always concurrent and safe to borrow
+		_dispatch_queue_push_list(dq, (void *)&da_dc[1], (void *)&da_dc[da.da_thr_cnt - 1]);
+		_dispatch_thread_setspecific(dispatch_queue_key, dq);
+		// The first da_dc[] element was explicitly not pushed on to the queue.
+		// We need to either call it like so:
+		//     da_dc[0].dc_func(da_dc[0].dc_ctxt);
+		// Or, given that we know the 'func' and 'ctxt', we can call it directly:
+		_dispatch_apply2(&da);
+		_dispatch_workitem_inc();
+		_dispatch_thread_setspecific(dispatch_queue_key, old_dq);
+	}
+	dispatch_semaphore_wait(da.da_sema, DISPATCH_TIME_FOREVER);
+	_dispatch_put_thread_semaphore(da.da_sema);
+}
+
+#if 0
+#ifdef __BLOCKS__
+void
+dispatch_stride(size_t offset, size_t stride, size_t iterations, dispatch_queue_t dq, void (^work)(size_t))
+{
+	struct Block_basic *bb = (void *)work;
+	dispatch_stride_f(offset, stride, iterations, dq, bb, (void *)bb->Block_invoke);
+}
+#endif
+
+DISPATCH_NOINLINE
+void
+dispatch_stride_f(size_t offset, size_t stride, size_t iterations,
+		dispatch_queue_t dq, void *ctxt, void (*func)(void *, size_t))
+{
+	if (stride == 0) {
+		stride = 1;
+	}
+	dispatch_apply(iterations / stride, queue, ^(size_t idx) {
+		size_t i = idx * stride + offset;
+		size_t stop = i + stride;
+		do {
+			func(ctxt, i++);
+		} while (i < stop);
+	});
+
+	dispatch_sync(queue, ^{
+		size_t i;
+		for (i = iterations - (iterations % stride); i < iterations; i++) {
+			func(ctxt, i + offset);
+		}
+	});
+}
+#endif

Added: trunk/src/base.h
===================================================================
--- trunk/src/base.h	                        (rev 0)
+++ trunk/src/base.h	2009-08-30 01:07:28 UTC (rev 2)
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2008-2009 Apple Inc. All rights reserved.
+ *
+ * @APPLE_APACHE_LICENSE_HEADER_START@
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * 
+ * @APPLE_APACHE_LICENSE_HEADER_END@
+ */
+
+#ifndef __DISPATCH_BASE__
+#define __DISPATCH_BASE__
+
+#ifndef __DISPATCH_INDIRECT__
+#error "Please #include <dispatch/dispatch.h> instead of this file directly."
+#endif
+
+#ifdef __cplusplus
+/*
+ * Dispatch objects are NOT C++ objects. Nevertheless, we can at least keep C++
+ * aware of type compatibility.
+ */
+typedef struct dispatch_object_s {
+private:
+	dispatch_object_s();
+	~dispatch_object_s();
+	dispatch_object_s(const dispatch_object_s &);
+	void operator=(const dispatch_object_s &);
+} *dispatch_object_t;
+#else
+typedef union {
+	struct dispatch_object_s *_do;
+	struct dispatch_continuation_s *_dc;
+	struct dispatch_queue_s *_dq;
+	struct dispatch_queue_attr_s *_dqa;
+	struct dispatch_group_s *_dg;
+	struct dispatch_source_s *_ds;
+	struct dispatch_source_attr_s *_dsa;
+	struct dispatch_semaphore_s *_dsema;
+} dispatch_object_t __attribute__((transparent_union));
+#endif
+
+typedef void (*dispatch_function_t)(void *);
+
+#ifdef __cplusplus
+#define DISPATCH_DECL(name) typedef struct name##_s : public dispatch_object_s {} *name##_t;
+#else
+/*! @parseOnly */
+#define DISPATCH_DECL(name) typedef struct name##_s *name##_t;
+#endif
+
+#ifdef __GNUC__
+#define DISPATCH_NORETURN __attribute__((__noreturn__))
+#define DISPATCH_NOTHROW __attribute__((__nothrow__))
+#define DISPATCH_NONNULL1 __attribute__((__nonnull__(1)))
+#define DISPATCH_NONNULL2 __attribute__((__nonnull__(2)))
+#define DISPATCH_NONNULL3 __attribute__((__nonnull__(3)))
+#define DISPATCH_NONNULL4 __attribute__((__nonnull__(4)))
+#define DISPATCH_NONNULL5 __attribute__((__nonnull__(5)))
+#define DISPATCH_NONNULL6 __attribute__((__nonnull__(6)))
+#define DISPATCH_NONNULL7 __attribute__((__nonnull__(7)))
+#if __clang__
+// rdar://problem/6857843
+#define DISPATCH_NONNULL_ALL
+#else
+#define DISPATCH_NONNULL_ALL __attribute__((__nonnull__))
+#endif
+#define DISPATCH_SENTINEL __attribute__((__sentinel__))
+#define DISPATCH_PURE __attribute__((__pure__))
+#define DISPATCH_WARN_RESULT __attribute__((__warn_unused_result__))
+#define DISPATCH_MALLOC __attribute__((__malloc__))
+#else
+/*! @parseOnly */
+#define DISPATCH_NORETURN
+/*! @parseOnly */
+#define DISPATCH_NOTHROW
+/*! @parseOnly */
+#define DISPATCH_NONNULL1
+/*! @parseOnly */
+#define DISPATCH_NONNULL2
+/*! @parseOnly */
+#define DISPATCH_NONNULL3
+/*! @parseOnly */
+#define DISPATCH_NONNULL4
+/*! @parseOnly */
+#define DISPATCH_NONNULL5
+/*! @parseOnly */
+#define DISPATCH_NONNULL6
+/*! @parseOnly */
+#define DISPATCH_NONNULL7
+/*! @parseOnly */
+#define DISPATCH_NONNULL_ALL
+/*! @parseOnly */
+#define DISPATCH_SENTINEL
+/*! @parseOnly */
+#define DISPATCH_PURE
+/*! @parseOnly */
+#define DISPATCH_WARN_RESULT
+/*! @parseOnly */
+#define DISPATCH_MALLOC
+#endif
+
+#endif

Added: trunk/src/benchmark.c
===================================================================
--- trunk/src/benchmark.c	                        (rev 0)
+++ trunk/src/benchmark.c	2009-08-30 01:07:28 UTC (rev 2)
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2008-2009 Apple Inc. All rights reserved.
+ *
+ * @APPLE_APACHE_LICENSE_HEADER_START@
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * 
+ * @APPLE_APACHE_LICENSE_HEADER_END@
+ */
+
+#include "internal.h"
+
+
+struct __dispatch_benchmark_data_s {
+	mach_timebase_info_data_t tbi;
+	uint64_t loop_cost;
+	void (*func)(void *);
+	void *ctxt;
+	size_t count;
+};
+
+static void
+_dispatch_benchmark_init(void *context)
+{
+	struct __dispatch_benchmark_data_s *bdata = context;
+	// try and simulate performance of real benchmark as much as possible
+	// keep 'f', 'c' and 'cnt' in registers
+	register void (*f)(void *) = bdata->func;
+	register void *c = bdata->ctxt;
+	register size_t cnt = bdata->count;
+	uint64_t start, delta;
+#ifdef __LP64__
+	__uint128_t lcost;
+#else
+	long double lcost;
+#endif
+	kern_return_t kr;
+	size_t i = 0;
+
+	kr = mach_timebase_info(&bdata->tbi);
+	dispatch_assert_zero(kr);
+
+	start = mach_absolute_time();
+	do {
+		i++;
+		f(c);
+	} while (i < cnt);
+	delta = mach_absolute_time() - start;
+
+	lcost = delta;
+	lcost *= bdata->tbi.numer;
+	lcost /= bdata->tbi.denom;
+	lcost /= cnt;
+
+	bdata->loop_cost = lcost;
+}
+
+#ifdef __BLOCKS__
+uint64_t
+dispatch_benchmark(size_t count, void (^block)(void))
+{
+	struct Block_basic *bb = (void *)block;
+	return dispatch_benchmark_f(count, block, (void *)bb->Block_invoke);
+}
+#endif
+
+uint64_t
+dispatch_benchmark_f(size_t count, register void *ctxt, register void (*func)(void *))
+{
+	static struct __dispatch_benchmark_data_s bdata = {
+		.func = (void *)dummy_function,
+		.count = 10000000ul, // ten million
+	};
+	static dispatch_once_t pred;
+	uint64_t ns, start, delta;
+#ifdef __LP64__
+	__uint128_t conversion, big_denom;
+#else
+	long double conversion, big_denom;
+#endif
+	size_t i = 0;
+
+	dispatch_once_f(&pred, &bdata, _dispatch_benchmark_init);
+
+	if (slowpath(count == 0)) {
+		return 0;
+	}
+
+	start = mach_absolute_time();
+	do {
+		i++;
+		func(ctxt);
+	} while (i < count);
+	delta = mach_absolute_time() - start;
+
+	conversion = delta;
+	conversion *= bdata.tbi.numer;
+	big_denom = bdata.tbi.denom;
+	big_denom *= count;
+	conversion /= big_denom;
+	ns = conversion;
+
+	return ns - bdata.loop_cost;
+}

Added: trunk/src/benchmark.h
===================================================================
--- trunk/src/benchmark.h	                        (rev 0)
+++ trunk/src/benchmark.h	2009-08-30 01:07:28 UTC (rev 2)
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2008-2009 Apple Inc. All rights reserved.
+ *
+ * @APPLE_APACHE_LICENSE_HEADER_START@
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * 
+ * @APPLE_APACHE_LICENSE_HEADER_END@
+ */
+
+/*
+ * IMPORTANT: This header file describes INTERNAL interfaces to libdispatch
+ * which are subject to change in future releases of Mac OS X. Any applications
+ * relying on these interfaces WILL break.
+ */
+
+#ifndef __DISPATCH_BENCHMARK__
+#define __DISPATCH_BENCHMARK__
+
+#ifndef __DISPATCH_INDIRECT__
+#error "Please #include <dispatch/dispatch.h> instead of this file directly."
+#include <dispatch/base.h> // for HeaderDoc
+#endif
+
+__BEGIN_DECLS
+
+/*!
+ * @function dispatch_benchmark
+ *
+ * @abstract
+ * Count the average number of cycles a given block takes to execute.
+ *
+ * @param count
+ * The number of times to serially execute the given block.
+ *
+ * @param block
+ * The block to execute.
+ *
+ * @result
+ * The approximate number of cycles the block takes to execute.
+ *
+ * @discussion
+ * This function is for debugging and performance analysis work. For the best
+ * results, pass a high count value to dispatch_benchmark(). When benchmarking
+ * concurrent code, please compare the serial version of the code against the
+ * concurrent version, and compare the concurrent version on different classes
+ * of hardware. Please look for inflection points with various data sets and
+ * keep the following facts in mind:
+ *
+ * 1) Code bound by computational bandwidth may be inferred by proportional
+ *    changes in performance as concurrency is increased.
+ * 2) Code bound by memory bandwidth may be inferred by negligible changes in
+ *    performance as concurrency is increased.
+ * 3) Code bound by critical sections may be inferred by retrograde changes in
+ *    performance as concurrency is increased.
+ * 3a) Intentional: locks, mutexes, and condition variables.
+ * 3b) Accidental: unrelated and frequently modified data on the same cache-line.
+ */
+#ifdef __BLOCKS__
+__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA)
+DISPATCH_NONNULL2 DISPATCH_NOTHROW
+uint64_t
+dispatch_benchmark(size_t count, void (^block)(void));
+#endif
+
+__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA)
+DISPATCH_NONNULL3 DISPATCH_NOTHROW
+uint64_t
+dispatch_benchmark_f(size_t count, void *ctxt, void (*func)(void *));
+
+__END_DECLS
+
+#endif

Added: trunk/src/dispatch.h
===================================================================
--- trunk/src/dispatch.h	                        (rev 0)
+++ trunk/src/dispatch.h	2009-08-30 01:07:28 UTC (rev 2)
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2008-2009 Apple Inc. All rights reserved.
+ *
+ * @APPLE_APACHE_LICENSE_HEADER_START@
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * 
+ * @APPLE_APACHE_LICENSE_HEADER_END@
+ */
+
+#ifndef __DISPATCH_PUBLIC__
+#define __DISPATCH_PUBLIC__
+
+#include <Availability.h>
+#include <sys/cdefs.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <stdarg.h>
+
+#define DISPATCH_API_VERSION 20090501
+
+#ifndef __DISPATCH_BUILDING_DISPATCH__
+
+#ifndef __DISPATCH_INDIRECT__
+#define __DISPATCH_INDIRECT__
+#endif
+
+#include <dispatch/base.h>
+#include <dispatch/object.h>
+#include <dispatch/time.h>
+#include <dispatch/queue.h>
+#include <dispatch/source.h>
+#include <dispatch/group.h>
+#include <dispatch/semaphore.h>
+#include <dispatch/once.h>
+
+#undef __DISPATCH_INDIRECT__
+
+#endif /* !__DISPATCH_BUILDING_DISPATCH__ */
+
+#endif

Added: trunk/src/group.h
===================================================================
--- trunk/src/group.h	                        (rev 0)
+++ trunk/src/group.h	2009-08-30 01:07:28 UTC (rev 2)
@@ -0,0 +1,273 @@
+/*
+ * Copyright (c) 2008-2009 Apple Inc. All rights reserved.
+ *
+ * @APPLE_APACHE_LICENSE_HEADER_START@
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * 
+ * @APPLE_APACHE_LICENSE_HEADER_END@
+ */
+
+#ifndef __DISPATCH_GROUP__
+#define __DISPATCH_GROUP__
+
+#ifndef __DISPATCH_INDIRECT__
+#error "Please #include <dispatch/dispatch.h> instead of this file directly."
+#include <dispatch/base.h> // for HeaderDoc
+#endif
+
+/*!
+ * @typedef dispatch_group_t
+ * @abstract
+ * A group of blocks submitted to queues for asynchronous invocation.
+ */
+DISPATCH_DECL(dispatch_group);
+
+__BEGIN_DECLS
+
+/*!
+ * @function dispatch_group_create
+ *
+ * @abstract
+ * Creates new group with which blocks may be associated.
+ * 
+ * @discussion
+ * This function creates a new group with which blocks may be associated.
+ * The dispatch group may be used to wait for the completion of the blocks it
+ * references. The group object memory is freed with dispatch_release().
+ *
+ * @result
+ * The newly created group, or NULL on failure.
+ */
+__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA)
+DISPATCH_WARN_RESULT
+dispatch_group_t
+dispatch_group_create(void);
+
+/*!
+ * @function dispatch_group_async
+ *
+ * @abstract
+ * Submits a block to a dispatch queue and associates the block with the given
+ * dispatch group.
+ *
+ * @discussion
+ * Submits a block to a dispatch queue and associates the block with the given
+ * dispatch group. The dispatch group may be used to wait for the completion
+ * of the blocks it references.
+ *
+ * @param group
+ * A dispatch group to associate with the submitted block.
+ * The result of passing NULL in this parameter is undefined.
+ *
+ * @param queue
+ * The dispatch queue to which the block will be submitted for asynchronous
+ * invocation.
+ *
+ * @param block
+ * The block to perform asynchronously.
+ */
+#ifdef __BLOCKS__
+__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA)
+DISPATCH_NONNULL_ALL
+void
+dispatch_group_async(dispatch_group_t group,
+	dispatch_queue_t queue,
+	dispatch_block_t block);
+#endif /* __BLOCKS__ */
+
+/*!
+ * @function dispatch_group_async_f
+ *
+ * @abstract
+ * Submits a function to a dispatch queue and associates the block with the
+ * given dispatch group.
+ *
+ * @discussion
+ * See dispatch_group_async() for details.
+ *
+ * @param group
+ * A dispatch group to associate with the submitted function.
+ * The result of passing NULL in this parameter is undefined.
+ *
+ * @param queue
+ * The dispatch queue to which the function will be submitted for asynchronous
+ * invocation.
+ *
+ * @param context
+ * The application-defined context parameter to pass to the function.
+ *
+ * @param work
+ * The application-defined function to invoke on the target queue. The first
+ * parameter passed to this function is the context provided to
+ * dispatch_group_async_f().
+ */
+__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA)
+DISPATCH_NONNULL1 DISPATCH_NONNULL2 DISPATCH_NONNULL4
+void
+dispatch_group_async_f(dispatch_group_t group,
+	dispatch_queue_t queue,
+	void *context,
+	dispatch_function_t work);
+
+/*!
+ * @function dispatch_group_wait
+ *
+ * @abstract
+ * Wait synchronously for the previously submitted blocks to complete;
+ * returns if the blocks have not completed within the specified timeout.
+ *
+ * @discussion
+ * This function waits  for the completion of the blocks associated with the
+ * given dispatch group, and returns after all blocks have completed or when
+ * the specified timeout has elapsed. When a timeout occurs, the group is
+ * restored to its original state.
+ *
+ * This function will return immediately if there are no blocks associated
+ * with the dispatch group (i.e. the group is empty).
+ *
+ * The result of calling this function from mulitple threads simultaneously
+ * with the same dispatch group is undefined.
+ *
+ * After the successful return of this function, the dispatch group is empty.
+ * It may either be released with dispatch_release() or re-used for additional
+ * blocks. See dispatch_group_async() for more information.
+ *
+ * @param group
+ * The dispatch group to wait on.
+ * The result of passing NULL in this parameter is undefined.
+ *
+ * @param timeout
+ * When to timeout (see dispatch_time). As a convenience, there are the
+ * DISPATCH_TIME_NOW and DISPATCH_TIME_FOREVER constants.
+ *
+ * @result
+ * Returns zero on success (all blocks associated with the group completed
+ * within the specified timeout) or non-zero on error (i.e. timed out).
+ */
+__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA)
+DISPATCH_NONNULL_ALL
+long
+dispatch_group_wait(dispatch_group_t group, dispatch_time_t timeout);
+
+/*!
+ * @function dispatch_group_notify
+ *
+ * @abstract
+ * Schedule a block to be submitted to a queue when a group of previously
+ * submitted blocks have completed.
+ *
+ * @discussion
+ * This function schedules a notification block to be submitted to the specified
+ * queue once all blocks associated with the dispatch group have completed.
+ *
+ * If no blocks are associated with the dispatch group (i.e. the group is empty)
+ * then the notification block will be submitted immediately.
+ * 
+ * The group will be empty at the time the notification block is submitted to
+ * the target queue. The group may either be released with dispatch_release()
+ * or reused for additional operations.
+ * See dispatch_group_async() for more information.
+ *
+ * @param group
+ * The dispatch group to observe.
+ * The result of passing NULL in this parameter is undefined.
+ *
+ * @param queue
+ * The queue to which the supplied block will be submitted when the group
+ * completes.
+ *
+ * @param block
+ * The block to submit when the group completes.
+ */
+#ifdef __BLOCKS__
+__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA)
+DISPATCH_NONNULL_ALL
+void
+dispatch_group_notify(dispatch_group_t group,
+	dispatch_queue_t queue,
+	dispatch_block_t block);
+#endif /* __BLOCKS__ */
+
+/*!
+ * @function dispatch_group_notify_f
+ *
+ * @abstract
+ * Schedule a function to be submitted to a queue when a group of previously
+ * submitted functions have completed.
+ *
+ * @discussion
+ * See dispatch_group_notify() for details.
+ *
+ * @param group
+ * The dispatch group to observe.
+ * The result of passing NULL in this parameter is undefined.
+ *
+ * @param context
+ * The application-defined context parameter to pass to the function.
+ *
+ * @param work
+ * The application-defined function to invoke on the target queue. The first
+ * parameter passed to this function is the context provided to
+ * dispatch_group_notify_f().
+ */
+__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA)
+DISPATCH_NONNULL1 DISPATCH_NONNULL2 DISPATCH_NONNULL4
+void
+dispatch_group_notify_f(dispatch_group_t group,
+	dispatch_queue_t queue,
+	void *context,
+	dispatch_function_t work);
+
+/*!
+ * @function dispatch_group_enter
+ *
+ * @abstract
+ * Manually indicate a block has entered the group
+ *
+ * @discussion
+ * Calling this function indicates another block has joined the group through
+ * a means other than dispatch_group_async(). Calls to this function must be
+ * balanced with dispatch_group_leave().
+ *
+ * @param group
+ * The dispatch group to update.
+ * The result of passing NULL in this parameter is undefined.
+ */
+__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA)
+DISPATCH_NOTHROW DISPATCH_NONNULL_ALL
+void
+dispatch_group_enter(dispatch_group_t group);
+
+/*!
+ * @function dispatch_group_leave
+ *
+ * @abstract
+ * Manually indicate a block in the group has completed
+ *
+ * @discussion
+ * Calling this function indicates block has completed and left the dispatch
+ * groupJ by a means other than dispatch_group_async().
+ *
+ * @param group
+ * The dispatch group to update.
+ * The result of passing NULL in this parameter is undefined.
+ */
+__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA)
+DISPATCH_NOTHROW DISPATCH_NONNULL_ALL
+void
+dispatch_group_leave(dispatch_group_t group);
+
+__END_DECLS
+
+#endif

Added: trunk/src/hw_shims.h
===================================================================
--- trunk/src/hw_shims.h	                        (rev 0)
+++ trunk/src/hw_shims.h	2009-08-30 01:07:28 UTC (rev 2)
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2008-2009 Apple Inc. All rights reserved.
+ *
+ * @APPLE_APACHE_LICENSE_HEADER_START@
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * 
+ * @APPLE_APACHE_LICENSE_HEADER_END@
+ */
+
+/*
+ * IMPORTANT: This header file describes INTERNAL interfaces to libdispatch
+ * which are subject to change in future releases of Mac OS X. Any applications
+ * relying on these interfaces WILL break.
+ */
+
+#ifndef __DISPATCH_HW_SHIMS__
+#define __DISPATCH_HW_SHIMS__
+
+/* x86 has a 64 byte cacheline */
+#define DISPATCH_CACHELINE_SIZE	64
+#define ROUND_UP_TO_CACHELINE_SIZE(x)	(((x) + (DISPATCH_CACHELINE_SIZE - 1)) & ~(DISPATCH_CACHELINE_SIZE - 1))
+#define ROUND_UP_TO_VECTOR_SIZE(x)	(((x) + 15) & ~15)
+
+#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 2)
+// GCC generates suboptimal register pressure
+// LLVM does better, but doesn't support tail calls
+// 6248590 __sync_*() intrinsics force a gratuitous "lea" instruction, with resulting register pressure
+#if 0 && defined(__i386__) || defined(__x86_64__)
+#define dispatch_atomic_xchg(p, n)	({ typeof(*(p)) _r; asm("xchg %0, %1" : "=r" (_r) : "m" (*(p)), "0" (n)); _r; })
+#else
+#define dispatch_atomic_xchg(p, n)	__sync_lock_test_and_set((p), (n))
+#endif
+#define dispatch_atomic_cmpxchg(p, o, n)	__sync_bool_compare_and_swap((p), (o), (n))
+#define dispatch_atomic_inc(p)	__sync_add_and_fetch((p), 1)
+#define dispatch_atomic_dec(p)	__sync_sub_and_fetch((p), 1)
+#define dispatch_atomic_add(p, v)	__sync_add_and_fetch((p), (v))
+#define dispatch_atomic_sub(p, v)	__sync_sub_and_fetch((p), (v))
+#define dispatch_atomic_or(p, v)	__sync_fetch_and_or((p), (v))
+#define dispatch_atomic_and(p, v)	__sync_fetch_and_and((p), (v))
+#if defined(__i386__) || defined(__x86_64__)
+/* GCC emits nothing for __sync_synchronize() on i386/x86_64. */
+#define dispatch_atomic_barrier()	__asm__ __volatile__("mfence")
+#else
+#define dispatch_atomic_barrier()	__sync_synchronize()
+#endif
+#else
+#error "Please upgrade to GCC 4.2 or newer."
+#endif
+
+#if defined(__i386__) || defined(__x86_64__)
+#define _dispatch_hardware_pause() asm("pause")
+#define _dispatch_debugger() asm("int3")
+#else
+#define _dispatch_hardware_pause() asm("")
+#define _dispatch_debugger() asm("trap")
+#endif
+// really just a low level abort()
+#define _dispatch_hardware_crash() __builtin_trap()
+
+
+#endif

Added: trunk/src/internal.h
===================================================================
--- trunk/src/internal.h	                        (rev 0)
+++ trunk/src/internal.h	2009-08-30 01:07:28 UTC (rev 2)
@@ -0,0 +1,299 @@
+/*
+ * Copyright (c) 2008-2009 Apple Inc. All rights reserved.
+ *
+ * @APPLE_APACHE_LICENSE_HEADER_START@
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * 
+ * @APPLE_APACHE_LICENSE_HEADER_END@
+ */
+
+/*
+ * IMPORTANT: This header file describes INTERNAL interfaces to libdispatch
+ * which are subject to change in future releases of Mac OS X. Any applications
+ * relying on these interfaces WILL break.
+ */
+
+#ifndef __DISPATCH_INTERNAL__
+#define __DISPATCH_INTERNAL__
+
+#define __DISPATCH_BUILDING_DISPATCH__
+#define __DISPATCH_INDIRECT__
+#include "dispatch.h"
+#include "base.h"
+#include "time.h"
+#include "queue.h"
+#include "object.h"
+#include "source.h"
+#include "group.h"
+#include "semaphore.h"
+#include "once.h"
+#include "benchmark.h"
+
+/* private.h uses #include_next and must be included last to avoid picking
+ * up installed headers. */
+#include "queue_private.h"
+#include "source_private.h"
+#include "private.h"
+#include "legacy.h"
+/* More #includes at EOF (dependent on the contents of internal.h) ... */
+
+/* The "_debug" library build */
+#ifndef DISPATCH_DEBUG
+#define DISPATCH_DEBUG 0
+#endif
+
+
+#include <libkern/OSCrossEndian.h>
+#include <libkern/OSAtomic.h>
+#include <mach/boolean.h>
+#include <mach/clock_types.h>
+#include <mach/clock.h>
+#include <mach/exception.h>
+#include <mach/mach.h>
+#include <mach/mach_error.h>
+#include <mach/mach_host.h>
+#include <mach/mach_interface.h>
+#include <mach/mach_time.h>
+#include <mach/mach_traps.h>
+#include <mach/message.h>
+#include <mach/mig_errors.h>
+#include <mach/host_info.h>
+#include <mach/notify.h>
+#include <malloc/malloc.h>
+#include <sys/event.h>
+#include <sys/mount.h>
+#include <sys/queue.h>
+#include <sys/stat.h>
+#include <sys/sysctl.h>
+#include <sys/syslimits.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+
+#ifdef __BLOCKS__
+#include <Block_private.h>
+#include <Block.h>
+#endif /* __BLOCKS__ */
+
+#include <assert.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <search.h>
+#include <signal.h>
+#include <stdarg.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syslog.h>
+#include <unistd.h>
+
+#define DISPATCH_NOINLINE	__attribute__((noinline))
+
+// workaround 6368156
+#ifdef NSEC_PER_SEC
+#undef NSEC_PER_SEC
+#endif
+#ifdef USEC_PER_SEC
+#undef USEC_PER_SEC
+#endif
+#ifdef NSEC_PER_USEC
+#undef NSEC_PER_USEC
+#endif
+#define NSEC_PER_SEC 1000000000ull
+#define USEC_PER_SEC 1000000ull
+#define NSEC_PER_USEC 1000ull
+
+/* I wish we had __builtin_expect_range() */
+#define fastpath(x)	((typeof(x))__builtin_expect((long)(x), ~0l))
+#define slowpath(x)	((typeof(x))__builtin_expect((long)(x), 0l))
+
+void _dispatch_bug(size_t line, long val) __attribute__((__noinline__));
+void _dispatch_abort(size_t line, long val) __attribute__((__noinline__,__noreturn__));
+void _dispatch_log(const char *msg, ...) __attribute__((__noinline__,__format__(printf,1,2)));
+void _dispatch_logv(const char *msg, va_list) __attribute__((__noinline__,__format__(printf,1,0)));
+
+/*
+ * For reporting bugs within libdispatch when using the "_debug" version of the library.
+ */
+#define dispatch_assert(e)	do {	\
+		if (__builtin_constant_p(e)) {	\
+			char __compile_time_assert__[(bool)(e) ? 1 : -1] __attribute__((unused));	\
+		} else {	\
+			typeof(e) _e = fastpath(e); /* always eval 'e' */	\
+			if (DISPATCH_DEBUG && !_e) {	\
+				_dispatch_abort(__LINE__, (long)_e);	\
+			}	\
+		}	\
+	} while (0)
+/* A lot of API return zero upon success and not-zero on fail. Let's capture and log the non-zero value */
+#define dispatch_assert_zero(e)	do {	\
+		if (__builtin_constant_p(e)) {	\
+			char __compile_time_assert__[(bool)(!(e)) ? 1 : -1] __attribute__((unused));	\
+		} else {	\
+			typeof(e) _e = slowpath(e); /* always eval 'e' */	\
+			if (DISPATCH_DEBUG && _e) {	\
+				_dispatch_abort(__LINE__, (long)_e);	\
+			}	\
+		}	\
+	} while (0)
+
+/*
+ * For reporting bugs or impedance mismatches between libdispatch and external subsystems.
+ * These do NOT abort(), and are always compiled into the product.
+ *
+ * In particular, we wrap all system-calls with assume() macros.
+ */
+#define dispatch_assume(e)	({	\
+		typeof(e) _e = fastpath(e); /* always eval 'e' */	\
+		if (!_e) {	\
+			if (__builtin_constant_p(e)) {	\
+				char __compile_time_assert__[(e) ? 1 : -1];	\
+				(void)__compile_time_assert__;	\
+			}	\
+			_dispatch_bug(__LINE__, (long)_e);	\
+		}	\
+		_e;	\
+	})
+/* A lot of API return zero upon success and not-zero on fail. Let's capture and log the non-zero value */
+#define dispatch_assume_zero(e)	({	\
+		typeof(e) _e = slowpath(e); /* always eval 'e' */	\
+		if (_e) {	\
+			if (__builtin_constant_p(e)) {	\
+				char __compile_time_assert__[(e) ? -1 : 1];	\
+				(void)__compile_time_assert__;	\
+			}	\
+			_dispatch_bug(__LINE__, (long)_e);	\
+		}	\
+		_e;	\
+	})
+
+/*
+ * For reporting bugs in clients when using the "_debug" version of the library.
+ */
+#define dispatch_debug_assert(e, msg, args...)	do {	\
+		if (__builtin_constant_p(e)) {	\
+			char __compile_time_assert__[(bool)(e) ? 1 : -1] __attribute__((unused));	\
+		} else {	\
+			typeof(e) _e = fastpath(e); /* always eval 'e' */	\
+			if (DISPATCH_DEBUG && !_e) {	\
+				_dispatch_log("%s() 0x%lx: " msg, __func__, (long)_e, ##args);	\
+				abort();	\
+			}	\
+		}	\
+	} while (0)
+
+
+
+#ifdef __BLOCKS__
+dispatch_block_t _dispatch_Block_copy(dispatch_block_t block);
+void _dispatch_call_block_and_release(void *block);
+void _dispatch_call_block_and_release2(void *block, void *ctxt);
+#endif /* __BLOCKS__ */
+
+void dummy_function(void);
+long dummy_function_r0(void);
+
+
+/* Make sure the debug statments don't get too stale */
+#define _dispatch_debug(x, args...)	\
+({	\
+	if (DISPATCH_DEBUG) {	\
+		_dispatch_log("libdispatch: %u\t%p\t" x, __LINE__, _dispatch_thread_self(), ##args);	\
+	}	\
+})
+
+
+#if DISPATCH_DEBUG
+void dispatch_debug_kevents(struct kevent* kev, size_t count, const char* str);
+#else
+#define dispatch_debug_kevents(x, y, z)
+#endif
+
+uint64_t _dispatch_get_nanoseconds(void);
+
+void _dispatch_source_drain_kevent(struct kevent *);
+
+dispatch_source_t
+_dispatch_source_create2(dispatch_source_t ds,
+	dispatch_source_attr_t attr,
+	void *context,
+	dispatch_source_handler_function_t handler);
+
+void _dispatch_update_kq(const struct kevent *);
+void _dispatch_run_timers(void);
+// Returns howsoon with updated time value, or NULL if no timers active.
+struct timespec *_dispatch_get_next_timer_fire(struct timespec *howsoon);
+
+dispatch_semaphore_t _dispatch_get_thread_semaphore(void);
+void _dispatch_put_thread_semaphore(dispatch_semaphore_t);
+
+bool _dispatch_source_testcancel(dispatch_source_t);
+
+uint64_t _dispatch_timeout(dispatch_time_t when);
+
+__private_extern__ bool _dispatch_safe_fork;
+
+__private_extern__ struct _dispatch_hw_config_s {
+	uint32_t cc_max_active;
+	uint32_t cc_max_logical;
+	uint32_t cc_max_physical;
+} _dispatch_hw_config;
+
+/* #includes dependent on internal.h */
+#include "object_internal.h"
+#include "hw_shims.h"
+#include "os_shims.h"
+#include "queue_internal.h"
+#include "semaphore_internal.h"
+#include "source_internal.h"
+
+// MIG_REPLY_MISMATCH means either:
+// 1) A signal handler is NOT using async-safe API. See the sigaction(2) man page for more info.
+// 2) A hand crafted call to mach_msg*() screwed up. Use MIG.
+#define DISPATCH_VERIFY_MIG(x) do {	\
+		if ((x) == MIG_REPLY_MISMATCH) {	\
+			__crashreporter_info__ = "MIG_REPLY_MISMATCH";	\
+			_dispatch_hardware_crash();	\
+		}	\
+	} while (0)
+
+#if defined(__x86_64__) || defined(__i386__)
+// total hack to ensure that return register of a function is not trashed
+#define DISPATCH_CRASH(x)	do {	\
+		asm("mov	%1, %0" : "=m" (__crashreporter_info__) : "c" ("BUG IN LIBDISPATCH: " x));	\
+		_dispatch_hardware_crash();	\
+	} while (0)
+
+#define DISPATCH_CLIENT_CRASH(x)	do {	\
+		asm("mov	%1, %0" : "=m" (__crashreporter_info__) : "c" ("BUG IN CLIENT OF LIBDISPATCH: " x));	\
+		_dispatch_hardware_crash();	\
+	} while (0)
+
+#else
+
+#define DISPATCH_CRASH(x)	do {	\
+		__crashreporter_info__ = "BUG IN LIBDISPATCH: " x;	\
+		_dispatch_hardware_crash();	\
+	} while (0)
+
+#define DISPATCH_CLIENT_CRASH(x)	do {	\
+		__crashreporter_info__ = "BUG IN CLIENT OF LIBDISPATCH: " x;	\
+		_dispatch_hardware_crash();	\
+	} while (0)
+
+#endif
+
+
+#endif /* __DISPATCH_INTERNAL__ */

Added: trunk/src/legacy.c
===================================================================
--- trunk/src/legacy.c	                        (rev 0)
+++ trunk/src/legacy.c	2009-08-30 01:07:28 UTC (rev 2)
@@ -0,0 +1,444 @@
+/*
+ * Copyright (c) 2008-2009 Apple Inc. All rights reserved.
+ *
+ * @APPLE_APACHE_LICENSE_HEADER_START@
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * 
+ * @APPLE_APACHE_LICENSE_HEADER_END@
+ */
+
+#include "internal.h"
+#include "legacy.h"
+
+/*
+ * LEGACY: This header file describles LEGACY interfaces to libdispatch from an
+ * earlier revision of the API. These interfaces WILL be removed in the future.
+ */
+
+DISPATCH_PUBLIC_API DISPATCH_NONNULL1 DISPATCH_NONNULL2
+dispatch_item_t
+LEGACY_dispatch_call(dispatch_queue_t, dispatch_legacy_block_t work, dispatch_legacy_block_t completion)
+__asm__("_dispatch_call2");
+
+DISPATCH_PUBLIC_API DISPATCH_PURE DISPATCH_WARN_RESULT
+dispatch_queue_t
+LEGACY_dispatch_queue_get_current(void)
+__asm__("_dispatch_queue_get_current");
+
+/////////////////////////////////////////////////////////////////////////////
+
+dispatch_queue_t
+LEGACY_dispatch_queue_get_current(void)
+{
+	return _dispatch_queue_get_current();
+}
+
+dispatch_item_t
+LEGACY_dispatch_call(dispatch_queue_t dq,
+	dispatch_legacy_block_t dispatch_block,
+	dispatch_legacy_block_t callback_block)
+{
+	dispatch_queue_t lq = _dispatch_queue_get_current() ?: dispatch_get_main_queue();
+	dispatch_item_t di;
+
+	di = dispatch_block ? calloc(1, ROUND_UP_TO_CACHELINE_SIZE(sizeof(*di))) : NULL;
+
+	if (!di) {
+		return di;
+	}
+
+	if (callback_block) {
+		dispatch_retain(lq);
+	}
+
+	dispatch_async(dq, ^{
+		dispatch_block(di);
+
+		if (callback_block) {
+			dispatch_async(lq, ^{
+				callback_block(di);
+				free(di);
+				dispatch_release(lq);
+			});
+		} else {
+			free(di);
+		}
+	});
+
+	return di;
+}
+
+sigset_t
+dispatch_event_get_signals(dispatch_event_t de)
+{
+	sigset_t ret;
+	sigemptyset(&ret);
+	sigaddset(&ret, (int)dispatch_event_get_signal(de));
+	return ret;
+}
+
+void dispatch_cancel(dispatch_source_t ds) { dispatch_source_cancel(ds); }
+long dispatch_testcancel(dispatch_source_t ds) { return dispatch_source_testcancel(ds); }
+
+void dispatch_queue_resume(dispatch_queue_t dq) { dispatch_resume(dq); }
+void dispatch_queue_retain(dispatch_queue_t dq) { dispatch_retain(dq); }
+void dispatch_queue_release(dispatch_queue_t dq) { dispatch_release(dq); }
+
+void dispatch_source_suspend(dispatch_source_t ds) { dispatch_suspend(ds); }
+void dispatch_source_resume(dispatch_source_t ds) { dispatch_resume(ds); }
+void dispatch_source_release(dispatch_source_t ds) { dispatch_release(ds); }
+
+void dispatch_source_attr_release(dispatch_source_attr_t attr) { dispatch_release(attr); }
+void dispatch_queue_attr_release(dispatch_queue_attr_t attr) { dispatch_release(attr); }
+
+void *dispatch_queue_get_context(dispatch_queue_t dq) { return dispatch_get_context(dq); }
+void  dispatch_queue_set_context(dispatch_queue_t dq, void *context) { dispatch_set_context(dq, context); }
+
+void *dispatch_source_get_context(dispatch_source_t ds) { return dispatch_get_context(ds); }
+void  dispatch_source_set_context(dispatch_source_t ds, void *context) { dispatch_set_context(ds, context); }
+
+void dispatch_source_custom_trigger(dispatch_source_t ds) { dispatch_source_merge_data(ds, 1); }
+
+void
+dispatch_source_trigger(dispatch_source_t ds, unsigned long val)
+{
+	dispatch_source_merge_data(ds, val);
+}
+
+int dispatch_source_get_descriptor(dispatch_source_t ds) { return (int)dispatch_source_get_handle(ds); }
+
+pid_t dispatch_source_get_pid(dispatch_source_t ds) { return (pid_t)dispatch_source_get_handle(ds); }
+
+mach_port_t dispatch_source_get_machport(dispatch_source_t ds) { return (mach_port_t)dispatch_source_get_handle(ds); }
+
+uint64_t dispatch_source_get_flags(dispatch_source_t ds) { return dispatch_source_get_mask(ds); }
+
+dispatch_source_t dispatch_event_get_source(dispatch_event_t event) { return event; }
+
+long dispatch_event_get_error(dispatch_event_t event, long* error) { return dispatch_source_get_error(event, error); }
+
+uint64_t dispatch_event_get_flags(dispatch_event_t event)  { return dispatch_source_get_data(event); }
+
+size_t dispatch_event_get_bytes_available(dispatch_event_t event) { return (size_t)dispatch_source_get_data(event); }
+
+unsigned long dispatch_event_get_count(dispatch_event_t event) { return (unsigned long)dispatch_source_get_data(event); }
+
+long dispatch_event_get_signal(dispatch_event_t event) { return (long)dispatch_source_get_handle(event); }
+
+dispatch_source_t
+dispatch_source_custom_create(
+							  unsigned long behavior,
+							  dispatch_source_attr_t attr,
+							  dispatch_queue_t queue,
+							  dispatch_event_handler_t handler) {
+	return dispatch_source_data_create(behavior, attr, queue, handler);
+}
+
+dispatch_source_t
+dispatch_source_custom_create_f(
+								unsigned long behavior,
+								dispatch_source_attr_t attr,
+								dispatch_queue_t queue,
+								void *h_context,
+								dispatch_event_handler_function_t handler) {
+	return dispatch_source_data_create_f(behavior, attr, queue, h_context, handler);
+}
+
+#define _dispatch_source_call_block ((void *)-1)
+
+
+
+#ifdef __BLOCKS__
+dispatch_source_t
+dispatch_source_timer_create(uint64_t flags,
+	uint64_t nanoseconds,
+	uint64_t leeway,
+	dispatch_source_attr_t attr,
+	dispatch_queue_t q,
+	dispatch_source_handler_t callback)
+{
+	return dispatch_source_timer_create_f(flags, nanoseconds, leeway,
+		attr, q, callback, _dispatch_source_call_block);
+}
+#endif
+
+dispatch_source_t
+dispatch_source_timer_create_f(uint64_t timer_flags,
+	uint64_t nanoseconds,
+	uint64_t leeway,
+	dispatch_source_attr_t attr,
+	dispatch_queue_t q,
+	void *context, 
+	dispatch_source_handler_function_t callback)
+{
+	dispatch_source_t ds;
+	dispatch_time_t start;
+
+	// 6866347 - make sure nanoseconds won't overflow
+	if ((int64_t)nanoseconds < 0) {
+		nanoseconds = INT64_MAX;
+	}
+
+	if (timer_flags & DISPATCH_TIMER_ONESHOT) {
+		timer_flags |= DISPATCH_TIMER_WALL_CLOCK;
+	}
+	if (timer_flags == (DISPATCH_TIMER_ABSOLUTE|DISPATCH_TIMER_WALL_CLOCK)) {
+		static const struct timespec t0;
+		start = dispatch_walltime(&t0, nanoseconds);
+	} else if (timer_flags & DISPATCH_TIMER_WALL_CLOCK) {
+		start = dispatch_walltime(DISPATCH_TIME_NOW, nanoseconds);
+	} else {
+		start = dispatch_time(DISPATCH_TIME_NOW, nanoseconds);
+	}
+	if (timer_flags & DISPATCH_TIMER_ONESHOT) {
+		// 6866347 - make sure nanoseconds won't overflow
+		nanoseconds = INT64_MAX; // non-repeating (~292 years)
+	}
+
+	ds = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, (unsigned long)timer_flags, q);
+	if (!ds) {
+		return NULL;
+	}
+	ds = _dispatch_source_create2(ds, attr, context, callback);
+	if (!ds) {
+		return NULL;
+	}
+	dispatch_source_set_timer(ds, start, nanoseconds, leeway);
+
+	return ds;
+}
+
+#ifdef __BLOCKS__
+dispatch_source_t
+dispatch_source_read_create(int descriptor,
+	dispatch_source_attr_t attr,
+	dispatch_queue_t q,
+	dispatch_source_handler_t callback)
+{
+	return dispatch_source_read_create_f(descriptor,
+		attr, q, callback, _dispatch_source_call_block);
+}
+#endif
+
+dispatch_source_t
+dispatch_source_read_create_f(int fd,
+	dispatch_source_attr_t attr,
+	dispatch_queue_t q,
+	void *context,
+	dispatch_source_handler_function_t callback)
+{
+	dispatch_source_t ds;
+	ds = dispatch_source_create(DISPATCH_SOURCE_TYPE_READ, fd, 0, q);
+	return _dispatch_source_create2(ds, attr, context, callback);
+}
+
+#ifdef __BLOCKS__
+dispatch_source_t
+dispatch_source_write_create(int descriptor,
+	dispatch_source_attr_t attr,
+	dispatch_queue_t q,
+	dispatch_source_handler_t callback)
+{
+	return dispatch_source_write_create_f(descriptor,
+		attr, q, callback, _dispatch_source_call_block);
+}
+#endif
+
+dispatch_source_t
+dispatch_source_write_create_f(int fd,
+	dispatch_source_attr_t attr,
+	dispatch_queue_t q,
+	void *context,
+	dispatch_source_handler_function_t callback)
+{
+	dispatch_source_t ds;
+	ds = dispatch_source_create(DISPATCH_SOURCE_TYPE_WRITE, fd, 0, q);
+	return _dispatch_source_create2(ds, attr, context, callback);
+}
+
+#ifdef __BLOCKS__
+dispatch_source_t
+dispatch_source_vnode_create(int descriptor,
+	uint64_t flags,
+	dispatch_source_attr_t attr,
+	dispatch_queue_t q,
+	dispatch_source_handler_t callback)
+{
+	return dispatch_source_vnode_create_f(descriptor,
+		flags, attr, q, callback, _dispatch_source_call_block);
+}
+#endif
+
+dispatch_source_t
+dispatch_source_vnode_create_f(int fd,
+	uint64_t event_mask,
+	dispatch_source_attr_t attr,
+	dispatch_queue_t q,
+	void *context,
+	dispatch_source_handler_function_t callback)
+{
+	dispatch_source_t ds;
+	ds = dispatch_source_create(DISPATCH_SOURCE_TYPE_VNODE, fd, (unsigned long)event_mask, q);
+	return _dispatch_source_create2(ds, attr, context, callback);
+}
+
+#ifdef __BLOCKS__
+dispatch_source_t
+dispatch_source_signal_create(unsigned long sig,
+	dispatch_source_attr_t attr,
+	dispatch_queue_t q,
+	dispatch_source_handler_t callback)
+{
+	return dispatch_source_signal_create_f(sig,
+		attr, q, callback, _dispatch_source_call_block);
+}
+#endif
+
+dispatch_source_t
+dispatch_source_signal_create_f(unsigned long signo,
+	dispatch_source_attr_t attr,
+	dispatch_queue_t q,
+	void *context,
+	dispatch_source_handler_function_t callback)
+{
+	dispatch_source_t ds;
+	ds = dispatch_source_create(DISPATCH_SOURCE_TYPE_SIGNAL, signo, 0, q);
+	return _dispatch_source_create2(ds, attr, context, callback);
+}
+
+#ifdef __BLOCKS__
+dispatch_source_t
+dispatch_source_proc_create(pid_t pid,
+	uint64_t flags,
+	dispatch_source_attr_t attr,
+	dispatch_queue_t q,
+	dispatch_source_handler_t callback)
+{
+	return dispatch_source_proc_create_f(pid,
+		flags, attr, q, callback, _dispatch_source_call_block);
+}
+#endif
+
+dispatch_source_t
+dispatch_source_proc_create_f(pid_t pid,
+	uint64_t event_mask,
+	dispatch_source_attr_t attr,
+	dispatch_queue_t q,
+	void *context,
+	dispatch_source_handler_function_t callback)
+{
+	dispatch_source_t ds;
+	ds = dispatch_source_create(DISPATCH_SOURCE_TYPE_PROC, pid, (unsigned long)event_mask, q);
+	return _dispatch_source_create2(ds, attr, context, callback);
+}
+
+#ifdef __BLOCKS__
+dispatch_source_t
+dispatch_source_vfs_create(uint64_t flags,
+	dispatch_source_attr_t attr,
+	dispatch_queue_t q,
+	dispatch_source_handler_t callback)
+{
+	return dispatch_source_vfs_create_f(flags,
+		attr, q, callback, _dispatch_source_call_block);
+}
+#endif
+
+dispatch_source_t
+dispatch_source_vfs_create_f(uint64_t event_mask,
+	dispatch_source_attr_t attr,
+	dispatch_queue_t q,
+	void *context,
+	dispatch_source_handler_function_t callback)
+{
+	dispatch_source_t ds;
+	ds = dispatch_source_create(DISPATCH_SOURCE_TYPE_VFS, 0, (unsigned long)event_mask, q);
+	return _dispatch_source_create2(ds, attr, context, callback);
+}
+
+#ifdef __BLOCKS__
+dispatch_source_t
+dispatch_source_data_create(unsigned long behavior,
+	dispatch_source_attr_t attr,
+	dispatch_queue_t q,
+	dispatch_source_handler_t callback)
+{
+	return dispatch_source_data_create_f(behavior,
+		attr, q, callback, _dispatch_source_call_block);
+}
+#endif
+
+#ifdef __BLOCKS__
+dispatch_source_t
+dispatch_source_machport_create(mach_port_t mport,
+	uint64_t flags,
+	dispatch_source_attr_t attr,
+	dispatch_queue_t dq,
+	dispatch_source_handler_t callback)
+{
+	return dispatch_source_machport_create_f(mport, flags,
+		attr, dq, callback, _dispatch_source_call_block);
+}
+#endif
+
+dispatch_source_t
+dispatch_source_data_create_f(unsigned long behavior,
+	dispatch_source_attr_t attr,
+	dispatch_queue_t q,
+	void *context,
+	dispatch_source_handler_function_t callback)
+{
+	dispatch_source_t ds;
+	dispatch_source_type_t type;
+	switch (behavior) {
+		case DISPATCH_SOURCE_CUSTOM_ADD:
+			type = DISPATCH_SOURCE_TYPE_DATA_ADD;
+			break;
+		case DISPATCH_SOURCE_CUSTOM_OR:
+			type = DISPATCH_SOURCE_TYPE_DATA_OR;
+			break;
+		default:
+			return NULL;
+	}
+	ds = dispatch_source_create(type, 0, 0, q);
+	return _dispatch_source_create2(ds, attr, context, callback);
+}
+
+dispatch_source_t
+dispatch_source_machport_create_f(mach_port_t mport,
+	uint64_t flags,
+	dispatch_source_attr_t attr,
+	dispatch_queue_t dq,
+	void *ctxt,
+	dispatch_source_handler_function_t func)
+{
+	dispatch_source_t ds;
+	dispatch_source_type_t type;
+	unsigned long newflags = 0;
+
+	if (flags & ~(DISPATCH_MACHPORT_DEAD|DISPATCH_MACHPORT_RECV)) {
+		return NULL;
+	}
+	// XXX DELETED
+	if (flags & DISPATCH_MACHPORT_DEAD) {
+		type = DISPATCH_SOURCE_TYPE_MACH_SEND;
+		newflags |= DISPATCH_MACH_SEND_DEAD;
+	} else {
+		type = DISPATCH_SOURCE_TYPE_MACH_RECV;
+	}
+
+	ds = dispatch_source_create(type, mport, newflags, dq);
+	return _dispatch_source_create2(ds, attr, ctxt, func);
+}
+

Added: trunk/src/legacy.h
===================================================================
--- trunk/src/legacy.h	                        (rev 0)
+++ trunk/src/legacy.h	2009-08-30 01:07:28 UTC (rev 2)
@@ -0,0 +1,748 @@
+/*
+ * Copyright (c) 2008-2009 Apple Inc. All rights reserved.
+ *
+ * @APPLE_APACHE_LICENSE_HEADER_START@
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * 
+ * @APPLE_APACHE_LICENSE_HEADER_END@
+ */
+
+/*
+ * IMPORTANT: This header file describes INTERNAL interfaces to libdispatch
+ * which are subject to change in future releases of Mac OS X. Any applications
+ * relying on these interfaces WILL break.
+ */
+
+/*
+ * LEGACY: This header file describles LEGACY interfaces to libdispatch from an
+ * earlier revision of the API. These interfaces WILL be removed in the future.
+ */
+ 
+#ifndef __DISPATCH_LEGACY__
+#define __DISPATCH_LEGACY__
+
+#ifndef __DISPATCH_INDIRECT__
+#error "Please #include <dispatch/dispatch.h> instead of this file directly."
+#include <dispatch/base.h> // for HeaderDoc
+#endif
+
+#include <mach/mach_types.h>
+
+#define DISPATCH_DEPRECATED __attribute__((deprecated))
+#define DISPATCH_PUBLIC_API __attribute__((visibility("default")))
+
+typedef struct dispatch_item_s *dispatch_item_t;
+
+struct dispatch_item_s {
+	void *                                        di_objc_isa;    /* FIXME -- someday... */
+	struct dispatch_item_s *volatile        di_next;
+	dispatch_queue_t                        di_cback_q;
+	uint32_t                                di_flags;
+	semaphore_t                             di_semaphore;
+	void *					di_work_func;
+	void *                                  di_work_ctxt;
+	void *					di_cback_func;
+	void *                                  di_cback_ctxt;
+	void *                                  di_ctxt;
+};
+
+// Use: dispatch_source_t
+typedef struct dispatch_source_s *dispatch_event_t;
+
+// Obsolete
+#ifdef __BLOCKS__
+typedef void (^dispatch_legacy_block_t)(dispatch_item_t);
+typedef void (^dispatch_queue_deletion_block_t)(dispatch_queue_t queue);
+typedef void (^dispatch_source_deletion_t)(dispatch_source_t source);
+typedef void (^dispatch_event_callback_t)(dispatch_event_t event);
+typedef void (^dispatch_source_handler_t)(dispatch_source_t source);
+typedef dispatch_source_handler_t dispatch_event_handler_t;
+typedef void (^dispatch_source_finalizer_t)(dispatch_source_t source);
+#endif /* __BLOCKS__ */
+
+// Obsolete
+typedef void (*dispatch_source_handler_function_t)(void *, dispatch_source_t);
+typedef void (*dispatch_source_finalizer_function_t)(void *, dispatch_source_t);
+typedef dispatch_source_handler_function_t dispatch_event_handler_function_t;
+
+DISPATCH_DECL(dispatch_source_attr);
+
+#define DISPATCH_SOURCE_CREATE_SUSPENDED	((dispatch_source_attr_t)~0ul)
+
+#ifdef __BLOCKS__
+typedef void (^dispatch_queue_finalizer_t)(dispatch_queue_t queue);
+#endif
+
+typedef void (*dispatch_queue_finalizer_function_t)(void *, dispatch_queue_t);
+
+__BEGIN_DECLS
+
+/*!
+ * @function dispatch_queue_attr_create
+ *
+ * @abstract
+ * Creates a new dispatch queue attribute structure. These attributes may be
+ * provided at creation time to modify the default behavior of the queue.
+ *
+ * @discussion
+ * The values present in this structure are copied to newly created queues.
+ * The same attribute structure may be provided to multiple calls to
+ * dispatch_queue_create() but only the values in the structure at the time the
+ * call is made will be used.
+ *
+ * @result
+ * The new dispatch queue attribute structure, initialized to default values.
+ */
+__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA)
+DISPATCH_MALLOC DISPATCH_WARN_RESULT DISPATCH_NOTHROW
+dispatch_queue_attr_t
+dispatch_queue_attr_create(void);
+
+/*!
+ * @function dispatch_queue_attr_set_priority
+ *
+ * @abstract
+ * Set the priority level for a dispatch queue.
+ *
+ * @discussion
+ * Priority levels may be:
+ * - DISPATCH_QUEUE_PRIORITY_HIGH
+ * - DISPATCH_QUEUE_PRIORITY_DEFAULT
+ * - DISPATCH_QUEUE_PRIORITY_LOW
+ * Queues set to high priority will be processed
+ * before queues set to default priority or low priority.
+ * Queues set to low priority will be processed only if all
+ * high priority and default priority queues are empty.
+ */
+__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA)
+DISPATCH_NONNULL1 DISPATCH_NOTHROW
+void
+dispatch_queue_attr_set_priority(dispatch_queue_attr_t attr, int priority);
+
+#ifdef __BLOCKS__
+__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA)
+DISPATCH_NONNULL1 DISPATCH_NOTHROW
+long
+dispatch_queue_attr_set_finalizer(
+								  dispatch_queue_attr_t attr,
+								  dispatch_queue_finalizer_t finalizer);
+#endif
+
+__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA)
+DISPATCH_NONNULL1 DISPATCH_NOTHROW
+void
+dispatch_queue_attr_set_finalizer_f(dispatch_queue_attr_t attr, void *context, dispatch_queue_finalizer_function_t finalizer);
+
+/*!
+ * @function dispatch_get_concurrent_queue
+ *
+ * @abstract
+ * Returns a well-known global concurrent queue of a given priority level.
+ *
+ * @discussion
+ * Blocks submitted to the returned queue may be invoked concurrently with
+ * respect to each other.
+ *
+ * These queues are useful for performing one-shot asynchronous operations,
+ * e.g. dispatch_async() to an "anonymous" queue; or for performing parallel
+ * loops concurrently on multiple processors, e.g. dispatch_apply().
+ *
+ * The dispatch queues returned by this function are managed by the system for
+ * the lifetime of the application, and need not be retained or released
+ * directly by the application. Furthermore, dispatch_suspend() and
+ * dispatch_queue_resume() are not supported on these global queues, and will
+ * be ignored.
+ *
+ * @param priority
+ * The requested priority level for the queue (default is zero):
+ * - DISPATCH_QUEUE_PRIORITY_HIGH
+ * - DISPATCH_QUEUE_PRIORITY_DEFAULT
+ * - DISPATCH_QUEUE_PRIORITY_LOW
+ *
+ * @result
+ * Returns a concurrent dispatch queue for use with dispatch_async(),
+ * dispatch_apply(), et al.
+ */
+__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA)
+DISPATCH_PURE DISPATCH_WARN_RESULT DISPATCH_NOTHROW
+dispatch_queue_t
+dispatch_get_concurrent_queue(long priority);
+
+DISPATCH_PUBLIC_API //DISPATCH_DEPRECATED
+void
+dispatch_queue_attr_set_flags(dispatch_queue_attr_t attr, uint64_t flags);
+
+#ifdef __BLOCKS__
+DISPATCH_PUBLIC_API DISPATCH_NONNULL1 DISPATCH_NONNULL2 DISPATCH_DEPRECATED
+dispatch_item_t
+dispatch_call(dispatch_queue_t, dispatch_legacy_block_t work, dispatch_legacy_block_t completion)
+__asm__("_dispatch_call2");
+#endif /* __BLOCKS__ */
+
+DISPATCH_PUBLIC_API DISPATCH_PURE DISPATCH_WARN_RESULT DISPATCH_DEPRECATED
+dispatch_queue_t
+dispatch_queue_get_current(void);
+
+// Use: dispatch_retain
+DISPATCH_PUBLIC_API DISPATCH_NONNULL_ALL DISPATCH_DEPRECATED
+void
+dispatch_queue_retain(dispatch_queue_t);
+
+// Use: dispatch_release
+DISPATCH_PUBLIC_API DISPATCH_NONNULL_ALL DISPATCH_DEPRECATED
+void
+dispatch_queue_release(dispatch_queue_t);
+
+// Use: dispatch_resume
+DISPATCH_PUBLIC_API DISPATCH_NONNULL_ALL DISPATCH_DEPRECATED
+void
+dispatch_queue_resume(dispatch_queue_t);
+
+// Use: dispatch_release
+DISPATCH_PUBLIC_API DISPATCH_NONNULL_ALL DISPATCH_DEPRECATED
+void
+dispatch_source_release(dispatch_source_t);
+
+// Use: dispatch_suspend
+DISPATCH_PUBLIC_API DISPATCH_NONNULL_ALL DISPATCH_DEPRECATED
+void
+dispatch_source_suspend(dispatch_source_t);
+
+// Use: dispatch_resume
+DISPATCH_PUBLIC_API DISPATCH_NONNULL_ALL DISPATCH_DEPRECATED
+void
+dispatch_source_resume(dispatch_source_t);
+
+// Use: dispatch_release
+DISPATCH_PUBLIC_API DISPATCH_NONNULL_ALL DISPATCH_DEPRECATED
+void
+dispatch_queue_attr_release(dispatch_queue_attr_t);
+
+// Use: dispatch_release
+DISPATCH_PUBLIC_API DISPATCH_NONNULL_ALL DISPATCH_DEPRECATED
+void
+dispatch_source_attr_release(dispatch_source_attr_t);
+
+// Use: dispatch_source_get_handle
+DISPATCH_PUBLIC_API DISPATCH_NONNULL_ALL DISPATCH_WARN_RESULT DISPATCH_DEPRECATED
+sigset_t
+dispatch_event_get_signals(dispatch_event_t event);
+
+// Use: dispatch_get_context
+DISPATCH_PUBLIC_API DISPATCH_NONNULL_ALL //DISPATCH_DEPRECATED
+void *
+dispatch_queue_get_context(dispatch_queue_t queue);
+  
+// Use: dispatch_set_context
+DISPATCH_PUBLIC_API DISPATCH_NONNULL1 //DISPATCH_DEPRECATED
+void
+dispatch_queue_set_context(dispatch_queue_t queue, void *context);
+
+// Use: dispatch_get_context
+DISPATCH_PUBLIC_API DISPATCH_NONNULL_ALL //DISPATCH_DEPRECATED
+void *
+dispatch_source_get_context(dispatch_source_t source);
+
+// Use: dispatch_set_context
+DISPATCH_PUBLIC_API DISPATCH_NONNULL1 //DISPATCH_DEPRECATED
+void
+dispatch_source_set_context(dispatch_source_t source, void * context);
+
+// Use: dispatch_source_merge_data
+DISPATCH_PUBLIC_API DISPATCH_NONNULL_ALL DISPATCH_DEPRECATED
+void
+dispatch_source_custom_trigger(dispatch_source_t ds);
+
+// Use: dispatch_source_cancel
+__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA)
+DISPATCH_NONNULL_ALL DISPATCH_NOTHROW
+void
+dispatch_cancel(dispatch_source_t);
+
+// Use: dispatch_source_testcancel
+__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA)
+DISPATCH_NONNULL_ALL DISPATCH_NOTHROW
+long
+dispatch_testcancel(dispatch_source_t);
+
+// Use: dispatch_source_set_timer
+__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA)
+DISPATCH_NONNULL1 DISPATCH_NOTHROW
+long
+dispatch_source_timer_set_time(dispatch_source_t ds,
+							   uint64_t nanoseconds,
+							   uint64_t leeway);
+
+// Use: dispatch_source_merge_data
+__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA)
+DISPATCH_NONNULL_ALL DISPATCH_NOTHROW
+void
+dispatch_source_trigger(dispatch_source_t source, unsigned long value);
+
+enum {
+	DISPATCH_ERROR_DOMAIN_NO_ERROR = 0,
+	DISPATCH_ERROR_DOMAIN_POSIX = 1,
+	DISPATCH_ERROR_DOMAIN_MACH = 2,
+};
+
+// Obsolete
+__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA)
+DISPATCH_NONNULL1 DISPATCH_WARN_RESULT DISPATCH_NOTHROW
+long
+dispatch_source_get_error(dispatch_source_t source, long* error);
+
+// Use: dispatch_source_get_handle
+__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA)
+DISPATCH_NONNULL_ALL DISPATCH_WARN_RESULT DISPATCH_NOTHROW
+mach_port_t
+dispatch_source_get_machport(dispatch_source_t source);
+
+// Use: dispatch_source_get_handle
+__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA)
+DISPATCH_NONNULL_ALL DISPATCH_WARN_RESULT DISPATCH_NOTHROW
+pid_t
+dispatch_source_get_descriptor(dispatch_source_t source);
+
+// Use: dispatch_source_get_handle
+__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA)
+DISPATCH_NONNULL_ALL DISPATCH_WARN_RESULT DISPATCH_NOTHROW
+pid_t
+dispatch_source_get_pid(dispatch_source_t source);
+
+// Use: dispatch_source_get_mask
+__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA)
+DISPATCH_NONNULL_ALL DISPATCH_WARN_RESULT DISPATCH_NOTHROW
+uint64_t
+dispatch_source_get_flags(dispatch_source_t source);
+
+// LEGACY: dispatch_event_t == dispatch_source_t
+__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA)
+DISPATCH_NONNULL_ALL DISPATCH_WARN_RESULT DISPATCH_NOTHROW
+dispatch_source_t
+dispatch_event_get_source(dispatch_event_t event);
+
+// Use: dispatch_source_get_error
+__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA)
+DISPATCH_NONNULL1 DISPATCH_WARN_RESULT DISPATCH_NOTHROW
+long
+dispatch_event_get_error(dispatch_event_t event, long* error);
+
+__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA)
+DISPATCH_NONNULL_ALL DISPATCH_WARN_RESULT DISPATCH_NOTHROW
+uint64_t
+dispatch_event_get_nanoseconds(dispatch_event_t event);
+
+// Use: dispatch_source_get_handle
+__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA)
+DISPATCH_NONNULL_ALL DISPATCH_WARN_RESULT DISPATCH_NOTHROW
+long
+dispatch_event_get_signal(dispatch_event_t event);
+
+// Use: dispatch_source_get_data
+__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA)
+DISPATCH_NONNULL_ALL DISPATCH_WARN_RESULT DISPATCH_NOTHROW
+uint64_t
+dispatch_event_get_flags(dispatch_event_t event);
+
+// Use: dispatch_source_get_data
+__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA)
+DISPATCH_NONNULL_ALL DISPATCH_WARN_RESULT DISPATCH_NOTHROW
+size_t
+dispatch_event_get_bytes_available(dispatch_event_t event);
+
+// Use: dispatch_source_get_data
+__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA)
+DISPATCH_NONNULL_ALL DISPATCH_NOTHROW
+unsigned long
+dispatch_event_get_count(dispatch_event_t event);
+
+// Obsolete
+__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA)
+DISPATCH_MALLOC DISPATCH_WARN_RESULT DISPATCH_NOTHROW
+dispatch_source_attr_t
+dispatch_source_attr_create(void);
+
+// Obsolete
+#if defined(__BLOCKS__)
+__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA)
+DISPATCH_NOTHROW
+dispatch_source_finalizer_t
+dispatch_source_attr_get_finalizer(dispatch_source_attr_t attr);
+#endif /* __BLOCKS__ */
+
+// Obsolete
+__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA)
+DISPATCH_MALLOC DISPATCH_WARN_RESULT DISPATCH_NOTHROW
+dispatch_source_attr_t
+dispatch_source_attr_copy(dispatch_source_attr_t proto);
+
+// Obsolete
+#ifdef __BLOCKS__
+__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA)
+DISPATCH_NONNULL1 DISPATCH_NOTHROW
+long
+dispatch_source_attr_set_finalizer(
+	dispatch_source_attr_t attr,
+	dispatch_source_finalizer_t finalizer);
+#endif /* __BLOCKS__ */
+
+// Obsolete
+__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA)
+DISPATCH_NONNULL1 DISPATCH_NOTHROW
+void
+dispatch_source_attr_set_finalizer_f(
+	dispatch_source_attr_t attr,
+	void *context,
+	dispatch_source_finalizer_function_t finalizer);
+
+// Obsolete
+__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA)
+DISPATCH_NONNULL1 DISPATCH_NOTHROW
+void
+dispatch_source_attr_set_context(
+	dispatch_source_attr_t attr,
+	void *context);
+
+// Use: dispatch_source_create(DISPATCH_SOURCE_TYPE_MACH_RECV, ...)
+__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA)
+DISPATCH_MALLOC DISPATCH_NONNULL4 DISPATCH_NONNULL5 DISPATCH_NOTHROW
+dispatch_source_t
+dispatch_source_mig_create(
+	mach_port_t mport, 
+	size_t max_size,
+	dispatch_source_attr_t attr,
+	dispatch_queue_t queue,
+	dispatch_mig_callback_t mig_callback);
+
+enum {
+	DISPATCH_TIMER_WALL_CLOCK	= 0x4,
+};
+
+enum {
+	DISPATCH_TIMER_INTERVAL	= 0x0,
+	DISPATCH_TIMER_ONESHOT	= 0x1,
+	DISPATCH_TIMER_ABSOLUTE	= 0x3,
+};
+
+// Use: dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, ...)
+#ifdef __BLOCKS__
+__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA)
+DISPATCH_MALLOC DISPATCH_NONNULL5 DISPATCH_NONNULL6 DISPATCH_NOTHROW
+dispatch_source_t
+dispatch_source_timer_create(
+	uint64_t flags,
+	uint64_t nanoseconds,
+	uint64_t leeway,
+	dispatch_source_attr_t attr,
+	dispatch_queue_t queue,
+	dispatch_source_handler_t handler);
+#endif /* __BLOCKS__ */
+
+// Use: dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, ...)
+__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA)
+DISPATCH_MALLOC DISPATCH_NONNULL5 DISPATCH_NONNULL7 DISPATCH_NOTHROW
+dispatch_source_t
+dispatch_source_timer_create_f(
+	uint64_t flags,
+	uint64_t nanoseconds,
+	uint64_t leeway,
+	dispatch_source_attr_t attr,
+	dispatch_queue_t queue,
+	void *h_context,
+	dispatch_source_handler_function_t handler);
+
+// Use: dispatch_source_create(DISPATCH_SOURCE_TYPE_SIGNAL, ...)
+#ifdef __BLOCKS__
+__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA)
+DISPATCH_MALLOC DISPATCH_NOTHROW
+dispatch_source_t
+dispatch_source_signal_create(
+	unsigned long signo,
+	dispatch_source_attr_t attr,
+	dispatch_queue_t queue,
+	dispatch_source_handler_t handler);
+#endif /* __BLOCKS__ */
+
+// Use: dispatch_source_create(DISPATCH_SOURCE_TYPE_SIGNAL, ...)
+__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA)
+DISPATCH_MALLOC DISPATCH_NONNULL3 DISPATCH_NONNULL5 DISPATCH_NOTHROW
+dispatch_source_t
+dispatch_source_signal_create_f(
+	unsigned long sig,
+	dispatch_source_attr_t attr,
+	dispatch_queue_t queue,
+	void *h_context,
+	dispatch_source_handler_function_t handler);
+
+// Use: dispatch_source_create(DISPATCH_SOURCE_TYPE_READ, ...)
+#ifdef __BLOCKS__
+__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA)
+DISPATCH_MALLOC DISPATCH_NONNULL3 DISPATCH_NONNULL4 DISPATCH_NOTHROW
+dispatch_source_t
+dispatch_source_read_create(
+	int descriptor,
+	dispatch_source_attr_t attr,
+	dispatch_queue_t queue,
+	dispatch_source_handler_t handler);
+#endif /* __BLOCKS__ */
+
+// Use: dispatch_source_create(DISPATCH_SOURCE_TYPE_READ, ...)
+__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA)
+DISPATCH_MALLOC DISPATCH_NONNULL3 DISPATCH_NONNULL5 DISPATCH_NOTHROW
+dispatch_source_t
+dispatch_source_read_create_f(
+	int descriptor,
+	dispatch_source_attr_t attr,
+	dispatch_queue_t queue,
+	void *h_context,
+	dispatch_source_handler_function_t handler);
+
+// Use: dispatch_source_create(DISPATCH_SOURCE_TYPE_WRITE, ...)
+#ifdef __BLOCKS__
+__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA)
+DISPATCH_MALLOC DISPATCH_NONNULL3 DISPATCH_NONNULL4 DISPATCH_NOTHROW
+dispatch_source_t
+dispatch_source_write_create(
+	int descriptor, 
+	dispatch_source_attr_t attr,
+	dispatch_queue_t queue,
+	dispatch_source_handler_t handler);
+#endif /* __BLOCKS__ */
+
+// Use: dispatch_source_create(DISPATCH_SOURCE_TYPE_WRITE, ...)
+__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA)
+DISPATCH_MALLOC DISPATCH_NONNULL3 DISPATCH_NONNULL5 DISPATCH_NOTHROW
+dispatch_source_t
+dispatch_source_write_create_f(
+	int descriptor, 
+	dispatch_source_attr_t attr,
+	dispatch_queue_t queue,
+	void *h_context,
+	dispatch_source_handler_function_t handler);
+
+// Use: dispatch_source_create(DISPATCH_SOURCE_TYPE_VNODE, ...)
+#ifdef __BLOCKS__
+__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA)
+DISPATCH_MALLOC DISPATCH_NONNULL4 DISPATCH_NONNULL5 DISPATCH_NOTHROW
+dispatch_source_t
+dispatch_source_vnode_create(
+	int descriptor,
+	uint64_t flags,
+	dispatch_source_attr_t attr,
+	dispatch_queue_t queue,
+	dispatch_source_handler_t handler);
+#endif /* __BLOCKS__ */
+
+// Use: dispatch_source_create(DISPATCH_SOURCE_TYPE_VNODE, ...)
+__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA)
+DISPATCH_MALLOC DISPATCH_NONNULL4 DISPATCH_NONNULL6 DISPATCH_NOTHROW
+dispatch_source_t
+dispatch_source_vnode_create_f(
+	int descriptor,
+	uint64_t flags,
+	dispatch_source_attr_t attr,
+	dispatch_queue_t queue,
+	void *h_context,
+	dispatch_source_handler_function_t handler);
+
+// Use: dispatch_source_create(DISPATCH_SOURCE_TYPE_PROC, ...)
+#ifdef __BLOCKS__
+__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA)
+DISPATCH_MALLOC DISPATCH_NONNULL4 DISPATCH_NONNULL5 DISPATCH_NOTHROW
+dispatch_source_t
+dispatch_source_proc_create(
+	pid_t pid,
+	uint64_t flags,
+	dispatch_source_attr_t attr,
+	dispatch_queue_t queue,
+	dispatch_source_handler_t handler);
+#endif /* __BLOCKS__ */
+
+// Use: dispatch_source_create(DISPATCH_SOURCE_TYPE_PROC, ...)
+__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA)
+DISPATCH_MALLOC DISPATCH_NONNULL4 DISPATCH_NONNULL6 DISPATCH_NOTHROW
+dispatch_source_t
+dispatch_source_proc_create_f(
+	pid_t pid,
+	uint64_t flags, 
+	dispatch_source_attr_t attr,
+	dispatch_queue_t queue,
+	void *h_context,
+	dispatch_source_handler_function_t handler);
+
+enum {
+	DISPATCH_MACHPORT_DEAD = 0x1,
+	DISPATCH_MACHPORT_RECV = 0x2,
+	DISPATCH_MACHPORT_DELETED = 0x4,
+};
+
+// Use: dispatch_source_create(DISPATCH_SOURCE_TYPE_MACH_RECV, ...)
+#ifdef __BLOCKS__
+__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA)
+DISPATCH_MALLOC DISPATCH_NOTHROW
+dispatch_source_t
+dispatch_source_machport_create(
+	mach_port_t mport,
+	uint64_t flags, 
+	dispatch_source_attr_t attr,
+	dispatch_queue_t queue,
+	dispatch_source_handler_t handler);
+#endif /* __BLOCKS__ */
+
+// Use: dispatch_source_create(DISPATCH_SOURCE_TYPE_MACH_RECV, ...)
+__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA)
+DISPATCH_MALLOC DISPATCH_NOTHROW
+dispatch_source_t
+dispatch_source_machport_create_f(
+	mach_port_t mport,
+	uint64_t flags, 
+	dispatch_source_attr_t attr,
+	dispatch_queue_t queue,
+	void *h_context,
+	dispatch_source_handler_function_t handler);
+
+enum {
+	DISPATCH_SOURCE_DATA_ADD = 1,
+	DISPATCH_SOURCE_DATA_OR,
+};
+
+// Use: dispatch_source_create(DISPATCH_SOURCE_TYPE_DATA..., ...)
+#ifdef __BLOCKS__
+__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA)
+DISPATCH_MALLOC DISPATCH_NONNULL3 DISPATCH_NONNULL4 DISPATCH_NOTHROW
+dispatch_source_t
+dispatch_source_data_create(
+	unsigned long behavior,
+	dispatch_source_attr_t attr,
+	dispatch_queue_t queue,
+	dispatch_source_handler_t handler);
+#endif /* __BLOCKS__ */
+
+// Use: dispatch_source_create(DISPATCH_SOURCE_TYPE_DATA..., ...)
+__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA)
+DISPATCH_MALLOC DISPATCH_NONNULL3 DISPATCH_NONNULL5 DISPATCH_NOTHROW
+dispatch_source_t
+dispatch_source_data_create_f(
+	unsigned long behavior,
+	dispatch_source_attr_t attr,
+	dispatch_queue_t queue,
+	void *h_context,
+	dispatch_source_handler_function_t handler);
+
+enum {
+	DISPATCH_SOURCE_CUSTOM_ADD = DISPATCH_SOURCE_DATA_ADD,
+	DISPATCH_SOURCE_CUSTOM_OR = DISPATCH_SOURCE_DATA_OR,
+};
+
+// Use: dispatch_source_create(DISPATCH_SOURCE_TYPE_DATA..., ...)
+#ifdef __BLOCKS__
+__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA)
+DISPATCH_MALLOC DISPATCH_NONNULL2 DISPATCH_NONNULL3 DISPATCH_NOTHROW
+dispatch_source_t
+dispatch_source_custom_create(
+							  unsigned long behavior,
+							  dispatch_source_attr_t attr,
+							  dispatch_queue_t queue,
+							  dispatch_event_handler_t handler);
+#endif /* __BLOCKS__ */
+
+// Use: dispatch_source_create(DISPATCH_SOURCE_TYPE_DATA..., ...)
+__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA)
+DISPATCH_MALLOC DISPATCH_NONNULL2 DISPATCH_NONNULL4 DISPATCH_NOTHROW
+dispatch_source_t
+dispatch_source_custom_create_f(
+								unsigned long behavior,
+								dispatch_source_attr_t attr,
+								dispatch_queue_t queue,
+								void *h_context,
+								dispatch_event_handler_function_t handler);
+
+// Use: dispatch_source_create(DISPATCH_SOURCE_TYPE_VFS, ...)
+#if defined(__BLOCKS__)
+__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA)
+DISPATCH_MALLOC DISPATCH_NONNULL3 DISPATCH_NONNULL4
+dispatch_source_t
+dispatch_source_vfs_create(
+						   uint64_t flags,
+						   dispatch_source_attr_t attr,
+						   dispatch_queue_t queue,
+						   dispatch_source_handler_t handler);
+#endif /* __BLOCKS__ */
+
+// Use: dispatch_source_create(DISPATCH_SOURCE_TYPE_VFS, ...)
+__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA)
+DISPATCH_MALLOC DISPATCH_NONNULL3 DISPATCH_NONNULL5
+dispatch_source_t
+dispatch_source_vfs_create_f(
+							 uint64_t flags,
+							 dispatch_source_attr_t attr,
+							 dispatch_queue_t queue,
+							 void *h_context,
+							 dispatch_source_handler_function_t handler);
+
+/*
+ * Raw Mach message support from MIG source.
+ *
+ * It is possible to use the following callback style with the MIG source to
+ * obtain the raw mach message (and send no reply) similar to CFMachPort.
+ * (For more specific CFMachPort compatibility, see below).
+ *
+ * void handle_mach_msg(mach_msg_header *msg) { ... }
+ * ...
+ * DISPATCH_MACHPORT_CALLBACK_DECL(mig_compat_callback, handle_mach_msg);
+ * ...
+ * mig = dispatch_source_mig_create(mp, MY_MAX_MSG_SIZE, NULL,
+ *         queue, mig_compat_callback);
+ */
+__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA)
+boolean_t
+_dispatch_machport_callback(mach_msg_header_t *msg, mach_msg_header_t *reply, void (*callback)(mach_msg_header_t *));
+
+#define DISPATCH_MACHPORT_CALLBACK_DECL(new_callback, existing_callback) \
+__private_extern__ boolean_t \
+new_callback(mach_msg_header_t *msg, mach_msg_header_t *reply) \
+{ return _dispatch_machport_callback(msg, reply, existing_callback); }
+
+/*
+ * CFMachPort compatibility.
+ *
+ * It is possible to use existing CFMachPort callbacks with dispatch mig sources
+ * by delcaring the following shim and using the shim as the mig server callback
+ * to dispatch_source_mig_create().
+ * The CFMachPortRef "port" parameter of the CFMachPortCallBack will be NULL. 
+ * If mach_port_set_context() is used, that value will be passed into the "info"
+ * parameter of the CFMachPortCallBack.
+ *
+ * DISPATCH_CFMACHPORT_CALLBACK_DECL(mig_callback, MyCFMachPortCallBack);
+ *
+ * ...
+ * {
+ * kr = mach_port_set_context(mach_task_self(), mp, (mach_vm_address_t)context);
+ * mig = dispatch_source_mig_create(mp, MY_MAX_MSG_SIZE, NULL,
+ *         queue, mig_callback);
+ */
+struct __CFMachPort;
+
+__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA)
+boolean_t
+_dispatch_CFMachPortCallBack(mach_msg_header_t *msg, mach_msg_header_t *reply, void (*callback)(struct __CFMachPort *, void *msg, signed long size, void *));
+
+#define DISPATCH_CFMACHPORT_CALLBACK_DECL(new_callback, existing_callback) \
+__private_extern__ boolean_t \
+new_callback(mach_msg_header_t *msg, mach_msg_header_t *reply) \
+{ return _dispatch_CFMachPortCallBack(msg, reply, existing_callback); }
+
+__END_DECLS
+
+#endif

Added: trunk/src/object.c
===================================================================
--- trunk/src/object.c	                        (rev 0)
+++ trunk/src/object.c	2009-08-30 01:07:28 UTC (rev 2)
@@ -0,0 +1,200 @@
+/*
+ * Copyright (c) 2008-2009 Apple Inc. All rights reserved.
+ *
+ * @APPLE_APACHE_LICENSE_HEADER_START@
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * 
+ * @APPLE_APACHE_LICENSE_HEADER_END@
+ */
+
+#include "internal.h"
+
+
+void
+dispatch_debug(dispatch_object_t dou, const char *msg, ...)
+{
+	va_list ap;
+
+	va_start(ap, msg);
+
+	dispatch_debugv(dou._do, msg, ap);
+
+	va_end(ap);
+}
+
+void
+dispatch_debugv(dispatch_object_t dou, const char *msg, va_list ap)
+{
+	char buf[4096];
+	size_t offs;
+
+	if (dou._do && dou._do->do_vtable->do_debug) {
+		offs = dx_debug(dou._do, buf, sizeof(buf));
+	} else {
+		offs = snprintf(buf, sizeof(buf), "NULL vtable slot");
+	}
+
+	snprintf(buf + offs, sizeof(buf) - offs, ": %s", msg);
+
+	_dispatch_logv(buf, ap);
+}
+
+void
+dispatch_retain(dispatch_object_t dou)
+{
+	if (dou._do->do_xref_cnt == DISPATCH_OBJECT_GLOBAL_REFCNT) {
+		return; // global object
+	}
+	if ((dispatch_atomic_inc(&dou._do->do_xref_cnt) - 1) == 0) {
+		DISPATCH_CLIENT_CRASH("Resurrection of an object");
+	}
+}
+
+void
+_dispatch_retain(dispatch_object_t dou)
+{
+	if (dou._do->do_ref_cnt == DISPATCH_OBJECT_GLOBAL_REFCNT) {
+		return; // global object
+	}
+	if ((dispatch_atomic_inc(&dou._do->do_ref_cnt) - 1) == 0) {
+		DISPATCH_CLIENT_CRASH("Resurrection of an object");
+	}
+}
+
+void
+dispatch_release(dispatch_object_t dou)
+{
+	typeof(dou._do->do_xref_cnt) oldval;
+
+	if (dou._do->do_xref_cnt == DISPATCH_OBJECT_GLOBAL_REFCNT) {
+		return;
+	}
+
+	oldval = dispatch_atomic_dec(&dou._do->do_xref_cnt) + 1;
+	
+	if (fastpath(oldval > 1)) {
+		return;
+	}
+	if (oldval == 1) {
+#ifndef DISPATCH_NO_LEGACY
+		if (dou._do->do_vtable == (void*)&_dispatch_source_kevent_vtable) {
+			return _dispatch_source_legacy_xref_release(dou._ds);
+		}
+#endif
+		if (slowpath(DISPATCH_OBJECT_SUSPENDED(dou._do))) {
+			// Arguments for and against this assert are within 6705399
+			DISPATCH_CLIENT_CRASH("Release of a suspended object");
+		}
+		return _dispatch_release(dou._do);
+	}
+	DISPATCH_CLIENT_CRASH("Over-release of an object");
+}
+
+void
+_dispatch_dispose(dispatch_object_t dou)
+{
+	dispatch_queue_t tq = dou._do->do_targetq;
+	dispatch_function_t func = dou._do->do_finalizer;
+	void *ctxt = dou._do->do_ctxt;
+
+	dou._do->do_vtable = (void *)0x200;
+
+	free(dou._do);
+
+	if (func && ctxt) {
+		dispatch_async_f(tq, ctxt, func);
+	}
+	_dispatch_release(tq);
+}
+
+void
+_dispatch_release(dispatch_object_t dou)
+{
+	typeof(dou._do->do_ref_cnt) oldval;
+
+	if (dou._do->do_ref_cnt == DISPATCH_OBJECT_GLOBAL_REFCNT) {
+		return; // global object
+	}
+
+	oldval = dispatch_atomic_dec(&dou._do->do_ref_cnt) + 1;
+	
+	if (fastpath(oldval > 1)) {
+		return;
+	}
+	if (oldval == 1) {
+		if (dou._do->do_next != DISPATCH_OBJECT_LISTLESS) {
+			DISPATCH_CRASH("release while enqueued");
+		}
+		if (dou._do->do_xref_cnt) {
+			DISPATCH_CRASH("release while external references exist");
+		}
+
+		return dx_dispose(dou._do);
+	}
+	DISPATCH_CRASH("over-release");
+}
+
+void *
+dispatch_get_context(dispatch_object_t dou)
+{
+	return dou._do->do_ctxt;
+}
+
+void
+dispatch_set_context(dispatch_object_t dou, void *context)
+{
+	if (dou._do->do_ref_cnt != DISPATCH_OBJECT_GLOBAL_REFCNT) {
+		dou._do->do_ctxt = context;
+	}
+}
+
+void
+dispatch_set_finalizer_f(dispatch_object_t dou, dispatch_function_t finalizer)
+{
+	dou._do->do_finalizer = finalizer;
+}
+
+void
+dispatch_suspend(dispatch_object_t dou)
+{
+	if (slowpath(dou._do->do_ref_cnt == DISPATCH_OBJECT_GLOBAL_REFCNT)) {
+		return;
+	}
+	dispatch_atomic_add(&dou._do->do_suspend_cnt, DISPATCH_OBJECT_SUSPEND_INTERVAL);
+}
+
+void
+dispatch_resume(dispatch_object_t dou)
+{
+	if (slowpath(dou._do->do_ref_cnt == DISPATCH_OBJECT_GLOBAL_REFCNT)) {
+		return;
+	}
+	switch (dispatch_atomic_sub(&dou._do->do_suspend_cnt, DISPATCH_OBJECT_SUSPEND_INTERVAL) + DISPATCH_OBJECT_SUSPEND_INTERVAL) {
+	case DISPATCH_OBJECT_SUSPEND_INTERVAL:
+		_dispatch_wakeup(dou._do);
+		break;
+	case 0:
+		DISPATCH_CLIENT_CRASH("Over-resume of an object");
+		break;
+	default:
+		break;
+	}
+}
+
+size_t
+dispatch_object_debug_attr(dispatch_object_t dou, char* buf, size_t bufsiz)
+{
+	return snprintf(buf, bufsiz, "refcnt = 0x%x, suspend_cnt = 0x%x, ",
+					dou._do->do_ref_cnt, dou._do->do_suspend_cnt);
+}

Added: trunk/src/object.h
===================================================================
--- trunk/src/object.h	                        (rev 0)
+++ trunk/src/object.h	2009-08-30 01:07:28 UTC (rev 2)
@@ -0,0 +1,195 @@
+/*
+ * Copyright (c) 2008-2009 Apple Inc. All rights reserved.
+ *
+ * @APPLE_APACHE_LICENSE_HEADER_START@
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * 
+ * @APPLE_APACHE_LICENSE_HEADER_END@
+ */
+
+#ifndef __DISPATCH_OBJECT__
+#define __DISPATCH_OBJECT__
+
+#ifndef __DISPATCH_INDIRECT__
+#error "Please #include <dispatch/dispatch.h> instead of this file directly."
+#include <dispatch/base.h> // for HeaderDoc
+#endif
+
+__BEGIN_DECLS
+
+/*!
+ * @function dispatch_debug
+ *
+ * @abstract
+ * Programmatically log debug information about a dispatch object.
+ *
+ * @param object
+ * The object to introspect.
+ *
+ * @param message
+ * The message to log above and beyond the introspection.
+ */
+__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA)
+DISPATCH_NONNULL2 DISPATCH_NOTHROW __attribute__((__format__(printf,2,3)))
+void
+dispatch_debug(dispatch_object_t object, const char *message, ...);
+
+__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA)
+DISPATCH_NONNULL2 DISPATCH_NOTHROW __attribute__((__format__(printf,2,0)))
+void
+dispatch_debugv(dispatch_object_t object, const char *message, va_list ap);
+
+/*!
+ * @function dispatch_retain
+ *
+ * @abstract
+ * Increment the reference count of a dispatch object.
+ *
+ * @discussion
+ * Calls to dispatch_retain() must be balanced with calls to
+ * dispatch_release().
+ *
+ * @param object
+ * The object to retain.
+ * The result of passing NULL in this parameter is undefined.
+ */
+__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA)
+DISPATCH_NONNULL_ALL DISPATCH_NOTHROW
+void
+dispatch_retain(dispatch_object_t object);
+
+/*!
+ * @function dispatch_release
+ *
+ * @abstract
+ * Decrement the reference count of a dispatch object.
+ *
+ * @discussion
+ * A dispatch object is asynchronously deallocated once all references are
+ * released (i.e. the reference count becomes zero). The system does not
+ * guarantee that a given client is the last or only reference to a given
+ * object.
+ *
+ * @param object
+ * The object to release.
+ * The result of passing NULL in this parameter is undefined.
+ */
+__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA)
+DISPATCH_NONNULL_ALL DISPATCH_NOTHROW
+void
+dispatch_release(dispatch_object_t object);
+
+/*!
+ * @function dispatch_get_context
+ *
+ * @abstract
+ * Returns the application defined context of the object.
+ *
+ * @param object
+ * The result of passing NULL in this parameter is undefined.
+ *
+ * @result
+ * The context of the object; may be NULL.
+ */
+__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA)
+DISPATCH_NONNULL_ALL DISPATCH_PURE DISPATCH_WARN_RESULT DISPATCH_NOTHROW
+void *
+dispatch_get_context(dispatch_object_t object);
+
+/*!
+ * @function dispatch_set_context
+ *
+ * @abstract
+ * Associates an application defined context with the object.
+ *
+ * @param object
+ * The result of passing NULL in this parameter is undefined.
+ *
+ * @param context
+ * The new client defined context for the object. This may be NULL.
+ *
+ */
+__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA)
+DISPATCH_NOTHROW //DISPATCH_NONNULL1
+void
+dispatch_set_context(dispatch_object_t object, void *context);
+
+/*!
+ * @function dispatch_set_finalizer_f
+ *
+ * @abstract
+ * Set the finalizer function for a dispatch object.
+ *
+ * @param
+ * The dispatch object to modify.
+ * The result of passing NULL in this parameter is undefined.
+ *
+ * @param
+ * The finalizer function pointer.
+ *
+ * @discussion
+ * A dispatch object's finalizer will be invoked on the object's target queue
+ * after all references to the object have been released. This finalizer may be
+ * used by the application to release any resources associated with the object,
+ * such as freeing the object's context.
+ * The context parameter passed to the finalizer function is the current
+ * context of the dispatch object at the time the finalizer call is made.
+ */
+__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA)
+DISPATCH_NOTHROW //DISPATCH_NONNULL1
+void
+dispatch_set_finalizer_f(dispatch_object_t object,
+	dispatch_function_t finalizer);
+
+/*!
+ * @function dispatch_suspend
+ *
+ * @abstract
+ * Suspends the invocation of blocks on a dispatch object.
+ *
+ * @discussion
+ * A suspended object will not invoke any blocks associated with it. The
+ * suspension of an object will occur after any running block associated with
+ * the object completes.
+ *
+ * Calls to dispatch_suspend() must be balanced with calls
+ * to dispatch_resume().
+ *
+ * @param	object
+ * The object to be suspended.
+ * The result of passing NULL in this parameter is undefined.
+ */
+__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA)
+DISPATCH_NONNULL_ALL DISPATCH_NOTHROW
+void
+dispatch_suspend(dispatch_object_t object);
+
+/*!
+ * @function dispatch_resume
+ *
+ * @abstract
+ * Resumes the invocation of blocks on a dispatch object.
+ *
+ * @param	object
+ * The object to be resumed.
+ * The result of passing NULL in this parameter is undefined.
+ */
+__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA)
+DISPATCH_NONNULL_ALL DISPATCH_NOTHROW
+void
+dispatch_resume(dispatch_object_t object);
+
+__END_DECLS
+
+#endif

Added: trunk/src/object_internal.h
===================================================================
--- trunk/src/object_internal.h	                        (rev 0)
+++ trunk/src/object_internal.h	2009-08-30 01:07:28 UTC (rev 2)
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2008-2009 Apple Inc. All rights reserved.
+ *
+ * @APPLE_APACHE_LICENSE_HEADER_START@
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * 
+ * @APPLE_APACHE_LICENSE_HEADER_END@
+ */
+
+/*
+ * IMPORTANT: This header file describes INTERNAL interfaces to libdispatch
+ * which are subject to change in future releases of Mac OS X. Any applications
+ * relying on these interfaces WILL break.
+ */
+
+#ifndef __DISPATCH_OBJECT_INTERNAL__
+#define __DISPATCH_OBJECT_INTERNAL__
+
+enum {
+	_DISPATCH_CONTINUATION_TYPE		=	 0x00000, // meta-type for continuations
+	_DISPATCH_QUEUE_TYPE			=    0x10000, // meta-type for queues
+	_DISPATCH_SOURCE_TYPE			=    0x20000, // meta-type for sources
+	_DISPATCH_SEMAPHORE_TYPE		=    0x30000, // meta-type for semaphores
+	_DISPATCH_ATTR_TYPE				= 0x10000000, // meta-type for attribute structures
+	
+	DISPATCH_CONTINUATION_TYPE		= _DISPATCH_CONTINUATION_TYPE,
+	
+	DISPATCH_QUEUE_ATTR_TYPE		= _DISPATCH_QUEUE_TYPE | _DISPATCH_ATTR_TYPE,
+
+	DISPATCH_QUEUE_TYPE				= 1 | _DISPATCH_QUEUE_TYPE,
+	DISPATCH_QUEUE_GLOBAL_TYPE		= 2 | _DISPATCH_QUEUE_TYPE,
+	DISPATCH_QUEUE_MGR_TYPE			= 3 | _DISPATCH_QUEUE_TYPE,
+
+	DISPATCH_SEMAPHORE_TYPE			= _DISPATCH_SEMAPHORE_TYPE,
+	
+	DISPATCH_SOURCE_ATTR_TYPE		= _DISPATCH_SOURCE_TYPE | _DISPATCH_ATTR_TYPE,
+	
+	DISPATCH_SOURCE_KEVENT_TYPE		= 1 | _DISPATCH_SOURCE_TYPE,
+};
+
+#define DISPATCH_VTABLE_HEADER(x)	\
+	unsigned long const do_type;	\
+	const char *const do_kind; \
+	size_t (*const do_debug)(struct x *, char *, size_t);	\
+	struct dispatch_queue_s *(*const do_invoke)(struct x *);	\
+	bool (*const do_probe)(struct x *); \
+	void (*const do_dispose)(struct x *)
+
+#define dx_type(x) (x)->do_vtable->do_type
+#define dx_kind(x) (x)->do_vtable->do_kind
+#define dx_debug(x, y, z) (x)->do_vtable->do_debug((x), (y), (z))
+#define dx_dispose(x) (x)->do_vtable->do_dispose(x)
+#define dx_invoke(x) (x)->do_vtable->do_invoke(x)
+#define dx_probe(x) (x)->do_vtable->do_probe(x)
+
+#define DISPATCH_STRUCT_HEADER(x, y)	\
+	const struct y *do_vtable;	\
+	struct x *volatile do_next;	\
+	unsigned int do_ref_cnt;	\
+	unsigned int do_xref_cnt;	\
+	unsigned int do_suspend_cnt;	\
+	struct dispatch_queue_s *do_targetq;	\
+	void *do_ctxt; \
+	void *do_finalizer
+
+#define DISPATCH_OBJECT_GLOBAL_REFCNT	(~0u)
+#define DISPATCH_OBJECT_SUSPEND_LOCK		1u	// "word and bit" must be a power of two to be safely subtracted
+#define DISPATCH_OBJECT_SUSPEND_INTERVAL	2u
+#define DISPATCH_OBJECT_SUSPENDED(x)	((x)->do_suspend_cnt >= DISPATCH_OBJECT_SUSPEND_INTERVAL)
+#ifdef __LP64__
+// the bottom nibble must not be zero, the rest of the bits should be random
+// we sign extend the 64-bit version so that a better instruction encoding is generated on Intel
+#define DISPATCH_OBJECT_LISTLESS	((void *)0xffffffff89abcdef)
+#else
+#define DISPATCH_OBJECT_LISTLESS	((void *)0x89abcdef)
+#endif
+
+#define _dispatch_trysuspend(x) __sync_bool_compare_and_swap(&(x)->do_suspend_cnt, 0, DISPATCH_OBJECT_SUSPEND_INTERVAL)
+// _dispatch_source_invoke() relies on this testing the whole suspend count
+// word, not just the lock bit. In other words, no point taking the lock
+// if the source is suspended or canceled.
+#define _dispatch_trylock(x)	dispatch_atomic_cmpxchg(&(x)->do_suspend_cnt, 0, DISPATCH_OBJECT_SUSPEND_LOCK)
+
+struct dispatch_object_vtable_s {
+	DISPATCH_VTABLE_HEADER(dispatch_object_s);
+};
+
+struct dispatch_object_s {
+	DISPATCH_STRUCT_HEADER(dispatch_object_s, dispatch_object_vtable_s);
+};
+
+size_t dispatch_object_debug_attr(dispatch_object_t dou, char* buf, size_t bufsiz);
+
+void _dispatch_retain(dispatch_object_t dou);
+void _dispatch_release(dispatch_object_t dou);
+void _dispatch_dispose(dispatch_object_t dou);
+dispatch_queue_t _dispatch_wakeup(dispatch_object_t dou);
+
+#endif

Added: trunk/src/once.c
===================================================================
--- trunk/src/once.c	                        (rev 0)
+++ trunk/src/once.c	2009-08-30 01:07:28 UTC (rev 2)
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2008-2009 Apple Inc. All rights reserved.
+ *
+ * @APPLE_APACHE_LICENSE_HEADER_START@
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * 
+ * @APPLE_APACHE_LICENSE_HEADER_END@
+ */
+
+#include "internal.h"
+
+#undef dispatch_once
+#undef dispatch_once_f
+
+#ifdef __BLOCKS__
+void
+dispatch_once(dispatch_once_t *val, void (^block)(void))
+{
+	struct Block_basic *bb = (void *)block;
+
+	dispatch_once_f(val, block, (void *)bb->Block_invoke);
+}
+#endif
+
+DISPATCH_NOINLINE
+void
+dispatch_once_f(dispatch_once_t *val, void *ctxt, void (*func)(void *))
+{
+	volatile long *vval = val;
+
+	if (dispatch_atomic_cmpxchg(val, 0l, 1l)) {
+		func(ctxt);
+
+		// The next barrier must be long and strong.
+		//
+		// The scenario: SMP systems with weakly ordered memory models
+		// and aggressive out-of-order instruction execution.
+		//
+		// The problem:
+		//
+		// The dispatch_once*() wrapper macro causes the callee's
+		// instruction stream to look like this (pseudo-RISC):
+		//
+		// 	load r5, pred-addr
+		// 	cmpi r5, -1
+		// 	beq  1f
+		// 	call dispatch_once*()
+		// 1f:
+		// 	load r6, data-addr
+		//
+		// May be re-ordered like so:
+		//
+		// 	load r6, data-addr
+		// 	load r5, pred-addr
+		// 	cmpi r5, -1
+		// 	beq  1f
+		// 	call dispatch_once*()
+		// 1f:
+		//
+		// Normally, a barrier on the read side is used to workaround
+		// the weakly ordered memory model. But barriers are expensive
+		// and we only need to synchronize once!  After func(ctxt)
+		// completes, the predicate will be marked as "done" and the
+		// branch predictor will correctly skip the call to
+		// dispatch_once*().
+		//
+		// A far faster alternative solution: Defeat the speculative
+		// read-ahead of peer CPUs.
+		//
+		// Modern architectures will throw away speculative results
+		// once a branch mis-prediction occurs. Therefore, if we can
+		// ensure that the predicate is not marked as being complete
+		// until long after the last store by func(ctxt), then we have
+		// defeated the read-ahead of peer CPUs.
+		//
+		// In other words, the last "store" by func(ctxt) must complete
+		// and then N cycles must elapse before ~0l is stored to *val.
+		// The value of N is whatever is sufficient to defeat the
+		// read-ahead mechanism of peer CPUs.
+		//
+		// On some CPUs, the most fully synchronizing instruction might
+		// need to be issued.
+	
+		dispatch_atomic_barrier();
+		*val = ~0l;
+	} else {
+		do {
+			_dispatch_hardware_pause();
+		} while (*vval != ~0l);
+
+		dispatch_atomic_barrier();
+	}
+}

Added: trunk/src/once.h
===================================================================
--- trunk/src/once.h	                        (rev 0)
+++ trunk/src/once.h	2009-08-30 01:07:28 UTC (rev 2)
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2008-2009 Apple Inc. All rights reserved.
+ *
+ * @APPLE_APACHE_LICENSE_HEADER_START@
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * 
+ * @APPLE_APACHE_LICENSE_HEADER_END@
+ */
+
+#ifndef __DISPATCH_ONCE__
+#define __DISPATCH_ONCE__
+
+#ifndef __DISPATCH_INDIRECT__
+#error "Please #include <dispatch/dispatch.h> instead of this file directly."
+#include <dispatch/base.h> // for HeaderDoc
+#endif
+
+__BEGIN_DECLS
+
+/*!
+ * @typedef dispatch_once_t
+ *
+ * @abstract
+ * A predicate for use with dispatch_once(). It must be initialized to zero.
+ * Note: static and global variables default to zero.
+ */
+typedef long dispatch_once_t;
+
+/*!
+ * @function dispatch_once
+ *
+ * @abstract
+ * Execute a block once and only once.
+ *
+ * @param predicate
+ * A pointer to a dispatch_once_t that is used to test whether the block has
+ * completed or not.
+ *
+ * @param block
+ * The block to execute once.
+ *
+ * @discussion
+ * Always call dispatch_once() before using or testing any variables that are
+ * initialized by the block.
+ */
+#ifdef __BLOCKS__
+__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA)
+DISPATCH_NONNULL_ALL DISPATCH_NOTHROW
+void
+dispatch_once(dispatch_once_t *predicate, dispatch_block_t block);
+#ifdef __GNUC__
+#define dispatch_once(x, ...) do { if (__builtin_expect(*(x), ~0l) != ~0l) dispatch_once((x), (__VA_ARGS__)); } while (0)
+#endif
+#endif
+
+__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA)
+DISPATCH_NONNULL1 DISPATCH_NONNULL3 DISPATCH_NOTHROW
+void
+dispatch_once_f(dispatch_once_t *predicate, void *context, void (*function)(void *));
+#ifdef __GNUC__
+#define dispatch_once_f(x, y, z) do { if (__builtin_expect(*(x), ~0l) != ~0l) dispatch_once_f((x), (y), (z)); } while (0)
+#endif
+
+__END_DECLS
+
+#endif

Added: trunk/src/os_shims.h
===================================================================
--- trunk/src/os_shims.h	                        (rev 0)
+++ trunk/src/os_shims.h	2009-08-30 01:07:28 UTC (rev 2)
@@ -0,0 +1,152 @@
+/*
+ * Copyright (c) 2008-2009 Apple Inc. All rights reserved.
+ *
+ * @APPLE_APACHE_LICENSE_HEADER_START@
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * 
+ * @APPLE_APACHE_LICENSE_HEADER_END@
+ */
+
+/*
+ * IMPORTANT: This header file describes INTERNAL interfaces to libdispatch
+ * which are subject to change in future releases of Mac OS X. Any applications
+ * relying on these interfaces WILL break.
+ */
+
+#ifndef __DISPATCH_OS_SHIMS__
+#define __DISPATCH_OS_SHIMS__
+
+#include <pthread.h>
+#include <pthread_machdep.h>
+#include <pthread_workqueue.h>
+
+__private_extern__ const char *__crashreporter_info__;
+
+static const unsigned long dispatch_queue_key = __PTK_LIBDISPATCH_KEY0;
+static const unsigned long dispatch_sema4_key = __PTK_LIBDISPATCH_KEY1;
+static const unsigned long dispatch_cache_key = __PTK_LIBDISPATCH_KEY2;
+static const unsigned long dispatch_bcounter_key = __PTK_LIBDISPATCH_KEY3;
+//__PTK_LIBDISPATCH_KEY4
+//__PTK_LIBDISPATCH_KEY5
+
+
+#define SIMULATE_5491082 1
+#ifndef _PTHREAD_TSD_OFFSET
+#define _PTHREAD_TSD_OFFSET 0
+#endif
+
+static inline void
+_dispatch_thread_setspecific(unsigned long k, void *v)
+{
+#if defined(SIMULATE_5491082) && defined(__i386__)
+	asm("movl %1, %%gs:%0" : "=m" (*(void **)(k * sizeof(void *) + _PTHREAD_TSD_OFFSET)) : "ri" (v) : "memory");
+#elif defined(SIMULATE_5491082) && defined(__x86_64__)
+	asm("movq %1, %%gs:%0" : "=m" (*(void **)(k * sizeof(void *) + _PTHREAD_TSD_OFFSET)) : "rn" (v) : "memory");
+#else
+	int res;
+	if (_pthread_has_direct_tsd()) {
+		res = _pthread_setspecific_direct(k, v);
+	} else {
+		res = pthread_setspecific(k, v);
+	}
+	dispatch_assert_zero(res);
+#endif
+}
+
+static inline void *
+_dispatch_thread_getspecific(unsigned long k)
+{
+#if defined(SIMULATE_5491082) && (defined(__i386__) || defined(__x86_64__))
+	void *rval;
+	asm("mov %%gs:%1, %0" : "=r" (rval) : "m" (*(void **)(k * sizeof(void *) + _PTHREAD_TSD_OFFSET)));
+	return rval;
+#else
+	if (_pthread_has_direct_tsd()) {
+		return _pthread_getspecific_direct(k);
+	} else {
+		return pthread_getspecific(k);
+	}
+#endif
+}
+
+static inline void
+_dispatch_thread_key_init_np(unsigned long k, void (*d)(void *))
+{
+	dispatch_assert_zero(pthread_key_init_np((int)k, d));
+}
+
+#define _dispatch_thread_self pthread_self
+
+
+#if DISPATCH_PERF_MON
+
+#if defined(SIMULATE_5491082) && (defined(__i386__) || defined(__x86_64__))
+#ifdef __LP64__
+#define _dispatch_workitem_inc()	asm("incq %%gs:%0" : "+m"	\
+		(*(void **)(dispatch_bcounter_key * sizeof(void *) + _PTHREAD_TSD_OFFSET)) :: "cc")
+#define _dispatch_workitem_dec()	asm("decq %%gs:%0" : "+m"	\
+		(*(void **)(dispatch_bcounter_key * sizeof(void *) + _PTHREAD_TSD_OFFSET)) :: "cc")
+#else
+#define _dispatch_workitem_inc()	asm("incl %%gs:%0" : "+m"	\
+		(*(void **)(dispatch_bcounter_key * sizeof(void *) + _PTHREAD_TSD_OFFSET)) :: "cc")
+#define _dispatch_workitem_dec()	asm("decl %%gs:%0" : "+m"	\
+		(*(void **)(dispatch_bcounter_key * sizeof(void *) + _PTHREAD_TSD_OFFSET)) :: "cc")
+#endif
+#else
+static inline void
+_dispatch_workitem_inc(void)
+{
+	unsigned long cnt = (unsigned long)_dispatch_thread_getspecific(dispatch_bcounter_key);
+	_dispatch_thread_setspecific(dispatch_bcounter_key, (void *)++cnt);
+}
+static inline void
+_dispatch_workitem_dec(void)
+{
+	unsigned long cnt = (unsigned long)_dispatch_thread_getspecific(dispatch_bcounter_key);
+	_dispatch_thread_setspecific(dispatch_bcounter_key, (void *)--cnt);
+}
+#endif
+
+// C99 doesn't define flsll() or ffsll()
+#ifdef __LP64__
+#define flsll(x) flsl(x)
+#else
+static inline unsigned int
+flsll(uint64_t val)
+{
+	union {
+		struct {
+#ifdef __BIG_ENDIAN__
+			unsigned int hi, low;
+#else
+			unsigned int low, hi;
+#endif
+		} words;
+		uint64_t word;
+	} _bucket = {
+		.word = val,
+	};
+	if (_bucket.words.hi) {
+		return fls(_bucket.words.hi) + 32;
+	}
+	return fls(_bucket.words.low);
+}
+#endif
+
+#else
+#define _dispatch_workitem_inc()
+#define _dispatch_workitem_dec()
+#endif	// DISPATCH_PERF_MON
+
+#endif

Added: trunk/src/private.h
===================================================================
--- trunk/src/private.h	                        (rev 0)
+++ trunk/src/private.h	2009-08-30 01:07:28 UTC (rev 2)
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2008-2009 Apple Inc. All rights reserved.
+ *
+ * @APPLE_APACHE_LICENSE_HEADER_START@
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * 
+ * @APPLE_APACHE_LICENSE_HEADER_END@
+ */
+
+/*
+ * IMPORTANT: This header file describes INTERNAL interfaces to libdispatch
+ * which are subject to change in future releases of Mac OS X. Any applications
+ * relying on these interfaces WILL break.
+ */
+
+#ifndef __DISPATCH_PRIVATE__
+#define __DISPATCH_PRIVATE__
+
+#include <mach/boolean.h>
+#include <mach/mach.h>
+#include <mach/message.h>
+#include <unistd.h>
+#include <sys/cdefs.h>
+#include <sys/event.h>
+#include <pthread.h>
+
+#ifndef __DISPATCH_BUILDING_DISPATCH__
+#include_next <dispatch/dispatch.h>
+
+// Workaround <rdar://problem/6597365/>
+#ifndef __DISPATCH_PUBLIC__
+#include "/usr/include/dispatch/dispatch.h"
+#endif
+
+#ifndef __DISPATCH_INDIRECT__
+#define __DISPATCH_INDIRECT__
+#endif
+
+#include <dispatch/benchmark.h>
+#include <dispatch/queue_private.h>
+#include <dispatch/source_private.h>
+
+#ifndef DISPATCH_NO_LEGACY
+#include <dispatch/legacy.h>
+#endif
+
+#undef __DISPATCH_INDIRECT__
+
+#endif /* !__DISPATCH_BUILDING_DISPATCH__ */
+
+/* LEGACY: Use DISPATCH_API_VERSION */
+#define LIBDISPATCH_VERSION DISPATCH_API_VERSION
+
+__BEGIN_DECLS
+
+DISPATCH_NOTHROW
+void
+libdispatch_init(void);
+
+#define DISPATCH_COCOA_COMPAT 1
+#if DISPATCH_COCOA_COMPAT
+
+__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA)
+DISPATCH_NOTHROW
+mach_port_t
+_dispatch_get_main_queue_port_4CF(void);
+
+__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA)
+DISPATCH_NOTHROW
+void
+_dispatch_main_queue_callback_4CF(mach_msg_header_t *msg);
+
+__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA)
+extern void (*dispatch_begin_thread_4GC)(void);
+
+__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA)
+extern void (*dispatch_end_thread_4GC)(void);
+
+__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA)
+extern void *(*_dispatch_begin_NSAutoReleasePool)(void);
+
+__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA)
+extern void (*_dispatch_end_NSAutoReleasePool)(void *);
+
+#endif
+
+/* pthreads magic */
+
+DISPATCH_NOTHROW void dispatch_atfork_prepare(void);
+DISPATCH_NOTHROW void dispatch_atfork_parent(void);
+DISPATCH_NOTHROW void dispatch_atfork_child(void);
+DISPATCH_NOTHROW void dispatch_init_pthread(pthread_t);
+
+/*
+ * Extract the context pointer from a mach message trailer.
+ */
+__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA)
+void *
+dispatch_mach_msg_get_context(mach_msg_header_t *msg);
+
+__END_DECLS
+
+#endif

Added: trunk/src/protocol.defs
===================================================================
--- trunk/src/protocol.defs	                        (rev 0)
+++ trunk/src/protocol.defs	2009-08-30 01:07:28 UTC (rev 2)
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2009 Apple Inc. All rights reserved.
+ *
+ * @APPLE_APACHE_LICENSE_HEADER_START@
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * 
+ * @APPLE_APACHE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 2008-2009 Apple Inc. All rights reserved.
+ */
+
+#include <mach/std_types.defs>
+#include <mach/mach_types.defs>
+
+// '64' is used to align with Mach notifications and so that we don't fight with the notify symbols in Libsystem
+subsystem libdispatch_internal_protocol 64;
+
+serverprefix _dispatch_;
+userprefix _dispatch_send_;
+
+skip;	/* was MACH_NOTIFY_FIRST: 64 */
+
+/* MACH_NOTIFY_PORT_DELETED: 65 */
+simpleroutine
+mach_notify_port_deleted(
+				_notify	: mach_port_move_send_once_t;
+				_name	: mach_port_name_t
+);
+
+skip;   /* was MACH_NOTIFY_MSG_ACCEPTED: 66 */
+
+skip;   /* was NOTIFY_OWNERSHIP_RIGHTS: 67 */
+
+skip;   /* was NOTIFY_RECEIVE_RIGHTS: 68 */
+
+/* MACH_NOTIFY_PORT_DESTROYED: 69 */
+simpleroutine
+mach_notify_port_destroyed(
+				_notify	: mach_port_move_send_once_t;
+				_rights	: mach_port_move_receive_t
+);
+
+/* MACH_NOTIFY_NO_SENDERS: 70 */
+simpleroutine
+mach_notify_no_senders(
+				_notify	: mach_port_move_send_once_t;
+				_mscnt	: mach_port_mscount_t
+);
+
+/* MACH_NOTIFY_SEND_ONCE: 71 */
+simpleroutine
+mach_notify_send_once(
+				_notify	: mach_port_move_send_once_t
+);
+
+/* MACH_NOTIFY_DEAD_NAME: 72 */
+simpleroutine
+mach_notify_dead_name(
+				_notify	: mach_port_move_send_once_t;
+				_name	: mach_port_name_t
+);
+
+/* highly unlikely additional Mach notifications */
+skip;
+skip;
+skip;
+skip;
+skip;
+
+simpleroutine
+wakeup_main_thread(
+				_port			: mach_port_t;
+	WaitTime	_waitTimeout	: natural_t
+);
+
+simpleroutine
+consume_send_once_right(
+				_port			: mach_port_move_send_once_t
+);

Added: trunk/src/queue.c
===================================================================
--- trunk/src/queue.c	                        (rev 0)
+++ trunk/src/queue.c	2009-08-30 01:07:28 UTC (rev 2)
@@ -0,0 +1,2080 @@
+/*
+ * Copyright (c) 2008-2009 Apple Inc. All rights reserved.
+ *
+ * @APPLE_APACHE_LICENSE_HEADER_START@
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * 
+ * @APPLE_APACHE_LICENSE_HEADER_END@
+ */
+
+#include "internal.h"
+#include "protocol.h"
+
+void
+dummy_function(void)
+{
+}
+
+long
+dummy_function_r0(void)
+{
+	return 0;
+}
+
+static bool _dispatch_select_workaround;
+static fd_set _dispatch_rfds;
+static fd_set _dispatch_wfds;
+static void *_dispatch_rfd_ptrs[FD_SETSIZE];
+static void *_dispatch_wfd_ptrs[FD_SETSIZE];
+
+
+static struct dispatch_semaphore_s _dispatch_thread_mediator[] = {
+	{
+		.do_vtable = &_dispatch_semaphore_vtable,
+		.do_ref_cnt = DISPATCH_OBJECT_GLOBAL_REFCNT,
+		.do_xref_cnt = DISPATCH_OBJECT_GLOBAL_REFCNT,
+	},
+	{
+		.do_vtable = &_dispatch_semaphore_vtable,
+		.do_ref_cnt = DISPATCH_OBJECT_GLOBAL_REFCNT,
+		.do_xref_cnt = DISPATCH_OBJECT_GLOBAL_REFCNT,
+	},
+	{
+		.do_vtable = &_dispatch_semaphore_vtable,
+		.do_ref_cnt = DISPATCH_OBJECT_GLOBAL_REFCNT,
+		.do_xref_cnt = DISPATCH_OBJECT_GLOBAL_REFCNT,
+	},
+	{
+		.do_vtable = &_dispatch_semaphore_vtable,
+		.do_ref_cnt = DISPATCH_OBJECT_GLOBAL_REFCNT,
+		.do_xref_cnt = DISPATCH_OBJECT_GLOBAL_REFCNT,
+	},
+	{
+		.do_vtable = &_dispatch_semaphore_vtable,
+		.do_ref_cnt = DISPATCH_OBJECT_GLOBAL_REFCNT,
+		.do_xref_cnt = DISPATCH_OBJECT_GLOBAL_REFCNT,
+	},
+	{
+		.do_vtable = &_dispatch_semaphore_vtable,
+		.do_ref_cnt = DISPATCH_OBJECT_GLOBAL_REFCNT,
+		.do_xref_cnt = DISPATCH_OBJECT_GLOBAL_REFCNT,
+	},
+};
+
+static struct dispatch_queue_s _dispatch_root_queues[];
+
+static inline dispatch_queue_t
+_dispatch_get_root_queue(long priority, bool overcommit)
+{
+	if (overcommit) switch (priority) {
+	case DISPATCH_QUEUE_PRIORITY_LOW:
+		return &_dispatch_root_queues[1];
+	case DISPATCH_QUEUE_PRIORITY_DEFAULT:
+		return &_dispatch_root_queues[3];
+	case DISPATCH_QUEUE_PRIORITY_HIGH:
+		return &_dispatch_root_queues[5];
+	}
+	switch (priority) {
+	case DISPATCH_QUEUE_PRIORITY_LOW:
+		return &_dispatch_root_queues[0];
+	case DISPATCH_QUEUE_PRIORITY_DEFAULT:
+		return &_dispatch_root_queues[2];
+	case DISPATCH_QUEUE_PRIORITY_HIGH:
+		return &_dispatch_root_queues[4];
+	default:
+		return NULL;
+	}
+}
+
+#ifdef __BLOCKS__
+dispatch_block_t
+_dispatch_Block_copy(dispatch_block_t db)
+{
+	dispatch_block_t rval;
+
+	while (!(rval = Block_copy(db))) {
+		sleep(1);
+	}
+
+	return rval;
+}
+#define _dispatch_Block_copy(x) ((typeof(x))_dispatch_Block_copy(x))
+
+void
+_dispatch_call_block_and_release(void *block)
+{
+	void (^b)(void) = block;
+	b();
+	Block_release(b);
+}
+
+void
+_dispatch_call_block_and_release2(void *block, void *ctxt)
+{
+	void (^b)(void*) = block;
+	b(ctxt);
+	Block_release(b);
+}
+
+#endif /* __BLOCKS__ */
+
+struct dispatch_queue_attr_vtable_s {
+	DISPATCH_VTABLE_HEADER(dispatch_queue_attr_s);
+};
+
+struct dispatch_queue_attr_s {
+	DISPATCH_STRUCT_HEADER(dispatch_queue_attr_s, dispatch_queue_attr_vtable_s);
+
+	// Public:
+	int qa_priority;
+	void* finalizer_ctxt;
+	dispatch_queue_finalizer_function_t finalizer_func;
+
+	// Private:
+	unsigned long qa_flags;
+};
+
+static int _dispatch_pthread_sigmask(int how, sigset_t *set, sigset_t *oset);
+
+#define _dispatch_queue_trylock(dq) dispatch_atomic_cmpxchg(&(dq)->dq_running, 0, 1)
+static inline void _dispatch_queue_unlock(dispatch_queue_t dq);
+static void _dispatch_queue_invoke(dispatch_queue_t dq);
+static void _dispatch_queue_serial_drain_till_empty(dispatch_queue_t dq);
+static bool _dispatch_queue_wakeup_global(dispatch_queue_t dq);
+static struct dispatch_object_s *_dispatch_queue_concurrent_drain_one(dispatch_queue_t dq);
+
+static bool _dispatch_program_is_probably_callback_driven;
+
+#if DISPATCH_COCOA_COMPAT
+void (*dispatch_begin_thread_4GC)(void) = dummy_function;
+void (*dispatch_end_thread_4GC)(void) = dummy_function;
+void *(*_dispatch_begin_NSAutoReleasePool)(void) = (void *)dummy_function;
+void (*_dispatch_end_NSAutoReleasePool)(void *) = (void *)dummy_function;
+static void _dispatch_queue_wakeup_main(void);
+
+static dispatch_once_t _dispatch_main_q_port_pred;
+static bool main_q_is_draining;
+static mach_port_t main_q_port;
+#endif
+
+static void _dispatch_cache_cleanup2(void *value);
+static void _dispatch_force_cache_cleanup(void);
+
+static const struct dispatch_queue_vtable_s _dispatch_queue_vtable = {
+	.do_type = DISPATCH_QUEUE_TYPE,
+	.do_kind = "queue",
+	.do_dispose = _dispatch_queue_dispose,
+	.do_invoke = (void *)dummy_function_r0,
+	.do_probe = (void *)dummy_function_r0,
+	.do_debug = dispatch_queue_debug,
+};
+
+static const struct dispatch_queue_vtable_s _dispatch_queue_root_vtable = {
+	.do_type = DISPATCH_QUEUE_GLOBAL_TYPE,
+	.do_kind = "global-queue",
+	.do_debug = dispatch_queue_debug,
+	.do_probe = _dispatch_queue_wakeup_global,
+};
+
+#define MAX_THREAD_COUNT 255
+
+struct dispatch_root_queue_context_s {
+	pthread_workqueue_t dgq_kworkqueue;
+	uint32_t dgq_pending;
+	uint32_t dgq_thread_pool_size;
+	dispatch_semaphore_t dgq_thread_mediator;
+};
+
+#define DISPATCH_ROOT_QUEUE_COUNT (DISPATCH_QUEUE_PRIORITY_COUNT * 2)
+static struct dispatch_root_queue_context_s _dispatch_root_queue_contexts[] = {
+	{
+		.dgq_thread_mediator = &_dispatch_thread_mediator[0],
+		.dgq_thread_pool_size = MAX_THREAD_COUNT,
+	},
+	{
+		.dgq_thread_mediator = &_dispatch_thread_mediator[1],
+		.dgq_thread_pool_size = MAX_THREAD_COUNT,
+	},
+	{
+		.dgq_thread_mediator = &_dispatch_thread_mediator[2],
+		.dgq_thread_pool_size = MAX_THREAD_COUNT,
+	},
+	{
+		.dgq_thread_mediator = &_dispatch_thread_mediator[3],
+		.dgq_thread_pool_size = MAX_THREAD_COUNT,
+	},
+	{
+		.dgq_thread_mediator = &_dispatch_thread_mediator[4],
+		.dgq_thread_pool_size = MAX_THREAD_COUNT,
+	},
+	{
+		.dgq_thread_mediator = &_dispatch_thread_mediator[5],
+		.dgq_thread_pool_size = MAX_THREAD_COUNT,
+	},
+};
+
+// 6618342 Contact the team that owns the Instrument DTrace probe before renaming this symbol
+// dq_running is set to 2 so that barrier operations go through the slow path
+static struct dispatch_queue_s _dispatch_root_queues[] = {
+	{
+		.do_vtable = &_dispatch_queue_root_vtable,
+		.do_ref_cnt = DISPATCH_OBJECT_GLOBAL_REFCNT,
+		.do_xref_cnt = DISPATCH_OBJECT_GLOBAL_REFCNT,
+		.do_suspend_cnt = DISPATCH_OBJECT_SUSPEND_LOCK,
+		.do_ctxt = &_dispatch_root_queue_contexts[0],
+
+		.dq_label = "com.apple.root.low-priority",
+		.dq_running = 2,
+		.dq_width = UINT32_MAX,
+		.dq_serialnum = 4,
+	},
+	{
+		.do_vtable = &_dispatch_queue_root_vtable,
+		.do_ref_cnt = DISPATCH_OBJECT_GLOBAL_REFCNT,
+		.do_xref_cnt = DISPATCH_OBJECT_GLOBAL_REFCNT,
+		.do_suspend_cnt = DISPATCH_OBJECT_SUSPEND_LOCK,
+		.do_ctxt = &_dispatch_root_queue_contexts[1],
+
+		.dq_label = "com.apple.root.low-overcommit-priority",
+		.dq_running = 2,
+		.dq_width = UINT32_MAX,
+		.dq_serialnum = 5,
+	},
+	{
+		.do_vtable = &_dispatch_queue_root_vtable,
+		.do_ref_cnt = DISPATCH_OBJECT_GLOBAL_REFCNT,
+		.do_xref_cnt = DISPATCH_OBJECT_GLOBAL_REFCNT,
+		.do_suspend_cnt = DISPATCH_OBJECT_SUSPEND_LOCK,
+		.do_ctxt = &_dispatch_root_queue_contexts[2],
+
+		.dq_label = "com.apple.root.default-priority",
+		.dq_running = 2,
+		.dq_width = UINT32_MAX,
+		.dq_serialnum = 6,
+	},
+	{
+		.do_vtable = &_dispatch_queue_root_vtable,
+		.do_ref_cnt = DISPATCH_OBJECT_GLOBAL_REFCNT,
+		.do_xref_cnt = DISPATCH_OBJECT_GLOBAL_REFCNT,
+		.do_suspend_cnt = DISPATCH_OBJECT_SUSPEND_LOCK,
+		.do_ctxt = &_dispatch_root_queue_contexts[3],
+
+		.dq_label = "com.apple.root.default-overcommit-priority",
+		.dq_running = 2,
+		.dq_width = UINT32_MAX,
+		.dq_serialnum = 7,
+	},
+	{
+		.do_vtable = &_dispatch_queue_root_vtable,
+		.do_ref_cnt = DISPATCH_OBJECT_GLOBAL_REFCNT,
+		.do_xref_cnt = DISPATCH_OBJECT_GLOBAL_REFCNT,
+		.do_suspend_cnt = DISPATCH_OBJECT_SUSPEND_LOCK,
+		.do_ctxt = &_dispatch_root_queue_contexts[4],
+
+		.dq_label = "com.apple.root.high-priority",
+		.dq_running = 2,
+		.dq_width = UINT32_MAX,
+		.dq_serialnum = 8,
+	},
+	{
+		.do_vtable = &_dispatch_queue_root_vtable,
+		.do_ref_cnt = DISPATCH_OBJECT_GLOBAL_REFCNT,
+		.do_xref_cnt = DISPATCH_OBJECT_GLOBAL_REFCNT,
+		.do_suspend_cnt = DISPATCH_OBJECT_SUSPEND_LOCK,
+		.do_ctxt = &_dispatch_root_queue_contexts[5],
+
+		.dq_label = "com.apple.root.high-overcommit-priority",
+		.dq_running = 2,
+		.dq_width = UINT32_MAX,
+		.dq_serialnum = 9,
+	},
+};
+
+// 6618342 Contact the team that owns the Instrument DTrace probe before renaming this symbol
+struct dispatch_queue_s _dispatch_main_q = {
+	.do_vtable = &_dispatch_queue_vtable,
+	.do_ref_cnt = DISPATCH_OBJECT_GLOBAL_REFCNT,
+	.do_xref_cnt = DISPATCH_OBJECT_GLOBAL_REFCNT,
+	.do_suspend_cnt = DISPATCH_OBJECT_SUSPEND_LOCK,
+	.do_targetq = &_dispatch_root_queues[DISPATCH_ROOT_QUEUE_COUNT / 2],
+
+	.dq_label = "com.apple.main-thread",
+	.dq_running = 1,
+	.dq_width = 1,
+	.dq_serialnum = 1,
+};
+
+#if DISPATCH_PERF_MON
+static OSSpinLock _dispatch_stats_lock;
+static size_t _dispatch_bad_ratio;
+static struct {
+	uint64_t time_total;
+	uint64_t count_total;
+	uint64_t thread_total;
+} _dispatch_stats[65]; // ffs*/fls*() returns zero when no bits are set
+static void _dispatch_queue_merge_stats(uint64_t start);
+#endif
+
+static void *_dispatch_worker_thread(void *context);
+static void _dispatch_worker_thread2(void *context);
+
+malloc_zone_t *_dispatch_ccache_zone;
+
+static inline void
+_dispatch_continuation_free(dispatch_continuation_t dc)
+{
+	dispatch_continuation_t prev_dc = _dispatch_thread_getspecific(dispatch_cache_key);
+	dc->do_next = prev_dc;
+	_dispatch_thread_setspecific(dispatch_cache_key, dc);
+}
+
+static inline void
+_dispatch_continuation_pop(dispatch_object_t dou)
+{
+	dispatch_continuation_t dc = dou._dc;
+	dispatch_group_t dg;
+
+	if (DISPATCH_OBJ_IS_VTABLE(dou._do)) {
+		return _dispatch_queue_invoke(dou._dq);
+	}
+
+	// Add the item back to the cache before calling the function. This
+	// allows the 'hot' continuation to be used for a quick callback.
+	//
+	// The ccache version is per-thread.
+	// Therefore, the object has not been reused yet.
+	// This generates better assembly.
+	if ((long)dou._do->do_vtable & DISPATCH_OBJ_ASYNC_BIT) {
+		_dispatch_continuation_free(dc);
+	}
+	if ((long)dou._do->do_vtable & DISPATCH_OBJ_GROUP_BIT) {
+		dg = dc->dc_group;
+	} else {
+		dg = NULL;
+	}
+	dc->dc_func(dc->dc_ctxt);
+	if (dg) {
+		dispatch_group_leave(dg);
+		_dispatch_release(dg);
+	}
+}
+
+struct dispatch_object_s *
+_dispatch_queue_concurrent_drain_one(dispatch_queue_t dq)
+{
+	struct dispatch_object_s *head, *next, *const mediator = (void *)~0ul;
+
+	// The mediator value acts both as a "lock" and a signal
+	head = dispatch_atomic_xchg(&dq->dq_items_head, mediator);
+
+	if (slowpath(head == NULL)) {
+		// The first xchg on the tail will tell the enqueueing thread that it
+		// is safe to blindly write out to the head pointer. A cmpxchg honors
+		// the algorithm.
+		dispatch_atomic_cmpxchg(&dq->dq_items_head, mediator, NULL);
+		_dispatch_debug("no work on global work queue");
+		return NULL;
+	}
+
+	if (slowpath(head == mediator)) {
+		// This thread lost the race for ownership of the queue.
+		//
+		// The ratio of work to libdispatch overhead must be bad. This
+		// scenario implies that there are too many threads in the pool.
+		// Create a new pending thread and then exit this thread.
+		// The kernel will grant a new thread when the load subsides.
+		_dispatch_debug("Contention on queue: %p", dq);
+		_dispatch_queue_wakeup_global(dq);
+#if DISPATCH_PERF_MON
+		dispatch_atomic_inc(&_dispatch_bad_ratio);
+#endif
+		return NULL;
+	}
+
+	// Restore the head pointer to a sane value before returning.
+	// If 'next' is NULL, then this item _might_ be the last item.
+	next = fastpath(head->do_next);
+
+	if (slowpath(!next)) {
+		dq->dq_items_head = NULL;
+		
+		if (dispatch_atomic_cmpxchg(&dq->dq_items_tail, head, NULL)) {
+			// both head and tail are NULL now
+			goto out;
+		}
+
+		// There must be a next item now. This thread won't wait long.
+		while (!(next = head->do_next)) {
+			_dispatch_hardware_pause();
+		}
+	}
+
+	dq->dq_items_head = next;
+	_dispatch_queue_wakeup_global(dq);
+out:
+	return head;
+}
+
+dispatch_queue_t
+dispatch_get_current_queue(void)
+{
+	return _dispatch_queue_get_current() ?: _dispatch_get_root_queue(0, true);
+}
+
+#undef dispatch_get_main_queue
+__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA)
+dispatch_queue_t dispatch_get_main_queue(void);
+
+dispatch_queue_t
+dispatch_get_main_queue(void)
+{
+	return &_dispatch_main_q;
+}
+#define dispatch_get_main_queue() (&_dispatch_main_q)
+
+struct _dispatch_hw_config_s _dispatch_hw_config;
+
+static void
+_dispatch_queue_set_width_init(void)
+{
+	size_t valsz = sizeof(uint32_t);
+
+	errno = 0;
+	sysctlbyname("hw.activecpu", &_dispatch_hw_config.cc_max_active, &valsz, NULL, 0);
+	dispatch_assume_zero(errno);
+	dispatch_assume(valsz == sizeof(uint32_t));
+
+	errno = 0;
+	sysctlbyname("hw.logicalcpu_max", &_dispatch_hw_config.cc_max_logical, &valsz, NULL, 0);
+	dispatch_assume_zero(errno);
+	dispatch_assume(valsz == sizeof(uint32_t));
+
+	errno = 0;
+	sysctlbyname("hw.physicalcpu_max", &_dispatch_hw_config.cc_max_physical, &valsz, NULL, 0);
+	dispatch_assume_zero(errno);
+	dispatch_assume(valsz == sizeof(uint32_t));
+}
+
+void
+dispatch_queue_set_width(dispatch_queue_t dq, long width)
+{
+	int w = (int)width;	// intentional truncation
+	uint32_t tmp;
+
+	if (slowpath(dq->do_ref_cnt == DISPATCH_OBJECT_GLOBAL_REFCNT)) {
+		return;
+	}
+	if (w == 1 || w == 0) {
+		dq->dq_width = 1;
+		return;
+	}
+	if (w > 0) {
+		tmp = w;
+	} else switch (w) {
+	case DISPATCH_QUEUE_WIDTH_MAX_PHYSICAL_CPUS:
+		tmp = _dispatch_hw_config.cc_max_physical;
+		break;
+	case DISPATCH_QUEUE_WIDTH_ACTIVE_CPUS:
+		tmp = _dispatch_hw_config.cc_max_active;
+		break;
+	default:
+		// fall through
+	case DISPATCH_QUEUE_WIDTH_MAX_LOGICAL_CPUS:
+		tmp = _dispatch_hw_config.cc_max_logical;
+		break;
+	}
+	// multiply by two since the running count is inc/dec by two (the low bit == barrier)
+	dq->dq_width = tmp * 2;
+
+	// XXX if the queue has items and the width is increased, we should try to wake the queue
+}
+
+// skip zero
+// 1 - main_q
+// 2 - mgr_q
+// 3 - _unused_
+// 4,5,6,7,8,9 - global queues
+// we use 'xadd' on Intel, so the initial value == next assigned
+static unsigned long _dispatch_queue_serial_numbers = 10;
+
+// Note to later developers: ensure that any initialization changes are
+// made for statically allocated queues (i.e. _dispatch_main_q).
+inline void
+_dispatch_queue_init(dispatch_queue_t dq)
+{
+	dq->do_vtable = &_dispatch_queue_vtable;
+	dq->do_next = DISPATCH_OBJECT_LISTLESS;
+	dq->do_ref_cnt = 1;
+	dq->do_xref_cnt = 1;
+	dq->do_targetq = _dispatch_get_root_queue(0, true);
+	dq->dq_running = 0;
+	dq->dq_width = 1;
+	dq->dq_serialnum = dispatch_atomic_inc(&_dispatch_queue_serial_numbers) - 1;
+}
+
+dispatch_queue_t
+dispatch_queue_create(const char *label, dispatch_queue_attr_t attr)
+{
+	dispatch_queue_t dq;
+	size_t label_len;
+
+	if (!label) {
+		label = "";
+	}
+
+	label_len = strlen(label);
+	if (label_len < (DISPATCH_QUEUE_MIN_LABEL_SIZE - 1)) {
+		label_len = (DISPATCH_QUEUE_MIN_LABEL_SIZE - 1);
+	}
+
+	// XXX switch to malloc()
+	dq = calloc(1ul, sizeof(struct dispatch_queue_s) - DISPATCH_QUEUE_MIN_LABEL_SIZE + label_len + 1);
+	if (slowpath(!dq)) {
+		return dq;
+	}
+
+	_dispatch_queue_init(dq);
+	strcpy(dq->dq_label, label);
+
+#ifndef DISPATCH_NO_LEGACY
+	if (slowpath(attr)) {
+		dq->do_targetq = _dispatch_get_root_queue(attr->qa_priority, attr->qa_flags & DISPATCH_QUEUE_OVERCOMMIT);
+		dq->dq_finalizer_ctxt = attr->finalizer_ctxt;
+		dq->dq_finalizer_func = attr->finalizer_func;
+#ifdef __BLOCKS__
+		if (attr->finalizer_func == (void*)_dispatch_call_block_and_release2) {
+			// if finalizer_ctxt is a Block, retain it.
+ 			dq->dq_finalizer_ctxt = Block_copy(dq->dq_finalizer_ctxt);
+			if (!(dq->dq_finalizer_ctxt)) {
+				goto out_bad;
+			}
+		}
+#endif
+	}
+#endif
+
+	return dq;
+
+out_bad:
+	free(dq);
+	return NULL;
+}
+
+// 6618342 Contact the team that owns the Instrument DTrace probe before renaming this symbol
+void
+_dispatch_queue_dispose(dispatch_queue_t dq)
+{
+	if (slowpath(dq == _dispatch_queue_get_current())) {
+		DISPATCH_CRASH("Release of a queue by itself");
+	}
+	if (slowpath(dq->dq_items_tail)) {
+		DISPATCH_CRASH("Release of a queue while items are enqueued");
+	}
+
+#ifndef DISPATCH_NO_LEGACY
+	if (dq->dq_finalizer_func) {
+		dq->dq_finalizer_func(dq->dq_finalizer_ctxt, dq);
+	}
+#endif
+
+	// trash the tail queue so that use after free will crash
+	dq->dq_items_tail = (void *)0x200;
+
+	_dispatch_dispose(dq);
+}
+
+DISPATCH_NOINLINE
+static void
+_dispatch_barrier_async_f_slow(dispatch_queue_t dq, void *context, dispatch_function_t func)
+{
+	dispatch_continuation_t dc = fastpath(_dispatch_continuation_alloc_from_heap());
+
+	dc->do_vtable = (void *)(DISPATCH_OBJ_ASYNC_BIT | DISPATCH_OBJ_BARRIER_BIT);
+	dc->dc_func = func;
+	dc->dc_ctxt = context;
+
+	_dispatch_queue_push(dq, dc);
+}
+
+#ifdef __BLOCKS__
+void
+dispatch_barrier_async(dispatch_queue_t dq, void (^work)(void))
+{
+	dispatch_barrier_async_f(dq, _dispatch_Block_copy(work), _dispatch_call_block_and_release);
+}
+#endif
+
+DISPATCH_NOINLINE
+void
+dispatch_barrier_async_f(dispatch_queue_t dq, void *context, dispatch_function_t func)
+{
+	dispatch_continuation_t dc = fastpath(_dispatch_continuation_alloc_cacheonly());
+
+	if (!dc) {
+		return _dispatch_barrier_async_f_slow(dq, context, func);
+	}
+
+	dc->do_vtable = (void *)(DISPATCH_OBJ_ASYNC_BIT | DISPATCH_OBJ_BARRIER_BIT);
+	dc->dc_func = func;
+	dc->dc_ctxt = context;
+
+	_dispatch_queue_push(dq, dc);
+}
+
+DISPATCH_NOINLINE
+static void
+_dispatch_async_f_slow(dispatch_queue_t dq, void *context, dispatch_function_t func)
+{
+	dispatch_continuation_t dc = fastpath(_dispatch_continuation_alloc_from_heap());
+
+	dc->do_vtable = (void *)DISPATCH_OBJ_ASYNC_BIT;
+	dc->dc_func = func;
+	dc->dc_ctxt = context;
+
+	_dispatch_queue_push(dq, dc);
+}
+
+#ifdef __BLOCKS__
+void
+dispatch_async(dispatch_queue_t dq, void (^work)(void))
+{
+	dispatch_async_f(dq, _dispatch_Block_copy(work), _dispatch_call_block_and_release);
+}
+#endif
+
+DISPATCH_NOINLINE
+void
+dispatch_async_f(dispatch_queue_t dq, void *ctxt, dispatch_function_t func)
+{
+	dispatch_continuation_t dc = fastpath(_dispatch_continuation_alloc_cacheonly());
+
+	// unlike dispatch_sync_f(), we do NOT need to check the queue width,
+	// the "drain" function will do this test
+
+	if (!dc) {
+		return _dispatch_async_f_slow(dq, ctxt, func);
+	}
+
+	dc->do_vtable = (void *)DISPATCH_OBJ_ASYNC_BIT;
+	dc->dc_func = func;
+	dc->dc_ctxt = ctxt;
+
+	_dispatch_queue_push(dq, dc);
+}
+
+struct dispatch_barrier_sync_slow2_s {
+	dispatch_function_t dbss2_func;
+	dispatch_function_t dbss2_ctxt;
+	dispatch_semaphore_t dbss2_sema;
+};
+
+static void
+_dispatch_barrier_sync_f_slow_invoke(void *ctxt)
+{
+	struct dispatch_barrier_sync_slow2_s *dbss2 = ctxt;
+
+	dbss2->dbss2_func(dbss2->dbss2_ctxt);
+	dispatch_semaphore_signal(dbss2->dbss2_sema);
+}
+
+DISPATCH_NOINLINE
+static void
+_dispatch_barrier_sync_f_slow(dispatch_queue_t dq, void *ctxt, dispatch_function_t func)
+{
+	struct dispatch_barrier_sync_slow2_s dbss2 = {
+		.dbss2_func = func,
+		.dbss2_ctxt = ctxt,
+		.dbss2_sema = _dispatch_get_thread_semaphore(),
+	};
+	struct dispatch_barrier_sync_slow_s {
+		DISPATCH_CONTINUATION_HEADER(dispatch_barrier_sync_slow_s);
+	} dbss = {
+		.do_vtable = (void *)DISPATCH_OBJ_BARRIER_BIT,
+		.dc_func = _dispatch_barrier_sync_f_slow_invoke,
+		.dc_ctxt = &dbss2,
+	};
+
+	_dispatch_queue_push(dq, (void *)&dbss);
+
+	while (dispatch_semaphore_wait(dbss2.dbss2_sema, dispatch_time(0, 3ull * NSEC_PER_SEC))) {
+		if (DISPATCH_OBJECT_SUSPENDED(dq)) {
+			continue;
+		}
+		if (_dispatch_queue_trylock(dq)) {
+			_dispatch_queue_drain(dq);
+			_dispatch_queue_unlock(dq);
+		}
+	}
+	_dispatch_put_thread_semaphore(dbss2.dbss2_sema);
+}
+
+#ifdef __BLOCKS__
+void
+dispatch_barrier_sync(dispatch_queue_t dq, void (^work)(void))
+{
+	struct Block_basic *bb = (void *)work;
+
+	dispatch_barrier_sync_f(dq, work, (dispatch_function_t)bb->Block_invoke);
+}
+#endif
+
+DISPATCH_NOINLINE
+void
+dispatch_barrier_sync_f(dispatch_queue_t dq, void *ctxt, dispatch_function_t func)
+{
+	dispatch_queue_t old_dq = _dispatch_thread_getspecific(dispatch_queue_key);
+
+	// 1) ensure that this thread hasn't enqueued anything ahead of this call
+	// 2) the queue is not suspended
+	// 3) the queue is not weird
+	if (slowpath(dq->dq_items_tail)
+			|| slowpath(DISPATCH_OBJECT_SUSPENDED(dq))
+			|| slowpath(!_dispatch_queue_trylock(dq))) {
+		return _dispatch_barrier_sync_f_slow(dq, ctxt, func);
+	}
+
+	_dispatch_thread_setspecific(dispatch_queue_key, dq);
+	func(ctxt);
+	_dispatch_workitem_inc();
+	_dispatch_thread_setspecific(dispatch_queue_key, old_dq);
+	_dispatch_queue_unlock(dq);
+}
+
+static void
+_dispatch_sync_f_slow2(void *ctxt)
+{
+	dispatch_queue_t dq = _dispatch_queue_get_current();
+	dispatch_atomic_add(&dq->dq_running, 2);
+	dispatch_semaphore_signal(ctxt);
+}
+
+DISPATCH_NOINLINE
+static void
+_dispatch_sync_f_slow(dispatch_queue_t dq)
+{
+	// the global root queues do not need strict ordering
+	if (dq->do_targetq == NULL) {
+		dispatch_atomic_add(&dq->dq_running, 2);
+		return;
+	}
+
+	struct dispatch_sync_slow_s {
+		DISPATCH_CONTINUATION_HEADER(dispatch_sync_slow_s);
+	} dss = {
+		.do_vtable = NULL,
+		.dc_func = _dispatch_sync_f_slow2,
+		.dc_ctxt = _dispatch_get_thread_semaphore(),
+	};
+
+	// XXX FIXME -- concurrent queues can be come serial again
+	_dispatch_queue_push(dq, (void *)&dss);
+
+	dispatch_semaphore_wait(dss.dc_ctxt, DISPATCH_TIME_FOREVER);
+	_dispatch_put_thread_semaphore(dss.dc_ctxt);
+}
+
+#ifdef __BLOCKS__
+void
+dispatch_sync(dispatch_queue_t dq, void (^work)(void))
+{
+	struct Block_basic *bb = (void *)work;
+	dispatch_sync_f(dq, work, (dispatch_function_t)bb->Block_invoke);
+}
+#endif
+
+DISPATCH_NOINLINE
+void
+dispatch_sync_f(dispatch_queue_t dq, void *ctxt, dispatch_function_t func)
+{
+	typeof(dq->dq_running) prev_cnt;
+	dispatch_queue_t old_dq;
+
+	if (dq->dq_width == 1) {
+		return dispatch_barrier_sync_f(dq, ctxt, func);
+	}
+
+	// 1) ensure that this thread hasn't enqueued anything ahead of this call
+	// 2) the queue is not suspended
+	if (slowpath(dq->dq_items_tail) || slowpath(DISPATCH_OBJECT_SUSPENDED(dq))) {
+		_dispatch_sync_f_slow(dq);
+	} else {
+		prev_cnt = dispatch_atomic_add(&dq->dq_running, 2) - 2;
+
+		if (slowpath(prev_cnt & 1)) {
+			if (dispatch_atomic_sub(&dq->dq_running, 2) == 0) {
+				_dispatch_wakeup(dq);
+			}
+			_dispatch_sync_f_slow(dq);
+		}
+	}
+
+	old_dq = _dispatch_thread_getspecific(dispatch_queue_key);
+	_dispatch_thread_setspecific(dispatch_queue_key, dq);
+	func(ctxt);
+	_dispatch_workitem_inc();
+	_dispatch_thread_setspecific(dispatch_queue_key, old_dq);
+
+	if (slowpath(dispatch_atomic_sub(&dq->dq_running, 2) == 0)) {
+		_dispatch_wakeup(dq);
+	}
+}
+
+const char *
+dispatch_queue_get_label(dispatch_queue_t dq)
+{
+	return dq->dq_label;
+}
+
+#if DISPATCH_COCOA_COMPAT
+static void
+_dispatch_main_q_port_init(void *ctxt __attribute__((unused)))
+{
+	kern_return_t kr;
+
+	kr = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &main_q_port);
+	DISPATCH_VERIFY_MIG(kr);
+	dispatch_assume_zero(kr);
+	kr = mach_port_insert_right(mach_task_self(), main_q_port, main_q_port, MACH_MSG_TYPE_MAKE_SEND);
+	DISPATCH_VERIFY_MIG(kr);
+	dispatch_assume_zero(kr);
+
+	_dispatch_program_is_probably_callback_driven = true;
+	_dispatch_safe_fork = false;
+}
+
+// 6618342 Contact the team that owns the Instrument DTrace probe before renaming this symbol
+DISPATCH_NOINLINE
+static void
+_dispatch_queue_set_mainq_drain_state(bool arg)
+{
+	main_q_is_draining = arg;
+}
+#endif
+
+void
+dispatch_main(void)
+{
+	if (pthread_main_np()) {
+		_dispatch_program_is_probably_callback_driven = true;
+		pthread_exit(NULL);
+		DISPATCH_CRASH("pthread_exit() returned");
+	}
+	DISPATCH_CLIENT_CRASH("dispatch_main() must be called on the main thread");
+}
+
+static void
+_dispatch_sigsuspend(void *ctxt __attribute__((unused)))
+{
+	static const sigset_t mask;
+
+	for (;;) {
+		sigsuspend(&mask);
+	}
+}
+
+DISPATCH_NOINLINE
+static void
+_dispatch_queue_cleanup2(void)
+{
+	dispatch_atomic_dec(&_dispatch_main_q.dq_running);
+
+	if (dispatch_atomic_sub(&_dispatch_main_q.do_suspend_cnt, DISPATCH_OBJECT_SUSPEND_LOCK) == 0) {
+		_dispatch_wakeup(&_dispatch_main_q);
+	}
+
+	// overload the "probably" variable to mean that dispatch_main() or
+	// similar non-POSIX API was called
+	// this has to run before the DISPATCH_COCOA_COMPAT below
+	if (_dispatch_program_is_probably_callback_driven) {
+		dispatch_async_f(_dispatch_get_root_queue(0, 0), NULL, _dispatch_sigsuspend);
+		sleep(1);	// workaround 6778970
+	}
+
+#if DISPATCH_COCOA_COMPAT
+	dispatch_once_f(&_dispatch_main_q_port_pred, NULL, _dispatch_main_q_port_init);
+
+	mach_port_t mp = main_q_port;
+	kern_return_t kr;
+
+	main_q_port = 0;
+
+	if (mp) {
+		kr = mach_port_deallocate(mach_task_self(), mp);
+		DISPATCH_VERIFY_MIG(kr);
+		dispatch_assume_zero(kr);
+		kr = mach_port_mod_refs(mach_task_self(), mp, MACH_PORT_RIGHT_RECEIVE, -1);
+		DISPATCH_VERIFY_MIG(kr);
+		dispatch_assume_zero(kr);
+	}
+#endif
+}
+
+dispatch_queue_t
+dispatch_get_concurrent_queue(long pri)
+{
+	if (pri > 0) {
+		pri = DISPATCH_QUEUE_PRIORITY_HIGH;
+	} else if (pri < 0) {
+		pri = DISPATCH_QUEUE_PRIORITY_LOW;
+	}
+	return _dispatch_get_root_queue(pri, false);
+}
+
+static void
+_dispatch_queue_cleanup(void *ctxt)
+{
+	if (ctxt == &_dispatch_main_q) {
+		return _dispatch_queue_cleanup2();
+	}
+	// POSIX defines that destructors are only called if 'ctxt' is non-null
+	DISPATCH_CRASH("Premature thread exit while a dispatch queue is running");
+}
+
+dispatch_queue_t
+dispatch_get_global_queue(long priority, unsigned long flags)
+{
+	if (flags & ~DISPATCH_QUEUE_OVERCOMMIT) {
+		return NULL;
+	}
+	return _dispatch_get_root_queue(priority, flags & DISPATCH_QUEUE_OVERCOMMIT);
+}
+
+#define countof(x)	(sizeof(x) / sizeof(x[0]))
+void
+libdispatch_init(void)
+{
+	dispatch_assert(DISPATCH_QUEUE_PRIORITY_COUNT == 3);
+	dispatch_assert(DISPATCH_ROOT_QUEUE_COUNT == 6);
+
+	dispatch_assert(DISPATCH_QUEUE_PRIORITY_LOW == -DISPATCH_QUEUE_PRIORITY_HIGH);
+	dispatch_assert(countof(_dispatch_root_queues) == DISPATCH_ROOT_QUEUE_COUNT);
+	dispatch_assert(countof(_dispatch_thread_mediator) == DISPATCH_ROOT_QUEUE_COUNT);
+	dispatch_assert(countof(_dispatch_root_queue_contexts) == DISPATCH_ROOT_QUEUE_COUNT);
+
+	_dispatch_thread_key_init_np(dispatch_queue_key, _dispatch_queue_cleanup);
+	_dispatch_thread_key_init_np(dispatch_sema4_key, (void (*)(void *))dispatch_release);	// use the extern release
+	_dispatch_thread_key_init_np(dispatch_cache_key, _dispatch_cache_cleanup2);
+#if DISPATCH_PERF_MON
+	_dispatch_thread_key_init_np(dispatch_bcounter_key, NULL);
+#endif
+
+	_dispatch_thread_setspecific(dispatch_queue_key, &_dispatch_main_q);
+
+	_dispatch_queue_set_width_init();
+}
+
+void
+_dispatch_queue_unlock(dispatch_queue_t dq)
+{
+	if (slowpath(dispatch_atomic_dec(&dq->dq_running))) {
+		return;
+	}
+
+	_dispatch_wakeup(dq);
+}
+
+// 6618342 Contact the team that owns the Instrument DTrace probe before renaming this symbol
+dispatch_queue_t
+_dispatch_wakeup(dispatch_object_t dou)
+{
+	dispatch_queue_t tq;
+
+	if (slowpath(DISPATCH_OBJECT_SUSPENDED(dou._do))) {
+		return NULL;
+	}
+	if (!dx_probe(dou._do) && !dou._dq->dq_items_tail) {
+		return NULL;
+	}
+
+	if (!_dispatch_trylock(dou._do)) {
+#if DISPATCH_COCOA_COMPAT
+		if (dou._dq == &_dispatch_main_q) {
+			_dispatch_queue_wakeup_main();
+		}
+#endif
+		return NULL;
+	}
+	_dispatch_retain(dou._do);
+	tq = dou._do->do_targetq;
+	_dispatch_queue_push(tq, dou._do);
+	return tq;	// libdispatch doesn't need this, but the Instrument DTrace probe does
+}
+
+#if DISPATCH_COCOA_COMPAT
+DISPATCH_NOINLINE
+void
+_dispatch_queue_wakeup_main(void)
+{
+	kern_return_t kr;
+
+	dispatch_once_f(&_dispatch_main_q_port_pred, NULL, _dispatch_main_q_port_init);
+
+	kr = _dispatch_send_wakeup_main_thread(main_q_port, 0);
+
+	switch (kr) {
+	case MACH_SEND_TIMEOUT:
+	case MACH_SEND_TIMED_OUT:
+	case MACH_SEND_INVALID_DEST:
+		break;
+	default:
+		dispatch_assume_zero(kr);
+		break;
+	}
+
+	_dispatch_safe_fork = false;
+}
+#endif
+
+static inline int
+_dispatch_rootq2wq_pri(long idx)
+{
+#ifdef WORKQ_DEFAULT_PRIOQUEUE
+	switch (idx) {
+	case 0:
+	case 1:
+		return WORKQ_LOW_PRIOQUEUE;
+	case 2:
+	case 3:
+	default:
+		return WORKQ_DEFAULT_PRIOQUEUE;
+	case 4:
+	case 5:
+		return WORKQ_HIGH_PRIOQUEUE;
+	}
+#else
+	return pri;
+#endif
+}
+
+static void
+_dispatch_root_queues_init(void *context __attribute__((unused)))
+{
+	bool disable_wq = getenv("LIBDISPATCH_DISABLE_KWQ");
+	pthread_workqueue_attr_t pwq_attr;
+	kern_return_t kr;
+	int i, r;
+
+	r = pthread_workqueue_attr_init_np(&pwq_attr);
+	dispatch_assume_zero(r);
+
+	for (i = 0; i < DISPATCH_ROOT_QUEUE_COUNT; i++) {
+		r = pthread_workqueue_attr_setqueuepriority_np(&pwq_attr, _dispatch_rootq2wq_pri(i));
+		dispatch_assume_zero(r);
+		r = pthread_workqueue_attr_setovercommit_np(&pwq_attr, i & 1);
+		dispatch_assume_zero(r);
+// some software hangs if the non-overcommitting queues do not overcommit when threads block
+#if 0
+		if (!(i & 1)) {
+			dispatch_root_queue_contexts[i].dgq_thread_pool_size = _dispatch_hw_config.cc_max_active;
+		}
+#endif
+
+		r = 0;
+		if (disable_wq || (r = pthread_workqueue_create_np(&_dispatch_root_queue_contexts[i].dgq_kworkqueue, &pwq_attr))) {
+			if (r != ENOTSUP) {
+				dispatch_assume_zero(r);
+			}
+			// override the default FIFO behavior for the pool semaphores
+			kr = semaphore_create(mach_task_self(), &_dispatch_thread_mediator[i].dsema_port, SYNC_POLICY_LIFO, 0);
+			DISPATCH_VERIFY_MIG(kr);
+			dispatch_assume_zero(kr);
+			dispatch_assume(_dispatch_thread_mediator[i].dsema_port);
+		} else {
+			dispatch_assume(_dispatch_root_queue_contexts[i].dgq_kworkqueue);
+		}
+	}
+
+	r = pthread_workqueue_attr_destroy_np(&pwq_attr);
+	dispatch_assume_zero(r);
+}
+
+bool
+_dispatch_queue_wakeup_global(dispatch_queue_t dq)
+{
+	static dispatch_once_t pred;
+	struct dispatch_root_queue_context_s *qc = dq->do_ctxt;
+	pthread_workitem_handle_t wh;
+	unsigned int gen_cnt;
+	pthread_t pthr;
+	int r, t_count;
+
+	if (!dq->dq_items_tail) {
+		return false;
+	}
+
+	_dispatch_safe_fork = false;
+
+	dispatch_debug_queue(dq, __PRETTY_FUNCTION__);
+
+	dispatch_once_f(&pred, NULL, _dispatch_root_queues_init);
+
+	if (qc->dgq_kworkqueue) {
+		if (dispatch_atomic_cmpxchg(&qc->dgq_pending, 0, 1)) {
+			_dispatch_debug("requesting new worker thread");
+
+			r = pthread_workqueue_additem_np(qc->dgq_kworkqueue, _dispatch_worker_thread2, dq, &wh, &gen_cnt);
+			dispatch_assume_zero(r);
+		} else {
+			_dispatch_debug("work thread request still pending on global queue: %p", dq);
+		}
+		goto out;
+	}
+
+	if (dispatch_semaphore_signal(qc->dgq_thread_mediator)) {
+		goto out;
+	}
+
+	do {
+		t_count = qc->dgq_thread_pool_size;
+		if (!t_count) {
+			_dispatch_debug("The thread pool is full: %p", dq);
+			goto out;
+		}
+	} while (!dispatch_atomic_cmpxchg(&qc->dgq_thread_pool_size, t_count, t_count - 1));
+
+	while ((r = pthread_create(&pthr, NULL, _dispatch_worker_thread, dq))) {
+		if (r != EAGAIN) {
+			dispatch_assume_zero(r);
+		}
+		sleep(1);
+	}
+	r = pthread_detach(pthr);
+	dispatch_assume_zero(r);
+
+out:
+	return false;
+}
+
+void
+_dispatch_queue_serial_drain_till_empty(dispatch_queue_t dq)
+{
+#if DISPATCH_PERF_MON
+	uint64_t start = mach_absolute_time();
+#endif
+	_dispatch_queue_drain(dq);
+#if DISPATCH_PERF_MON
+	_dispatch_queue_merge_stats(start);
+#endif
+	_dispatch_force_cache_cleanup();
+}
+
+// 6618342 Contact the team that owns the Instrument DTrace probe before renaming this symbol
+DISPATCH_NOINLINE
+void
+_dispatch_queue_invoke(dispatch_queue_t dq)
+{
+	dispatch_queue_t tq = dq->do_targetq;
+
+	if (!slowpath(DISPATCH_OBJECT_SUSPENDED(dq)) && fastpath(_dispatch_queue_trylock(dq))) {
+		_dispatch_queue_drain(dq);
+		if (tq == dq->do_targetq) {
+			tq = dx_invoke(dq);
+		} else {
+			tq = dq->do_targetq;
+		}
+		// We do not need to check the result.
+		// When the suspend-count lock is dropped, then the check will happen.
+		dispatch_atomic_dec(&dq->dq_running);
+		if (tq) {
+			return _dispatch_queue_push(tq, dq);
+		}
+	}
+
+	dq->do_next = DISPATCH_OBJECT_LISTLESS;
+	if (dispatch_atomic_sub(&dq->do_suspend_cnt, DISPATCH_OBJECT_SUSPEND_LOCK) == 0) {
+		if (dq->dq_running == 0) {
+			_dispatch_wakeup(dq);	// verify that the queue is idle
+		}
+	}
+	_dispatch_release(dq);	// added when the queue is put on the list
+}
+
+// 6618342 Contact the team that owns the Instrument DTrace probe before renaming this symbol
+static void
+_dispatch_set_target_queue2(void *ctxt)
+{
+	dispatch_queue_t prev_dq, dq = _dispatch_queue_get_current();
+		  
+	prev_dq = dq->do_targetq;
+	dq->do_targetq = ctxt;
+	_dispatch_release(prev_dq);
+}
+
+void
+dispatch_set_target_queue(dispatch_object_t dou, dispatch_queue_t dq)
+{
+	if (slowpath(dou._do->do_xref_cnt == DISPATCH_OBJECT_GLOBAL_REFCNT)) {
+		return;
+	}
+	// NOTE: we test for NULL target queues internally to detect root queues
+	// therefore, if the retain crashes due to a bad input, that is OK
+	_dispatch_retain(dq);
+	dispatch_barrier_async_f(dou._dq, dq, _dispatch_set_target_queue2);
+}
+
+static void
+_dispatch_async_f_redirect2(void *_ctxt)
+{
+	struct dispatch_continuation_s *dc = _ctxt;
+	struct dispatch_continuation_s *other_dc = dc->dc_data[1];
+	dispatch_queue_t old_dq, dq = dc->dc_data[0];
+
+	old_dq = _dispatch_thread_getspecific(dispatch_queue_key);
+	_dispatch_thread_setspecific(dispatch_queue_key, dq);
+	_dispatch_continuation_pop(other_dc);
+	_dispatch_thread_setspecific(dispatch_queue_key, old_dq);
+
+	if (dispatch_atomic_sub(&dq->dq_running, 2) == 0) {
+		_dispatch_wakeup(dq);
+	}
+	_dispatch_release(dq);
+}
+
+static void
+_dispatch_async_f_redirect(dispatch_queue_t dq, struct dispatch_object_s *other_dc)
+{
+	dispatch_continuation_t dc = (void *)other_dc;
+	dispatch_queue_t root_dq = dq;
+
+	if (dc->dc_func == _dispatch_sync_f_slow2) {
+		return dc->dc_func(dc->dc_ctxt);
+	}
+
+	dispatch_atomic_add(&dq->dq_running, 2);
+	_dispatch_retain(dq);
+
+	dc = _dispatch_continuation_alloc_cacheonly() ?: _dispatch_continuation_alloc_from_heap();
+
+	dc->do_vtable = (void *)DISPATCH_OBJ_ASYNC_BIT;
+	dc->dc_func = _dispatch_async_f_redirect2;
+	dc->dc_ctxt = dc;
+	dc->dc_data[0] = dq;
+	dc->dc_data[1] = other_dc;
+
+	do {
+		root_dq = root_dq->do_targetq;
+	} while (root_dq->do_targetq);
+
+	_dispatch_queue_push(root_dq, dc);
+}
+
+
+void
+_dispatch_queue_drain(dispatch_queue_t dq)
+{
+	dispatch_queue_t orig_tq, old_dq = _dispatch_thread_getspecific(dispatch_queue_key);
+	struct dispatch_object_s *dc = NULL, *next_dc = NULL;
+
+	orig_tq = dq->do_targetq;
+
+	_dispatch_thread_setspecific(dispatch_queue_key, dq);
+
+	while (dq->dq_items_tail) {
+		while (!fastpath(dq->dq_items_head)) {
+			_dispatch_hardware_pause();
+		}
+
+		dc = dq->dq_items_head;
+		dq->dq_items_head = NULL;
+
+		do {
+			// Enqueue is TIGHTLY controlled, we won't wait long.
+			do {
+				next_dc = fastpath(dc->do_next);
+			} while (!next_dc && !dispatch_atomic_cmpxchg(&dq->dq_items_tail, dc, NULL));
+			if (DISPATCH_OBJECT_SUSPENDED(dq)) {
+				goto out;
+			}
+			if (dq->dq_running > dq->dq_width) {
+				goto out;
+			}
+			if (orig_tq != dq->do_targetq) {
+				goto out;
+			}
+			if (fastpath(dq->dq_width == 1)) {
+				_dispatch_continuation_pop(dc);
+				_dispatch_workitem_inc();
+			} else if ((long)dc->do_vtable & DISPATCH_OBJ_BARRIER_BIT) {
+				if (dq->dq_running > 1) {
+					goto out;
+				}
+				_dispatch_continuation_pop(dc);
+				_dispatch_workitem_inc();
+			} else {
+				_dispatch_async_f_redirect(dq, dc);
+			}
+		} while ((dc = next_dc));
+	}
+
+out:
+	// if this is not a complete drain, we must undo some things
+	if (slowpath(dc)) {
+		// 'dc' must NOT be "popped"
+		// 'dc' might be the last item
+		if (next_dc || dispatch_atomic_cmpxchg(&dq->dq_items_tail, NULL, dc)) {
+			dq->dq_items_head = dc;
+		} else {
+			while (!(next_dc = dq->dq_items_head)) {
+				_dispatch_hardware_pause();
+			}
+			dq->dq_items_head = dc;
+			dc->do_next = next_dc;
+		}
+	}
+
+	_dispatch_thread_setspecific(dispatch_queue_key, old_dq);
+}
+
+// 6618342 Contact the team that owns the Instrument DTrace probe before renaming this symbol
+void *
+_dispatch_worker_thread(void *context)
+{
+	dispatch_queue_t dq = context;
+	struct dispatch_root_queue_context_s *qc = dq->do_ctxt;
+	sigset_t mask;
+	int r;
+
+	// workaround tweaks the kernel workqueue does for us
+	r = sigfillset(&mask);
+	dispatch_assume_zero(r);
+	r = _dispatch_pthread_sigmask(SIG_BLOCK, &mask, NULL);
+	dispatch_assume_zero(r);
+
+	do {
+		_dispatch_worker_thread2(context);
+		// we use 65 seconds in case there are any timers that run once a minute
+	} while (dispatch_semaphore_wait(qc->dgq_thread_mediator, dispatch_time(0, 65ull * NSEC_PER_SEC)) == 0);
+
+	dispatch_atomic_inc(&qc->dgq_thread_pool_size);
+	if (dq->dq_items_tail) {
+		_dispatch_queue_wakeup_global(dq);
+	}
+
+	return NULL;
+}
+
+// 6618342 Contact the team that owns the Instrument DTrace probe before renaming this symbol
+void
+_dispatch_worker_thread2(void *context)
+{
+	struct dispatch_object_s *item;
+	dispatch_queue_t dq = context;
+	struct dispatch_root_queue_context_s *qc = dq->do_ctxt;
+
+	if (_dispatch_thread_getspecific(dispatch_queue_key)) {
+		DISPATCH_CRASH("Premature thread recycling");
+	}
+
+	_dispatch_thread_setspecific(dispatch_queue_key, dq);
+	qc->dgq_pending = 0;
+
+#if DISPATCH_COCOA_COMPAT
+	// ensure that high-level memory management techniques do not leak/crash
+	dispatch_begin_thread_4GC();
+	void *pool = _dispatch_begin_NSAutoReleasePool();
+#endif
+
+#if DISPATCH_PERF_MON
+	uint64_t start = mach_absolute_time();
+#endif
+	while ((item = fastpath(_dispatch_queue_concurrent_drain_one(dq)))) {
+		_dispatch_continuation_pop(item);
+	}
+#if DISPATCH_PERF_MON
+	_dispatch_queue_merge_stats(start);
+#endif
+
+#if DISPATCH_COCOA_COMPAT
+	_dispatch_end_NSAutoReleasePool(pool);
+	dispatch_end_thread_4GC();
+#endif
+
+	_dispatch_thread_setspecific(dispatch_queue_key, NULL);
+
+	_dispatch_force_cache_cleanup();
+}
+
+#if DISPATCH_PERF_MON
+void
+_dispatch_queue_merge_stats(uint64_t start)
+{
+	uint64_t avg, delta = mach_absolute_time() - start;
+	unsigned long count, bucket;
+
+	count = (size_t)_dispatch_thread_getspecific(dispatch_bcounter_key);
+	_dispatch_thread_setspecific(dispatch_bcounter_key, NULL);
+
+	if (count) {
+		avg = delta / count;
+		bucket = flsll(avg);
+	} else {
+		bucket = 0;
+	}
+
+	// 64-bit counters on 32-bit require a lock or a queue
+	OSSpinLockLock(&_dispatch_stats_lock);
+
+	_dispatch_stats[bucket].time_total += delta;
+	_dispatch_stats[bucket].count_total += count;
+	_dispatch_stats[bucket].thread_total++;
+
+	OSSpinLockUnlock(&_dispatch_stats_lock);
+}
+#endif
+
+size_t
+dispatch_queue_debug_attr(dispatch_queue_t dq, char* buf, size_t bufsiz)
+{
+	return snprintf(buf, bufsiz, "parent = %p ", dq->do_targetq);
+}
+
+size_t
+dispatch_queue_debug(dispatch_queue_t dq, char* buf, size_t bufsiz)
+{
+	size_t offset = 0;
+	offset += snprintf(&buf[offset], bufsiz - offset, "%s[%p] = { ", dq->dq_label, dq);
+	offset += dispatch_object_debug_attr(dq, &buf[offset], bufsiz - offset);
+	offset += dispatch_queue_debug_attr(dq, &buf[offset], bufsiz - offset);
+	offset += snprintf(&buf[offset], bufsiz - offset, "}");
+	return offset;
+}
+
+#if DISPATCH_DEBUG
+void
+dispatch_debug_queue(dispatch_queue_t dq, const char* str) {
+	if (fastpath(dq)) {
+		dispatch_debug(dq, "%s", str);
+	} else {
+		_dispatch_log("queue[NULL]: %s", str);
+	}
+}
+#endif
+
+#if DISPATCH_COCOA_COMPAT
+void
+_dispatch_main_queue_callback_4CF(mach_msg_header_t *msg __attribute__((unused)))
+{
+	if (main_q_is_draining) {
+		return;
+	}
+	_dispatch_queue_set_mainq_drain_state(true);
+	_dispatch_queue_serial_drain_till_empty(&_dispatch_main_q);
+	_dispatch_queue_set_mainq_drain_state(false);
+}
+
+mach_port_t
+_dispatch_get_main_queue_port_4CF(void)
+{
+	dispatch_once_f(&_dispatch_main_q_port_pred, NULL, _dispatch_main_q_port_init);
+	return main_q_port;
+}
+#endif
+
+static void
+dispatch_queue_attr_dispose(dispatch_queue_attr_t attr)
+{
+	dispatch_queue_attr_set_finalizer(attr, NULL);
+	_dispatch_dispose(attr);
+}
+
+static const struct dispatch_queue_attr_vtable_s dispatch_queue_attr_vtable = {
+	.do_type = DISPATCH_QUEUE_ATTR_TYPE,
+	.do_kind = "queue-attr",
+	.do_dispose = dispatch_queue_attr_dispose,
+};
+
+dispatch_queue_attr_t
+dispatch_queue_attr_create(void)
+{
+	dispatch_queue_attr_t a = calloc(1, sizeof(struct dispatch_queue_attr_s));
+
+	if (a) {
+		a->do_vtable = &dispatch_queue_attr_vtable;
+		a->do_next = DISPATCH_OBJECT_LISTLESS;
+		a->do_ref_cnt = 1;
+		a->do_xref_cnt = 1;
+		a->do_targetq = _dispatch_get_root_queue(0, 0);
+		a->qa_flags = DISPATCH_QUEUE_OVERCOMMIT;
+	}
+	return a;
+}
+
+void
+dispatch_queue_attr_set_flags(dispatch_queue_attr_t attr, uint64_t flags)
+{
+	dispatch_assert_zero(flags & ~DISPATCH_QUEUE_FLAGS_MASK);
+	attr->qa_flags = (unsigned long)flags & DISPATCH_QUEUE_FLAGS_MASK;
+}
+	
+void
+dispatch_queue_attr_set_priority(dispatch_queue_attr_t attr, int priority)
+{
+	dispatch_debug_assert(attr, "NULL pointer");
+	dispatch_debug_assert(priority <= DISPATCH_QUEUE_PRIORITY_HIGH && priority >= DISPATCH_QUEUE_PRIORITY_LOW, "Invalid priority");
+
+	if (priority > 0) {
+		priority = DISPATCH_QUEUE_PRIORITY_HIGH;
+	} else if (priority < 0) {
+		priority = DISPATCH_QUEUE_PRIORITY_LOW;
+	}
+
+	attr->qa_priority = priority;
+}
+
+void
+dispatch_queue_attr_set_finalizer_f(dispatch_queue_attr_t attr,
+        void *context, dispatch_queue_finalizer_function_t finalizer)
+{
+#ifdef __BLOCKS__
+	if (attr->finalizer_func == (void*)_dispatch_call_block_and_release2) {
+		Block_release(attr->finalizer_ctxt);
+	}
+#endif
+	attr->finalizer_ctxt = context;
+	attr->finalizer_func = finalizer;
+}
+
+#ifdef __BLOCKS__
+long
+dispatch_queue_attr_set_finalizer(dispatch_queue_attr_t attr,
+        dispatch_queue_finalizer_t finalizer)
+{
+	void *ctxt;
+	dispatch_queue_finalizer_function_t func;
+
+	if (finalizer) {
+		if (!(ctxt = Block_copy(finalizer))) {
+			return 1;
+		}
+		func = (void *)_dispatch_call_block_and_release2;
+	} else {
+		ctxt = NULL;
+		func = NULL;
+	}
+
+	dispatch_queue_attr_set_finalizer_f(attr, ctxt, func);
+
+	return 0;
+}
+#endif
+
+static void
+_dispatch_ccache_init(void *context __attribute__((unused)))
+{
+	_dispatch_ccache_zone = malloc_create_zone(0, 0);
+	dispatch_assert(_dispatch_ccache_zone);
+	malloc_set_zone_name(_dispatch_ccache_zone, "DispatchContinuations");
+}
+
+dispatch_continuation_t
+_dispatch_continuation_alloc_from_heap(void)
+{
+	static dispatch_once_t pred;
+	dispatch_continuation_t dc;
+
+	dispatch_once_f(&pred, NULL, _dispatch_ccache_init);
+
+	while (!(dc = fastpath(malloc_zone_calloc(_dispatch_ccache_zone, 1, ROUND_UP_TO_CACHELINE_SIZE(sizeof(*dc)))))) {
+		sleep(1);
+	}
+
+	return dc;
+}
+
+void
+_dispatch_force_cache_cleanup(void)
+{
+	dispatch_continuation_t dc = _dispatch_thread_getspecific(dispatch_cache_key);
+	if (dc) {
+		_dispatch_thread_setspecific(dispatch_cache_key, NULL);
+		_dispatch_cache_cleanup2(dc);
+	}
+}
+
+DISPATCH_NOINLINE
+void
+_dispatch_cache_cleanup2(void *value)
+{
+	dispatch_continuation_t dc, next_dc = value;
+
+	while ((dc = next_dc)) {
+		next_dc = dc->do_next;
+		malloc_zone_free(_dispatch_ccache_zone, dc);
+	}
+}
+
+static char _dispatch_build[16];
+
+static void
+_dispatch_bug_init(void *context __attribute__((unused)))
+{
+	int mib[] = { CTL_KERN, KERN_OSVERSION };
+	size_t bufsz = sizeof(_dispatch_build);
+
+	sysctl(mib, 2, _dispatch_build, &bufsz, NULL, 0);
+}
+
+void
+_dispatch_bug(size_t line, long val)
+{
+	static dispatch_once_t pred;
+	static void *last_seen;
+	void *ra = __builtin_return_address(0);
+
+	dispatch_once_f(&pred, NULL, _dispatch_bug_init);
+	if (last_seen != ra) {
+		last_seen = ra;
+		_dispatch_log("BUG in libdispatch: %s - %lu - 0x%lx", _dispatch_build, line, val);
+	}
+}
+
+void
+_dispatch_abort(size_t line, long val)
+{
+	_dispatch_bug(line, val);
+	abort();
+}
+
+void
+_dispatch_log(const char *msg, ...)
+{
+	va_list ap;
+
+	va_start(ap, msg);
+
+	_dispatch_logv(msg, ap);
+
+	va_end(ap);
+}
+
+void
+_dispatch_logv(const char *msg, va_list ap)
+{
+#if DISPATCH_DEBUG
+	static FILE *logfile, *tmp;
+	char newbuf[strlen(msg) + 2];
+	char path[PATH_MAX];
+
+	sprintf(newbuf, "%s\n", msg);
+
+	if (!logfile) {
+		snprintf(path, sizeof(path), "/var/tmp/libdispatch.%d.log", getpid());
+		tmp = fopen(path, "a");
+		assert(tmp);
+		if (!dispatch_atomic_cmpxchg(&logfile, NULL, tmp)) {
+			fclose(tmp);
+		} else {
+			struct timeval tv;
+			gettimeofday(&tv, NULL);
+			fprintf(logfile, "=== log file opened for %s[%u] at %ld.%06u ===\n",
+					getprogname() ?: "", getpid(), tv.tv_sec, tv.tv_usec);
+		}
+	}
+	vfprintf(logfile, newbuf, ap);
+	fflush(logfile);
+#else
+	vsyslog(LOG_NOTICE, msg, ap);
+#endif
+}
+
+int
+_dispatch_pthread_sigmask(int how, sigset_t *set, sigset_t *oset)
+{
+	int r;
+
+	/* Workaround: 6269619 Not all signals can be delivered on any thread */
+
+	r = sigdelset(set, SIGILL);
+	dispatch_assume_zero(r);
+	r = sigdelset(set, SIGTRAP);
+	dispatch_assume_zero(r);
+	r = sigdelset(set, SIGEMT);
+	dispatch_assume_zero(r);
+	r = sigdelset(set, SIGFPE);
+	dispatch_assume_zero(r);
+	r = sigdelset(set, SIGBUS);
+	dispatch_assume_zero(r);
+	r = sigdelset(set, SIGSEGV);
+	dispatch_assume_zero(r);
+	r = sigdelset(set, SIGSYS);
+	dispatch_assume_zero(r);
+	r = sigdelset(set, SIGPIPE);
+	dispatch_assume_zero(r);
+
+	return pthread_sigmask(how, set, oset);
+}
+
+bool _dispatch_safe_fork = true;
+
+void
+dispatch_atfork_prepare(void)
+{
+}
+
+void
+dispatch_atfork_parent(void)
+{
+}
+
+void
+dispatch_atfork_child(void)
+{
+	void *crash = (void *)0x100;
+	size_t i;
+
+	if (_dispatch_safe_fork) {
+		return;
+	}
+
+	_dispatch_main_q.dq_items_head = crash;
+	_dispatch_main_q.dq_items_tail = crash;
+
+	_dispatch_mgr_q.dq_items_head = crash;
+	_dispatch_mgr_q.dq_items_tail = crash;
+
+	for (i = 0; i < DISPATCH_ROOT_QUEUE_COUNT; i++) {
+		_dispatch_root_queues[i].dq_items_head = crash;
+		_dispatch_root_queues[i].dq_items_tail = crash;
+	}
+}
+
+void
+dispatch_init_pthread(pthread_t pthr __attribute__((unused)))
+{
+}
+
+static int _dispatch_kq;
+
+static void
+_dispatch_get_kq_init(void *context __attribute__((unused)))
+{
+	static const struct kevent kev = {
+		.ident = 1,
+		.filter = EVFILT_USER,
+		.flags = EV_ADD|EV_CLEAR,
+	};
+
+	_dispatch_kq = kqueue();
+	_dispatch_safe_fork = false;
+	// in case we fall back to select()
+	FD_SET(_dispatch_kq, &_dispatch_rfds);
+
+	if (_dispatch_kq == -1) {
+		dispatch_assert_zero(errno);
+	}
+
+	dispatch_assume_zero(kevent(_dispatch_kq, &kev, 1, NULL, 0, NULL)); 
+
+	_dispatch_queue_push(_dispatch_mgr_q.do_targetq, &_dispatch_mgr_q);
+}
+
+static int
+_dispatch_get_kq(void)
+{
+	static dispatch_once_t pred;
+
+	dispatch_once_f(&pred, NULL, _dispatch_get_kq_init);
+
+	return _dispatch_kq;
+}
+
+static void
+_dispatch_mgr_thread2(struct kevent *kev, size_t cnt)
+{
+	size_t i;
+
+	for (i = 0; i < cnt; i++) {
+		// EVFILT_USER isn't used by sources
+		if (kev[i].filter == EVFILT_USER) {
+			// If _dispatch_mgr_thread2() ever is changed to return to the
+			// caller, then this should become _dispatch_queue_drain()
+			_dispatch_queue_serial_drain_till_empty(&_dispatch_mgr_q);
+		} else {
+			_dispatch_source_drain_kevent(&kev[i]);
+		}
+    }
+}
+
+static dispatch_queue_t
+_dispatch_mgr_invoke(dispatch_queue_t dq)
+{
+	static const struct timespec timeout_immediately = { 0, 0 };
+	struct timespec timeout;
+	const struct timespec *timeoutp;
+	struct timeval sel_timeout, *sel_timeoutp;
+	fd_set tmp_rfds, tmp_wfds;
+	struct kevent kev[1];
+	int k_cnt, k_err, i, r;
+
+	_dispatch_thread_setspecific(dispatch_queue_key, dq);
+
+	for (;;) {
+		_dispatch_run_timers();
+
+		timeoutp = _dispatch_get_next_timer_fire(&timeout);
+		
+		if (_dispatch_select_workaround) {
+			FD_COPY(&_dispatch_rfds, &tmp_rfds);
+			FD_COPY(&_dispatch_wfds, &tmp_wfds);
+			if (timeoutp) {
+				sel_timeout.tv_sec = timeoutp->tv_sec;
+				sel_timeout.tv_usec = (typeof(sel_timeout.tv_usec))(timeoutp->tv_nsec / 1000u);
+				sel_timeoutp = &sel_timeout;
+			} else {
+				sel_timeoutp = NULL;
+			}
+			
+			r = select(FD_SETSIZE, &tmp_rfds, &tmp_wfds, NULL, sel_timeoutp);
+			if (r == -1) {
+				if (errno != EBADF) {
+					dispatch_assume_zero(errno);
+					continue;
+				}
+				for (i = 0; i < FD_SETSIZE; i++) {
+					if (i == _dispatch_kq) {
+						continue;
+					}
+					if (!FD_ISSET(i, &_dispatch_rfds) && !FD_ISSET(i, &_dispatch_wfds)) {
+						continue;
+					}
+					r = dup(i);
+					if (r != -1) {
+						close(r);
+					} else {
+						FD_CLR(i, &_dispatch_rfds);
+						FD_CLR(i, &_dispatch_wfds);
+						_dispatch_rfd_ptrs[i] = 0;
+						_dispatch_wfd_ptrs[i] = 0;
+					}
+				}
+				continue;
+			}
+			
+			if (r > 0) {
+				for (i = 0; i < FD_SETSIZE; i++) {
+					if (i == _dispatch_kq) {
+						continue;
+					}
+					if (FD_ISSET(i, &tmp_rfds)) {
+						FD_CLR(i, &_dispatch_rfds);	// emulate EV_DISABLE
+						EV_SET(&kev[0], i, EVFILT_READ, EV_ADD|EV_ENABLE|EV_DISPATCH, 0, 1, _dispatch_rfd_ptrs[i]);
+						_dispatch_rfd_ptrs[i] = 0;
+						_dispatch_mgr_thread2(kev, 1);
+					}
+					if (FD_ISSET(i, &tmp_wfds)) {
+						FD_CLR(i, &_dispatch_wfds);	// emulate EV_DISABLE
+						EV_SET(&kev[0], i, EVFILT_WRITE, EV_ADD|EV_ENABLE|EV_DISPATCH, 0, 1, _dispatch_wfd_ptrs[i]);
+						_dispatch_wfd_ptrs[i] = 0;
+						_dispatch_mgr_thread2(kev, 1);
+					}
+				}
+			}
+			
+			timeoutp = &timeout_immediately;
+		}
+		
+		k_cnt = kevent(_dispatch_kq, NULL, 0, kev, sizeof(kev) / sizeof(kev[0]), timeoutp);
+		k_err = errno;
+
+		switch (k_cnt) {
+		case -1:
+			if (k_err == EBADF) {
+				DISPATCH_CLIENT_CRASH("Do not close random Unix descriptors");
+			}
+			dispatch_assume_zero(k_err);
+			continue;
+		default:
+			_dispatch_mgr_thread2(kev, (size_t)k_cnt);
+			// fall through
+		case 0:
+			_dispatch_force_cache_cleanup();
+			continue;
+		}
+	}
+
+	return NULL;
+}
+
+static bool
+_dispatch_mgr_wakeup(dispatch_queue_t dq)
+{
+	static const struct kevent kev = {
+		.ident = 1,
+		.filter = EVFILT_USER,
+#ifdef EV_TRIGGER
+		.flags = EV_TRIGGER,
+#endif
+#ifdef NOTE_TRIGGER
+		.fflags = NOTE_TRIGGER,
+#endif
+	};
+
+	_dispatch_debug("waking up the _dispatch_mgr_q: %p", dq);
+
+	_dispatch_update_kq(&kev);
+
+	return false;
+}
+
+void
+_dispatch_update_kq(const struct kevent *kev)
+{
+	struct kevent kev_copy = *kev;
+	kev_copy.flags |= EV_RECEIPT;
+
+	if (kev_copy.flags & EV_DELETE) {
+		switch (kev_copy.filter) {
+		case EVFILT_READ:
+			if (FD_ISSET((int)kev_copy.ident, &_dispatch_rfds)) {
+				FD_CLR((int)kev_copy.ident, &_dispatch_rfds);
+				_dispatch_rfd_ptrs[kev_copy.ident] = 0;
+				return;
+			}
+		case EVFILT_WRITE:
+			if (FD_ISSET((int)kev_copy.ident, &_dispatch_wfds)) {
+				FD_CLR((int)kev_copy.ident, &_dispatch_wfds);
+				_dispatch_wfd_ptrs[kev_copy.ident] = 0;
+				return;
+			}
+		default:
+			break;
+		}
+	}
+	
+	int rval = kevent(_dispatch_get_kq(), &kev_copy, 1, &kev_copy, 1, NULL);
+	if (rval == -1) { 
+		// If we fail to register with kevents, for other reasons aside from
+		// changelist elements.
+		dispatch_assume_zero(errno);
+		//kev_copy.flags |= EV_ERROR;
+		//kev_copy.data = error;
+		return;
+	}
+
+	// The following select workaround only applies to adding kevents
+	if (!(kev->flags & EV_ADD)) {
+		return;
+	}
+
+	switch (kev_copy.data) {
+	case 0:
+		return;
+	case EBADF:
+		break;
+	default:
+		// If an error occurred while registering with kevent, and it was 
+		// because of a kevent changelist processing && the kevent involved
+		// either doing a read or write, it would indicate we were trying
+		// to register a /dev/* port; fall back to select
+		switch (kev_copy.filter) {
+		case EVFILT_READ:
+			_dispatch_select_workaround = true;
+			FD_SET((int)kev_copy.ident, &_dispatch_rfds);
+			_dispatch_rfd_ptrs[kev_copy.ident] = kev_copy.udata;
+			break;
+		case EVFILT_WRITE:
+			_dispatch_select_workaround = true;
+			FD_SET((int)kev_copy.ident, &_dispatch_wfds);
+			_dispatch_wfd_ptrs[kev_copy.ident] = kev_copy.udata;
+			break;
+		default:
+			_dispatch_source_drain_kevent(&kev_copy); 
+			break;
+		}
+		break;
+	}
+}
+
+static const struct dispatch_queue_vtable_s _dispatch_queue_mgr_vtable = {
+	.do_type = DISPATCH_QUEUE_MGR_TYPE,
+	.do_kind = "mgr-queue",
+	.do_invoke = _dispatch_mgr_invoke,
+	.do_debug = dispatch_queue_debug,
+	.do_probe = _dispatch_mgr_wakeup,
+};
+
+// 6618342 Contact the team that owns the Instrument DTrace probe before renaming this symbol
+struct dispatch_queue_s _dispatch_mgr_q = {
+	.do_vtable = &_dispatch_queue_mgr_vtable,
+	.do_ref_cnt = DISPATCH_OBJECT_GLOBAL_REFCNT,
+	.do_xref_cnt = DISPATCH_OBJECT_GLOBAL_REFCNT,
+	.do_suspend_cnt = DISPATCH_OBJECT_SUSPEND_LOCK,
+	.do_targetq = &_dispatch_root_queues[DISPATCH_ROOT_QUEUE_COUNT - 1],
+
+	.dq_label = "com.apple.libdispatch-manager",
+	.dq_width = 1,
+	.dq_serialnum = 2,
+};
+
+const struct dispatch_queue_offsets_s dispatch_queue_offsets = {
+	.dqo_version = 3,
+	.dqo_label = offsetof(struct dispatch_queue_s, dq_label),
+	.dqo_label_size = sizeof(_dispatch_main_q.dq_label),
+	.dqo_flags = 0,
+	.dqo_flags_size = 0,
+	.dqo_width = offsetof(struct dispatch_queue_s, dq_width),
+	.dqo_width_size = sizeof(_dispatch_main_q.dq_width),
+	.dqo_serialnum = offsetof(struct dispatch_queue_s, dq_serialnum),
+	.dqo_serialnum_size = sizeof(_dispatch_main_q.dq_serialnum),
+	.dqo_running = offsetof(struct dispatch_queue_s, dq_running),
+	.dqo_running_size = sizeof(_dispatch_main_q.dq_running),
+};
+
+#ifdef __BLOCKS__
+void
+dispatch_after(dispatch_time_t when, dispatch_queue_t queue, dispatch_block_t work)
+{
+	// test before the copy of the block
+	if (when == DISPATCH_TIME_FOREVER) {
+#if DISPATCH_DEBUG
+		DISPATCH_CLIENT_CRASH("dispatch_after() called with 'when' == infinity");
+#endif
+		return;
+	}
+	dispatch_after_f(when, queue, _dispatch_Block_copy(work), _dispatch_call_block_and_release);
+}
+#endif
+
+DISPATCH_NOINLINE
+void
+dispatch_after_f(dispatch_time_t when, dispatch_queue_t queue, void *ctxt, void (*func)(void *))
+{
+	uint64_t delta;
+	if (when == DISPATCH_TIME_FOREVER) {
+#if DISPATCH_DEBUG
+		DISPATCH_CLIENT_CRASH("dispatch_after_f() called with 'when' == infinity");
+#endif
+		return;
+	}
+
+	// this function can and should be optimized to not use a dispatch source
+again:
+	delta = _dispatch_timeout(when);
+	if (delta == 0) {
+		return dispatch_async_f(queue, ctxt, func);
+	}
+	if (!dispatch_source_timer_create(DISPATCH_TIMER_INTERVAL, delta, 0, NULL, queue, ^(dispatch_source_t ds) {
+		long err_dom, err_val;
+		if ((err_dom = dispatch_source_get_error(ds, &err_val))) {
+			dispatch_assert(err_dom == DISPATCH_ERROR_DOMAIN_POSIX);
+			dispatch_assert(err_val == ECANCELED);
+			func(ctxt);
+			dispatch_release(ds);	// MUST NOT be _dispatch_release()
+		} else {
+			dispatch_source_cancel(ds);
+		}
+	})) {
+		goto again;
+	}
+}

Added: trunk/src/queue.h
===================================================================
--- trunk/src/queue.h	                        (rev 0)
+++ trunk/src/queue.h	2009-08-30 01:07:28 UTC (rev 2)
@@ -0,0 +1,568 @@
+/*
+ * Copyright (c) 2008-2009 Apple Inc. All rights reserved.
+ *
+ * @APPLE_APACHE_LICENSE_HEADER_START@
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * 
+ * @APPLE_APACHE_LICENSE_HEADER_END@
+ */
+
+#ifndef __DISPATCH_QUEUE__
+#define __DISPATCH_QUEUE__
+
+#ifndef __DISPATCH_INDIRECT__
+#error "Please #include <dispatch/dispatch.h> instead of this file directly."
+#include <dispatch/base.h> // for HeaderDoc
+#endif
+
+/*!
+ * @header
+ *
+ * Dispatch is an abstract model for expressing concurrency via simple but
+ * powerful API. 
+ *
+ * At the core, dispatch provides serial FIFO queues to which blocks may be
+ * submitted. Blocks submitted to these dispatch queues are invoked on a pool
+ * of threads fully managed by the system. No guarantee is made regarding
+ * which thread a block will be invoked on; however, it is guaranteed that only
+ * one block submitted to the FIFO dispatch queue will be invoked at a time.
+ *
+ * When multiple queues have blocks to be processed, the system is free to
+ * allocate additional threads to invoke the blocks concurrently. When the
+ * queues become empty, these threads are automatically released.
+ */
+
+/*!
+ * @typedef dispatch_queue_t
+ *
+ * @abstract
+ * Dispatch queues invoke blocks submitted to them serially in FIFO order. A
+ * queue will only invoke one block at a time, but independent queues may each
+ * invoke their blocks concurrently with respect to each other.
+ *
+ * @discussion
+ * Dispatch queues are lightweight objects to which blocks may be submitted.
+ * The system manages a pool of threads which process dispatch queues and
+ * invoke blocks submitted to them.
+ *
+ * Conceptually a dispatch queue may have its own thread of execution, and
+ * interaction between queues is highly asynchronous.
+ *
+ * Dispatch queues are reference counted via calls to dispatch_retain() and
+ * dispatch_release(). Pending blocks submitted to a queue also hold a
+ * reference to the queue until they have finished. Once all references to a
+ * queue have been released, the queue will be deallocated by the system.
+ */
+DISPATCH_DECL(dispatch_queue);
+
+/*!
+ * @typedef dispatch_queue_attr_t
+ *
+ * @abstract
+ * Attribute and policy extensions for dispatch queues.
+ */
+DISPATCH_DECL(dispatch_queue_attr);
+
+/*!
+ * @typedef dispatch_block_t
+ *
+ * @abstract
+ * The prototype of blocks submitted to dispatch queues, which take no
+ * arguments and have no return value.
+ *
+ * @discussion
+ * The declaration of a block allocates storage on the stack. Therefore, this
+ * is an invalid construct:
+ *
+ * dispatch_block_t block;
+ *
+ * if (x) {
+ *     block = ^{ printf("true\n"); };
+ * } else {
+ *     block = ^{ printf("false\n"); };
+ * }
+ * block(); // unsafe!!!
+ *
+ * What is happening behind the scenes:
+ *
+ * if (x) {
+ *     struct Block __tmp_1 = ...; // setup details
+ *     block = &__tmp_1;
+ * } else {
+ *     struct Block __tmp_2 = ...; // setup details
+ *     block = &__tmp_2;
+ * }
+ *
+ * As the example demonstrates, the address of a stack variable is escaping the
+ * scope in which it is allocated. That is a classic C bug.
+ */
+#ifdef __BLOCKS__
+typedef void (^dispatch_block_t)(void);
+#endif
+
+__BEGIN_DECLS
+
+/*!
+ * @function dispatch_async
+ *
+ * @abstract
+ * Submits a block for asynchronous execution on a dispatch queue.
+ *
+ * @discussion
+ * The dispatch_async() function is the fundamental mechanism for submitting
+ * blocks to a dispatch queue.
+ *
+ * Calls to dispatch_async() always return immediately after the block has
+ * been submitted, and never wait for the block to be invoked.
+ *
+ * The target queue determines whether the block will be invoked serially or
+ * concurrently with respect to other blocks submitted to that same queue.
+ * Serial queues are processed concurrently with with respect to each other.
+ * 
+ * @param queue
+ * The target dispatch queue to which the block is submitted.
+ * The system will hold a reference on the target queue until the block
+ * has finished.
+ * The result of passing NULL in this parameter is undefined.
+ *
+ * @param block
+ * The block to submit to the target dispatch queue. This function performs
+ * Block_copy() and Block_release() on behalf of callers.
+ * The result of passing NULL in this parameter is undefined.
+ */
+#ifdef __BLOCKS__
+__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA)
+DISPATCH_NONNULL_ALL DISPATCH_NOTHROW
+void
+dispatch_async(dispatch_queue_t queue, dispatch_block_t block);
+#endif
+
+/*!
+ * @function dispatch_async_f
+ *
+ * @abstract
+ * Submits a function for asynchronous execution on a dispatch queue.
+ *
+ * @discussion
+ * See dispatch_async() for details.
+ * 
+ * @param queue
+ * The target dispatch queue to which the function is submitted.
+ * The system will hold a reference on the target queue until the function
+ * has returned.
+ * The result of passing NULL in this parameter is undefined.
+ *
+ * @param context
+ * The application-defined context parameter to pass to the function.
+ *
+ * @param work
+ * The application-defined function to invoke on the target queue. The first
+ * parameter passed to this function is the context provided to
+ * dispatch_async_f().
+ * The result of passing NULL in this parameter is undefined.
+ */
+__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA)
+DISPATCH_NONNULL1 DISPATCH_NONNULL3 DISPATCH_NOTHROW
+void
+dispatch_async_f(dispatch_queue_t queue,
+	void *context,
+	dispatch_function_t work);
+
+/*!
+ * @function dispatch_sync
+ *
+ * @abstract
+ * Submits a block for synchronous execution on a dispatch queue.
+ *
+ * @discussion
+ * Submits a block to a dispatch queue like dispatch_async(), however
+ * dispatch_sync() will not return until the block has finished.
+ *
+ * Calls to dispatch_sync() targeting the current queue will result
+ * in dead-lock. Use of dispatch_sync() is also subject to the same
+ * multi-party dead-lock problems that may result from the use of a mutex.
+ * Use of dispatch_async() is preferred.
+ *
+ * Unlike dispatch_async(), no retain is performed on the target queue. Because
+ * calls to this function are synchronous, the dispatch_sync() "borrows" the
+ * reference of the caller.
+ *
+ * As an optimization, dispatch_sync() invokes the block on the current
+ * thread when possible.
+ *
+ * @param queue
+ * The target dispatch queue to which the block is submitted.
+ * The result of passing NULL in this parameter is undefined.
+ *
+ * @param block
+ * The block to be invoked on the target dispatch queue.
+ * The result of passing NULL in this parameter is undefined.
+ */
+#ifdef __BLOCKS__
+__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA)
+DISPATCH_NONNULL_ALL DISPATCH_NOTHROW
+void
+dispatch_sync(dispatch_queue_t queue, dispatch_block_t block);
+#endif
+
+/*!
+ * @function dispatch_sync_f
+ *
+ * @abstract
+ * Submits a function for synchronous execution on a dispatch queue.
+ *
+ * @discussion
+ * See dispatch_sync() for details.
+ *
+ * @param queue
+ * The target dispatch queue to which the function is submitted.
+ * The result of passing NULL in this parameter is undefined.
+ *
+ * @param context
+ * The application-defined context parameter to pass to the function.
+ *
+ * @param work
+ * The application-defined function to invoke on the target queue. The first
+ * parameter passed to this function is the context provided to
+ * dispatch_sync_f().
+ * The result of passing NULL in this parameter is undefined.
+ */
+__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA)
+DISPATCH_NONNULL1 DISPATCH_NONNULL3 DISPATCH_NOTHROW
+void
+dispatch_sync_f(dispatch_queue_t queue,
+	void *context,
+	dispatch_function_t work);
+
+/*!
+ * @function dispatch_apply
+ *
+ * @abstract
+ * Submits a block to a dispatch queue for multiple invocations.
+ *
+ * @discussion
+ * Submits a block to a dispatch queue for multiple invocations. This function
+ * waits for the task block to complete before returning. If the target queue
+ * is a concurrent queue returned by dispatch_get_concurrent_queue(), the block
+ * may be invoked concurrently, and it must therefore be reentrant safe.
+ * 
+ * Each invocation of the block will be passed the current index of iteration.
+ *
+ * @param iterations
+ * The number of iterations to perform.
+ *
+ * @param queue
+ * The target dispatch queue to which the block is submitted.
+ * The result of passing NULL in this parameter is undefined.
+ *
+ * @param block
+ * The block to be invoked the specified number of iterations.
+ * The result of passing NULL in this parameter is undefined.
+ */
+#ifdef __BLOCKS__
+__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA)
+DISPATCH_NONNULL_ALL DISPATCH_NOTHROW
+void
+dispatch_apply(size_t iterations, dispatch_queue_t queue, void (^block)(size_t));
+#endif
+
+/*!
+ * @function dispatch_apply_f
+ *
+ * @abstract
+ * Submits a function to a dispatch queue for multiple invocations.
+ *
+ * @discussion
+ * See dispatch_apply() for details.
+ *
+ * @param iterations
+ * The number of iterations to perform.
+ *
+ * @param queue
+ * The target dispatch queue to which the function is submitted.
+ * The result of passing NULL in this parameter is undefined.
+ *
+ * @param context
+ * The application-defined context parameter to pass to the function.
+ *
+ * @param work
+ * The application-defined function to invoke on the target queue. The first
+ * parameter passed to this function is the context provided to
+ * dispatch_apply_f(). The second parameter passed to this function is the
+ * current index of iteration.
+ * The result of passing NULL in this parameter is undefined.
+ */
+__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA)
+DISPATCH_NONNULL2 DISPATCH_NONNULL4 DISPATCH_NOTHROW
+void
+dispatch_apply_f(size_t iterations, dispatch_queue_t queue,
+	void *context,
+	void (*work)(void *, size_t));
+
+/*!
+ * @function dispatch_get_current_queue
+ *
+ * @abstract
+ * Returns the queue on which the currently executing block is running.
+ * 
+ * @discussion
+ * Returns the queue on which the currently executing block is running.
+ *
+ * When dispatch_get_current_queue() is called outside of the context of a
+ * submitted block, it will return the default concurrent queue.
+ *
+ * @result
+ * Returns the current queue.
+ */
+__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA)
+DISPATCH_PURE DISPATCH_WARN_RESULT DISPATCH_NOTHROW
+dispatch_queue_t
+dispatch_get_current_queue(void);
+
+/*!
+ * @function dispatch_get_main_queue
+ *
+ * @abstract
+ * Returns the default queue that is bound to the main thread.
+ *
+ * @discussion
+ * In order to invoke blocks submitted to the main queue, the application must
+ * call dispatch_main(), NSApplicationMain(), or use a CFRunLoop on the main
+ * thread.
+ *
+ * @result
+ * Returns the main queue. This queue is created automatically on behalf of
+ * the main thread before main() is called.
+ */
+__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA)
+extern struct dispatch_queue_s _dispatch_main_q;
+#define dispatch_get_main_queue() (&_dispatch_main_q)
+
+/*!
+ * @enum dispatch_queue_priority_t
+ *
+ * @constant DISPATCH_QUEUE_PRIORITY_HIGH
+ * Items dispatched to the queue will run at high priority,
+ * i.e. the queue will be scheduled for execution before
+ * any default priority or low priority queue.
+ *
+ * @constant DISPATCH_QUEUE_PRIORITY_DEFAULT
+ * Items dispatched to the queue will run at the default
+ * priority, i.e. the queue will be scheduled for execution
+ * after all high priority queues have been scheduled, but
+ * before any low priority queues have been scheduled.
+ *
+ * @constant DISPATCH_QUEUE_PRIORITY_LOW
+ * Items dispatched to the queue will run at low priority,
+ * i.e. the queue will be scheduled for execution after all
+ * default priority and high priority queues have been
+ * scheduled.
+ */
+enum {
+	DISPATCH_QUEUE_PRIORITY_HIGH = 2,
+	DISPATCH_QUEUE_PRIORITY_DEFAULT = 0,
+	DISPATCH_QUEUE_PRIORITY_LOW = -2,
+};
+
+/*!
+ * @function dispatch_get_global_queue
+ *
+ * @abstract
+ * Returns a well-known global concurrent queue of a given priority level.
+ *
+ * @discussion
+ * The well-known global concurrent queues may not be modified. Calls to
+ * dispatch_suspend(), dispatch_resume(), dispatch_set_context(), etc., will
+ * have no effect when used with queues returned by this function.
+ *
+ * @param priority
+ * A priority defined in dispatch_queue_priority_t
+ *
+ * @param flags
+ * Reserved for future use. Passing any value other than zero may result in
+ * a NULL return value.
+ *
+ * @result
+ * Returns the requested global queue.
+ */
+__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA)
+DISPATCH_PURE DISPATCH_WARN_RESULT DISPATCH_NOTHROW
+dispatch_queue_t
+dispatch_get_global_queue(long priority, unsigned long flags);
+
+/*!
+ * @function dispatch_queue_create
+ *
+ * @abstract
+ * Creates a new dispatch queue to which blocks may be submitted.
+ *
+ * @discussion
+ * Dispatch queues invoke blocks serially in FIFO order.
+ *
+ * When the dispatch queue is no longer needed, it should be released
+ * with dispatch_release(). Note that any pending blocks submitted
+ * to a queue will hold a reference to that queue. Therefore a queue
+ * will not be deallocated until all pending blocks have finished.
+ *
+ * @param label
+ * A string label to attach to the queue.
+ * This parameter is optional and may be NULL.
+ *
+ * @param attr
+ * Unused. Pass NULL for now.
+ *
+ * @result
+ * The newly created dispatch queue.
+ */
+__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA)
+DISPATCH_MALLOC DISPATCH_WARN_RESULT DISPATCH_NOTHROW
+dispatch_queue_t
+dispatch_queue_create(const char *label, dispatch_queue_attr_t attr);
+
+/*!
+ * @function dispatch_queue_get_label
+ *
+ * @abstract
+ * Returns the label of the queue that was specified when the
+ * queue was created.
+ *
+ * @param queue
+ * The result of passing NULL in this parameter is undefined.
+ *
+ * @result
+ * The label of the queue. The result may be NULL.
+ */
+__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA)
+DISPATCH_NONNULL_ALL DISPATCH_PURE DISPATCH_WARN_RESULT DISPATCH_NOTHROW
+const char *
+dispatch_queue_get_label(dispatch_queue_t queue);
+
+/*!
+ * @function dispatch_set_target_queue
+ *
+ * @abstract
+ * Sets the target queue for the given object.
+ *
+ * @discussion
+ * An object's target queue is responsible for processing the object.
+ *
+ * A dispatch queue's priority is inherited by its target queue. Use the
+ * dispatch_get_global_queue() function to obtain suitable target queue
+ * of the desired priority.
+ *
+ * A dispatch source's target queue specifies where its event handler and
+ * cancellation handler blocks will be submitted.
+ *
+ * The result of calling dispatch_set_target_queue() on any other type of
+ * dispatch object is undefined.
+ *
+ * @param       object
+ * The object to modify.
+ * The result of passing NULL in this parameter is undefined.
+ *
+ * @param       queue
+ * The new target queue for the object. The queue is retained, and the
+ * previous one, if any, is released.
+ * The result of passing NULL in this parameter is undefined.
+ */
+__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA)
+DISPATCH_NONNULL_ALL DISPATCH_NOTHROW
+void
+dispatch_set_target_queue(dispatch_object_t object, dispatch_queue_t queue);
+
+/*!
+ * @function dispatch_main
+ *
+ * @abstract
+ * Execute blocks submitted to the main queue.
+ *
+ * @discussion
+ * This function "parks" the main thread and waits for blocks to be submitted
+ * to the main queue. This function never returns.
+ *
+ * Applications that call NSApplicationMain() or CFRunLoopRun() on the
+ * main thread do not need to call dispatch_main().
+ */
+__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA)
+DISPATCH_NOTHROW DISPATCH_NORETURN
+void
+dispatch_main(void);
+
+/*!
+ * @function dispatch_after
+ *
+ * @abstract
+ * Schedule a block for execution on a given queue at a specified time.
+ *
+ * @discussion
+ * Passing DISPATCH_TIME_NOW as the "when" parameter is supported, but not as
+ * optimal as calling dispatch_async() instead. Passing DISPATCH_TIME_FOREVER
+ * is undefined.
+ *
+ * @param when
+ * A temporal milestone returned by dispatch_time() or dispatch_walltime().
+ *
+ * @param queue
+ * A queue to which the given block will be submitted at the specified time.
+ * The result of passing NULL in this parameter is undefined.
+ *
+ * @param block
+ * The block of code to execute.
+ * The result of passing NULL in this parameter is undefined.
+ */
+#ifdef __BLOCKS__
+__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA)
+DISPATCH_NONNULL2 DISPATCH_NONNULL3 DISPATCH_NOTHROW
+void
+dispatch_after(dispatch_time_t when,
+	dispatch_queue_t queue,
+	dispatch_block_t block);
+#endif
+
+/*!
+ * @function dispatch_after_f
+ *
+ * @abstract
+ * Schedule a function for execution on a given queue at a specified time.
+ *
+ * @discussion
+ * See dispatch_after() for details.
+ *
+ * @param when
+ * A temporal milestone returned by dispatch_time() or dispatch_walltime().
+ *
+ * @param queue
+ * A queue to which the given function will be submitted at the specified time.
+ * The result of passing NULL in this parameter is undefined.
+ *
+ * @param context
+ * The application-defined context parameter to pass to the function.
+ *
+ * @param work
+ * The application-defined function to invoke on the target queue. The first
+ * parameter passed to this function is the context provided to
+ * dispatch_after_f().
+ * The result of passing NULL in this parameter is undefined.
+ */
+__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA)
+DISPATCH_NONNULL2 DISPATCH_NONNULL4 DISPATCH_NOTHROW
+void
+dispatch_after_f(dispatch_time_t when,
+	dispatch_queue_t queue,
+	void *context,
+	dispatch_function_t work);
+
+__END_DECLS
+
+#endif

Added: trunk/src/queue_internal.h
===================================================================
--- trunk/src/queue_internal.h	                        (rev 0)
+++ trunk/src/queue_internal.h	2009-08-30 01:07:28 UTC (rev 2)
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 2008-2009 Apple Inc. All rights reserved.
+ *
+ * @APPLE_APACHE_LICENSE_HEADER_START@
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * 
+ * @APPLE_APACHE_LICENSE_HEADER_END@
+ */
+
+/*
+ * IMPORTANT: This header file describes INTERNAL interfaces to libdispatch
+ * which are subject to change in future releases of Mac OS X. Any applications
+ * relying on these interfaces WILL break.
+ */
+
+#ifndef __DISPATCH_QUEUE_INTERNAL__
+#define __DISPATCH_QUEUE_INTERNAL__
+
+#ifndef __DISPATCH_INDIRECT__
+#error "Please #include <dispatch/dispatch.h> instead of this file directly."
+#include <dispatch/base.h> // for HeaderDoc
+#endif
+
+// If dc_vtable is less than 127, then the object is a continuation.
+// Otherwise, the object has a private layout and memory management rules. The
+// first two words must align with normal objects.
+#define DISPATCH_CONTINUATION_HEADER(x)	\
+	const void *				do_vtable;	\
+	struct x *volatile	do_next;	\
+	dispatch_function_t	dc_func;	\
+	void *						dc_ctxt
+
+#define DISPATCH_OBJ_ASYNC_BIT	0x1
+#define DISPATCH_OBJ_BARRIER_BIT	0x2
+#define DISPATCH_OBJ_GROUP_BIT	0x4
+// vtables are pointers far away from the low page in memory
+#define DISPATCH_OBJ_IS_VTABLE(x)	((unsigned long)(x)->do_vtable > 127ul)
+
+struct dispatch_continuation_s {
+	DISPATCH_CONTINUATION_HEADER(dispatch_continuation_s);
+	dispatch_group_t	dc_group;
+	void *				dc_data[3];
+};
+
+typedef struct dispatch_continuation_s *dispatch_continuation_t;
+
+
+struct dispatch_queue_vtable_s {
+	DISPATCH_VTABLE_HEADER(dispatch_queue_s);
+};
+
+#define DISPATCH_QUEUE_MIN_LABEL_SIZE	64
+
+#define DISPATCH_QUEUE_HEADER \
+	uint32_t dq_running; \
+	uint32_t dq_width; \
+	struct dispatch_object_s *dq_items_tail; \
+	struct dispatch_object_s *volatile dq_items_head; \
+	unsigned long dq_serialnum; \
+	void *dq_finalizer_ctxt; \
+	dispatch_queue_finalizer_function_t dq_finalizer_func
+
+struct dispatch_queue_s {
+	DISPATCH_STRUCT_HEADER(dispatch_queue_s, dispatch_queue_vtable_s);
+	DISPATCH_QUEUE_HEADER;
+	char dq_label[DISPATCH_QUEUE_MIN_LABEL_SIZE];	// must be last
+};
+
+extern struct dispatch_queue_s _dispatch_mgr_q;
+
+void _dispatch_queue_init(dispatch_queue_t dq);
+void _dispatch_queue_drain(dispatch_queue_t dq);
+void _dispatch_queue_dispose(dispatch_queue_t dq);
+
+__attribute__((always_inline))
+static inline void
+_dispatch_queue_push_list(dispatch_queue_t dq, dispatch_object_t _head, dispatch_object_t _tail)
+{
+	struct dispatch_object_s *prev, *head = _head._do, *tail = _tail._do;
+
+	tail->do_next = NULL;
+	prev = fastpath(dispatch_atomic_xchg(&dq->dq_items_tail, tail));
+	if (prev) {
+		// if we crash here with a value less than 0x1000, then we are at a known bug in client code
+		// for example, see _dispatch_queue_dispose or _dispatch_atfork_child
+		prev->do_next = head;
+	} else {
+		dq->dq_items_head = head;
+		_dispatch_wakeup(dq);
+	}
+}
+
+#define _dispatch_queue_push(x, y) _dispatch_queue_push_list((x), (y), (y))
+
+#define DISPATCH_QUEUE_PRIORITY_COUNT 3
+
+#if DISPATCH_DEBUG
+void dispatch_debug_queue(dispatch_queue_t dq, const char* str);
+#else
+static inline void dispatch_debug_queue(dispatch_queue_t dq __attribute__((unused)), const char* str __attribute__((unused))) {}
+#endif
+
+size_t dispatch_queue_debug(dispatch_queue_t dq, char* buf, size_t bufsiz);
+size_t dispatch_queue_debug_attr(dispatch_queue_t dq, char* buf, size_t bufsiz);
+
+static inline dispatch_queue_t
+_dispatch_queue_get_current(void)
+{
+	return _dispatch_thread_getspecific(dispatch_queue_key);
+}
+
+__private_extern__ malloc_zone_t *_dispatch_ccache_zone;
+dispatch_continuation_t _dispatch_continuation_alloc_from_heap(void);
+
+static inline dispatch_continuation_t
+_dispatch_continuation_alloc_cacheonly(void)
+{
+	dispatch_continuation_t dc = fastpath(_dispatch_thread_getspecific(dispatch_cache_key));
+	if (dc) {
+		_dispatch_thread_setspecific(dispatch_cache_key, dc->do_next);
+	}
+	return dc;
+}
+
+#endif

Added: trunk/src/queue_private.h
===================================================================
--- trunk/src/queue_private.h	                        (rev 0)
+++ trunk/src/queue_private.h	2009-08-30 01:07:28 UTC (rev 2)
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2008-2009 Apple Inc. All rights reserved.
+ *
+ * @APPLE_APACHE_LICENSE_HEADER_START@
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * 
+ * @APPLE_APACHE_LICENSE_HEADER_END@
+ */
+
+/*
+ * IMPORTANT: This header file describes INTERNAL interfaces to libdispatch
+ * which are subject to change in future releases of Mac OS X. Any applications
+ * relying on these interfaces WILL break.
+ */
+
+#ifndef __DISPATCH_QUEUE_PRIVATE__
+#define __DISPATCH_QUEUE_PRIVATE__
+
+#ifndef __DISPATCH_INDIRECT__
+#error "Please #include <dispatch/dispatch.h> instead of this file directly."
+#include <dispatch/base.h> // for HeaderDoc
+#endif
+
+__BEGIN_DECLS
+
+
+/*!
+ * @enum dispatch_queue_flags_t
+ *
+ * @constant DISPATCH_QUEUE_OVERCOMMIT
+ * The queue will create a new thread for invoking blocks, regardless of how
+ * busy the computer is.
+ */
+enum {
+	DISPATCH_QUEUE_OVERCOMMIT = 0x2ull,
+};
+
+#define DISPATCH_QUEUE_FLAGS_MASK	(DISPATCH_QUEUE_OVERCOMMIT)
+
+#ifdef __BLOCKS__
+__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA)
+DISPATCH_NONNULL_ALL DISPATCH_NOTHROW
+void
+dispatch_barrier_sync(dispatch_queue_t queue, dispatch_block_t block);
+#endif
+
+__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA)
+DISPATCH_NONNULL1 DISPATCH_NONNULL3 DISPATCH_NOTHROW
+void
+dispatch_barrier_sync_f(dispatch_queue_t dq, void *context, dispatch_function_t work);
+
+#ifdef __BLOCKS__
+__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA)
+DISPATCH_NONNULL_ALL DISPATCH_NOTHROW
+void
+dispatch_barrier_async(dispatch_queue_t queue, dispatch_block_t block);
+#endif
+
+__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA)
+DISPATCH_NONNULL1 DISPATCH_NONNULL3 DISPATCH_NOTHROW
+void
+dispatch_barrier_async_f(dispatch_queue_t dq, void *context, dispatch_function_t work);
+
+/*!
+ * @function dispatch_queue_set_width
+ *
+ * @abstract
+ * Set the width of concurrency for a given queue. The default width of a
+ * privately allocated queue is one.
+ *
+ * @param queue
+ * The queue to adjust. Passing the main queue, a default concurrent queue or
+ * any other default queue will be ignored.
+ *
+ * @param width
+ * The new maximum width of concurrency depending on available resources.
+ * If zero is passed, then the value is promoted to one.
+ * Negative values are magic values that map to automatic width values.
+ * Unknown negative values default to DISPATCH_QUEUE_WIDTH_MAX_LOGICAL_CPUS.
+ */
+#define DISPATCH_QUEUE_WIDTH_ACTIVE_CPUS	-1
+#define DISPATCH_QUEUE_WIDTH_MAX_PHYSICAL_CPUS	-2
+#define DISPATCH_QUEUE_WIDTH_MAX_LOGICAL_CPUS	-3
+
+__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA)
+DISPATCH_NONNULL_ALL DISPATCH_NOTHROW
+void
+dispatch_queue_set_width(dispatch_queue_t dq, long width);
+
+
+
+__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA)
+extern const struct dispatch_queue_offsets_s {
+	// always add new fields at the end
+	const uint16_t dqo_version;
+	const uint16_t dqo_label;
+	const uint16_t dqo_label_size;
+	const uint16_t dqo_flags;
+	const uint16_t dqo_flags_size;
+	const uint16_t dqo_serialnum;
+	const uint16_t dqo_serialnum_size;
+	const uint16_t dqo_width;
+	const uint16_t dqo_width_size;
+	const uint16_t dqo_running;
+	const uint16_t dqo_running_size;
+} dispatch_queue_offsets;
+
+
+__END_DECLS
+
+#endif

Added: trunk/src/semaphore.c
===================================================================
--- trunk/src/semaphore.c	                        (rev 0)
+++ trunk/src/semaphore.c	2009-08-30 01:07:28 UTC (rev 2)
@@ -0,0 +1,532 @@
+/*
+ * Copyright (c) 2008-2009 Apple Inc. All rights reserved.
+ *
+ * @APPLE_APACHE_LICENSE_HEADER_START@
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * 
+ * @APPLE_APACHE_LICENSE_HEADER_END@
+ */
+
+#include "internal.h"
+
+// semaphores are too fundamental to use the dispatch_assume*() macros
+#define DISPATCH_SEMAPHORE_VERIFY_KR(x)	do {	\
+		if (x) {	\
+			DISPATCH_CRASH("flawed group/semaphore logic");	\
+		}	\
+	} while (0)
+
+struct dispatch_semaphore_vtable_s {
+	DISPATCH_VTABLE_HEADER(dispatch_semaphore_s);
+};
+
+static void _dispatch_semaphore_dispose(dispatch_semaphore_t dsema);
+static size_t _dispatch_semaphore_debug(dispatch_semaphore_t dsema, char *buf, size_t bufsiz);
+static long _dispatch_group_wake(dispatch_semaphore_t dsema);
+
+const struct dispatch_semaphore_vtable_s _dispatch_semaphore_vtable = {
+	.do_type = DISPATCH_SEMAPHORE_TYPE,
+	.do_kind = "semaphore",
+	.do_dispose = _dispatch_semaphore_dispose,
+	.do_debug = _dispatch_semaphore_debug,
+};
+
+dispatch_semaphore_t
+_dispatch_get_thread_semaphore(void)
+{
+	dispatch_semaphore_t dsema;
+	
+	dsema = fastpath(_dispatch_thread_getspecific(dispatch_sema4_key));
+	if (!dsema) {
+		while (!(dsema = dispatch_semaphore_create(0))) {
+			sleep(1);
+		}
+	}
+	_dispatch_thread_setspecific(dispatch_sema4_key, NULL);
+	return dsema;
+}
+
+void
+_dispatch_put_thread_semaphore(dispatch_semaphore_t dsema)
+{
+	dispatch_semaphore_t old_sema = _dispatch_thread_getspecific(dispatch_sema4_key);
+	_dispatch_thread_setspecific(dispatch_sema4_key, dsema);
+	if (old_sema) {
+		dispatch_release(old_sema);
+	}
+}
+
+dispatch_group_t
+dispatch_group_create(void)
+{
+	return (dispatch_group_t)dispatch_semaphore_create(LONG_MAX);
+}
+
+dispatch_semaphore_t
+dispatch_semaphore_create(long value)
+{
+	dispatch_semaphore_t dsema;
+	
+	// If the internal value is negative, then the absolute of the value is
+	// equal to the number of waiting threads. Therefore it is bogus to
+	// initialize the semaphore with a negative value.
+	if (value < 0) {
+		return NULL;
+	}
+	
+	dsema = calloc(1, sizeof(struct dispatch_semaphore_s));
+	
+	if (fastpath(dsema)) {
+		dsema->do_vtable = &_dispatch_semaphore_vtable;
+		dsema->do_next = DISPATCH_OBJECT_LISTLESS;
+		dsema->do_ref_cnt = 1;
+		dsema->do_xref_cnt = 1;
+		dsema->do_targetq = dispatch_get_global_queue(0, 0);
+		dsema->dsema_value = value;
+		dsema->dsema_orig = value;
+	}
+	
+	return dsema;
+}
+
+static void
+_dispatch_semaphore_create_port(semaphore_t *s4)
+{
+	kern_return_t kr;
+	semaphore_t tmp;
+
+	if (*s4) {
+		return;
+	}
+	
+	// lazily allocate the semaphore port
+	
+	// Someday:
+	// 1) Switch to a doubly-linked FIFO in user-space.
+	// 2) User-space timers for the timeout.
+	// 3) Use the per-thread semaphore port.
+	
+	while (dispatch_assume_zero(kr = semaphore_create(mach_task_self(), &tmp, SYNC_POLICY_FIFO, 0))) {
+		DISPATCH_VERIFY_MIG(kr);
+		sleep(1);
+	}
+	
+	if (!dispatch_atomic_cmpxchg(s4, 0, tmp)) {
+		kr = semaphore_destroy(mach_task_self(), tmp);
+		DISPATCH_SEMAPHORE_VERIFY_KR(kr);
+	}
+
+	_dispatch_safe_fork = false;
+}
+
+DISPATCH_NOINLINE
+static long
+_dispatch_semaphore_wait_slow(dispatch_semaphore_t dsema, dispatch_time_t timeout)
+{
+	mach_timespec_t _timeout;
+	kern_return_t kr;
+	uint64_t nsec;
+	long orig;
+	
+again:
+	// Mach semaphores appear to sometimes spuriously wake up.  Therefore,
+	// we keep a parallel count of the number of times a Mach semaphore is
+	// signaled.
+	while ((orig = dsema->dsema_sent_ksignals)) {
+		if (dispatch_atomic_cmpxchg(&dsema->dsema_sent_ksignals, orig, orig - 1)) {
+			return 0;
+		}
+	}
+
+	_dispatch_semaphore_create_port(&dsema->dsema_port);
+
+	// From xnu/osfmk/kern/sync_sema.c:
+	// wait_semaphore->count = -1;  /* we don't keep an actual count */
+	//
+	// The code above does not match the documentation, and that fact is
+	// not surprising. The documented semantics are clumsy to use in any
+	// practical way. The above hack effectively tricks the rest of the
+	// Mach semaphore logic to behave like the libdispatch algorithm.
+
+	switch (timeout) {
+	default:
+		do {
+			// timeout() already calculates relative time left
+			nsec = _dispatch_timeout(timeout);
+			_timeout.tv_sec = (typeof(_timeout.tv_sec))(nsec / NSEC_PER_SEC);
+			_timeout.tv_nsec = (typeof(_timeout.tv_nsec))(nsec % NSEC_PER_SEC);
+			kr = slowpath(semaphore_timedwait(dsema->dsema_port, _timeout));
+		} while (kr == KERN_ABORTED);
+
+		if (kr != KERN_OPERATION_TIMED_OUT) {
+			DISPATCH_SEMAPHORE_VERIFY_KR(kr);
+			break;
+		}
+		// Fall through and try to undo what the fast path did to dsema->dsema_value
+	case DISPATCH_TIME_NOW:
+		while ((orig = dsema->dsema_value) < 0) {
+			if (dispatch_atomic_cmpxchg(&dsema->dsema_value, orig, orig + 1)) {
+				return KERN_OPERATION_TIMED_OUT;
+			}
+		}
+		// Another thread called semaphore_signal().
+		// Fall through and drain the wakeup.
+	case DISPATCH_TIME_FOREVER:
+		do {
+			kr = semaphore_wait(dsema->dsema_port);
+		} while (kr == KERN_ABORTED);
+		DISPATCH_SEMAPHORE_VERIFY_KR(kr);
+		break;
+	}
+
+	goto again;
+}
+
+DISPATCH_NOINLINE
+void
+dispatch_group_enter(dispatch_group_t dg)
+{
+	dispatch_semaphore_t dsema = (dispatch_semaphore_t)dg;
+#if defined(__OPTIMIZE__) && defined(__GNUC__) && (defined(__x86_64__) || defined(__i386__))
+	// This assumes:
+	// 1) Way too much about the optimizer of GCC.
+	// 2) There will never be more than LONG_MAX threads.
+	//    Therefore: no overflow detection
+	asm(
+#ifdef __LP64__ 
+		"lock decq	%0\n\t"
+#else
+		"lock decl	%0\n\t"
+#endif
+		"js 	1f\n\t"
+		"xor	%%eax, %%eax\n\t"
+		"ret\n\t"
+		"1:"
+		: "+m" (dsema->dsema_value)
+		:
+		: "cc"
+	);
+	_dispatch_semaphore_wait_slow(dsema, DISPATCH_TIME_FOREVER);
+#else
+	dispatch_semaphore_wait(dsema, DISPATCH_TIME_FOREVER);
+#endif
+}
+
+DISPATCH_NOINLINE
+long
+dispatch_semaphore_wait(dispatch_semaphore_t dsema, dispatch_time_t timeout)
+{
+#if defined(__OPTIMIZE__) && defined(__GNUC__) && (defined(__x86_64__) || defined(__i386__))
+	// This assumes:
+	// 1) Way too much about the optimizer of GCC.
+	// 2) There will never be more than LONG_MAX threads.
+	//    Therefore: no overflow detection
+	asm(
+#ifdef __LP64__ 
+		"lock decq	%0\n\t"
+#else
+		"lock decl	%0\n\t"
+#endif
+		"js 	1f\n\t"
+		"xor	%%eax, %%eax\n\t"
+		"ret\n\t"
+		"1:"
+		: "+m" (dsema->dsema_value)
+		:
+		: "cc"
+	);
+#else
+	if (dispatch_atomic_dec(&dsema->dsema_value) >= 0) {
+		return 0;
+	}
+#endif
+	return _dispatch_semaphore_wait_slow(dsema, timeout);
+}
+
+DISPATCH_NOINLINE
+static long
+_dispatch_semaphore_signal_slow(dispatch_semaphore_t dsema)
+{
+	kern_return_t kr;
+	
+	_dispatch_semaphore_create_port(&dsema->dsema_port);
+
+	// Before dsema_sent_ksignals is incremented we can rely on the reference
+	// held by the waiter. However, once this value is incremented the waiter
+	// may return between the atomic increment and the semaphore_signal(),
+	// therefore an explicit reference must be held in order to safely access
+	// dsema after the atomic increment.
+	_dispatch_retain(dsema);
+	
+	dispatch_atomic_inc(&dsema->dsema_sent_ksignals);
+	
+	kr = semaphore_signal(dsema->dsema_port);
+	DISPATCH_SEMAPHORE_VERIFY_KR(kr);
+
+	_dispatch_release(dsema);
+	
+	return 1;
+}
+
+void
+dispatch_group_leave(dispatch_group_t dg)
+{
+	dispatch_semaphore_t dsema = (dispatch_semaphore_t)dg;
+
+	dispatch_semaphore_signal(dsema);
+
+	if (dsema->dsema_value == dsema->dsema_orig) {
+		_dispatch_group_wake(dsema);
+	}
+}
+
+DISPATCH_NOINLINE
+long
+dispatch_semaphore_signal(dispatch_semaphore_t dsema)
+{
+#if defined(__OPTIMIZE__) && defined(__GNUC__) && (defined(__x86_64__) || defined(__i386__))
+	// overflow detection
+	// this assumes way too much about the optimizer of GCC
+	asm(
+#ifdef __LP64__ 
+		"lock incq	%0\n\t"
+#else
+		"lock incl	%0\n\t"
+#endif
+		"jo 	1f\n\t"
+		"jle 	2f\n\t"
+		"xor	%%eax, %%eax\n\t"
+		"ret\n\t"
+		"1:\n\t"
+		"int	$4\n\t"
+		"2:"
+		: "+m" (dsema->dsema_value)
+		:
+		: "cc"
+	);
+#else
+	if (dispatch_atomic_inc(&dsema->dsema_value) > 0) {
+		return 0;
+	}
+#endif
+	return _dispatch_semaphore_signal_slow(dsema);
+}
+
+DISPATCH_NOINLINE
+long
+_dispatch_group_wake(dispatch_semaphore_t dsema)
+{
+	struct dispatch_sema_notify_s *tmp, *head = dispatch_atomic_xchg(&dsema->dsema_notify_head, NULL);
+	long rval = dispatch_atomic_xchg(&dsema->dsema_group_waiters, 0);
+	bool do_rel = head;
+	long kr;
+
+	// wake any "group" waiter or notify blocks
+	
+	if (rval) {
+		_dispatch_semaphore_create_port(&dsema->dsema_waiter_port);
+		do {
+			kr = semaphore_signal(dsema->dsema_waiter_port);
+			DISPATCH_SEMAPHORE_VERIFY_KR(kr);
+		} while (--rval);
+	}
+	while (head) {
+		dispatch_async_f(head->dsn_queue, head->dsn_ctxt, head->dsn_func);
+		_dispatch_release(head->dsn_queue);
+		do {
+			tmp = head->dsn_next;
+		} while (!tmp && !dispatch_atomic_cmpxchg(&dsema->dsema_notify_tail, head, NULL));
+		free(head);
+		head = tmp;
+	}
+	if (do_rel) {
+		_dispatch_release(dsema);
+	}
+	return 0;
+}
+
+DISPATCH_NOINLINE
+static long
+_dispatch_group_wait_slow(dispatch_semaphore_t dsema, dispatch_time_t timeout)
+{
+	mach_timespec_t _timeout;
+	kern_return_t kr;
+	uint64_t nsec;
+	long orig;
+	
+again:
+	// check before we cause another signal to be sent by incrementing dsema->dsema_group_waiters
+	if (dsema->dsema_value == dsema->dsema_orig) {
+		return _dispatch_group_wake(dsema);
+	}
+	// Mach semaphores appear to sometimes spuriously wake up.  Therefore,
+	// we keep a parallel count of the number of times a Mach semaphore is
+	// signaled.
+	dispatch_atomic_inc(&dsema->dsema_group_waiters);
+	// check the values again in case we need to wake any threads
+	if (dsema->dsema_value == dsema->dsema_orig) {
+		return _dispatch_group_wake(dsema);
+	}
+
+	_dispatch_semaphore_create_port(&dsema->dsema_waiter_port);
+	
+	// From xnu/osfmk/kern/sync_sema.c:
+	// wait_semaphore->count = -1;  /* we don't keep an actual count */
+	//
+	// The code above does not match the documentation, and that fact is
+	// not surprising. The documented semantics are clumsy to use in any
+	// practical way. The above hack effectively tricks the rest of the
+	// Mach semaphore logic to behave like the libdispatch algorithm.
+	
+	switch (timeout) {
+	default:
+		do {
+			nsec = _dispatch_timeout(timeout);
+			_timeout.tv_sec = (typeof(_timeout.tv_sec))(nsec / NSEC_PER_SEC);
+			_timeout.tv_nsec = (typeof(_timeout.tv_nsec))(nsec % NSEC_PER_SEC);
+			kr = slowpath(semaphore_timedwait(dsema->dsema_waiter_port, _timeout));
+		} while (kr == KERN_ABORTED);
+		if (kr != KERN_OPERATION_TIMED_OUT) {
+			DISPATCH_SEMAPHORE_VERIFY_KR(kr);
+			break;
+		}
+		// Fall through and try to undo the earlier change to dsema->dsema_group_waiters
+	case DISPATCH_TIME_NOW:
+		while ((orig = dsema->dsema_group_waiters)) {
+			if (dispatch_atomic_cmpxchg(&dsema->dsema_group_waiters, orig, orig - 1)) {
+				return KERN_OPERATION_TIMED_OUT;
+			}
+		}
+		// Another thread called semaphore_signal().
+		// Fall through and drain the wakeup.
+	case DISPATCH_TIME_FOREVER:
+		do {
+			kr = semaphore_wait(dsema->dsema_waiter_port);
+		} while (kr == KERN_ABORTED);
+		DISPATCH_SEMAPHORE_VERIFY_KR(kr);
+		break;
+	}
+
+	goto again;
+}
+
+long
+dispatch_group_wait(dispatch_group_t dg, dispatch_time_t timeout)
+{
+	dispatch_semaphore_t dsema = (dispatch_semaphore_t)dg;
+
+	if (dsema->dsema_value == dsema->dsema_orig) {
+		return 0;
+	}
+	if (timeout == 0) {
+		return KERN_OPERATION_TIMED_OUT;
+	}
+	return _dispatch_group_wait_slow(dsema, timeout);
+}
+
+#ifdef __BLOCKS__
+void
+dispatch_group_notify(dispatch_group_t dg, dispatch_queue_t dq, dispatch_block_t db)
+{
+	dispatch_group_notify_f(dg, dq, _dispatch_Block_copy(db), _dispatch_call_block_and_release);
+}
+#endif
+
+void
+dispatch_group_notify_f(dispatch_group_t dg, dispatch_queue_t dq, void *ctxt, void (*func)(void *))
+{
+	dispatch_semaphore_t dsema = (dispatch_semaphore_t)dg;
+	struct dispatch_sema_notify_s *dsn, *prev;
+
+	// FIXME -- this should be updated to use the continuation cache
+	while (!(dsn = malloc(sizeof(*dsn)))) {
+		sleep(1);
+	}
+
+	dsn->dsn_next = NULL;
+	dsn->dsn_queue = dq;
+	dsn->dsn_ctxt = ctxt;
+	dsn->dsn_func = func;
+	_dispatch_retain(dq);
+
+	prev = dispatch_atomic_xchg(&dsema->dsema_notify_tail, dsn);
+	if (fastpath(prev)) {
+		prev->dsn_next = dsn;
+	} else {
+		_dispatch_retain(dg);
+		dsema->dsema_notify_head = dsn;
+		if (dsema->dsema_value == dsema->dsema_orig) {
+			_dispatch_group_wake(dsema);
+		}
+	}
+}
+
+void
+_dispatch_semaphore_dispose(dispatch_semaphore_t dsema)
+{
+	kern_return_t kr;
+	
+	if (dsema->dsema_value < dsema->dsema_orig) {
+		DISPATCH_CLIENT_CRASH("Semaphore/group object deallocated while in use");
+	}
+	
+	if (dsema->dsema_port) {
+		kr = semaphore_destroy(mach_task_self(), dsema->dsema_port);
+		DISPATCH_SEMAPHORE_VERIFY_KR(kr);
+	}
+	if (dsema->dsema_waiter_port) {
+		kr = semaphore_destroy(mach_task_self(), dsema->dsema_waiter_port);
+		DISPATCH_SEMAPHORE_VERIFY_KR(kr);
+	}
+	
+	_dispatch_dispose(dsema);
+}
+
+size_t
+_dispatch_semaphore_debug(dispatch_semaphore_t dsema, char *buf, size_t bufsiz)
+{
+	size_t offset = 0;
+	offset += snprintf(&buf[offset], bufsiz - offset, "%s[%p] = { ", dx_kind(dsema), dsema);
+	offset += dispatch_object_debug_attr(dsema, &buf[offset], bufsiz - offset);
+	offset += snprintf(&buf[offset], bufsiz - offset, "port = 0x%u, value = %ld, orig = %ld }",
+					   dsema->dsema_port, dsema->dsema_value, dsema->dsema_orig);
+	return offset;
+}
+
+#ifdef __BLOCKS__
+void
+dispatch_group_async(dispatch_group_t dg, dispatch_queue_t dq, dispatch_block_t db)
+{
+	dispatch_group_async_f(dg, dq, _dispatch_Block_copy(db), _dispatch_call_block_and_release);
+}
+#endif
+
+DISPATCH_NOINLINE
+void
+dispatch_group_async_f(dispatch_group_t dg, dispatch_queue_t dq, void *ctxt, void (*func)(void *))
+{
+	dispatch_continuation_t dc;
+
+	_dispatch_retain(dg);
+	dispatch_group_enter(dg);
+
+	dc = _dispatch_continuation_alloc_cacheonly() ?: _dispatch_continuation_alloc_from_heap();
+
+	dc->do_vtable = (void *)(DISPATCH_OBJ_ASYNC_BIT|DISPATCH_OBJ_GROUP_BIT);
+	dc->dc_func = func;
+	dc->dc_ctxt = ctxt;
+	dc->dc_group = dg;
+
+	_dispatch_queue_push(dq, dc);
+}

Added: trunk/src/semaphore.h
===================================================================
--- trunk/src/semaphore.h	                        (rev 0)
+++ trunk/src/semaphore.h	2009-08-30 01:07:28 UTC (rev 2)
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2008-2009 Apple Inc. All rights reserved.
+ *
+ * @APPLE_APACHE_LICENSE_HEADER_START@
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * 
+ * @APPLE_APACHE_LICENSE_HEADER_END@
+ */
+
+#ifndef __DISPATCH_SEMAPHORE__
+#define __DISPATCH_SEMAPHORE__
+
+#ifndef __DISPATCH_INDIRECT__
+#error "Please #include <dispatch/dispatch.h> instead of this file directly."
+#include <dispatch/base.h> // for HeaderDoc
+#endif
+
+/*!
+ * @typedef dispatch_semaphore_t
+ *
+ * @abstract
+ * A counting semaphore.
+ */
+DISPATCH_DECL(dispatch_semaphore);
+
+__BEGIN_DECLS
+
+/*!
+ * @function dispatch_semaphore_create
+ *
+ * @abstract
+ * Creates new counting semaphore with an initial value.
+ *
+ * @discussion
+ * Passing zero for the value is useful for when two threads need to reconcile
+ * the completion of a particular event. Passing a value greather than zero is
+ * useful for managing a finite pool of resources, where the pool size is equal
+ * to the value.
+ *
+ * @param value
+ * The starting value for the semaphore. Passing a value less than zero will
+ * cause NULL to be returned.
+ *
+ * @result
+ * The newly created semaphore, or NULL on failure.
+ */
+__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA)
+DISPATCH_MALLOC DISPATCH_NOTHROW
+dispatch_semaphore_t
+dispatch_semaphore_create(long value);
+
+/*!
+ * @function dispatch_semaphore_wait
+ *
+ * @abstract
+ * Wait (decrement) for a semaphore.
+ *
+ * @discussion
+ * Decrement the counting semaphore. If the resulting value is less than zero,
+ * this function waits in FIFO order for a signal to occur before returning.
+ *
+ * @param dsema
+ * The semaphore. The result of passing NULL in this parameter is undefined.
+ *
+ * @param timeout
+ * When to timeout (see dispatch_time). As a convenience, there are the
+ * DISPATCH_TIME_NOW and DISPATCH_TIME_FOREVER constants.
+ *
+ * @result
+ * Returns zero on success, or non-zero if the timeout occurred.
+ */
+__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA)
+DISPATCH_NONNULL_ALL DISPATCH_NOTHROW
+long
+dispatch_semaphore_wait(dispatch_semaphore_t dsema, dispatch_time_t timeout);
+
+/*!
+ * @function dispatch_semaphore_signal
+ *
+ * @abstract
+ * Signal (increment) a semaphore.
+ *
+ * @discussion
+ * Increment the counting semaphore. If the previous value was less than zero,
+ * this function wakes a waiting thread before returning.
+ *
+ * @param dsema The counting semaphore.
+ * The result of passing NULL in this parameter is undefined.
+ *
+ * @result
+ * This function returns non-zero if a thread is woken. Otherwise, zero is
+ * returned.
+ */
+__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA)
+DISPATCH_NONNULL_ALL DISPATCH_NOTHROW
+long
+dispatch_semaphore_signal(dispatch_semaphore_t dsema);
+
+__END_DECLS
+
+#endif /* __DISPATCH_SEMAPHORE__ */

Added: trunk/src/semaphore_internal.h
===================================================================
--- trunk/src/semaphore_internal.h	                        (rev 0)
+++ trunk/src/semaphore_internal.h	2009-08-30 01:07:28 UTC (rev 2)
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2008-2009 Apple Inc. All rights reserved.
+ *
+ * @APPLE_APACHE_LICENSE_HEADER_START@
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * 
+ * @APPLE_APACHE_LICENSE_HEADER_END@
+ */
+
+/*
+ * IMPORTANT: This header file describes INTERNAL interfaces to libdispatch
+ * which are subject to change in future releases of Mac OS X. Any applications
+ * relying on these interfaces WILL break.
+ */
+
+#ifndef __DISPATCH_SEMAPHORE_INTERNAL__
+#define __DISPATCH_SEMAPHORE_INTERNAL__
+
+struct dispatch_sema_notify_s {
+	struct dispatch_sema_notify_s *dsn_next;
+	dispatch_queue_t dsn_queue;
+	void *dsn_ctxt;
+	void (*dsn_func)(void *);
+};
+
+struct dispatch_semaphore_s {
+	DISPATCH_STRUCT_HEADER(dispatch_semaphore_s, dispatch_semaphore_vtable_s);
+	long dsema_value;
+	long dsema_orig;
+	size_t dsema_sent_ksignals;
+	semaphore_t dsema_port;
+	semaphore_t dsema_waiter_port;
+	size_t dsema_group_waiters;
+	struct dispatch_sema_notify_s *dsema_notify_head;
+	struct dispatch_sema_notify_s *dsema_notify_tail;
+};
+
+extern const struct dispatch_semaphore_vtable_s _dispatch_semaphore_vtable;
+
+#endif

Added: trunk/src/shims.c
===================================================================
--- trunk/src/shims.c	                        (rev 0)
+++ trunk/src/shims.c	2009-08-30 01:07:28 UTC (rev 2)
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2008-2009 Apple Inc. All rights reserved.
+ *
+ * @APPLE_APACHE_LICENSE_HEADER_START@
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * 
+ * @APPLE_APACHE_LICENSE_HEADER_END@
+ */
+
+#include "internal.h"
+
+void *
+dispatch_mach_msg_get_context(mach_msg_header_t *msg)
+{
+	mach_msg_context_trailer_t *tp;
+	void *context = NULL;
+	
+	tp = (mach_msg_context_trailer_t *)((uint8_t *)msg + round_msg(msg->msgh_size));
+	if (tp->msgh_trailer_size >= (mach_msg_size_t)sizeof(mach_msg_context_trailer_t)) {
+		context = (void *)(uintptr_t)tp->msgh_context;
+	}
+	
+	return context;
+}
+
+/*
+ * Raw Mach message support
+ */
+boolean_t
+_dispatch_machport_callback(mach_msg_header_t *msg, mach_msg_header_t *reply,
+  void (*callback)(mach_msg_header_t *))
+{
+	mig_reply_setup(msg, reply);
+	((mig_reply_error_t*)reply)->RetCode = MIG_NO_REPLY;
+
+	callback(msg);
+
+	return TRUE;
+}
+
+/*
+ * CFMachPort compatibility
+ */
+boolean_t
+_dispatch_CFMachPortCallBack(mach_msg_header_t *msg, mach_msg_header_t *reply,
+  void (*callback)(struct __CFMachPort *, void *msg, signed long size, void *))
+{
+	mig_reply_setup(msg, reply);
+	((mig_reply_error_t*)reply)->RetCode = MIG_NO_REPLY;
+	
+	callback(NULL, msg, msg->msgh_size, dispatch_mach_msg_get_context(msg));
+
+	return TRUE;
+}

Added: trunk/src/source.c
===================================================================
--- trunk/src/source.c	                        (rev 0)
+++ trunk/src/source.c	2009-08-30 01:07:28 UTC (rev 2)
@@ -0,0 +1,1995 @@
+/*
+ * Copyright (c) 2008-2009 Apple Inc. All rights reserved.
+ *
+ * @APPLE_APACHE_LICENSE_HEADER_START@
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * 
+ * @APPLE_APACHE_LICENSE_HEADER_END@
+ */
+
+#include "internal.h"
+#include "protocol.h"
+#include "protocolServer.h"
+#include <sys/mount.h>
+
+#define DISPATCH_EVFILT_TIMER	(-EVFILT_SYSCOUNT - 1)
+#define DISPATCH_EVFILT_CUSTOM_ADD	(-EVFILT_SYSCOUNT - 2)
+#define DISPATCH_EVFILT_CUSTOM_OR	(-EVFILT_SYSCOUNT - 3)
+#define DISPATCH_EVFILT_SYSCOUNT	(EVFILT_SYSCOUNT + 3)
+
+#define DISPATCH_TIMER_INDEX_WALL 0
+#define DISPATCH_TIMER_INDEX_MACH 1
+static struct dispatch_kevent_s _dispatch_kevent_timer[] = {
+	{
+		.dk_kevent = {
+			.ident = DISPATCH_TIMER_INDEX_WALL,
+			.filter = DISPATCH_EVFILT_TIMER,
+			.udata = &_dispatch_kevent_timer[0],
+		},
+		.dk_sources = TAILQ_HEAD_INITIALIZER(_dispatch_kevent_timer[0].dk_sources),
+	},
+	{
+		.dk_kevent = {
+			.ident = DISPATCH_TIMER_INDEX_MACH,
+			.filter = DISPATCH_EVFILT_TIMER,
+			.udata = &_dispatch_kevent_timer[1],
+		},
+		.dk_sources = TAILQ_HEAD_INITIALIZER(_dispatch_kevent_timer[1].dk_sources),
+	},
+};
+#define DISPATCH_TIMER_COUNT (sizeof _dispatch_kevent_timer / sizeof _dispatch_kevent_timer[0])
+
+static struct dispatch_kevent_s _dispatch_kevent_data_or = {
+	.dk_kevent = {
+		.filter = DISPATCH_EVFILT_CUSTOM_OR,
+		.flags = EV_CLEAR,
+		.udata = &_dispatch_kevent_data_or,
+	},
+	.dk_sources = TAILQ_HEAD_INITIALIZER(_dispatch_kevent_data_or.dk_sources),
+};
+static struct dispatch_kevent_s _dispatch_kevent_data_add = {
+	.dk_kevent = {
+		.filter = DISPATCH_EVFILT_CUSTOM_ADD,
+		.udata = &_dispatch_kevent_data_add,
+	},
+	.dk_sources = TAILQ_HEAD_INITIALIZER(_dispatch_kevent_data_add.dk_sources),
+};
+
+#ifndef DISPATCH_NO_LEGACY
+struct dispatch_source_attr_vtable_s {
+	DISPATCH_VTABLE_HEADER(dispatch_source_attr_s);
+};
+
+struct dispatch_source_attr_s {
+	DISPATCH_STRUCT_HEADER(dispatch_source_attr_s, dispatch_source_attr_vtable_s);
+	void* finalizer_ctxt;
+	dispatch_source_finalizer_function_t finalizer_func;
+	void* context;
+};
+#endif /* DISPATCH_NO_LEGACY */
+
+#define _dispatch_source_call_block ((void *)-1)
+static void _dispatch_source_latch_and_call(dispatch_source_t ds);
+static void _dispatch_source_cancel_callout(dispatch_source_t ds);
+static bool _dispatch_source_probe(dispatch_source_t ds);
+static void _dispatch_source_dispose(dispatch_source_t ds);
+static void _dispatch_source_merge_kevent(dispatch_source_t ds, const struct kevent *ke);
+static size_t _dispatch_source_debug(dispatch_source_t ds, char* buf, size_t bufsiz);
+static size_t dispatch_source_debug_attr(dispatch_source_t ds, char* buf, size_t bufsiz);
+static dispatch_queue_t _dispatch_source_invoke(dispatch_source_t ds);
+
+static void _dispatch_kevent_merge(dispatch_source_t ds);
+static void _dispatch_kevent_release(dispatch_source_t ds);
+static void _dispatch_kevent_resume(dispatch_kevent_t dk, uint32_t new_flags, uint32_t del_flags);
+static void _dispatch_kevent_machport_resume(dispatch_kevent_t dk, uint32_t new_flags, uint32_t del_flags);
+static void _dispatch_kevent_machport_enable(dispatch_kevent_t dk);
+static void _dispatch_kevent_machport_disable(dispatch_kevent_t dk);
+
+static void _dispatch_drain_mach_messages(struct kevent *ke);
+static void _dispatch_timer_list_update(dispatch_source_t ds);
+
+static void
+_dispatch_mach_notify_source_init(void *context __attribute__((unused)));
+
+static const char *
+_evfiltstr(short filt)
+{
+	switch (filt) {
+#define _evfilt2(f) case (f): return #f
+	_evfilt2(EVFILT_READ);
+	_evfilt2(EVFILT_WRITE);
+	_evfilt2(EVFILT_AIO);
+	_evfilt2(EVFILT_VNODE);
+	_evfilt2(EVFILT_PROC);
+	_evfilt2(EVFILT_SIGNAL);
+	_evfilt2(EVFILT_TIMER);
+	_evfilt2(EVFILT_MACHPORT);
+	_evfilt2(EVFILT_FS);
+	_evfilt2(EVFILT_USER);
+	_evfilt2(EVFILT_SESSION);
+
+	_evfilt2(DISPATCH_EVFILT_TIMER);
+	_evfilt2(DISPATCH_EVFILT_CUSTOM_ADD);
+	_evfilt2(DISPATCH_EVFILT_CUSTOM_OR);
+	default:
+		return "EVFILT_missing";
+	}
+}
+
+#define DSL_HASH_SIZE 256u	// must be a power of two
+#define DSL_HASH(x)	((x) & (DSL_HASH_SIZE - 1))
+
+static TAILQ_HEAD(, dispatch_kevent_s) _dispatch_sources[DSL_HASH_SIZE];
+
+static dispatch_kevent_t
+_dispatch_kevent_find(uintptr_t ident, short filter)
+{
+	uintptr_t hash = DSL_HASH(filter == EVFILT_MACHPORT ? MACH_PORT_INDEX(ident) : ident);
+	dispatch_kevent_t dki;
+
+	TAILQ_FOREACH(dki, &_dispatch_sources[hash], dk_list) {
+		if (dki->dk_kevent.ident == ident && dki->dk_kevent.filter == filter) {
+			break;
+		}
+	}
+	return dki;
+}
+
+static void
+_dispatch_kevent_insert(dispatch_kevent_t dk)
+{
+	uintptr_t ident = dk->dk_kevent.ident;
+	uintptr_t hash = DSL_HASH(dk->dk_kevent.filter == EVFILT_MACHPORT ? MACH_PORT_INDEX(ident) : ident);
+
+	TAILQ_INSERT_TAIL(&_dispatch_sources[hash], dk, dk_list);
+}
+
+void
+dispatch_source_cancel(dispatch_source_t ds)
+{
+#if DISPATCH_DEBUG
+	dispatch_debug(ds, __FUNCTION__);
+#endif
+	dispatch_atomic_or(&ds->ds_atomic_flags, DSF_CANCELED);
+	_dispatch_wakeup(ds);
+}
+
+#ifndef DISPATCH_NO_LEGACY
+void
+_dispatch_source_legacy_xref_release(dispatch_source_t ds)
+{
+	if (ds->ds_is_legacy) {
+		if (!(ds->ds_timer.flags & DISPATCH_TIMER_ONESHOT)) {
+			dispatch_source_cancel(ds);
+		}
+
+		// Clients often leave sources suspended at the last release
+		dispatch_atomic_and(&ds->do_suspend_cnt, DISPATCH_OBJECT_SUSPEND_LOCK);
+	} else if (slowpath(DISPATCH_OBJECT_SUSPENDED(ds))) {
+		// Arguments for and against this assert are within 6705399
+		DISPATCH_CLIENT_CRASH("Release of a suspended object");
+	}
+	_dispatch_wakeup(ds);
+	_dispatch_release(ds);
+}
+#endif /* DISPATCH_NO_LEGACY */
+
+long
+dispatch_source_testcancel(dispatch_source_t ds)
+{
+	return (bool)(ds->ds_atomic_flags & DSF_CANCELED);
+}
+
+
+unsigned long
+dispatch_source_get_mask(dispatch_source_t ds)
+{
+	return ds->ds_pending_data_mask;
+}
+
+uintptr_t
+dispatch_source_get_handle(dispatch_source_t ds)
+{
+	return (int)ds->ds_ident_hack;
+}
+
+unsigned long
+dispatch_source_get_data(dispatch_source_t ds)
+{
+	return ds->ds_data;
+}
+
+#if DISPATCH_DEBUG
+void
+dispatch_debug_kevents(struct kevent* kev, size_t count, const char* str)
+{
+	size_t i;
+	for (i = 0; i < count; ++i) {
+		_dispatch_log("kevent[%lu] = { ident = %p, filter = %s, flags = 0x%x, fflags = 0x%x, data = %p, udata = %p }: %s",
+			i, (void*)kev[i].ident, _evfiltstr(kev[i].filter), kev[i].flags, kev[i].fflags, (void*)kev[i].data, (void*)kev[i].udata, str);
+	}
+}
+#endif
+
+static size_t
+_dispatch_source_kevent_debug(dispatch_source_t ds, char* buf, size_t bufsiz)
+{
+	size_t offset = _dispatch_source_debug(ds, buf, bufsiz);
+	offset += snprintf(&buf[offset], bufsiz - offset, "filter = %s }",
+			ds->ds_dkev ? _evfiltstr(ds->ds_dkev->dk_kevent.filter) : "????");
+	return offset;
+}
+
+static void
+_dispatch_source_init_tail_queue_array(void *context __attribute__((unused)))
+{
+	unsigned int i;
+	for (i = 0; i < DSL_HASH_SIZE; i++) {
+		TAILQ_INIT(&_dispatch_sources[i]);
+	}
+
+	TAILQ_INSERT_TAIL(&_dispatch_sources[DSL_HASH(DISPATCH_TIMER_INDEX_WALL)], &_dispatch_kevent_timer[DISPATCH_TIMER_INDEX_WALL], dk_list);
+	TAILQ_INSERT_TAIL(&_dispatch_sources[DSL_HASH(DISPATCH_TIMER_INDEX_MACH)], &_dispatch_kevent_timer[DISPATCH_TIMER_INDEX_MACH], dk_list);
+	TAILQ_INSERT_TAIL(&_dispatch_sources[0], &_dispatch_kevent_data_or, dk_list);
+	TAILQ_INSERT_TAIL(&_dispatch_sources[0], &_dispatch_kevent_data_add, dk_list);
+}
+
+// Find existing kevents, and merge any new flags if necessary
+void
+_dispatch_kevent_merge(dispatch_source_t ds)
+{
+	static dispatch_once_t pred;
+	dispatch_kevent_t dk;
+	typeof(dk->dk_kevent.fflags) new_flags;
+	bool do_resume = false;
+
+	if (ds->ds_is_installed) {
+		return;
+	}
+	ds->ds_is_installed = true;
+
+	dispatch_once_f(&pred, NULL, _dispatch_source_init_tail_queue_array);
+
+	dk = _dispatch_kevent_find(ds->ds_dkev->dk_kevent.ident, ds->ds_dkev->dk_kevent.filter);
+	
+	if (dk) {
+		// If an existing dispatch kevent is found, check to see if new flags
+		// need to be added to the existing kevent
+		new_flags = ~dk->dk_kevent.fflags & ds->ds_dkev->dk_kevent.fflags;
+		dk->dk_kevent.fflags |= ds->ds_dkev->dk_kevent.fflags;
+		free(ds->ds_dkev);
+		ds->ds_dkev = dk;
+		do_resume = new_flags;
+	} else {
+		dk = ds->ds_dkev;
+		_dispatch_kevent_insert(dk);
+		new_flags = dk->dk_kevent.fflags;
+		do_resume = true;
+	}
+
+	TAILQ_INSERT_TAIL(&dk->dk_sources, ds, ds_list);
+
+	// Re-register the kevent with the kernel if new flags were added
+	// by the dispatch kevent
+	if (do_resume) {
+		dk->dk_kevent.flags |= EV_ADD;
+		_dispatch_kevent_resume(ds->ds_dkev, new_flags, 0);
+		ds->ds_is_armed = true;
+	}
+}
+
+
+void
+_dispatch_kevent_resume(dispatch_kevent_t dk, uint32_t new_flags, uint32_t del_flags)
+{
+	switch (dk->dk_kevent.filter) {
+	case DISPATCH_EVFILT_TIMER:
+	case DISPATCH_EVFILT_CUSTOM_ADD:
+	case DISPATCH_EVFILT_CUSTOM_OR:
+		// these types not registered with kevent
+		return;
+	case EVFILT_MACHPORT:
+		_dispatch_kevent_machport_resume(dk, new_flags, del_flags);
+		break;
+	case EVFILT_PROC:
+		if (dk->dk_kevent.flags & EV_ONESHOT) {
+			return;
+		}
+		// fall through
+	default:
+		_dispatch_update_kq(&dk->dk_kevent);
+		if (dk->dk_kevent.flags & EV_DISPATCH) {
+			dk->dk_kevent.flags &= ~EV_ADD;
+		}
+		break;
+	}
+}
+
+dispatch_queue_t
+_dispatch_source_invoke(dispatch_source_t ds)
+{
+	// This function performs all source actions. Each action is responsible
+	// for verifying that it takes place on the appropriate queue. If the
+	// current queue is not the correct queue for this action, the correct queue
+	// will be returned and the invoke will be re-driven on that queue.
+
+	// The order of tests here in invoke and in probe should be consistent.
+	
+	dispatch_queue_t dq = _dispatch_queue_get_current();
+
+	if (!ds->ds_is_installed) {
+		// The source needs to be installed on the manager queue.
+		if (dq != &_dispatch_mgr_q) {
+			return &_dispatch_mgr_q;
+		}
+		_dispatch_kevent_merge(ds);
+	} else if ((ds->ds_atomic_flags & DSF_CANCELED) || (ds->do_xref_cnt == 0)) {
+		// The source has been cancelled and needs to be uninstalled from the
+		// manager queue. After uninstallation, the cancellation handler needs
+		// to be delivered to the target queue.
+		if (ds->ds_dkev) {
+			if (dq != &_dispatch_mgr_q) {
+				return &_dispatch_mgr_q;
+			}
+			_dispatch_kevent_release(ds);
+			return ds->do_targetq;
+		} else if (ds->ds_cancel_handler) {
+			if (dq != ds->do_targetq) {
+				return ds->do_targetq;
+			}
+		}	
+		_dispatch_source_cancel_callout(ds);
+	} else if (ds->ds_pending_data) {
+		// The source has pending data to deliver via the event handler callback
+		// on the target queue. Some sources need to be rearmed on the manager
+		// queue after event delivery.
+		if (dq != ds->do_targetq) {
+			return ds->do_targetq;
+		}
+		_dispatch_source_latch_and_call(ds);
+		if (ds->ds_needs_rearm) {
+			return &_dispatch_mgr_q;
+		}
+	} else if (ds->ds_needs_rearm && !ds->ds_is_armed) {
+		// The source needs to be rearmed on the manager queue.
+		if (dq != &_dispatch_mgr_q) {
+			return &_dispatch_mgr_q;
+		}
+		_dispatch_kevent_resume(ds->ds_dkev, 0, 0);
+		ds->ds_is_armed = true;
+	}
+
+	return NULL;
+}
+
+bool
+_dispatch_source_probe(dispatch_source_t ds)
+{
+	// This function determines whether the source needs to be invoked.
+	// The order of tests here in probe and in invoke should be consistent.
+
+	if (!ds->ds_is_installed) {
+		// The source needs to be installed on the manager queue.
+		return true;
+	} else if ((ds->ds_atomic_flags & DSF_CANCELED) || (ds->do_xref_cnt == 0)) {
+		// The source needs to be uninstalled from the manager queue, or the
+		// cancellation handler needs to be delivered to the target queue.
+		// Note: cancellation assumes installation.
+		if (ds->ds_dkev || ds->ds_cancel_handler) {
+			return true;
+		}
+	} else if (ds->ds_pending_data) {
+		// The source has pending data to deliver to the target queue.
+		return true;
+	} else if (ds->ds_needs_rearm && !ds->ds_is_armed) {
+		// The source needs to be rearmed on the manager queue.
+		return true;
+	}
+	// Nothing to do.
+	return false;
+}
+
+void
+_dispatch_source_dispose(dispatch_source_t ds)
+{
+	_dispatch_queue_dispose((dispatch_queue_t)ds);
+}
+
+static void
+_dispatch_kevent_debugger2(void *context, dispatch_source_t unused __attribute__((unused)))
+{
+	struct sockaddr sa;
+	socklen_t sa_len = sizeof(sa);
+	int c, fd = (int)(long)context;
+	unsigned int i;
+	dispatch_kevent_t dk;
+	dispatch_source_t ds;
+	FILE *debug_stream;
+
+	c = accept(fd, &sa, &sa_len);
+	if (c == -1) {
+		if (errno != EAGAIN) {
+			dispatch_assume_zero(errno);
+		}
+		return;
+	}
+#if 0
+	int r = fcntl(c, F_SETFL, 0);	// disable non-blocking IO
+	if (r == -1) {
+		dispatch_assume_zero(errno);
+	}
+#endif
+	debug_stream = fdopen(c, "a");
+	if (!dispatch_assume(debug_stream)) {
+		close(c);
+		return;
+	}
+
+	fprintf(debug_stream, "HTTP/1.0 200 OK\r\n");
+	fprintf(debug_stream, "Content-type: text/html\r\n");
+	fprintf(debug_stream, "Pragma: nocache\r\n");
+	fprintf(debug_stream, "\r\n");
+	fprintf(debug_stream, "<html>\n<head><title>PID %u</title></head>\n<body>\n<ul>\n", getpid());
+
+	//fprintf(debug_stream, "<tr><td>DK</td><td>DK</td><td>DK</td><td>DK</td><td>DK</td><td>DK</td><td>DK</td></tr>\n");
+
+	for (i = 0; i < DSL_HASH_SIZE; i++) {
+		if (TAILQ_EMPTY(&_dispatch_sources[i])) {
+			continue;
+		}
+		TAILQ_FOREACH(dk, &_dispatch_sources[i], dk_list) {
+			fprintf(debug_stream, "\t<br><li>DK %p ident %lu filter %s flags 0x%hx fflags 0x%x data 0x%lx udata %p\n",
+					dk, dk->dk_kevent.ident, _evfiltstr(dk->dk_kevent.filter), dk->dk_kevent.flags,
+					dk->dk_kevent.fflags, dk->dk_kevent.data, dk->dk_kevent.udata);
+			fprintf(debug_stream, "\t\t<ul>\n");
+			TAILQ_FOREACH(ds, &dk->dk_sources, ds_list) {
+				fprintf(debug_stream, "\t\t\t<li>DS %p refcnt 0x%x suspend 0x%x data 0x%lx mask 0x%lx flags 0x%x</li>\n",
+						ds, ds->do_ref_cnt, ds->do_suspend_cnt, ds->ds_pending_data, ds->ds_pending_data_mask,
+						ds->ds_atomic_flags);
+				if (ds->do_suspend_cnt == DISPATCH_OBJECT_SUSPEND_LOCK) {
+					dispatch_queue_t dq = ds->do_targetq;
+					fprintf(debug_stream, "\t\t<br>DQ: %p refcnt 0x%x suspend 0x%x label: %s\n", dq, dq->do_ref_cnt, dq->do_suspend_cnt, dq->dq_label);
+				}
+			}
+			fprintf(debug_stream, "\t\t</ul>\n");
+			fprintf(debug_stream, "\t</li>\n");
+		}
+	}
+	fprintf(debug_stream, "</ul>\n</body>\n</html>\n");
+	fflush(debug_stream);
+	fclose(debug_stream);
+}
+
+static void
+_dispatch_kevent_debugger(void *context __attribute__((unused)))
+{
+	union {
+		struct sockaddr_in sa_in;
+		struct sockaddr sa;
+	} sa_u = {
+		.sa_in = {
+			.sin_family = AF_INET,
+			.sin_addr = { htonl(INADDR_LOOPBACK), },
+		},
+	};
+	dispatch_source_t ds;
+	const char *valstr;
+	int val, r, fd, sock_opt = 1;
+	socklen_t slen = sizeof(sa_u);
+
+	if (issetugid()) {
+		return;
+	}
+	valstr = getenv("LIBDISPATCH_DEBUGGER");
+	if (!valstr) {
+		return;
+	}
+	val = atoi(valstr);
+	if (val == 2) {
+		sa_u.sa_in.sin_addr.s_addr = 0;
+	}
+	fd = socket(PF_INET, SOCK_STREAM, 0);
+	if (fd == -1) {
+		dispatch_assume_zero(errno);
+		return;
+	}
+	r = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void *)&sock_opt, (socklen_t) sizeof sock_opt);
+	if (r == -1) {
+		dispatch_assume_zero(errno);
+		goto out_bad;
+	}
+#if 0
+	r = fcntl(fd, F_SETFL, O_NONBLOCK);
+	if (r == -1) {
+		dispatch_assume_zero(errno);
+		goto out_bad;
+	}
+#endif
+	r = bind(fd, &sa_u.sa, sizeof(sa_u));
+	if (r == -1) {
+		dispatch_assume_zero(errno);
+		goto out_bad;
+	}
+	r = listen(fd, SOMAXCONN);
+	if (r == -1) {
+		dispatch_assume_zero(errno);
+		goto out_bad;
+	}
+	r = getsockname(fd, &sa_u.sa, &slen);
+	if (r == -1) {
+		dispatch_assume_zero(errno);
+		goto out_bad;
+	}
+	ds = dispatch_source_read_create_f(fd, NULL, &_dispatch_mgr_q, (void *)(long)fd, _dispatch_kevent_debugger2);
+	if (dispatch_assume(ds)) {
+		_dispatch_log("LIBDISPATCH: debug port: %hu", ntohs(sa_u.sa_in.sin_port));
+		return;
+	}
+out_bad:
+	close(fd);
+}
+
+void
+_dispatch_source_drain_kevent(struct kevent *ke)
+{
+	static dispatch_once_t pred;
+	dispatch_kevent_t dk = ke->udata;
+	dispatch_source_t dsi;
+
+	dispatch_once_f(&pred, NULL, _dispatch_kevent_debugger);
+
+	dispatch_debug_kevents(ke, 1, __func__);
+
+	if (ke->filter == EVFILT_MACHPORT) {
+		return _dispatch_drain_mach_messages(ke);
+	}
+	dispatch_assert(dk);
+
+	if (ke->flags & EV_ONESHOT) {
+		dk->dk_kevent.flags |= EV_ONESHOT;
+	}
+
+	TAILQ_FOREACH(dsi, &dk->dk_sources, ds_list) {
+		_dispatch_source_merge_kevent(dsi, ke);
+	}
+}
+
+static void
+_dispatch_kevent_dispose(dispatch_kevent_t dk)
+{
+	uintptr_t key;
+
+	switch (dk->dk_kevent.filter) {
+	case DISPATCH_EVFILT_TIMER:
+	case DISPATCH_EVFILT_CUSTOM_ADD:
+	case DISPATCH_EVFILT_CUSTOM_OR:
+		// these sources live on statically allocated lists
+		return;
+	case EVFILT_MACHPORT:
+		_dispatch_kevent_machport_resume(dk, 0, dk->dk_kevent.fflags);
+		break;
+	case EVFILT_PROC:
+		if (dk->dk_kevent.flags & EV_ONESHOT) {
+			break;	// implicitly deleted
+		}
+		// fall through
+	default:
+		if (~dk->dk_kevent.flags & EV_DELETE) {
+			dk->dk_kevent.flags |= EV_DELETE;
+			_dispatch_update_kq(&dk->dk_kevent);
+		}
+		break;
+	}
+
+	if (dk->dk_kevent.filter == EVFILT_MACHPORT) {
+		key = MACH_PORT_INDEX(dk->dk_kevent.ident);
+	} else {
+		key = dk->dk_kevent.ident;
+	}
+
+	TAILQ_REMOVE(&_dispatch_sources[DSL_HASH(key)], dk, dk_list);
+	free(dk);
+}
+
+void
+_dispatch_kevent_release(dispatch_source_t ds)
+{
+	dispatch_kevent_t dk = ds->ds_dkev;
+	dispatch_source_t dsi;
+	uint32_t del_flags, fflags = 0;
+
+	ds->ds_dkev = NULL;
+
+	TAILQ_REMOVE(&dk->dk_sources, ds, ds_list);
+
+	if (TAILQ_EMPTY(&dk->dk_sources)) {
+		_dispatch_kevent_dispose(dk);
+	} else {
+		TAILQ_FOREACH(dsi, &dk->dk_sources, ds_list) {
+			fflags |= (uint32_t)dsi->ds_pending_data_mask;
+		}
+		del_flags = (uint32_t)ds->ds_pending_data_mask & ~fflags;
+		if (del_flags) {
+			dk->dk_kevent.flags |= EV_ADD;
+			dk->dk_kevent.fflags = fflags;
+			_dispatch_kevent_resume(dk, 0, del_flags);
+		}
+	}
+
+	ds->ds_is_armed = false;
+	ds->ds_needs_rearm = false;	// re-arm is pointless and bad now
+	_dispatch_release(ds);	// the retain is done at creation time
+}
+
+void
+_dispatch_source_merge_kevent(dispatch_source_t ds, const struct kevent *ke)
+{
+	struct kevent fake;
+
+	if ((ds->ds_atomic_flags & DSF_CANCELED) || (ds->do_xref_cnt == 0)) {
+		return;
+	}
+
+	// EVFILT_PROC may fail with ESRCH when the process exists but is a zombie.
+	// We simulate an exit event in this case. <rdar://problem/5067725>
+	if (ke->flags & EV_ERROR) {
+		if (ke->filter == EVFILT_PROC && ke->data == ESRCH) {
+			fake = *ke;
+			fake.flags &= ~EV_ERROR;
+			fake.fflags = NOTE_EXIT;
+			fake.data = 0;
+			ke = &fake;
+		} else {
+			// log the unexpected error
+			dispatch_assume_zero(ke->data);
+			return;
+		}
+	}
+
+	if (ds->ds_is_level) {
+		// ke->data is signed and "negative available data" makes no sense
+		// zero bytes happens when EV_EOF is set
+		// 10A268 does not fail this assert with EVFILT_READ and a 10 GB file
+		dispatch_assert(ke->data >= 0l);
+		ds->ds_pending_data = ~ke->data;
+	} else if (ds->ds_is_adder) {
+		dispatch_atomic_add(&ds->ds_pending_data, ke->data);
+	} else {
+		dispatch_atomic_or(&ds->ds_pending_data, ke->fflags & ds->ds_pending_data_mask);
+	}
+
+	// EV_DISPATCH and EV_ONESHOT sources are no longer armed after delivery
+	if (ds->ds_needs_rearm) {
+		ds->ds_is_armed = false;
+	}
+
+	_dispatch_wakeup(ds);
+}
+
+void
+_dispatch_source_latch_and_call(dispatch_source_t ds)
+{
+	unsigned long prev;
+
+	if ((ds->ds_atomic_flags & DSF_CANCELED) || (ds->do_xref_cnt == 0)) {
+		return;
+	}
+	prev = dispatch_atomic_xchg(&ds->ds_pending_data, 0);
+	if (ds->ds_is_level) {
+		ds->ds_data = ~prev;
+	} else {
+		ds->ds_data = prev;
+	}
+	if (dispatch_assume(prev)) {
+		if (ds->ds_handler_func) {
+			ds->ds_handler_func(ds->ds_handler_ctxt, ds);
+		}
+	}
+}
+
+void
+_dispatch_source_cancel_callout(dispatch_source_t ds)
+{
+	ds->ds_pending_data_mask = 0;
+	ds->ds_pending_data = 0;
+	ds->ds_data = 0;
+
+#ifdef __BLOCKS__
+	if (ds->ds_handler_is_block) {
+		Block_release(ds->ds_handler_ctxt);
+		ds->ds_handler_is_block = false;
+		ds->ds_handler_func = NULL;
+		ds->ds_handler_ctxt = NULL;
+	}
+#endif
+
+	if (!ds->ds_cancel_handler) {
+		return;
+	}
+	if (ds->ds_cancel_is_block) {
+#ifdef __BLOCKS__
+		dispatch_block_t b = ds->ds_cancel_handler;
+		if (ds->ds_atomic_flags & DSF_CANCELED) {
+			b();
+		}
+		Block_release(ds->ds_cancel_handler);
+		ds->ds_cancel_is_block = false;
+#endif
+	} else {
+		dispatch_function_t f = ds->ds_cancel_handler;
+		if (ds->ds_atomic_flags & DSF_CANCELED) {
+			f(ds->do_ctxt);
+		}
+	}
+	ds->ds_cancel_handler = NULL;
+}
+
+const struct dispatch_source_vtable_s _dispatch_source_kevent_vtable = {
+	.do_type = DISPATCH_SOURCE_KEVENT_TYPE,
+	.do_kind = "kevent-source",
+	.do_invoke = _dispatch_source_invoke,
+	.do_dispose = _dispatch_source_dispose,
+	.do_probe = _dispatch_source_probe,
+	.do_debug = _dispatch_source_kevent_debug,
+};
+
+void
+dispatch_source_merge_data(dispatch_source_t ds, unsigned long val)
+{	
+	struct kevent kev = {
+		.fflags = (typeof(kev.fflags))val,
+		.data = val,
+	};
+
+	dispatch_assert(ds->ds_dkev->dk_kevent.filter == DISPATCH_EVFILT_CUSTOM_ADD ||
+					ds->ds_dkev->dk_kevent.filter == DISPATCH_EVFILT_CUSTOM_OR);
+
+	_dispatch_source_merge_kevent(ds, &kev);
+}
+
+size_t
+dispatch_source_debug_attr(dispatch_source_t ds, char* buf, size_t bufsiz)
+{
+	dispatch_queue_t target = ds->do_targetq;
+	return snprintf(buf, bufsiz,
+			"target = %s[%p], pending_data = 0x%lx, pending_data_mask = 0x%lx, ",
+			target ? target->dq_label : "", target,
+			ds->ds_pending_data, ds->ds_pending_data_mask);
+}
+
+size_t
+_dispatch_source_debug(dispatch_source_t ds, char* buf, size_t bufsiz)
+{
+        size_t offset = 0;
+        offset += snprintf(&buf[offset], bufsiz - offset, "%s[%p] = { ", dx_kind(ds), ds);
+        offset += dispatch_object_debug_attr(ds, &buf[offset], bufsiz - offset);
+        offset += dispatch_source_debug_attr(ds, &buf[offset], bufsiz - offset);
+        return offset;
+}
+
+#ifndef DISPATCH_NO_LEGACY
+static void
+dispatch_source_attr_dispose(dispatch_source_attr_t attr)
+{
+	// release the finalizer block if necessary
+	dispatch_source_attr_set_finalizer(attr, NULL);
+	_dispatch_dispose(attr);
+}
+
+static const struct dispatch_source_attr_vtable_s dispatch_source_attr_vtable = {
+	.do_type = DISPATCH_SOURCE_ATTR_TYPE,
+	.do_kind = "source-attr",
+	.do_dispose = dispatch_source_attr_dispose,
+};
+
+dispatch_source_attr_t
+dispatch_source_attr_create(void)
+{
+	dispatch_source_attr_t rval = calloc(1, sizeof(struct dispatch_source_attr_s));
+
+	if (rval) {
+		rval->do_vtable = &dispatch_source_attr_vtable;
+		rval->do_next = DISPATCH_OBJECT_LISTLESS;
+		rval->do_targetq = dispatch_get_global_queue(0, 0);
+		rval->do_ref_cnt = 1;
+		rval->do_xref_cnt = 1;
+	}
+
+	return rval;
+}
+
+void
+dispatch_source_attr_set_finalizer_f(dispatch_source_attr_t attr,
+	void *context, dispatch_source_finalizer_function_t finalizer)
+{
+#ifdef __BLOCKS__
+	if (attr->finalizer_func == (void*)_dispatch_call_block_and_release2) {
+		Block_release(attr->finalizer_ctxt);
+	}
+#endif
+
+	attr->finalizer_ctxt = context;
+	attr->finalizer_func = finalizer;
+}
+
+#ifdef __BLOCKS__
+long
+dispatch_source_attr_set_finalizer(dispatch_source_attr_t attr,
+	dispatch_source_finalizer_t finalizer)
+{
+	void *ctxt;
+	dispatch_source_finalizer_function_t func;
+
+	if (finalizer) {
+		if (!(ctxt = Block_copy(finalizer))) {
+			return 1;
+		}
+		func = (void *)_dispatch_call_block_and_release2;
+	} else {
+		ctxt = NULL;
+		func = NULL;
+	}
+
+	dispatch_source_attr_set_finalizer_f(attr, ctxt, func);
+
+	return 0;
+}
+
+dispatch_source_finalizer_t
+dispatch_source_attr_get_finalizer(dispatch_source_attr_t attr)
+{
+	if (attr->finalizer_func == (void*)_dispatch_call_block_and_release2) {
+		return (dispatch_source_finalizer_t)attr->finalizer_ctxt;
+	} else if (attr->finalizer_func == NULL) {
+		return NULL;
+	} else {
+		abort(); // finalizer is not a block...
+	}
+}
+#endif
+
+void
+dispatch_source_attr_set_context(dispatch_source_attr_t attr, void *context)
+{
+	attr->context = context;
+}
+
+dispatch_source_attr_t
+dispatch_source_attr_copy(dispatch_source_attr_t proto)
+{
+	dispatch_source_attr_t rval = NULL;
+
+	if (proto && (rval = malloc(sizeof(struct dispatch_source_attr_s)))) {
+		memcpy(rval, proto, sizeof(struct dispatch_source_attr_s));
+#ifdef __BLOCKS__
+		if (rval->finalizer_func == (void*)_dispatch_call_block_and_release2) {
+			rval->finalizer_ctxt = Block_copy(rval->finalizer_ctxt);
+		}
+#endif
+	} else if (!proto) {
+		rval = dispatch_source_attr_create();
+	}
+	return rval;
+}
+#endif /* DISPATCH_NO_LEGACY */
+
+
+struct dispatch_source_type_s {
+	struct kevent ke;
+	uint64_t mask;
+};
+
+const struct dispatch_source_type_s _dispatch_source_type_timer = {
+	.ke = {
+		.filter = DISPATCH_EVFILT_TIMER,
+	},
+	.mask = DISPATCH_TIMER_INTERVAL|DISPATCH_TIMER_ONESHOT|DISPATCH_TIMER_ABSOLUTE|DISPATCH_TIMER_WALL_CLOCK,
+};
+
+const struct dispatch_source_type_s _dispatch_source_type_read = {
+	.ke = {
+		.filter = EVFILT_READ,
+		.flags = EV_DISPATCH,
+	},
+};
+
+const struct dispatch_source_type_s _dispatch_source_type_write = {
+	.ke = {
+		.filter = EVFILT_WRITE,
+		.flags = EV_DISPATCH,
+	},
+};
+
+const struct dispatch_source_type_s _dispatch_source_type_proc = {
+	.ke = {
+		.filter = EVFILT_PROC,
+		.flags = EV_CLEAR,
+	},
+	.mask = NOTE_EXIT|NOTE_FORK|NOTE_EXEC|NOTE_SIGNAL|NOTE_REAP,
+};
+
+const struct dispatch_source_type_s _dispatch_source_type_signal = {
+	.ke = {
+		.filter = EVFILT_SIGNAL,
+	},
+};
+
+const struct dispatch_source_type_s _dispatch_source_type_vnode = {
+	.ke = {
+		.filter = EVFILT_VNODE,
+		.flags = EV_CLEAR,
+	},
+	.mask = NOTE_DELETE|NOTE_WRITE|NOTE_EXTEND|NOTE_ATTRIB|NOTE_LINK|NOTE_RENAME|NOTE_REVOKE|NOTE_NONE,
+};
+
+const struct dispatch_source_type_s _dispatch_source_type_vfs = {
+	.ke = {
+		.filter = EVFILT_FS,
+		.flags = EV_CLEAR,
+	},
+	.mask = VQ_NOTRESP|VQ_NEEDAUTH|VQ_LOWDISK|VQ_MOUNT|VQ_UNMOUNT|VQ_DEAD|VQ_ASSIST|VQ_NOTRESPLOCK|VQ_UPDATE|VQ_VERYLOWDISK,
+};
+
+const struct dispatch_source_type_s _dispatch_source_type_mach_send = {
+	.ke = {
+		.filter = EVFILT_MACHPORT,
+		.flags = EV_DISPATCH,
+		.fflags = DISPATCH_MACHPORT_DEAD,
+	},
+	.mask = DISPATCH_MACH_SEND_DEAD,
+};
+
+const struct dispatch_source_type_s _dispatch_source_type_mach_recv = {
+	.ke = {
+		.filter = EVFILT_MACHPORT,
+		.flags = EV_DISPATCH,
+		.fflags = DISPATCH_MACHPORT_RECV,
+	},
+};
+
+const struct dispatch_source_type_s _dispatch_source_type_data_add = {
+	.ke = {
+		.filter = DISPATCH_EVFILT_CUSTOM_ADD,
+	},
+};
+
+const struct dispatch_source_type_s _dispatch_source_type_data_or = {
+	.ke = {
+		.filter = DISPATCH_EVFILT_CUSTOM_OR,
+		.flags = EV_CLEAR,
+		.fflags = ~0,
+	},
+};
+
+dispatch_source_t
+dispatch_source_create(dispatch_source_type_t type,
+	uintptr_t handle,
+	unsigned long mask,
+	dispatch_queue_t q)
+{
+	const struct kevent *proto_kev = &type->ke;
+	dispatch_source_t ds = NULL;
+	dispatch_kevent_t dk = NULL;
+
+	// input validation
+	if (type == NULL || (mask & ~type->mask)) {
+		goto out_bad;
+	}
+
+	switch (type->ke.filter) {
+	case EVFILT_SIGNAL:
+		if (handle >= NSIG) {
+			goto out_bad;
+		}
+		break;
+	case EVFILT_FS:
+	case DISPATCH_EVFILT_CUSTOM_ADD:
+	case DISPATCH_EVFILT_CUSTOM_OR:
+	case DISPATCH_EVFILT_TIMER:
+		if (handle) {
+			goto out_bad;
+		}
+		break;
+	default:
+		break;
+	}
+	
+	ds = calloc(1ul, sizeof(struct dispatch_source_s));
+	if (slowpath(!ds)) {
+		goto out_bad;
+	}
+	dk = calloc(1ul, sizeof(struct dispatch_kevent_s));
+	if (slowpath(!dk)) {
+		goto out_bad;
+	}
+
+	dk->dk_kevent = *proto_kev;
+	dk->dk_kevent.ident = handle;
+	dk->dk_kevent.flags |= EV_ADD|EV_ENABLE;
+	dk->dk_kevent.fflags |= (uint32_t)mask;
+	dk->dk_kevent.udata = dk;
+	TAILQ_INIT(&dk->dk_sources);
+
+	// Initialize as a queue first, then override some settings below.
+	_dispatch_queue_init((dispatch_queue_t)ds);
+	strlcpy(ds->dq_label, "source", sizeof(ds->dq_label));
+
+	// Dispatch Object
+	ds->do_vtable = &_dispatch_source_kevent_vtable;
+	ds->do_ref_cnt++; // the reference the manger queue holds
+	ds->do_suspend_cnt = DISPATCH_OBJECT_SUSPEND_INTERVAL;
+	// do_targetq will be retained below, past point of no-return
+	ds->do_targetq = q;
+
+	// Dispatch Source
+	ds->ds_ident_hack = dk->dk_kevent.ident;
+	ds->ds_dkev = dk;
+	ds->ds_pending_data_mask = dk->dk_kevent.fflags;
+	if ((EV_DISPATCH|EV_ONESHOT) & proto_kev->flags) {
+		if (proto_kev->filter != EVFILT_MACHPORT) {
+			ds->ds_is_level = true;
+		}
+		ds->ds_needs_rearm = true;
+	} else if (!(EV_CLEAR & proto_kev->flags)) {
+		// we cheat and use EV_CLEAR to mean a "flag thingy"
+		ds->ds_is_adder = true;
+	}
+	
+	// If its a timer source, it needs to be re-armed
+	if (type->ke.filter == DISPATCH_EVFILT_TIMER) {
+		ds->ds_needs_rearm = true;
+	}
+	
+	dispatch_assert(!(ds->ds_is_level && ds->ds_is_adder));
+#if DISPATCH_DEBUG
+	dispatch_debug(ds, __FUNCTION__);
+#endif
+
+	// Some sources require special processing
+	if (type == DISPATCH_SOURCE_TYPE_MACH_SEND) {
+		static dispatch_once_t pred;
+		dispatch_once_f(&pred, NULL, _dispatch_mach_notify_source_init);
+	} else if (type == DISPATCH_SOURCE_TYPE_TIMER) {
+		ds->ds_timer.flags = mask;
+	}
+
+	_dispatch_retain(ds->do_targetq);
+	return ds;
+	
+out_bad:
+	free(ds);
+	free(dk);
+	return NULL;
+}
+
+// 6618342 Contact the team that owns the Instrument DTrace probe before renaming this symbol
+static void
+_dispatch_source_set_event_handler2(void *context)
+{
+	struct Block_layout *bl = context;
+
+	dispatch_source_t ds = (dispatch_source_t)_dispatch_queue_get_current();
+	dispatch_assert(ds->do_vtable == &_dispatch_source_kevent_vtable);
+	
+	if (ds->ds_handler_is_block && ds->ds_handler_ctxt) {
+		Block_release(ds->ds_handler_ctxt);
+	}
+	ds->ds_handler_func = bl ? (void *)bl->invoke : NULL;
+	ds->ds_handler_ctxt = bl;
+	ds->ds_handler_is_block = true;
+}
+
+void
+dispatch_source_set_event_handler(dispatch_source_t ds, dispatch_block_t handler)
+{
+	dispatch_assert(!ds->ds_is_legacy);
+	handler = _dispatch_Block_copy(handler);
+	dispatch_barrier_async_f((dispatch_queue_t)ds,
+		handler, _dispatch_source_set_event_handler2);
+}
+
+static void
+_dispatch_source_set_event_handler_f(void *context)
+{
+	dispatch_source_t ds = (dispatch_source_t)_dispatch_queue_get_current();
+	dispatch_assert(ds->do_vtable == &_dispatch_source_kevent_vtable);
+	
+	if (ds->ds_handler_is_block && ds->ds_handler_ctxt) {
+		Block_release(ds->ds_handler_ctxt);
+	}
+	ds->ds_handler_func = context;
+	ds->ds_handler_ctxt = ds->do_ctxt;
+	ds->ds_handler_is_block = false;
+}
+
+void
+dispatch_source_set_event_handler_f(dispatch_source_t ds,
+	dispatch_function_t handler)
+{
+	dispatch_assert(!ds->ds_is_legacy);
+	dispatch_barrier_async_f((dispatch_queue_t)ds,
+		handler, _dispatch_source_set_event_handler_f);
+}
+
+// 6618342 Contact the team that owns the Instrument DTrace probe before renaming this symbol
+static void
+_dispatch_source_set_cancel_handler2(void *context)
+{
+	dispatch_source_t ds = (dispatch_source_t)_dispatch_queue_get_current();
+	dispatch_assert(ds->do_vtable == &_dispatch_source_kevent_vtable);
+	
+	if (ds->ds_cancel_is_block && ds->ds_cancel_handler) {
+		Block_release(ds->ds_cancel_handler);
+	}
+	ds->ds_cancel_handler = context;
+	ds->ds_cancel_is_block = true;
+}
+
+void
+dispatch_source_set_cancel_handler(dispatch_source_t ds,
+	dispatch_block_t handler)
+{
+	dispatch_assert(!ds->ds_is_legacy);
+	handler = _dispatch_Block_copy(handler);
+	dispatch_barrier_async_f((dispatch_queue_t)ds,
+							 handler, _dispatch_source_set_cancel_handler2);
+}
+
+static void
+_dispatch_source_set_cancel_handler_f(void *context)
+{
+	dispatch_source_t ds = (dispatch_source_t)_dispatch_queue_get_current();
+	dispatch_assert(ds->do_vtable == &_dispatch_source_kevent_vtable);
+	
+	if (ds->ds_cancel_is_block && ds->ds_cancel_handler) {
+		Block_release(ds->ds_cancel_handler);
+	}
+	ds->ds_cancel_handler = context;
+	ds->ds_cancel_is_block = false;
+}
+
+void
+dispatch_source_set_cancel_handler_f(dispatch_source_t ds,
+	dispatch_function_t handler)
+{
+	dispatch_assert(!ds->ds_is_legacy);
+	dispatch_barrier_async_f((dispatch_queue_t)ds,
+							 handler, _dispatch_source_set_cancel_handler_f);
+}
+
+#ifndef DISPATCH_NO_LEGACY
+// 6618342 Contact the team that owns the Instrument DTrace probe before renaming this symbol
+dispatch_source_t
+_dispatch_source_create2(dispatch_source_t ds,
+	dispatch_source_attr_t attr,
+	void *context,
+	dispatch_source_handler_function_t handler)
+{
+	if (ds == NULL || handler == NULL) {
+		return NULL;
+	}
+
+	ds->ds_is_legacy = true;
+
+	ds->ds_handler_func = handler;
+	ds->ds_handler_ctxt = context;
+		
+	if (attr && attr != DISPATCH_SOURCE_CREATE_SUSPENDED) {
+		ds->dq_finalizer_ctxt = attr->finalizer_ctxt;
+		ds->dq_finalizer_func = (typeof(ds->dq_finalizer_func))attr->finalizer_func;
+		ds->do_ctxt = attr->context;
+	}
+#ifdef __BLOCKS__
+	if (ds->dq_finalizer_func == (void*)_dispatch_call_block_and_release2) {
+		ds->dq_finalizer_ctxt = Block_copy(ds->dq_finalizer_ctxt);
+		if (!ds->dq_finalizer_ctxt) {
+			goto out_bad;
+		}
+	}
+	if (handler == _dispatch_source_call_block) {
+		struct Block_layout *bl = ds->ds_handler_ctxt = Block_copy(context);
+		if (!ds->ds_handler_ctxt) {
+			if (ds->dq_finalizer_func == (void*)_dispatch_call_block_and_release2) {
+				Block_release(ds->dq_finalizer_ctxt);
+			}
+			goto out_bad;
+		}
+		ds->ds_handler_func = (void *)bl->invoke;
+		ds->ds_handler_is_block = true;
+	}
+
+	// all legacy sources get a cancellation event on the normal event handler.
+	dispatch_source_handler_function_t func = ds->ds_handler_func;
+	dispatch_source_handler_t block = ds->ds_handler_ctxt;
+	void *ctxt = ds->ds_handler_ctxt;
+	bool handler_is_block = ds->ds_handler_is_block;
+	
+	ds->ds_cancel_is_block = true;
+	if (handler_is_block) {
+		ds->ds_cancel_handler = _dispatch_Block_copy(^{
+			block(ds);
+		});
+	} else {
+		ds->ds_cancel_handler = _dispatch_Block_copy(^{
+			func(ctxt, ds);
+		});
+	}
+#endif
+	if (attr != DISPATCH_SOURCE_CREATE_SUSPENDED) {
+		dispatch_resume(ds);
+	}
+
+	return ds;
+
+out_bad:
+	free(ds);
+	return NULL;
+}
+
+long
+dispatch_source_get_error(dispatch_source_t ds, long *err_out)
+{
+	// 6863892 don't report ECANCELED until kevent is unregistered
+	if ((ds->ds_atomic_flags & DSF_CANCELED) && !ds->ds_dkev) {
+		if (err_out) {
+			*err_out = ECANCELED;
+		}
+		return DISPATCH_ERROR_DOMAIN_POSIX;
+	} else {
+		return DISPATCH_ERROR_DOMAIN_NO_ERROR;
+	}
+}
+#endif /* DISPATCH_NO_LEGACY */
+
+// Updates the ordered list of timers based on next fire date for changes to ds.
+// Should only be called from the context of _dispatch_mgr_q.
+void
+_dispatch_timer_list_update(dispatch_source_t ds)
+{
+	dispatch_source_t dsi = NULL;
+	int idx;
+	
+	dispatch_assert(_dispatch_queue_get_current() == &_dispatch_mgr_q);
+
+	// do not reschedule timers unregistered with _dispatch_kevent_release()
+	if (!ds->ds_dkev) {
+		return;
+	}
+
+	// Ensure the source is on the global kevent lists before it is removed and
+	// readded below.
+	_dispatch_kevent_merge(ds);
+	
+	TAILQ_REMOVE(&ds->ds_dkev->dk_sources, ds, ds_list);
+
+	// change the list if the clock type has changed
+	if (ds->ds_timer.flags & DISPATCH_TIMER_WALL_CLOCK) {
+		idx = DISPATCH_TIMER_INDEX_WALL;
+	} else {
+		idx = DISPATCH_TIMER_INDEX_MACH;
+	}
+	ds->ds_dkev = &_dispatch_kevent_timer[idx];
+
+	if (ds->ds_timer.target) {
+		TAILQ_FOREACH(dsi, &ds->ds_dkev->dk_sources, ds_list) {
+			if (dsi->ds_timer.target == 0 || ds->ds_timer.target < dsi->ds_timer.target) {
+				break;
+			}
+		}
+	}
+	
+	if (dsi) {
+		TAILQ_INSERT_BEFORE(dsi, ds, ds_list);
+	} else {
+		TAILQ_INSERT_TAIL(&ds->ds_dkev->dk_sources, ds, ds_list);
+	}
+}
+
+static void
+_dispatch_run_timers2(unsigned int timer)
+{
+	dispatch_source_t ds;
+	uint64_t now, missed;
+
+	if (timer == DISPATCH_TIMER_INDEX_MACH) {
+		now = mach_absolute_time();
+	} else {
+		now = _dispatch_get_nanoseconds();
+	}
+
+	while ((ds = TAILQ_FIRST(&_dispatch_kevent_timer[timer].dk_sources))) {
+		// We may find timers on the wrong list due to a pending update from
+		// dispatch_source_set_timer. Force an update of the list in that case.
+		if (timer != ds->ds_ident_hack) {
+			_dispatch_timer_list_update(ds);
+			continue;
+		}
+		if (!ds->ds_timer.target) {
+			// no configured timers on the list
+			break;
+		}
+		if (ds->ds_timer.target > now) {
+			// Done running timers for now.
+			break;
+		}
+
+		if (ds->ds_timer.flags & (DISPATCH_TIMER_ONESHOT|DISPATCH_TIMER_ABSOLUTE)) {
+			dispatch_atomic_inc(&ds->ds_pending_data);
+			ds->ds_timer.target = 0;
+		} else {
+			// Calculate number of missed intervals.
+			missed = (now - ds->ds_timer.target) / ds->ds_timer.interval;
+			dispatch_atomic_add(&ds->ds_pending_data, missed + 1);
+			ds->ds_timer.target += (missed + 1) * ds->ds_timer.interval;
+		}
+
+		_dispatch_timer_list_update(ds);
+		_dispatch_wakeup(ds);
+	}
+}
+
+void
+_dispatch_run_timers(void)
+{
+	unsigned int i;
+	for (i = 0; i < DISPATCH_TIMER_COUNT; i++) {
+		_dispatch_run_timers2(i);
+	}
+}
+
+#if defined(__i386__) || defined(__x86_64__)
+// these architectures always return mach_absolute_time() in nanoseconds
+#define _dispatch_convert_mach2nano(x) (x)
+#define _dispatch_convert_nano2mach(x) (x)
+#else
+static mach_timebase_info_data_t tbi;
+static dispatch_once_t tbi_pred;
+
+static void
+_dispatch_convert_init(void *context __attribute__((unused)))
+{
+	dispatch_assume_zero(mach_timebase_info(&tbi));
+}
+
+static uint64_t
+_dispatch_convert_mach2nano(uint64_t val)
+{
+#ifdef __LP64__
+	__uint128_t tmp;
+#else
+	long double tmp;
+#endif
+
+	dispatch_once_f(&tbi_pred, NULL, _dispatch_convert_init);
+
+	tmp = val;
+	tmp *= tbi.numer;
+	tmp /= tbi.denom;
+
+	return tmp;
+}
+
+static uint64_t
+_dispatch_convert_nano2mach(uint64_t val)
+{
+#ifdef __LP64__
+	__uint128_t tmp;
+#else
+	long double tmp;
+#endif
+
+	dispatch_once_f(&tbi_pred, NULL, _dispatch_convert_init);
+
+	tmp = val;
+	tmp *= tbi.denom;
+	tmp /= tbi.numer;
+
+	return tmp;
+}
+#endif
+
+// approx 1 year (60s * 60m * 24h * 365d)
+#define FOREVER_SEC 3153600l
+#define FOREVER_NSEC 31536000000000000ull
+
+struct timespec *
+_dispatch_get_next_timer_fire(struct timespec *howsoon)
+{
+	// <rdar://problem/6459649>
+	// kevent(2) does not allow large timeouts, so we use a long timeout
+	// instead (approximately 1 year).
+	dispatch_source_t ds = NULL;
+	unsigned int timer;
+	uint64_t now, delta_tmp, delta = UINT64_MAX;
+
+	// We are looking for the first unsuspended timer which has its target
+	// time set. Given timers are kept in order, if we hit an timer that's
+	// unset there's no point in continuing down the list.
+	for (timer = 0; timer < DISPATCH_TIMER_COUNT; timer++) {
+		TAILQ_FOREACH(ds, &_dispatch_kevent_timer[timer].dk_sources, ds_list) {
+			if (!ds->ds_timer.target) {
+				break;
+			}
+			if (DISPATCH_OBJECT_SUSPENDED(ds)) {
+				ds->ds_is_armed = false;
+			} else {
+				break;
+			}
+		}
+
+		if (!ds || !ds->ds_timer.target) {
+			continue;
+		}
+				
+		if (ds->ds_timer.flags & DISPATCH_TIMER_WALL_CLOCK) {
+			now = _dispatch_get_nanoseconds();
+		} else {
+			now = mach_absolute_time();
+		}
+		if (ds->ds_timer.target <= now) {
+			howsoon->tv_sec = 0;
+			howsoon->tv_nsec = 0;
+			return howsoon;
+		}
+
+		// the subtraction cannot go negative because the previous "if"
+		// verified that the target is greater than now.
+		delta_tmp = ds->ds_timer.target - now;
+		if (!(ds->ds_timer.flags & DISPATCH_TIMER_WALL_CLOCK)) {
+			delta_tmp = _dispatch_convert_mach2nano(delta_tmp);
+		}
+		if (delta_tmp < delta) {
+			delta = delta_tmp;
+		}
+	}
+	if (slowpath(delta > FOREVER_NSEC)) {
+		return NULL;
+	} else {
+		howsoon->tv_sec = (time_t)(delta / NSEC_PER_SEC);
+		howsoon->tv_nsec = (long)(delta % NSEC_PER_SEC);
+	}
+	return howsoon;
+}
+
+struct dispatch_set_timer_params {
+	dispatch_source_t ds;
+	uintptr_t ident;
+	struct dispatch_timer_source_s values;
+};
+
+// To be called from the context of the _dispatch_mgr_q
+static void
+_dispatch_source_set_timer2(void *context)
+{
+	struct dispatch_set_timer_params *params = context;
+	dispatch_source_t ds = params->ds;
+	ds->ds_ident_hack = params->ident;
+	ds->ds_timer = params->values;
+	_dispatch_timer_list_update(ds);
+	dispatch_resume(ds);
+	dispatch_release(ds);
+	free(params);
+}
+
+void
+dispatch_source_set_timer(dispatch_source_t ds,
+	dispatch_time_t start,
+	uint64_t interval,
+	uint64_t leeway)
+{
+	struct dispatch_set_timer_params *params;
+	
+	// we use zero internally to mean disabled
+	if (interval == 0) {
+		interval = 1;
+	} else if ((int64_t)interval < 0) {
+		// 6866347 - make sure nanoseconds won't overflow
+		interval = INT64_MAX;
+	}
+
+	// Suspend the source so that it doesn't fire with pending changes
+	// The use of suspend/resume requires the external retain/release
+	dispatch_retain(ds);
+	dispatch_suspend(ds);
+	
+	if (start == DISPATCH_TIME_NOW) {
+		start = mach_absolute_time();
+	} else if (start == DISPATCH_TIME_FOREVER) {
+		start = INT64_MAX;
+	}
+
+	while (!(params = malloc(sizeof(struct dispatch_set_timer_params)))) {
+		sleep(1);
+	}
+
+	params->ds = ds;
+	params->values.flags = ds->ds_timer.flags;
+
+	if ((int64_t)start < 0) {
+		// wall clock
+		params->ident = DISPATCH_TIMER_INDEX_WALL;
+		params->values.start = -((int64_t)start);
+		params->values.target = -((int64_t)start);
+		params->values.interval = interval;
+		params->values.leeway = leeway;
+		params->values.flags |= DISPATCH_TIMER_WALL_CLOCK;
+	} else {
+		// mach clock
+		params->ident = DISPATCH_TIMER_INDEX_MACH;
+		params->values.start = start;
+		params->values.target = start;
+		params->values.interval = _dispatch_convert_nano2mach(interval);
+		params->values.leeway = _dispatch_convert_nano2mach(leeway);
+		params->values.flags &= ~DISPATCH_TIMER_WALL_CLOCK;
+	}
+
+	dispatch_barrier_async_f(&_dispatch_mgr_q, params, _dispatch_source_set_timer2);
+}
+
+#ifndef DISPATCH_NO_LEGACY
+// LEGACY
+long
+dispatch_source_timer_set_time(dispatch_source_t ds, uint64_t nanoseconds, uint64_t leeway)
+{
+	dispatch_time_t start;
+	if (nanoseconds == 0) {
+		nanoseconds = 1;
+	}
+	if (ds->ds_timer.flags == (DISPATCH_TIMER_ABSOLUTE|DISPATCH_TIMER_WALL_CLOCK)) {
+		static const struct timespec t0;
+		start = dispatch_walltime(&t0, nanoseconds);
+	} else if (ds->ds_timer.flags & DISPATCH_TIMER_WALL_CLOCK) {
+		start = dispatch_walltime(DISPATCH_TIME_NOW, nanoseconds);
+	} else {
+		start = dispatch_time(DISPATCH_TIME_NOW, nanoseconds);
+	}
+	if (ds->ds_timer.flags & (DISPATCH_TIMER_ABSOLUTE|DISPATCH_TIMER_ONESHOT)) {
+		// 6866347 - make sure nanoseconds won't overflow
+		nanoseconds = INT64_MAX; // non-repeating (~292 years)
+	}
+	dispatch_source_set_timer(ds, start, nanoseconds, leeway);
+	return 0;
+}
+
+// LEGACY
+uint64_t
+dispatch_event_get_nanoseconds(dispatch_source_t ds)
+{
+	if (ds->ds_timer.flags & DISPATCH_TIMER_WALL_CLOCK) {
+		return ds->ds_timer.interval;
+	} else {
+		return _dispatch_convert_mach2nano(ds->ds_timer.interval);
+	}
+}
+#endif /* DISPATCH_NO_LEGACY */
+
+static dispatch_source_t _dispatch_mach_notify_source;
+static mach_port_t _dispatch_port_set;
+static mach_port_t _dispatch_event_port;
+
+#define _DISPATCH_IS_POWER_OF_TWO(v)	(!(v & (v - 1)) && v)
+#define _DISPATCH_HASH(x, y)    (_DISPATCH_IS_POWER_OF_TWO(y) ? (MACH_PORT_INDEX(x) & ((y) - 1)) : (MACH_PORT_INDEX(x) % (y)))
+
+#define _DISPATCH_MACHPORT_HASH_SIZE 32
+#define _DISPATCH_MACHPORT_HASH(x)    _DISPATCH_HASH((x), _DISPATCH_MACHPORT_HASH_SIZE)
+
+static void _dispatch_port_set_init(void *);
+static mach_port_t _dispatch_get_port_set(void);
+
+void
+_dispatch_drain_mach_messages(struct kevent *ke)
+{
+	dispatch_source_t dsi;
+	dispatch_kevent_t dk;
+	struct kevent ke2;
+
+	if (!dispatch_assume(ke->data)) {
+		return;
+	}
+	dk = _dispatch_kevent_find(ke->data, EVFILT_MACHPORT);
+	if (!dispatch_assume(dk)) {
+		return;
+	}
+	_dispatch_kevent_machport_disable(dk);	// emulate EV_DISPATCH
+
+	EV_SET(&ke2, ke->data, EVFILT_MACHPORT, EV_ADD|EV_ENABLE|EV_DISPATCH, DISPATCH_MACHPORT_RECV, 0, dk);
+
+	TAILQ_FOREACH(dsi, &dk->dk_sources, ds_list) {
+		_dispatch_source_merge_kevent(dsi, &ke2);
+	}
+}
+
+void
+_dispatch_port_set_init(void *context __attribute__((unused)))
+{
+	struct kevent kev = {
+		.filter = EVFILT_MACHPORT,
+		.flags = EV_ADD,
+	};
+	kern_return_t kr;
+
+	kr = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_PORT_SET, &_dispatch_port_set);
+	DISPATCH_VERIFY_MIG(kr);
+	dispatch_assume_zero(kr);
+	kr = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &_dispatch_event_port);
+	DISPATCH_VERIFY_MIG(kr);
+	dispatch_assume_zero(kr);
+	kr = mach_port_move_member(mach_task_self(), _dispatch_event_port, _dispatch_port_set);
+	DISPATCH_VERIFY_MIG(kr);
+	dispatch_assume_zero(kr);
+
+	kev.ident = _dispatch_port_set;
+
+	_dispatch_update_kq(&kev);
+}
+
+mach_port_t
+_dispatch_get_port_set(void)
+{
+	static dispatch_once_t pred;
+
+	dispatch_once_f(&pred, NULL, _dispatch_port_set_init);
+
+	return _dispatch_port_set;
+}
+
+void
+_dispatch_kevent_machport_resume(dispatch_kevent_t dk, uint32_t new_flags, uint32_t del_flags)
+{
+	mach_port_t previous, port = (mach_port_t)dk->dk_kevent.ident;
+	kern_return_t kr;
+
+	if ((new_flags & DISPATCH_MACHPORT_RECV) || (!new_flags && !del_flags && dk->dk_kevent.fflags & DISPATCH_MACHPORT_RECV)) {
+		_dispatch_kevent_machport_enable(dk);
+	}
+	if (new_flags & DISPATCH_MACHPORT_DEAD) {
+		kr = mach_port_request_notification(mach_task_self(), port, MACH_NOTIFY_DEAD_NAME, 1,
+				_dispatch_event_port, MACH_MSG_TYPE_MAKE_SEND_ONCE, &previous);
+		DISPATCH_VERIFY_MIG(kr);
+
+	
+		switch(kr) {
+			case KERN_INVALID_NAME:
+			case KERN_INVALID_RIGHT:
+				// Supress errors 
+				break;
+			default:
+			// Else, we dont expect any errors from mach. Log any errors if we do
+			if (dispatch_assume_zero(kr)) {
+				// log the error
+			} else if (dispatch_assume_zero(previous)) {
+				// Another subsystem has beat libdispatch to requesting the Mach
+				// dead-name notification on this port. We should technically cache the
+				// previous port and message it when the kernel messages our port. Or
+				// we can just say screw those subsystems and drop the previous port.
+				// They should adopt libdispatch :-P
+				kr = mach_port_deallocate(mach_task_self(), previous);
+				DISPATCH_VERIFY_MIG(kr);
+				dispatch_assume_zero(kr);
+			}
+		}
+	}
+
+	if (del_flags & DISPATCH_MACHPORT_RECV) {
+		_dispatch_kevent_machport_disable(dk);
+	}
+	if (del_flags & DISPATCH_MACHPORT_DEAD) {
+		kr = mach_port_request_notification(mach_task_self(), (mach_port_t)dk->dk_kevent.ident,
+				MACH_NOTIFY_DEAD_NAME, 1, MACH_PORT_NULL, MACH_MSG_TYPE_MAKE_SEND_ONCE, &previous);
+		DISPATCH_VERIFY_MIG(kr);
+
+		switch (kr) {
+			case KERN_INVALID_NAME:
+			case KERN_INVALID_RIGHT:
+			case KERN_INVALID_ARGUMENT:
+				break;
+			default:
+			if (dispatch_assume_zero(kr)) {
+				// log the error
+			} else if (previous) {
+				// the kernel has not consumed the right yet
+				dispatch_assume_zero(_dispatch_send_consume_send_once_right(previous));
+			}
+		}
+	}
+}
+
+void
+_dispatch_kevent_machport_enable(dispatch_kevent_t dk)
+{
+	mach_port_t mp = (mach_port_t)dk->dk_kevent.ident;
+	kern_return_t kr;
+
+	kr = mach_port_move_member(mach_task_self(), mp, _dispatch_get_port_set());
+	DISPATCH_VERIFY_MIG(kr);
+	switch (kr) {
+	case KERN_INVALID_NAME:
+#if DISPATCH_DEBUG
+		_dispatch_log("Corruption: Mach receive right 0x%x destroyed prematurely", mp);
+#endif
+		break;
+	default:
+	 	dispatch_assume_zero(kr);
+	}
+}
+
+void
+_dispatch_kevent_machport_disable(dispatch_kevent_t dk)
+{
+	mach_port_t mp = (mach_port_t)dk->dk_kevent.ident;
+	kern_return_t kr;
+
+	kr = mach_port_move_member(mach_task_self(), mp, 0);
+	DISPATCH_VERIFY_MIG(kr);
+	switch (kr) {
+	case KERN_INVALID_RIGHT:
+	case KERN_INVALID_NAME:
+#if DISPATCH_DEBUG
+		_dispatch_log("Corruption: Mach receive right 0x%x destroyed prematurely", mp);
+#endif
+		break;
+	case 0:
+		break;
+	default:
+		dispatch_assume_zero(kr);
+		break;
+	}
+}
+
+#define _DISPATCH_MIN_MSG_SZ (8ul * 1024ul - MAX_TRAILER_SIZE)
+#ifndef DISPATCH_NO_LEGACY
+dispatch_source_t
+dispatch_source_mig_create(mach_port_t mport, size_t max_msg_size, dispatch_source_attr_t attr,
+	dispatch_queue_t dq, dispatch_mig_callback_t mig_callback)
+{
+	if (max_msg_size < _DISPATCH_MIN_MSG_SZ) {
+		max_msg_size = _DISPATCH_MIN_MSG_SZ;
+	}
+	return dispatch_source_machport_create(mport, DISPATCH_MACHPORT_RECV, attr, dq,
+	^(dispatch_source_t ds) {
+		if (!dispatch_source_get_error(ds, NULL)) {
+			if (dq->dq_width != 1) {
+				dispatch_retain(ds);	// this is a shim -- use the external retain
+				dispatch_async(dq, ^{
+					dispatch_mig_server(ds, max_msg_size, mig_callback);
+					dispatch_release(ds);	// this is a shim -- use the external release
+				});
+			} else {
+				dispatch_mig_server(ds, max_msg_size, mig_callback);
+			}
+		}
+	});	
+}
+#endif /* DISPATCH_NO_LEGACY */
+
+static void
+_dispatch_mach_notify_source_init(void *context __attribute__((unused)))
+{
+	size_t maxsz = sizeof(union __RequestUnion___dispatch_send_libdispatch_internal_protocol_subsystem);
+
+	if (sizeof(union __ReplyUnion___dispatch_libdispatch_internal_protocol_subsystem) > maxsz) {
+		maxsz = sizeof(union __ReplyUnion___dispatch_libdispatch_internal_protocol_subsystem);
+	}
+
+	_dispatch_get_port_set();
+
+	_dispatch_mach_notify_source = dispatch_source_mig_create(_dispatch_event_port,
+			maxsz, NULL, &_dispatch_mgr_q, libdispatch_internal_protocol_server);
+
+	dispatch_assert(_dispatch_mach_notify_source);
+}
+
+kern_return_t
+_dispatch_mach_notify_port_deleted(mach_port_t notify __attribute__((unused)), mach_port_name_t name)
+{
+	dispatch_source_t dsi;
+	dispatch_kevent_t dk;
+	struct kevent kev;
+
+#if DISPATCH_DEBUG
+	_dispatch_log("Corruption: Mach send/send-once/dead-name right 0x%x deleted prematurely", name);
+#endif
+
+	dk = _dispatch_kevent_find(name, EVFILT_MACHPORT);
+	if (!dk) {
+		goto out;
+	}
+
+	EV_SET(&kev, name, EVFILT_MACHPORT, EV_ADD|EV_ENABLE|EV_DISPATCH|EV_EOF, DISPATCH_MACHPORT_DELETED, 0, dk);
+
+	TAILQ_FOREACH(dsi, &dk->dk_sources, ds_list) {
+		_dispatch_source_merge_kevent(dsi, &kev);
+		// this can never happen again
+		// this must happen after the merge
+		// this may be racy in the future, but we don't provide a 'setter' API for the mask yet
+		dsi->ds_pending_data_mask &= ~DISPATCH_MACHPORT_DELETED;
+	}
+
+	// no more sources have this flag
+	dk->dk_kevent.fflags &= ~DISPATCH_MACHPORT_DELETED;
+
+out:
+	return KERN_SUCCESS;
+}
+
+kern_return_t
+_dispatch_mach_notify_port_destroyed(mach_port_t notify __attribute__((unused)), mach_port_t name)
+{
+	kern_return_t kr;
+	// this function should never be called
+	dispatch_assume_zero(name);
+	kr = mach_port_mod_refs(mach_task_self(), name, MACH_PORT_RIGHT_RECEIVE, -1);
+	DISPATCH_VERIFY_MIG(kr);
+	dispatch_assume_zero(kr);
+	return KERN_SUCCESS;
+}
+
+kern_return_t
+_dispatch_mach_notify_no_senders(mach_port_t notify, mach_port_mscount_t mscnt __attribute__((unused)))
+{
+	// this function should never be called
+	dispatch_assume_zero(notify);
+	return KERN_SUCCESS;
+}
+
+kern_return_t
+_dispatch_mach_notify_send_once(mach_port_t notify __attribute__((unused)))
+{
+	// we only register for dead-name notifications
+	// some code deallocated our send-once right without consuming it
+#if DISPATCH_DEBUG
+	_dispatch_log("Corruption: An app/library deleted a libdispatch dead-name notification");
+#endif
+	return KERN_SUCCESS;
+}
+
+kern_return_t
+_dispatch_mach_notify_dead_name(mach_port_t notify __attribute__((unused)), mach_port_name_t name)
+{
+	dispatch_source_t dsi;
+	dispatch_kevent_t dk;
+	struct kevent kev;
+	kern_return_t kr;
+
+	dk = _dispatch_kevent_find(name, EVFILT_MACHPORT);
+	if (!dk) {
+		goto out;
+	}
+
+	EV_SET(&kev, name, EVFILT_MACHPORT, EV_ADD|EV_ENABLE|EV_DISPATCH|EV_EOF, DISPATCH_MACHPORT_DEAD, 0, dk);
+
+	TAILQ_FOREACH(dsi, &dk->dk_sources, ds_list) {
+		_dispatch_source_merge_kevent(dsi, &kev);
+		// this can never happen again
+		// this must happen after the merge
+		// this may be racy in the future, but we don't provide a 'setter' API for the mask yet
+		dsi->ds_pending_data_mask &= ~DISPATCH_MACHPORT_DEAD;
+	}
+
+	// no more sources have this flag
+	dk->dk_kevent.fflags &= ~DISPATCH_MACHPORT_DEAD;
+
+out:
+	// the act of receiving a dead name notification allocates a dead-name right that must be deallocated
+	kr = mach_port_deallocate(mach_task_self(), name);
+	DISPATCH_VERIFY_MIG(kr);
+	//dispatch_assume_zero(kr);
+
+	return KERN_SUCCESS;
+}
+
+kern_return_t
+_dispatch_wakeup_main_thread(mach_port_t mp __attribute__((unused)))
+{
+	// dummy function just to pop out the main thread out of mach_msg()
+	return 0;
+}
+
+kern_return_t
+_dispatch_consume_send_once_right(mach_port_t mp __attribute__((unused)))
+{
+	// dummy function to consume a send-once right
+	return 0;
+}
+
+mach_msg_return_t
+dispatch_mig_server(dispatch_source_t ds, size_t maxmsgsz, dispatch_mig_callback_t callback)
+{
+	mach_msg_options_t options = MACH_RCV_MSG | MACH_RCV_TIMEOUT
+		| MACH_RCV_TRAILER_ELEMENTS(MACH_RCV_TRAILER_CTX)
+		| MACH_RCV_TRAILER_TYPE(MACH_MSG_TRAILER_FORMAT_0);
+	mach_msg_options_t tmp_options = options;
+	mig_reply_error_t *bufTemp, *bufRequest, *bufReply;
+	mach_msg_return_t kr = 0;
+	unsigned int cnt = 1000;	// do not stall out serial queues
+	int demux_success;
+
+	maxmsgsz += MAX_TRAILER_SIZE;
+
+	// XXX FIXME -- allocate these elsewhere
+	bufRequest = alloca(maxmsgsz);
+	bufReply = alloca(maxmsgsz);
+	bufReply->Head.msgh_size = 0;	// make CLANG happy
+
+	// XXX FIXME -- change this to not starve out the target queue
+	for (;;) {
+		if (DISPATCH_OBJECT_SUSPENDED(ds) || (--cnt == 0)) {
+			options &= ~MACH_RCV_MSG;
+			tmp_options &= ~MACH_RCV_MSG;
+
+			if (!(tmp_options & MACH_SEND_MSG)) {
+				break;
+			}
+		}
+
+		kr = mach_msg(&bufReply->Head, tmp_options, bufReply->Head.msgh_size,
+				(mach_msg_size_t)maxmsgsz, (mach_port_t)ds->ds_ident_hack, 0, 0);
+
+		tmp_options = options;
+
+		if (slowpath(kr)) {
+			switch (kr) {
+			case MACH_SEND_INVALID_DEST:
+			case MACH_SEND_TIMED_OUT:
+				if (bufReply->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX) {
+					mach_msg_destroy(&bufReply->Head);
+				}
+				break;
+			case MACH_RCV_TIMED_OUT:
+			case MACH_RCV_INVALID_NAME:
+				break;
+			default:
+				dispatch_assume_zero(kr);
+				break;
+			}
+			break;
+		}
+
+		if (!(tmp_options & MACH_RCV_MSG)) {
+			break;
+		}
+
+		bufTemp = bufRequest;
+		bufRequest = bufReply;
+		bufReply = bufTemp;
+
+		demux_success = callback(&bufRequest->Head, &bufReply->Head);
+
+		if (!demux_success) {
+			// destroy the request - but not the reply port
+			bufRequest->Head.msgh_remote_port = 0;
+			mach_msg_destroy(&bufRequest->Head);
+		} else if (!(bufReply->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX)) {
+			// if MACH_MSGH_BITS_COMPLEX is _not_ set, then bufReply->RetCode is present
+			if (slowpath(bufReply->RetCode)) {
+				if (bufReply->RetCode == MIG_NO_REPLY) {
+					continue;
+				}
+
+				// destroy the request - but not the reply port
+				bufRequest->Head.msgh_remote_port = 0;
+				mach_msg_destroy(&bufRequest->Head);
+			}
+		}
+
+		if (bufReply->Head.msgh_remote_port) {
+			tmp_options |= MACH_SEND_MSG;
+			if (MACH_MSGH_BITS_REMOTE(bufReply->Head.msgh_bits) != MACH_MSG_TYPE_MOVE_SEND_ONCE) {
+				tmp_options |= MACH_SEND_TIMEOUT;
+			}
+		}
+	}
+
+	return kr;
+}

Added: trunk/src/source.h
===================================================================
--- trunk/src/source.h	                        (rev 0)
+++ trunk/src/source.h	2009-08-30 01:07:28 UTC (rev 2)
@@ -0,0 +1,583 @@
+/*
+ * Copyright (c) 2008-2009 Apple Inc. All rights reserved.
+ *
+ * @APPLE_APACHE_LICENSE_HEADER_START@
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * 
+ * @APPLE_APACHE_LICENSE_HEADER_END@
+ */
+
+#ifndef __DISPATCH_SOURCE__
+#define __DISPATCH_SOURCE__
+
+#ifndef __DISPATCH_INDIRECT__
+#error "Please #include <dispatch/dispatch.h> instead of this file directly."
+#include <dispatch/base.h> // for HeaderDoc
+#endif
+
+#include <mach/port.h>
+#include <mach/message.h>
+#include <sys/signal.h>
+
+/*!
+ * @header
+ * The dispatch framework provides a suite of interfaces for monitoring low-
+ * level system objects (file descriptors, Mach ports, signals, VFS nodes, etc.)
+ * for activity and automatically submitting event handler blocks to dispatch
+ * queues when such activity occurs.
+ *
+ * This suite of interfaces is known as the Dispatch Source API.
+ */
+
+/*!
+ * @typedef dispatch_source_t
+ *
+ * @abstract
+ * Dispatch sources are used to automatically submit event handler blocks to
+ * dispatch queues in response to external events.
+ */
+DISPATCH_DECL(dispatch_source);
+
+/*!
+ * @typedef dispatch_source_type_t
+ *
+ * @abstract
+ * Constants of this type represent the class of low-level system object that
+ * is being monitored by the dispatch source. Constants of this type are
+ * passed as a parameter to dispatch_source_create() and determine how the
+ * handle argument is interpreted (i.e. as a file descriptor, mach port,
+ * signal number, process identifer, etc.), and how the mask arugment is
+ * interpreted.
+ */
+typedef const struct dispatch_source_type_s *dispatch_source_type_t;
+
+/*!
+ * @const DISPATCH_SOURCE_TYPE_DATA_ADD
+ * @discussion A dispatch source that coalesces data obtained via calls to
+ * dispatch_source_merge_data(). An ADD is used to coalesce the data.
+ * The handle is unused (pass zero for now).
+ * The mask is unused (pass zero for now).
+ */
+#define DISPATCH_SOURCE_TYPE_DATA_ADD (&_dispatch_source_type_data_add)
+__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA)
+extern const struct dispatch_source_type_s _dispatch_source_type_data_add;
+
+/*!
+ * @const DISPATCH_SOURCE_TYPE_DATA_OR
+ * @discussion A dispatch source that coalesces data obtained via calls to
+ * dispatch_source_merge_data(). A logical OR is used to coalesce the data.
+ * The handle is unused (pass zero for now).
+ * The mask is used to perform a logical AND with the value passed to
+ * dispatch_source_merge_data().
+ */
+#define DISPATCH_SOURCE_TYPE_DATA_OR (&_dispatch_source_type_data_or)
+__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA)
+extern const struct dispatch_source_type_s _dispatch_source_type_data_or;
+
+/*!
+ * @const DISPATCH_SOURCE_TYPE_MACH_SEND
+ * @discussion A dispatch source that monitors a Mach port for dead name
+ * notifications (send right no longer has any corresponding receive right).
+ * The handle is a Mach port with a send or send-once right (mach_port_t).
+ * The mask is a mask of desired events from dispatch_source_mach_send_flags_t.
+ */
+#define DISPATCH_SOURCE_TYPE_MACH_SEND (&_dispatch_source_type_mach_send)
+__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA)
+extern const struct dispatch_source_type_s _dispatch_source_type_mach_send;
+
+/*!
+ * @const DISPATCH_SOURCE_TYPE_MACH_RECV
+ * @discussion A dispatch source that monitors a Mach port for pending messages.
+ * The handle is a Mach port with a receive right (mach_port_t).
+ * The mask is unused (pass zero for now).
+ */
+#define DISPATCH_SOURCE_TYPE_MACH_RECV (&_dispatch_source_type_mach_recv)
+__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA)
+extern const struct dispatch_source_type_s _dispatch_source_type_mach_recv;
+
+/*!
+ * @const DISPATCH_SOURCE_TYPE_PROC
+ * @discussion A dispatch source that monitors an external process for events
+ * defined by dispatch_source_proc_flags_t.
+ * The handle is a process identifier (pid_t).
+ * The mask is a mask of desired events from dispatch_source_proc_flags_t.
+ */
+#define DISPATCH_SOURCE_TYPE_PROC (&_dispatch_source_type_proc)
+__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA)
+extern const struct dispatch_source_type_s _dispatch_source_type_proc;
+
+/*!
+ * @const DISPATCH_SOURCE_TYPE_READ
+ * @discussion A dispatch source that monitors a file descriptor for pending
+ * bytes available to be read.
+ * The handle is a file descriptor (int).
+ * The mask is unused (pass zero for now).
+ */
+#define DISPATCH_SOURCE_TYPE_READ (&_dispatch_source_type_read)
+__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA)
+extern const struct dispatch_source_type_s _dispatch_source_type_read;
+
+/*!
+ * @const DISPATCH_SOURCE_TYPE_SIGNAL
+ * @discussion A dispatch source that monitors the current process for signals.
+ * The handle is a signal number (int).
+ * The mask is unused (pass zero for now).
+ */
+#define DISPATCH_SOURCE_TYPE_SIGNAL (&_dispatch_source_type_signal)
+__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA)
+extern const struct dispatch_source_type_s _dispatch_source_type_signal;
+
+/*!
+ * @const DISPATCH_SOURCE_TYPE_TIMER
+ * @discussion A dispatch source that submits the event handler block based
+ * on a timer.
+ * The handle is unused (pass zero for now).
+ * The mask is unused (pass zero for now).
+ */
+#define DISPATCH_SOURCE_TYPE_TIMER (&_dispatch_source_type_timer)
+__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA)
+extern const struct dispatch_source_type_s _dispatch_source_type_timer;
+
+/*!
+ * @const DISPATCH_SOURCE_TYPE_VNODE
+ * @discussion A dispatch source that monitors a file descriptor for events
+ * defined by dispatch_source_vnode_flags_t.
+ * The handle is a file descriptor (int).
+ * The mask is a mask of desired events from dispatch_source_vnode_flags_t.
+ */
+#define DISPATCH_SOURCE_TYPE_VNODE (&_dispatch_source_type_vnode)
+__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA)
+extern const struct dispatch_source_type_s _dispatch_source_type_vnode;
+
+/*!
+ * @const DISPATCH_SOURCE_TYPE_WRITE
+ * @discussion A dispatch source that monitors a file descriptor for available
+ * buffer space to write bytes.
+ * The handle is a file descriptor (int).
+ * The mask is unused (pass zero for now).
+ */
+#define DISPATCH_SOURCE_TYPE_WRITE (&_dispatch_source_type_write)
+__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA)
+extern const struct dispatch_source_type_s _dispatch_source_type_write;
+
+/*!
+ * @enum dispatch_source_mach_send_flags_t
+ *
+ * @constant DISPATCH_MACH_SEND_DEAD
+ * The receive right corresponding to the given send right was destroyed.
+ */
+enum {
+	DISPATCH_MACH_SEND_DEAD = 0x1,
+};
+
+/*!
+ * @enum dispatch_source_proc_flags_t
+ *
+ * @constant DISPATCH_PROC_EXIT
+ * The process has exited (perhaps cleanly, perhaps not).
+ *
+ * @constant DISPATCH_PROC_FORK
+ * The process has created one or more child processes.
+ *
+ * @constant DISPATCH_PROC_EXEC
+ * The process has become another executable image via
+ * exec*() or posix_spawn*().
+ *
+ * @constant DISPATCH_PROC_SIGNAL
+ * A Unix signal was delivered to the process.
+ */
+enum {
+	DISPATCH_PROC_EXIT = 0x80000000,
+	DISPATCH_PROC_FORK = 0x40000000,
+	DISPATCH_PROC_EXEC = 0x20000000,
+	DISPATCH_PROC_SIGNAL = 0x08000000,
+};
+
+/*!
+ * @enum dispatch_source_vnode_flags_t
+ *
+ * @constant DISPATCH_VNODE_DELETE
+ * The filesystem object was deleted from the namespace.
+ *
+ * @constant DISPATCH_VNODE_WRITE
+ * The filesystem object data changed.
+ *
+ * @constant DISPATCH_VNODE_EXTEND
+ * The filesystem object changed in size.
+ *
+ * @constant DISPATCH_VNODE_ATTRIB
+ * The filesystem object metadata changed.
+ *
+ * @constant DISPATCH_VNODE_LINK
+ * The filesystem object link count changed.
+ *
+ * @constant DISPATCH_VNODE_RENAME
+ * The filesystem object was renamed in the namespace.
+ *
+ * @constant DISPATCH_VNODE_REVOKE
+ * The filesystem object was revoked.
+ */
+enum {
+	DISPATCH_VNODE_DELETE = 0x1,
+	DISPATCH_VNODE_WRITE = 0x2,
+	DISPATCH_VNODE_EXTEND = 0x4,
+	DISPATCH_VNODE_ATTRIB = 0x8,
+	DISPATCH_VNODE_LINK	= 0x10,
+	DISPATCH_VNODE_RENAME = 0x20,
+	DISPATCH_VNODE_REVOKE = 0x40,
+};
+
+__BEGIN_DECLS
+
+/*!
+ * @function dispatch_source_create
+ *
+ * @abstract
+ * Creates a new dispatch source to monitor low-level system objects and auto-
+ * matically submit a handler block to a dispatch queue in response to events.
+ *
+ * @discussion
+ * Dispatch sources are not reentrant. Any events received while the dispatch
+ * source is suspended or while the event handler block is currently executing
+ * will be coalesced and delivered after the dispatch source is resumed or the
+ * event handler block has returned.
+ *
+ * Dispatch sources are created in a suspended state. After creating the
+ * source and setting any desired attributes (i.e. the handler, context, etc.),
+ * a call must be made to dispatch_resume() in order to begin event delivery.
+ *
+ * @param type
+ * Declares the type of the dispatch source. Must be one of the defined
+ * dispatch_source_type_t constants.
+ * @param handle
+ * The underlying system handle to monitor. The interpretation of this argument
+ * is determined by the constant provided in the type parameter.
+ * @param mask
+ * A mask of flags specifying which events are desired. The interpretation of
+ * this argument is determined by the constant provided in the type parameter.
+ * @param queue
+ * The dispatch queue to which the event handler block will be submited.
+ */
+__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA)
+DISPATCH_MALLOC DISPATCH_NOTHROW
+dispatch_source_t
+dispatch_source_create(dispatch_source_type_t type,
+	uintptr_t handle,
+	unsigned long mask,
+	dispatch_queue_t queue);
+
+/*!
+ * @function dispatch_source_set_event_handler
+ *
+ * @abstract
+ * Sets the event handler block for the given dispatch source.
+ *
+ * @param source
+ * The dispatch source to modify.
+ * The result of passing NULL in this parameter is undefined.
+ * 
+ * @param handler
+ * The event handler block to submit to the source's target queue.
+ */
+#ifdef __BLOCKS__
+__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA)
+DISPATCH_NONNULL1 DISPATCH_NOTHROW
+void
+dispatch_source_set_event_handler(dispatch_source_t source,
+	dispatch_block_t handler);
+#endif /* __BLOCKS__ */
+
+/*!
+ * @function dispatch_source_set_event_handler_f
+ *
+ * @abstract
+ * Sets the event handler function for the given dispatch source.
+ *
+ * @param source
+ * The dispatch source to modify.
+ * The result of passing NULL in this parameter is undefined.
+ *
+ * @param handler
+ * The event handler function to submit to the source's target queue.
+ * The context parameter passed to the event handler function is the current
+ * context of the dispatch source at the time the handler call is made.
+ * The result of passing NULL in this parameter is undefined.
+ */
+__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA)
+DISPATCH_NONNULL1 DISPATCH_NOTHROW
+void
+dispatch_source_set_event_handler_f(dispatch_source_t source,
+	dispatch_function_t handler);
+
+/*!
+ * @function dispatch_source_set_cancel_handler
+ *
+ * @abstract
+ * Sets the cancellation handler block for the given dispatch source.
+ *
+ * @discussion
+ * The cancellation handler (if specified) will be submitted to the source's
+ * target queue in response to a call to dispatch_source_cancel() once the
+ * system has released all references to the source's underlying handle and
+ * the source's event handler block has returned.
+ *
+ * IMPORTANT:
+ * A cancellation handler is required for file descriptor and mach port based
+ * sources in order to safely close the descriptor or destroy the port. Closing
+ * the descriptor or port before the cancellation handler may result in a race
+ * condition. If a new descriptor is allocated with the same value as the
+ * recently closed descriptor while the source's event handler is still running,
+ * the event handler may read/write data to the wrong descriptor.
+ *
+ * @param source
+ * The dispatch source to modify.
+ * The result of passing NULL in this parameter is undefined.
+ * 
+ * @param handler
+ * The cancellation handler block to submit to the source's target queue.
+ */
+#ifdef __BLOCKS__
+__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA)
+DISPATCH_NONNULL1 DISPATCH_NOTHROW
+void
+dispatch_source_set_cancel_handler(dispatch_source_t source,
+	dispatch_block_t cancel_handler);
+#endif /* __BLOCKS__ */
+
+/*!
+ * @function dispatch_source_set_cancel_handler_f
+ *
+ * @abstract
+ * Sets the cancellation handler function for the given dispatch source.
+ *
+ * @discussion
+ * See dispatch_source_set_cancel_handler() for more details.
+ *
+ * @param source
+ * The dispatch source to modify.
+ * The result of passing NULL in this parameter is undefined.
+ *
+ * @param handler
+ * The cancellation handler function to submit to the source's target queue.
+ * The context parameter passed to the event handler function is the current
+ * context of the dispatch source at the time the handler call is made.
+ */
+__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA)
+DISPATCH_NONNULL1 DISPATCH_NOTHROW
+void
+dispatch_source_set_cancel_handler_f(dispatch_source_t source,
+	dispatch_function_t cancel_handler);
+
+/*!
+ * @function dispatch_source_cancel
+ *
+ * @abstract
+ * Asynchronously cancel the dispatch source, preventing any further invocation
+ * of its event handler block.
+ *
+ * @discussion
+ * Cancellation prevents any further invocation of the event handler block for
+ * the specified dispatch source, but does not interrupt an event handler
+ * block that is already in progress.
+ *
+ * The cancellation handler is submitted to the source's target queue once the
+ * the source's event handler has finished, indicating it is now safe to close
+ * the source's handle (i.e. file descriptor or mach port).
+ *
+ * See dispatch_source_set_cancel_handler() for more information.
+ *
+ * @param source
+ * The dispatch source to be canceled.
+ * The result of passing NULL in this parameter is undefined.
+ */
+__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA)
+DISPATCH_NONNULL_ALL DISPATCH_NOTHROW
+void
+dispatch_source_cancel(dispatch_source_t source);
+
+/*!
+ * @function dispatch_source_testcancel
+ *
+ * @abstract
+ * Tests whether the given dispatch source has been canceled.
+ *
+ * @param source
+ * The dispatch source to be tested.
+ * The result of passing NULL in this parameter is undefined.
+ *
+ * @result
+ * Non-zero if canceled and zero if not canceled.
+ */
+__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA)
+DISPATCH_NONNULL_ALL DISPATCH_NOTHROW
+long
+dispatch_source_testcancel(dispatch_source_t source);
+
+/*!
+ * @function dispatch_source_get_handle
+ *
+ * @abstract
+ * Returns the underlying system handle associated with this dispatch source.
+ *
+ * @param source
+ * The result of passing NULL in this parameter is undefined.
+ *
+ * @result
+ * The return value should be interpreted according to the type of the dispatch
+ * source, and may be one of the following handles:
+ *
+ *  DISPATCH_SOURCE_TYPE_DATA_ADD:        n/a
+ *  DISPATCH_SOURCE_TYPE_DATA_OR:         n/a
+ *  DISPATCH_SOURCE_TYPE_MACH_SEND:       mach port (mach_port_t)
+ *  DISPATCH_SOURCE_TYPE_MACH_RECV:       mach port (mach_port_t)
+ *  DISPATCH_SOURCE_TYPE_PROC:            process identifier (pid_t)
+ *  DISPATCH_SOURCE_TYPE_READ:            file descriptor (int)
+ *  DISPATCH_SOURCE_TYPE_SIGNAL:          signal number (int) 
+ *  DISPATCH_SOURCE_TYPE_TIMER:           n/a
+ *  DISPATCH_SOURCE_TYPE_VNODE:           file descriptor (int)
+ *  DISPATCH_SOURCE_TYPE_WRITE:           file descriptor (int)
+ */
+__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA)
+DISPATCH_NONNULL_ALL DISPATCH_WARN_RESULT DISPATCH_PURE DISPATCH_NOTHROW
+uintptr_t
+dispatch_source_get_handle(dispatch_source_t source);
+
+/*!
+ * @function dispatch_source_get_mask
+ *
+ * @abstract
+ * Returns the mask of events monitored by the dispatch source.
+ *
+ * @param source
+ * The result of passing NULL in this parameter is undefined.
+ *
+ * @result
+ * The return value should be interpreted according to the type of the dispatch
+ * source, and may be one of the following flag sets:
+ *
+ *  DISPATCH_SOURCE_TYPE_DATA_ADD:        n/a
+ *  DISPATCH_SOURCE_TYPE_DATA_OR:         n/a
+ *  DISPATCH_SOURCE_TYPE_MACH_SEND:       dispatch_source_mach_send_flags_t
+ *  DISPATCH_SOURCE_TYPE_MACH_RECV:       n/a
+ *  DISPATCH_SOURCE_TYPE_PROC:            dispatch_source_proc_flags_t
+ *  DISPATCH_SOURCE_TYPE_READ:            n/a
+ *  DISPATCH_SOURCE_TYPE_SIGNAL:          n/a
+ *  DISPATCH_SOURCE_TYPE_TIMER:           n/a
+ *  DISPATCH_SOURCE_TYPE_VNODE:           dispatch_source_vnode_flags_t
+ *  DISPATCH_SOURCE_TYPE_WRITE:           n/a
+ */
+__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA)
+DISPATCH_NONNULL_ALL DISPATCH_WARN_RESULT DISPATCH_PURE DISPATCH_NOTHROW
+unsigned long
+dispatch_source_get_mask(dispatch_source_t source);
+
+/*!
+ * @function dispatch_source_get_data
+ *
+ * @abstract
+ * Returns pending data for the dispatch source.
+ *
+ * @discussion
+ * This function is intended to be called from within the event handler block.
+ * The result of calling this function outside of the event handler callback is
+ * undefined.
+ *
+ * @param source
+ * The result of passing NULL in this parameter is undefined.
+ *
+ * @result
+ * The return value should be interpreted according to the type of the dispatch
+ * source, and may be one of the following:
+ *
+ *  DISPATCH_SOURCE_TYPE_DATA_ADD:        application defined data
+ *  DISPATCH_SOURCE_TYPE_DATA_OR:         application defined data
+ *  DISPATCH_SOURCE_TYPE_MACH_SEND:       dispatch_source_mach_send_flags_t
+ *  DISPATCH_SOURCE_TYPE_MACH_RECV:       n/a
+ *  DISPATCH_SOURCE_TYPE_PROC:            dispatch_source_proc_flags_t
+ *  DISPATCH_SOURCE_TYPE_READ:            estimated bytes available to read
+ *  DISPATCH_SOURCE_TYPE_SIGNAL:          number of signals delivered since
+ *                                            the last handler invocation
+ *  DISPATCH_SOURCE_TYPE_TIMER:           number of times the timer has fired
+ *                                            since the last handler invocation
+ *  DISPATCH_SOURCE_TYPE_VNODE:           dispatch_source_vnode_flags_t
+ *  DISPATCH_SOURCE_TYPE_WRITE:           estimated buffer space available
+ */
+__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA)
+DISPATCH_NONNULL_ALL DISPATCH_WARN_RESULT DISPATCH_PURE DISPATCH_NOTHROW
+unsigned long
+dispatch_source_get_data(dispatch_source_t source);
+
+/*!
+ * @function dispatch_source_merge_data
+ *
+ * @abstract
+ * Merges data into a dispatch source of type DISPATCH_SOURCE_TYPE_DATA_ADD or
+ * DISPATCH_SOURCE_TYPE_DATA_OR and submits its event handler block to its
+ * target queue.
+ *
+ * @param source
+ * The result of passing NULL in this parameter is undefined.
+ *
+ * @param value
+ * The value to coalesce with the pending data using a logical OR or an ADD
+ * as specified by the dispatch source type. A value of zero has no effect
+ * and will not result in the submission of the event handler block.
+ */
+__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA)
+DISPATCH_NONNULL_ALL DISPATCH_NOTHROW
+void
+dispatch_source_merge_data(dispatch_source_t source, unsigned long value);
+
+/*!
+ * @function dispatch_source_set_timer
+ *
+ * @abstract
+ * Sets a start time, interval, and leeway value for a timer source.
+ *
+ * @discussion
+ * Calling this function has no effect if the timer source has already been
+ * canceled.
+ * 
+ * The start time argument also determines which clock will be used for the
+ * timer. If the start time is DISPATCH_TIME_NOW or created with
+ * dispatch_time() then the timer is based on mach_absolute_time(). Otherwise,
+ * if the start time of the timer is created with dispatch_walltime() then the
+ * timer is based on gettimeofday(3).
+ * 
+ * @param start
+ * The start time of the timer. See dispatch_time() and dispatch_walltime()
+ * for more information.
+ *
+ * @param interval
+ * The nanosecond interval for the timer.
+ *
+ * @param leeway
+ * A hint given to the system by the application for the amount of leeway, in
+ * nanoseconds, that the system may defer the timer in order to align with other
+ * system activity for improved system performance or power consumption. (For
+ * example, an application might perform a periodic task every 5 minutes, with
+ * a leeway of up to 30 seconds.)  Note that some latency is to be expected for
+ * all timers even when a leeway value of zero is specified.
+ */
+__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA)
+DISPATCH_NONNULL_ALL DISPATCH_NOTHROW
+void
+dispatch_source_set_timer(dispatch_source_t source,
+	dispatch_time_t start,
+	uint64_t interval,
+	uint64_t leeway);
+
+__END_DECLS
+
+#endif

Added: trunk/src/source_internal.h
===================================================================
--- trunk/src/source_internal.h	                        (rev 0)
+++ trunk/src/source_internal.h	2009-08-30 01:07:28 UTC (rev 2)
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2008-2009 Apple Inc. All rights reserved.
+ *
+ * @APPLE_APACHE_LICENSE_HEADER_START@
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * 
+ * @APPLE_APACHE_LICENSE_HEADER_END@
+ */
+
+/*
+ * IMPORTANT: This header file describes INTERNAL interfaces to libdispatch
+ * which are subject to change in future releases of Mac OS X. Any applications
+ * relying on these interfaces WILL break.
+ */
+
+#ifndef __DISPATCH_SOURCE_INTERNAL__
+#define __DISPATCH_SOURCE_INTERNAL__
+
+#ifndef __DISPATCH_INDIRECT__
+#error "Please #include <dispatch/dispatch.h> instead of this file directly."
+#include <dispatch/base.h> // for HeaderDoc
+#endif
+
+struct dispatch_source_vtable_s {
+	DISPATCH_VTABLE_HEADER(dispatch_source_s);
+};
+
+extern const struct dispatch_source_vtable_s _dispatch_source_kevent_vtable;
+
+struct dispatch_kevent_s {
+	TAILQ_ENTRY(dispatch_kevent_s) dk_list;
+	TAILQ_HEAD(, dispatch_source_s) dk_sources;
+	struct kevent dk_kevent;
+};
+
+typedef struct dispatch_kevent_s *dispatch_kevent_t;
+
+struct dispatch_timer_source_s {
+	uint64_t target;
+	uint64_t start;
+	uint64_t interval;
+	uint64_t leeway;
+	uint64_t flags; // dispatch_timer_flags_t
+};
+
+#define DSF_CANCELED 1u // cancellation has been requested
+
+struct dispatch_source_s {
+	DISPATCH_STRUCT_HEADER(dispatch_source_s, dispatch_source_vtable_s);
+	DISPATCH_QUEUE_HEADER;
+	// Instruments always copies DISPATCH_QUEUE_MIN_LABEL_SIZE, which is 64,
+	// so the remainder of the structure must be big enough
+	union {
+		char _ds_pad[DISPATCH_QUEUE_MIN_LABEL_SIZE];
+		struct {
+			char dq_label[8];
+			dispatch_kevent_t ds_dkev;
+			
+			dispatch_source_handler_function_t ds_handler_func;
+			void *ds_handler_ctxt;
+			
+			void *ds_cancel_handler;
+			
+			unsigned int ds_is_level:1,
+			ds_is_adder:1,
+			ds_is_installed:1,
+			ds_needs_rearm:1,
+			ds_is_armed:1,
+			ds_is_legacy:1,
+			ds_cancel_is_block:1,
+			ds_handler_is_block:1;
+
+			unsigned int ds_atomic_flags;
+
+			unsigned long ds_data;
+			unsigned long ds_pending_data;
+			unsigned long ds_pending_data_mask;
+			
+			TAILQ_ENTRY(dispatch_source_s) ds_list;
+			
+			unsigned long ds_ident_hack;
+			
+			struct dispatch_timer_source_s ds_timer;
+		};
+	};
+};
+
+
+void _dispatch_source_legacy_xref_release(dispatch_source_t ds);
+
+#endif /* __DISPATCH_SOURCE_INTERNAL__ */

Added: trunk/src/source_private.h
===================================================================
--- trunk/src/source_private.h	                        (rev 0)
+++ trunk/src/source_private.h	2009-08-30 01:07:28 UTC (rev 2)
@@ -0,0 +1,129 @@
+/*
+ * Copyright (c) 2008-2009 Apple Inc. All rights reserved.
+ *
+ * @APPLE_APACHE_LICENSE_HEADER_START@
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * 
+ * @APPLE_APACHE_LICENSE_HEADER_END@
+ */
+
+/*
+ * IMPORTANT: This header file describes INTERNAL interfaces to libdispatch
+ * which are subject to change in future releases of Mac OS X. Any applications
+ * relying on these interfaces WILL break.
+ */
+
+#ifndef __DISPATCH_SOURCE_PRIVATE__
+#define __DISPATCH_SOURCE_PRIVATE__
+
+#ifndef __DISPATCH_INDIRECT__
+#error "Please #include <dispatch/dispatch.h> instead of this file directly."
+#include <dispatch/base.h> // for HeaderDoc
+#endif
+
+/*!
+ * @const DISPATCH_SOURCE_TYPE_VFS
+ * @discussion Apple-internal dispatch source that monitors for vfs events
+ * defined by dispatch_vfs_flags_t.
+ * The handle is a process identifier (pid_t).
+ */
+#define DISPATCH_SOURCE_TYPE_VFS (&_dispatch_source_type_vfs)
+__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA)
+extern const struct dispatch_source_type_s _dispatch_source_type_vfs;
+
+/*!
+ * @enum dispatch_source_vfs_flags_t
+ *
+ * @constant DISPATCH_VFS_NOTRESP
+ * Server down.
+ *
+ * @constant DISPATCH_VFS_NEEDAUTH
+ * Server bad auth.
+ *
+ * @constant DISPATCH_VFS_LOWDISK
+ * We're low on space.
+ *
+ * @constant DISPATCH_VFS_MOUNT
+ * New filesystem arrived.
+ *
+ * @constant DISPATCH_VFS_UNMOUNT
+ * Filesystem has left.
+ *
+ * @constant DISPATCH_VFS_DEAD
+ * Filesystem is dead, needs force unmount.
+ *
+ * @constant DISPATCH_VFS_ASSIST
+ * Filesystem needs assistance from external program.
+ *
+ * @constant DISPATCH_VFS_NOTRESPLOCK
+ * Server lockd down.
+ *
+ * @constant DISPATCH_VFS_UPDATE
+ * Filesystem information has changed.
+ *
+ * @constant DISPATCH_VFS_VERYLOWDISK
+ * File system has *very* little disk space left.
+ */
+enum {
+	DISPATCH_VFS_NOTRESP = 0x0001,
+	DISPATCH_VFS_NEEDAUTH = 0x0002,
+	DISPATCH_VFS_LOWDISK = 0x0004,
+	DISPATCH_VFS_MOUNT = 0x0008,
+	DISPATCH_VFS_UNMOUNT = 0x0010,
+	DISPATCH_VFS_DEAD = 0x0020,
+	DISPATCH_VFS_ASSIST = 0x0040,
+	DISPATCH_VFS_NOTRESPLOCK = 0x0080,
+	DISPATCH_VFS_UPDATE = 0x0100,
+	DISPATCH_VFS_VERYLOWDISK = 0x0200,
+};
+
+/*!
+ * @enum dispatch_source_mach_send_flags_t
+ *
+ * @constant DISPATCH_MACH_SEND_DELETED
+ * The receive right corresponding to the given send right was destroyed.
+ */
+enum {
+	DISPATCH_MACH_SEND_DELETED = 0x2,
+};
+
+/*!
+ * @enum dispatch_source_proc_flags_t
+ *
+ * @constant DISPATCH_PROC_REAP
+ * The process has been reaped by the parent process via
+ * wait*().
+ */
+enum {
+	DISPATCH_PROC_REAP = 0x10000000,
+};
+
+__BEGIN_DECLS
+
+/*!
+ * @typedef dispatch_mig_callback_t
+ *
+ * @abstract
+ * The signature of a function that handles Mach message delivery and response.
+ */
+typedef boolean_t (*dispatch_mig_callback_t)(mach_msg_header_t *message, mach_msg_header_t *reply);
+
+__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA)
+DISPATCH_NONNULL_ALL DISPATCH_NOTHROW
+mach_msg_return_t
+dispatch_mig_server(dispatch_source_t ds, size_t maxmsgsz, dispatch_mig_callback_t callback);
+
+__END_DECLS
+
+#endif

Added: trunk/src/time.c
===================================================================
--- trunk/src/time.c	                        (rev 0)
+++ trunk/src/time.c	2009-08-30 01:07:28 UTC (rev 2)
@@ -0,0 +1,183 @@
+/*
+ * Copyright (c) 2008-2009 Apple Inc. All rights reserved.
+ *
+ * @APPLE_APACHE_LICENSE_HEADER_START@
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * 
+ * @APPLE_APACHE_LICENSE_HEADER_END@
+ */
+
+#include "internal.h"
+
+uint64_t 
+_dispatch_get_nanoseconds(void)
+{
+	struct timeval now;
+	int r = gettimeofday(&now, NULL);
+	dispatch_assert_zero(r);
+	dispatch_assert(sizeof(NSEC_PER_SEC) == 8);
+	dispatch_assert(sizeof(NSEC_PER_USEC) == 8);
+	return now.tv_sec * NSEC_PER_SEC + now.tv_usec * NSEC_PER_USEC;
+}
+
+#if defined(__i386__) || defined(__x86_64__)
+// x86 currently implements mach time in nanoseconds; this is NOT likely to change
+#define _dispatch_time_mach2nano(x) (x)
+#define _dispatch_time_nano2mach(x) (x)
+#else
+static struct _dispatch_host_time_data_s {
+	mach_timebase_info_data_t tbi;
+	uint64_t safe_numer_math;
+	dispatch_once_t pred;
+} _dispatch_host_time_data;
+
+static void
+_dispatch_get_host_time_init(void *context __attribute__((unused)))
+{
+	dispatch_assume_zero(mach_timebase_info(&_dispatch_host_time_data.tbi));
+	_dispatch_host_time_data.safe_numer_math = DISPATCH_TIME_FOREVER / _dispatch_host_time_data.tbi.numer;
+}
+
+static uint64_t
+_dispatch_time_mach2nano(uint64_t nsec)
+{
+	struct _dispatch_host_time_data_s *const data = &_dispatch_host_time_data;
+	uint64_t small_tmp = nsec;
+#ifdef __LP64__
+	__uint128_t big_tmp = nsec;
+#else
+	long double big_tmp = nsec;
+#endif
+
+	dispatch_once_f(&data->pred, NULL, _dispatch_get_host_time_init);
+
+	if (slowpath(data->tbi.numer != data->tbi.denom)) {
+		if (nsec < data->safe_numer_math) {
+			small_tmp *= data->tbi.numer;
+			small_tmp /= data->tbi.denom;
+		} else {
+			big_tmp *= data->tbi.numer;
+			big_tmp /= data->tbi.denom;
+			small_tmp = big_tmp;
+		}
+	}
+	return small_tmp;
+}
+
+static int64_t
+_dispatch_time_nano2mach(int64_t nsec)
+{
+	struct _dispatch_host_time_data_s *const data = &_dispatch_host_time_data;
+#ifdef __LP64__
+	__int128_t big_tmp = nsec;
+#else
+	long double big_tmp = nsec;
+#endif
+
+	dispatch_once_f(&data->pred, NULL, _dispatch_get_host_time_init);
+
+	if (fastpath(data->tbi.numer == data->tbi.denom)) {
+		return nsec;
+	}
+
+	// Multiply by the inverse to convert nsec to Mach absolute time
+	big_tmp *= data->tbi.denom;
+	big_tmp /= data->tbi.numer;
+
+	if (big_tmp > INT64_MAX) {
+		return INT64_MAX;
+	}
+	if (big_tmp < INT64_MIN) {
+		return INT64_MIN;
+	}
+	return big_tmp;
+}
+#endif
+
+dispatch_time_t
+dispatch_time(dispatch_time_t inval, int64_t delta)
+{
+	if (inval == DISPATCH_TIME_FOREVER) {
+		return DISPATCH_TIME_FOREVER;
+	}
+	if ((int64_t)inval < 0) {
+		// wall clock
+		if (delta >= 0) {
+			if ((int64_t)(inval -= delta) >= 0) {
+				return DISPATCH_TIME_FOREVER;      // overflow
+			}
+			return inval;
+		}
+		if ((int64_t)(inval -= delta) >= -1) {
+			// -1 is special == DISPATCH_TIME_FOREVER == forever
+			return -2;      // underflow
+		}
+		return inval;
+	}
+	// mach clock
+	delta = _dispatch_time_nano2mach(delta);
+   	if (inval == 0) {
+		inval = mach_absolute_time();
+	}
+	if (delta >= 0) {
+		if ((int64_t)(inval += delta) <= 0) {
+			return DISPATCH_TIME_FOREVER;      // overflow
+		}
+		return inval;
+	}
+	if ((int64_t)(inval += delta) < 1) {
+		return 1;       // underflow
+	}
+	return inval;
+}
+
+dispatch_time_t
+dispatch_walltime(const struct timespec *inval, int64_t delta)
+{
+	int64_t nsec;
+	
+	if (inval) {
+		nsec = inval->tv_sec * 1000000000ull + inval->tv_nsec;
+	} else {
+		nsec = _dispatch_get_nanoseconds();
+	}
+
+	nsec += delta;
+	if (nsec <= 1) {
+		// -1 is special == DISPATCH_TIME_FOREVER == forever
+		return delta >= 0 ? DISPATCH_TIME_FOREVER : (uint64_t)-2ll;
+	}
+
+	return -nsec;
+}
+
+uint64_t
+_dispatch_timeout(dispatch_time_t when)
+{
+	uint64_t now;
+
+	if (when == DISPATCH_TIME_FOREVER) {
+		return DISPATCH_TIME_FOREVER;
+	}
+	if (when == 0) {
+		return 0;
+	}
+	if ((int64_t)when < 0) {
+		when = -(int64_t)when;
+		now = _dispatch_get_nanoseconds();
+		return now >= when ? 0 : when - now;
+	}
+	now = mach_absolute_time();
+	return now >= when ? 0 : _dispatch_time_mach2nano(when - now);
+}

Added: trunk/src/time.h
===================================================================
--- trunk/src/time.h	                        (rev 0)
+++ trunk/src/time.h	2009-08-30 01:07:28 UTC (rev 2)
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2008-2009 Apple Inc. All rights reserved.
+ *
+ * @APPLE_APACHE_LICENSE_HEADER_START@
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * 
+ * @APPLE_APACHE_LICENSE_HEADER_END@
+ */
+
+#ifndef __DISPATCH_TIME__
+#define __DISPATCH_TIME__
+
+#ifndef __DISPATCH_INDIRECT__
+#error "Please #include <dispatch/dispatch.h> instead of this file directly."
+#include <dispatch/base.h> // for HeaderDoc
+#endif
+
+#include <stdint.h>
+
+__BEGIN_DECLS
+
+struct timespec;
+
+// 6368156
+#ifdef NSEC_PER_SEC
+#undef NSEC_PER_SEC
+#endif
+#ifdef USEC_PER_SEC
+#undef USEC_PER_SEC
+#endif
+#ifdef NSEC_PER_USEC
+#undef NSEC_PER_USEC
+#endif
+#define NSEC_PER_SEC 1000000000ull
+#define USEC_PER_SEC 1000000ull
+#define NSEC_PER_USEC 1000ull
+
+/*!
+ * @typedef dispatch_time_t
+ *
+ * @abstract
+ * An somewhat abstract representation of time; where zero means "now" and
+ * DISPATCH_TIME_FOREVER means "infinity" and every value in between is an
+ * opaque encoding.
+ */
+typedef uint64_t dispatch_time_t;
+
+#define DISPATCH_TIME_NOW 0
+#define DISPATCH_TIME_FOREVER (~0ull)
+
+/*!
+ * @function dispatch_time
+ *
+ * @abstract
+ * Create dispatch_time_t relative to the default clock or modify an existing
+ * dispatch_time_t.
+ *
+ * @discussion
+ * On Mac OS X the default clock is based on mach_absolute_time().
+ *
+ * @param when
+ * An optional dispatch_time_t to add nanoseconds to. If zero is passed, then
+ * dispatch_time() will use the result of mach_absolute_time().
+ *
+ * @param delta
+ * Nanoseconds to add.
+ *
+ * @result
+ * A new dispatch_time_t.
+ */
+__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA)
+DISPATCH_NOTHROW
+dispatch_time_t
+dispatch_time(dispatch_time_t when, int64_t delta);
+
+/*!
+ * @function dispatch_walltime
+ *
+ * @abstract
+ * Create a dispatch_time_t using the wall clock.
+ *
+ * @discussion
+ * On Mac OS X the wall clock is based on gettimeofday(3).
+ *
+ * @param when
+ * A struct timespect to add time to. If NULL is passed, then
+ * dispatch_walltime() will use the result of gettimeofday(3).
+ *
+ * @param delta
+ * Nanoseconds to add.
+ *
+ * @result
+ * A new dispatch_time_t.
+ */
+__OSX_AVAILABLE_STARTING(__MAC_10_6,__IPHONE_NA)
+DISPATCH_NOTHROW
+dispatch_time_t
+dispatch_walltime(const struct timespec *when, int64_t delta);
+
+__END_DECLS
+
+#endif
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/libdispatch-changes/attachments/20090910/97d88270/attachment-0001.html>


More information about the Libdispatch-changes mailing list