init
Some checks failed
Docker. / Ubuntu (push) Has been cancelled
User-agent updater. / User-agent (push) Failing after 15s
Lock Threads / lock (push) Failing after 10s
Waiting for answer. / waiting-for-answer (push) Failing after 22s
Needs user action. / needs-user-action (push) Failing after 8s
Can't reproduce. / cant-reproduce (push) Failing after 8s
Close stale issues and PRs / stale (push) Has been cancelled

This commit is contained in:
allhaileris
2026-02-16 15:50:16 +03:00
commit afb81b8278
13816 changed files with 3689732 additions and 0 deletions

31
Telegram/ThirdParty/dispatch/.gitignore vendored Normal file
View File

@@ -0,0 +1,31 @@
# Mac OS X filesystem metadata
.DS_Store
# Xcode user artifacts
xcuserdata
project.xcworkspace
# python generated files
*.pyc
# build files generated by the configure script
*.ninja
.ninja_deps
.ninja_log
Build
.build
# build files generated by autotools
Makefile
Makefile.in
config.log
configure
aclocal.m4
autom4te.cache
config.log
config.status
config
configure
libtool
.dirstamp

View File

134
Telegram/ThirdParty/dispatch/.mailmap vendored Normal file
View File

@@ -0,0 +1,134 @@
Adrian-Constantin Popescu <epsilon.gamma@gmail.com> <adrian-constantin.popescu@outlook.com>
Alex Blewitt <alblue@apple.com> <alex.blewitt@gmail.com>
Alex Hoppen <alex@alexhoppen.de> <alex@ateamer.de>
Alexis Beingessner <abeingessner@apple.com> <a.beingessner@gmail.com>
Alper Çugun <github@alper.nl> <alper@users.noreply.github.com>
Amr Aboelela <amraboelela@gmail.com> <amraboelela@users.noreply.github.com>
Ankit Aggarwal <ankit_aggarwal@apple.com> <ankit.spd@gmail.com>
Argyrios Kyrtzidis <kyrtzidis@apple.com> <akyrtzi@gmail.com>
Arsen Gasparyan <to.arsen.gasparyan@gmail.com> <frootloops@users.noreply.github.com>
Ben Cohen <ben_cohen@apple.com>
Ben Cohen <ben_cohen@apple.com> <airspeedswift@users.noreply.github.com>
Ben Cohen <ben_cohen@apple.com> <ben@airspeedvelocity.net>
Ben Langmuir <blangmuir@apple.com> <ben.langmuir@gmail.com>
Brent Royal-Gordon <brent@brentdax.com> <brent@architechies.com>
Brian Croom <bcroom@apple.com> <brian.s.croom@gmail.com>
Brian Gesiak <bgesiak@fb.com> <modocache@gmail.com>
Bryan Chan <bryan.chan@ca.ibm.com> <bryanpkc@gmail.com>
Calvin Hill <mr_j.c.h@hotmail.com> <return@users.noreply.github.com>
Chris Bieneman <beanz@apple.com>
Chris Bieneman <beanz@apple.com> <cbieneman@apple.com>
Chris Lattner <clattner@nondot.org> <clattner@apple.com>
Chris Lattner <clattner@nondot.org> <lattner@users.noreply.github.com>
Chris Lattner <clattner@nondot.org> <sabre@iMac.local>
Chris Williams <cwilliams@fitbit.com> <ultramiraculous@users.noreply.github.com>
codester <sahil.profile@gmail.com> codestergit <sahil.profile@gmail.com>
Dan Liew <dliew@apple.com> <36706441+danliew-apple@users.noreply.github.com>
Daniel Duan <daniel@duan.org> <danmarner@gmail.com>
Dante Broggi <34220985+Dante-Broggi@users.noreply.github.com>
Dave <davesweeris@mac.com>
Dave Abrahams <dabrahams@apple.com> <dave@boostpro.com>
Dave Abrahams <dabrahams@apple.com> <dave@fripp.apple.com>
Dave Abrahams <dabrahams@apple.com> <dave@Skree.local>
Dave Abrahams <dabrahams@apple.com> <dave@Wingy.local>
Dave Lee <davelee@lyft.com> <davelee.com@gmail.com>
David Rönnqvist <david.ronnqvist@gmail.com> <david.ronnqvist@skype.net>
David Zarzycki <dave@znu.io> <zarzycki@icloud.com>
David Zarzycki <dave@znu.io> <zarzycki@mac.com>
Davide Italiano <ditaliano@apple.com> <dcci@users.noreply.github.com>
Davide Italiano <ditaliano@apple.com> <dccitaliano@gmail.com>
Dmitri Gribenko <gribozavr@gmail.com> <dgribenko@apple.com>
Doug Coleman <doug_coleman@apple.com> <doug.coleman@gmail.com>
Enrico Granata <egranata@apple.com> <egranata@egranata.apple.com>
Enrico Granata <egranata@apple.com> <granata.enrico@gmail.com>
Erik Eckstein <eeckstein@apple.com> <eeckstein@apple.com>
Erik Eckstein <eeckstein@apple.com> <eeckstein@rad-main.corp.apple.com>
Erik Verbruggen <erik.verbruggen@me.com> <erikjv@users.noreply.github.com>
Ewa Matejska <ematejska@apple.com> <ematejska@apple.com>
Ewa Matejska <ematejska@apple.com> <ematejska@Ewas-MacBook-Pro.local>
Ewa Matejska <ematejska@apple.com> <ewamatejska@Ewas-iMac.local>
Florent Bruneau <florent.bruneau@intersec.com> <florent.bruneau_github@m4x.org>
Francis Ricci <fjricci@fb.com> <francisjricci@gmail.com>
GauravDS <er.gauravds@gmail.com> <gaurav.sharma@punchh.com>
Graydon Hoare <ghoare@apple.com> <graydon@users.noreply.github.com>
Greg Parker <gparker@apple.com> <gparker-github@sealiesoftware.com>
Guillaume Lessard <dhtnstff@gmail.com> <glessard@users.noreply.github.com>
Hamish <hamish2knight@gmail.com> <hamish2knight@gmail.com>
Han Sangjin <tinysun@jssolution.co.kr> <tinysun.net@gmail.com>
Harlan Haskins <harlan@apple.com> <harlan@harlanhaskins.com>
Hitster GTD <hitstergtd@users.noreply.github.com> <hitstergtd@users.noreply.github.com>
Huon Wilson <huon@apple.com> <dbau.pp+github@gmail.com>
Ingmar Stein <IngmarStein@users.noreply.github.com>
Itai Ferber <iferber@apple.com> <itai@itaiferber.net>
Jacob Bandes-Storch <jacob@bandes-stor.ch> <jacob@bandes-storch.net>
Jacob Mizraji <jmizraji@apple.com> <jacobmizraji@gmail.com>
Janosch Hildebrand <jnosh@jnosh.com> <jnosh+git@jnosh.com>
Janosch Hildebrand <jnosh@jnosh.com> <jnosh+github@jnosh.com>
Javier Soto <jsbustos@twitch.tv> <javier.api@gmail.com>
Javier Soto <jsbustos@twitch.tv> <javiers@twitter.com>
Joe <joe@iachieved.it>
Joe <joewillsher@icloud.com>
joe DeCapo <joe@polka.cat>
Joe Groff <jgroff@apple.com> <arcata@gmail.com>
Joe Shajrawi <shajrawi@apple.com> <joeshajrawi@iMac-2.local>
Joe Shajrawi <shajrawi@apple.com> <joeshajrawi@Joes-iMac-Pro.local>
Johannes Weiß <johannesweiss@apple.com> <github@tux4u.de>
John Regner <john@johnregner.com> <regnerjr@gmail.com>
Karoy Lorentey <klorentey@apple.com> <karoly@lorentey.hu>
Keith Smiley <k@keith.so> <keithbsmiley@gmail.com>
Kevin Ballard <kevin@sb.org> <kevin.ballard@postmates.com>
Kosuke Ogawa <ogawa_kousuke@aratana.jp> <koogawa.app@gmail.com>
Kuba Mracek <mracek@apple.com> <jbrecka@apple.com>
Luiz Fernando Silva <luizinho_mack@yahoo.com.br>
Luqman Aden <luqman@apple.com> <luqman_aden@apple.com>
Marcelo Fabri <me@marcelofabri.com> <marcelofabri@users.noreply.github.com>
Mark Lacey <mark.lacey@apple.com> <rudkx@icloud.com>
Mark Lacey <mark.lacey@apple.com> <rudkx@users.noreply.github.com>
Matt Rajca <matt.rajca@me.com> <mattrajca@users.noreply.github.com>
Max Moiseev <moiseev@apple.com> <maxim.moiseev@gmail.com>
Max Moiseev <moiseev@apple.com> <moiseev@users.noreply.github.com>
Maxwell Swadling <maxs@apple.com> <maxwellswadling@gmail.com>
Maxwell Swadling <maxs@apple.com> <mswadling@apple.com>
Mayur Raiturkar <mayur@mayur.xyz> <mayurkr@users.noreply.github.com>
Michael Gottesman <mgottesman@apple.com> <gottesmm@users.noreply.github.com>
Michael Ilseman <milseman@apple.com> <michael.ilseman@gmail.com>
Mike Ash <mikeash@apple.com> <mike@mikeash.com>
Mike Ferris <mferris@apple.com> <mike@lorax.com>
Mishal Awadah <mawadah@apple.com>
Mishal Shah <mishal_shah@apple.com> <shahmishal@users.noreply.github.com>
Nadav Rotem <nrotem@apple.com> <nadavrot@users.noreply.github.com>
Nate Cook <natecook@apple.com> <nate@Nates-MacBook-Pro.local>
Nate Cook <natecook@apple.com> <natecook@gmail.com>
Nate Cook <natecook@apple.com> <natecook1000@users.noreply.github.com>
Nate Cook <natecook@apple.com> <nmersethcook@apple.com>
Nathan Lanza <lanza@fb.com> <nathan@lanza.io>
Nicole Jacque <jacque@apple.com>
Niels Andriesse <andriesseniels@gmail.com> <nielsandriesse@users.noreply.github.com>
Paul Meng <mno2@mno2.org> <mno2.csie@gmail.com>
Pavel Yaskevich <pyaskevich@apple.com> <xedin@apache.org>
Paweł Szot <pszot@pgs-soft.com>
Paweł Szot <pszot@pgs-soft.com> <qwertyszot@gmail.com>
Pete Cooper <peter_cooper@apple.com>
Philip Ridgeway <pridgeway@vernier.com> <philip.ridgeway@gmail.com>
Richard Wei <rxwei@apple.com> <rxwei@google.com>
Rintaro Ishizaki <rishizaki@apple.com> <fs.output@gmail.com>
Robert Widmann <rwidmann@apple.com> <devteam.codafi@gmail.com>
Roman Levenstein <rlevenstein@apple.com> <swiftix@users.noreply.github.com>
Ross Bayer <ross.m.bayer@gmail.com> <Rostepher@users.noreply.github.com>
Russ Bishop <rbishopjr@apple.com> <russ@plangrid.com>
Ryan Lovelett <ryan@lovelett.me> <RLovelett@users.noreply.github.com>
Shawn Erickson <shawn.erickson@citrix.com> <shawnce@gmail.com>
Slava Pestov <spestov@apple.com> <spestov@rad-main.corp.apple.com>
Slava Pestov <spestov@apple.com> <sviatoslav.pestov@gmail.com>
Stephen Canon <scanon@apple.com>
Stephen Canon <scanon@apple.com> <stephentyrone@gmail.com>
Sukolsak Sakshuwong <sukolsak@gmail.com>
Todd Fiala <tfiala@apple.com> <todd.fiala@gmail.com>
Toni Suter <tonisuter@me.com> <tonisuter@users.noreply.github.com>
Vedant Kumar <vsk@apple.com> <vk@vedantk.com>
Xi Ge <xi_ge@apple.com> <xi_ge@rad-main.corp.apple.com>
Xin Tong <xin_tong@apple.com> <trent.xin.tong@gmail.com>
Xin Tong <xin_tong@apple.com> <trentxintong@Xins-MacBook-Pro.local>
Yuka Ezura <ezura@users.noreply.github.com> <2020337+ezura@users.noreply.github.com>
Yurii Samsoniuk <ura@google.com> <mr.sigito@gmail.com>
Zac Bowling <zbowling@google.com> <zac@zacbowling.com>

View File

@@ -0,0 +1,352 @@
cmake_minimum_required(VERSION 3.15.1)
list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules)
# NOTE(compnerd) enable CMP0091 - select MSVC runtime based on
# CMAKE_MSVC_RUNTIME_LIBRARY. Requires CMake 3.15 or newer.
if(POLICY CMP0091)
cmake_policy(SET CMP0091 NEW)
endif()
project(dispatch
VERSION 1.3
LANGUAGES C CXX)
if("${CMAKE_C_SIMULATE_ID}" STREQUAL "MSVC")
include(ClangClCompileRules)
endif()
if(CMAKE_SYSTEM_NAME STREQUAL Windows)
if(NOT MINGW)
include(DispatchWindowsSupport)
dispatch_windows_arch_spelling(${CMAKE_SYSTEM_PROCESSOR} DISPATCH_MSVC_ARCH)
dispatch_windows_include_for_arch(${DISPATCH_MSVC_ARCH} DISPATCH_INCLUDES)
include_directories(BEFORE SYSTEM ${DISPATCH_INCLUDES})
dispatch_windows_lib_for_arch(${CMAKE_SYSTEM_PROCESSOR} DISPATCH_LIBDIR)
link_directories(${DISPATCH_LIBDIR})
endif()
include(CheckCSourceCompiles)
include(CheckSymbolExists)
check_c_source_compiles([=[
#include <Windows.h>
int main(int argc, char *argv[]) {
switch ((LOGICAL_PROCESSOR_RELATIONSHIP)0) {
case RelationProcessorDie:
case RelationNumaNodeEx:
return 0;
}
return 0;
}
]=] DISPATCH_HAVE_EXTENDED_SLPI_20348)
if(DISPATCH_HAVE_EXTENDED_SLPI_20348)
add_compile_definitions(DISPATCH_HAVE_EXTENDED_SLPI_20348)
endif()
check_c_source_compiles([=[
#include <Windows.h>
int main(int argc, char *argv[]) {
switch ((LOGICAL_PROCESSOR_RELATIONSHIP)0) {
case RelationProcessorModule:
return 0;
}
return 0;
}
]=] DISPATCH_HAVE_EXTENDED_SLPI_22000)
if(DISPATCH_HAVE_EXTENDED_SLPI_22000)
add_compile_definitions(DISPATCH_HAVE_EXTENDED_SLPI_22000)
endif()
check_c_source_compiles([=[
#include <Windows.h>
#include <winternl.h>
int main(int argc, char *argv[]) {
FILE_PIPE_LOCAL_INFORMATION fpli;
}
]=] HAVE_FILE_PIPE_LOCAL_INFORMATION)
if(HAVE_FILE_PIPE_LOCAL_INFORMATION)
add_compile_definitions(HAVE_FILE_PIPE_LOCAL_INFORMATION)
endif()
check_symbol_exists(mkstemp "stdlib.h" HAVE_MKSTEMP)
if(HAVE_MKSTEMP)
add_compile_definitions(HAVE_MKSTEMP)
endif()
check_c_source_compiles([=[
#include <sys/types.h>
int main(int argc, char *argv[]) {
mode_t mode;
}
]=] HAVE_MODE_T)
if(HAVE_MODE_T)
add_compile_definitions(HAVE_MODE_T)
endif()
check_c_source_compiles([=[
#include <sys/types.h>
int main(int argc, char *argv[]) {
pid_t mode;
}
]=] HAVE_PID_T)
if(HAVE_PID_T)
add_compile_definitions(HAVE_PID_T)
endif()
endif()
set(CMAKE_C_STANDARD 11)
set(CMAKE_C_STANDARD_REQUIRED YES)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_C_VISIBILITY_PRESET hidden)
set(CMAKE_C_VISIBILITY_INLINES_HIDDEN YES)
# NOTE(compnerd) this is a horrible workaround for Windows to ensure that the
# tests can run as there is no rpath equivalent and `PATH` is used to lookup the
# libraries.
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
set(CMAKE_THREAD_PREFER_PTHREAD TRUE)
set(THREADS_PREFER_PTHREAD_FLAG TRUE)
if(ANDROID)
set(CMAKE_HAVE_LIBC_PTHREAD YES)
endif()
find_package(Threads REQUIRED)
include(CheckCCompilerFlag)
include(CheckCSourceCompiles)
include(CheckFunctionExists)
include(CheckIncludeFiles)
include(CheckLibraryExists)
include(CheckLinkerFlag)
include(CheckSymbolExists)
include(GNUInstallDirs)
include(CTest)
include(DispatchAppleOptions)
include(DispatchSanitization)
include(DispatchCompilerWarnings)
include(DTrace)
include(SwiftSupport)
# NOTE(abdulras) this is the CMake supported way to control whether we generate
# shared or static libraries. This impacts the behaviour of `add_library` in
# what type of library it generates.
option(BUILD_SHARED_LIBS "build shared libraries" ON)
option(DISPATCH_ENABLE_ASSERTS "enable debug assertions" FALSE)
option(ENABLE_DISPATCH_INIT_CONSTRUCTOR "enable libdispatch_init as a constructor" ON)
set(USE_LIBDISPATCH_INIT_CONSTRUCTOR ${ENABLE_DISPATCH_INIT_CONSTRUCTOR})
option(ENABLE_DTRACE "enable dtrace support" "")
if(CMAKE_SYSTEM_NAME STREQUAL Darwin OR CMAKE_SYSTEM_NAME STREQUAL FreeBSD)
set(ENABLE_INTERNAL_PTHREAD_WORKQUEUES_DEFAULT OFF)
else()
set(ENABLE_INTERNAL_PTHREAD_WORKQUEUES_DEFAULT ON)
endif()
option(ENABLE_INTERNAL_PTHREAD_WORKQUEUES "use libdispatch's own implementation of pthread workqueues" ${ENABLE_INTERNAL_PTHREAD_WORKQUEUES_DEFAULT})
if(ENABLE_INTERNAL_PTHREAD_WORKQUEUES)
set(DISPATCH_USE_INTERNAL_WORKQUEUE 1)
set(HAVE_PTHREAD_WORKQUEUES 0)
else()
check_include_files(pthread/workqueue_private.h HAVE_PTHREAD_WORKQUEUE_PRIVATE_H)
if(HAVE_PTHREAD_WORKQUEUE_PRIVATE_H)
set(HAVE_PTHREAD_WORKQUEUES 1)
set(DISPATCH_USE_INTERNAL_WORKQUEUE 0)
else()
set(HAVE_PTHREAD_WORKQUEUES 0)
set(DISPATCH_USE_INTERNAL_WORKQUEUE 1)
endif()
endif()
option(INSTALL_PRIVATE_HEADERS "installs private headers in the same location as the public ones" OFF)
option(ENABLE_SWIFT "enable libdispatch swift overlay" OFF)
if(ENABLE_SWIFT)
enable_language(Swift)
endif()
option(ENABLE_THREAD_LOCAL_STORAGE "enable usage of thread local storage via _Thread_local" ON)
set(DISPATCH_USE_THREAD_LOCAL_STORAGE ${ENABLE_THREAD_LOCAL_STORAGE})
check_linker_flag(C "LINKER:--build-id=sha1" LINKER_SUPPORTS_BUILD_ID)
check_symbol_exists(__GNU_LIBRARY__ "features.h" _GNU_SOURCE)
if(_GNU_SOURCE)
set(CMAKE_REQUIRED_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS} -D_GNU_SOURCE)
endif()
check_c_source_compiles("void __attribute__((__noreturn__)) main() { __builtin_trap(); }"
__BUILTIN_TRAP)
if(__BUILTIN_TRAP)
set(HAVE_NORETURN_BUILTIN_TRAP 1)
endif()
if(NOT CMAKE_SYSTEM_NAME STREQUAL Android)
find_package(LibRT)
endif()
check_function_exists(_pthread_workqueue_init HAVE__PTHREAD_WORKQUEUE_INIT)
check_function_exists(getprogname HAVE_GETPROGNAME)
check_function_exists(mach_absolute_time HAVE_MACH_ABSOLUTE_TIME)
check_function_exists(mach_approximate_time HAVE_MACH_APPROXIMATE_TIME)
check_function_exists(mach_port_construct HAVE_MACH_PORT_CONSTRUCT)
check_function_exists(malloc_create_zone HAVE_MALLOC_CREATE_ZONE)
check_function_exists(posix_fadvise HAVE_POSIX_FADVISE)
check_function_exists(posix_spawnp HAVE_POSIX_SPAWNP)
check_function_exists(pthread_key_init_np HAVE_PTHREAD_KEY_INIT_NP)
check_function_exists(pthread_attr_setcpupercent_np HAVE_PTHREAD_ATTR_SETCPUPERCENT_NP)
check_function_exists(pthread_yield_np HAVE_PTHREAD_YIELD_NP)
check_function_exists(pthread_main_np HAVE_PTHREAD_MAIN_NP)
check_function_exists(pthread_workqueue_setdispatch_np HAVE_PTHREAD_WORKQUEUE_SETDISPATCH_NP)
check_function_exists(strlcpy HAVE_STRLCPY)
check_function_exists(sysconf HAVE_SYSCONF)
check_function_exists(arc4random HAVE_ARC4RANDOM)
check_include_files("TargetConditionals.h" HAVE_TARGETCONDITIONALS_H)
check_include_files("dlfcn.h" HAVE_DLFCN_H)
check_include_files("fcntl.h" HAVE_FCNTL_H)
check_include_files("inttypes.h" HAVE_INTTYPES_H)
check_include_files("libkern/OSAtomic.h" HAVE_LIBKERN_OSATOMIC_H)
check_include_files("libkern/OSCrossEndian.h" HAVE_LIBKERN_OSCROSSENDIAN_H)
check_include_files("libproc_internal.h" HAVE_LIBPROC_INTERNAL_H)
check_include_files("mach/mach.h" HAVE_MACH)
if(HAVE_MACH)
set(__DARWIN_NON_CANCELABLE 1)
else()
set(__DARWIN_NON_CANCELABLE 0)
endif()
check_include_files("malloc/malloc.h" HAVE_MALLOC_MALLOC_H)
check_include_files("memory.h" HAVE_MEMORY_H)
check_include_files("pthread/qos.h" HAVE_PTHREAD_QOS_H)
check_include_files("pthread/workqueue_private.h" HAVE_PTHREAD_WORKQUEUE_PRIVATE_H)
check_include_files("pthread_machdep.h" HAVE_PTHREAD_MACHDEP_H)
check_include_files("pthread_np.h" HAVE_PTHREAD_NP_H)
check_include_files("pthread_workqueue.h" HAVE_PTHREAD_WORKQUEUE_H)
check_include_files("stdint.h" HAVE_STDINT_H)
check_include_files("stdlib.h" HAVE_STDLIB_H)
check_include_files("string.h" HAVE_STRING_H)
check_include_files("strings.h" HAVE_STRINGS_H)
check_include_files("sys/guarded.h" HAVE_SYS_GUARDED_H)
check_include_files("sys/stat.h" HAVE_SYS_STAT_H)
check_include_files("sys/types.h" HAVE_SYS_TYPES_H)
check_include_files("objc/objc-internal.h" HAVE_OBJC)
if(HAVE_MACH)
set(USE_MACH_SEM 1)
else()
set(USE_MACH_SEM 0)
endif()
if(CMAKE_SYSTEM_NAME STREQUAL Windows)
add_compile_definitions($<$<OR:$<COMPILE_LANGUAGE:C>,$<COMPILE_LANGUAGE:CXX>>:USE_WIN32_SEM>)
endif()
check_library_exists(pthread sem_init "" USE_POSIX_SEM)
# NOTE: android has not always provided a libpthread, but uses the pthreads API
if(CMAKE_SYSTEM_NAME STREQUAL Android)
set(USE_POSIX_SEM 1)
endif()
check_symbol_exists(CLOCK_UPTIME "time.h" HAVE_DECL_CLOCK_UPTIME)
check_symbol_exists(CLOCK_UPTIME_FAST "time.h" HAVE_DECL_CLOCK_UPTIME_FAST)
check_symbol_exists(CLOCK_MONOTONIC "time.h" HAVE_DECL_CLOCK_MONOTONIC)
check_symbol_exists(CLOCK_REALTIME "time.h" HAVE_DECL_CLOCK_REALTIME)
check_symbol_exists(CLOCK_MONOTONIC_COARSE "time.h" HAVE_DECL_CLOCK_MONOTONIC_COARSE)
check_symbol_exists(FD_COPY "sys/select.h" HAVE_DECL_FD_COPY)
check_symbol_exists(NOTE_LOWAT "sys/event.h" HAVE_DECL_NOTE_LOWAT)
check_symbol_exists(NOTE_NONE "sys/event.h" HAVE_DECL_NOTE_NONE)
check_symbol_exists(NOTE_REAP "sys/event.h" HAVE_DECL_NOTE_REAP)
check_symbol_exists(NOTE_REVOKE "sys/event.h" HAVE_DECL_NOTE_REVOKE)
check_symbol_exists(NOTE_SIGNAL "sys/event.h" HAVE_DECL_NOTE_SIGNAL)
check_symbol_exists(POSIX_SPAWN_START_SUSPENDED "sys/spawn.h" HAVE_DECL_POSIX_SPAWN_START_SUSPENDED)
check_symbol_exists(SIGEMT "signal.h" HAVE_DECL_SIGEMT)
check_symbol_exists(VQ_DESIRED_DISK "sys/mount.h" HAVE_DECL_VQ_DESIRED_DISK)
check_symbol_exists(VQ_NEARLOWDISK "sys/mount.h" HAVE_DECL_VQ_NEARLOWDISK)
check_symbol_exists(VQ_QUOTA "sys/mount.h" HAVE_DECL_VQ_QUOTA)
check_symbol_exists(VQ_UPDATE "sys/mount.h" HAVE_DECL_VQ_UPDATE)
check_symbol_exists(VQ_VERYLOWDISK "sys/mount.h" HAVE_DECL_VQ_VERYLOWDISK)
check_symbol_exists(VQ_FREE_SPACE_CHANGE "sys/mount.h" HAVE_DECL_VQ_FREE_SPACE_CHANGE)
check_symbol_exists(strlcpy "string.h" HAVE_STRLCPY)
check_symbol_exists(program_invocation_name "errno.h" HAVE_DECL_PROGRAM_INVOCATION_SHORT_NAME)
if (HAVE_DECL_PROGRAM_INVOCATION_SHORT_NAME)
add_compile_definitions($<$<OR:$<COMPILE_LANGUAGE:C>,$<COMPILE_LANGUAGE:CXX>>:_GNU_SOURCE=1>)
endif()
check_symbol_exists(__printflike "bsd/sys/cdefs.h" HAVE_PRINTFLIKE)
if(CMAKE_SYSTEM_NAME STREQUAL Android)
set(ENABLE_DTRACE_DEFAULT OFF)
endif()
if(CMAKE_SYSTEM_NAME STREQUAL FreeBSD)
add_compile_definitions($<$<OR:$<COMPILE_LANGUAGE:C>,$<COMPILE_LANGUAGE:CXX>>:_WITH_DPRINTF>)
endif()
if(ENABLE_DTRACE)
find_program(dtrace_EXECUTABLE dtrace)
if(NOT dtrace_EXECUTABLE AND NOT ENABLE_DTRACE STREQUAL "")
message(FATAL_ERROR "dtrace not found but explicitly requested")
endif()
endif()
if(dtrace_EXECUTABLE)
add_compile_definitions($<$<OR:$<COMPILE_LANGUAGE:C>,$<COMPILE_LANGUAGE:CXX>>:DISPATCH_USE_DTRACE=1>)
else()
add_compile_definitions($<$<OR:$<COMPILE_LANGUAGE:C>,$<COMPILE_LANGUAGE:CXX>>:DISPATCH_USE_DTRACE=0>)
endif()
find_program(leaks_EXECUTABLE leaks)
if(leaks_EXECUTABLE)
set(HAVE_LEAKS TRUE)
endif()
if(CMAKE_SYSTEM_NAME STREQUAL Darwin)
add_compile_options($<$<OR:$<COMPILE_LANGUAGE:C>,$<COMPILE_LANGUAGE:CXX>>:-fmodule-map-file=${PROJECT_SOURCE_DIR}/dispatch/darwin/module.modulemap>
$<$<OR:$<COMPILE_LANGUAGE:C>,$<COMPILE_LANGUAGE:CXX>>:-fmodule-map-file=${PROJECT_SOURCE_DIR}/private/darwin/module.modulemap>)
else()
add_compile_options($<$<OR:$<COMPILE_LANGUAGE:C>,$<COMPILE_LANGUAGE:CXX>>:-fmodule-map-file=${PROJECT_SOURCE_DIR}/dispatch/generic/module.modulemap>
$<$<OR:$<COMPILE_LANGUAGE:C>,$<COMPILE_LANGUAGE:CXX>>:-fmodule-map-file=${PROJECT_SOURCE_DIR}/private/generic/module.modulemap>)
endif()
configure_file("${PROJECT_SOURCE_DIR}/cmake/config.h.in"
"${PROJECT_BINARY_DIR}/config/config_ac.h")
add_compile_definitions($<$<OR:$<COMPILE_LANGUAGE:C>,$<COMPILE_LANGUAGE:CXX>>:HAVE_CONFIG_H>)
if(ENABLE_SWIFT)
if(NOT SWIFT_SYSTEM_NAME)
if(CMAKE_SYSTEM_NAME STREQUAL Darwin)
set(SWIFT_SYSTEM_NAME macosx)
else()
set(SWIFT_SYSTEM_NAME "$<LOWER_CASE:${CMAKE_SYSTEM_NAME}>")
endif()
endif()
set(INSTALL_TARGET_DIR "${CMAKE_INSTALL_LIBDIR}/swift$<$<NOT:$<BOOL:${BUILD_SHARED_LIBS}>>:_static>/${SWIFT_SYSTEM_NAME}" CACHE PATH "Path where the libraries will be installed")
set(INSTALL_DISPATCH_HEADERS_DIR "${CMAKE_INSTALL_LIBDIR}/swift$<$<NOT:$<BOOL:${BUILD_SHARED_LIBS}>>:_static>/dispatch" CACHE PATH "Path where the headers will be installed for libdispatch")
set(INSTALL_BLOCK_HEADERS_DIR "${CMAKE_INSTALL_LIBDIR}/swift$<$<NOT:$<BOOL:${BUILD_SHARED_LIBS}>>:_static>/Block" CACHE PATH "Path where the headers will be installed for the blocks runtime")
set(INSTALL_OS_HEADERS_DIR "${CMAKE_INSTALL_LIBDIR}/swift$<$<NOT:$<BOOL:${BUILD_SHARED_LIBS}>>:_static>/os" CACHE PATH "Path where the os/ headers will be installed")
else()
set(INSTALL_TARGET_DIR "${CMAKE_INSTALL_LIBDIR}" CACHE PATH "Path where the libraries will be installed")
set(INSTALL_DISPATCH_HEADERS_DIR "include/dispatch" CACHE PATH "Path where the headers will be installed")
set(INSTALL_BLOCK_HEADERS_DIR "include" CACHE PATH "Path where the headers will be installed for the blocks runtime")
set(INSTALL_OS_HEADERS_DIR "include/os" CACHE PATH "Path where the headers will be installed")
endif()
add_subdirectory(dispatch)
add_subdirectory(man)
add_subdirectory(os)
add_subdirectory(private)
add_subdirectory(src)
if(BUILD_TESTING)
add_subdirectory(tests)
endif()
add_subdirectory(cmake/modules)

View File

@@ -0,0 +1,10 @@
By submitting a pull request, you represent that you have the right to license
your contribution to Apple and the community, and agree by submitting the patch
that your contributions are licensed under the [Swift
license](https://swift.org/LICENSE.txt).
---
Before submitting the pull request, please make sure you have tested your
changes and that they follow the Swift project [guidelines for contributing
code](https://swift.org/contributing/#contributing-code).

170
Telegram/ThirdParty/dispatch/INSTALL.md vendored Normal file
View File

@@ -0,0 +1,170 @@
## Grand Central Dispatch (GCD)
GCD is a concurrent programming framework first shipped with Mac OS X Snow
Leopard. This package is an open source bundling of libdispatch, the core
user space library implementing GCD. At the time of writing, support for
the BSD kqueue API, and specifically extensions introduced in Mac OS X Snow
Leopard and FreeBSD 9-CURRENT, are required to use libdispatch. Linux is
supported, but requires specific packages to be installed (see Linux
section at the end of the file). Other systems are currently unsupported.
### Configuring and installing libdispatch (general comments)
GCD is built using autoconf, automake, and libtool, and has a number of
compile-time configuration options that should be reviewed before starting.
An uncustomized install of the C-API to libdispatch requires:
sh autogen.sh
./configure
make
make install
libdispatch can be optionally built to include a Swift API. This requires a
Swift toolchain to compile the Swift code in libdispatch and can be done
in two possible scenarios.
If you are building your own Swift toolchain from source, then you should build
libdispatch simply by giving additional arguments to swift/utils/build-script:
./swift/utils/build-script --libdispatch -- --install-libdispatch
To build libdispatch using a pre-built Swift toolchain and install libdispatch
into that toolchain (to allow that toolchain to compile Swift code containing
"import Dispatch") requires:
sh autogen.sh
./configure --with-swift-toolchain=<PATH_TO_SWIFT_TOOLCHAIN> --prefix=<PATH_TO_SWIFT_TOOLCHAIN>
make
make install
Note that once libdispatch is installed into a Swift toolchain, that
toolchain cannot be used to compile libdispatch again (you must 'make uninstall'
libdispatch from the toolchain before using it to rebuild libdispatch).
You can also use the build-toolchain script to create a toolchain
that includes libdispatch on Linux:
1. Add libdispatch and install-libdispatch lines to ./swift/utils/build-presets.ini under `[preset: buildbot_linux]` section, as following:
```
[preset: buildbot_linux]
mixin-preset=mixin_linux_installation
build-subdir=buildbot_linux
lldb
release
test
validation-test
long-test
libdispatch
foundation
lit-args=-v
dash-dash
install-libdispatch
install-foundation
reconfigure
```
2. Run:
```
./swift/utils/build-toolchain local.swift
```
Note that adding libdispatch in build-presets.ini is for Linux only as Swift on macOS platforms uses the system installed libdispatch, so its not required.
### Building and installing on OS X
The following configure options may be of general interest:
`--with-apple-libpthread-source`
Specify the path to Apple's libpthread package, so that appropriate headers
can be found and used.
`--with-apple-libplatform-source`
Specify the path to Apple's libplatform package, so that appropriate headers
can be found and used.
`--with-apple-xnu-source`
Specify the path to Apple's XNU package, so that appropriate headers can be
found and used.
`--with-blocks-runtime`
On systems where -fblocks is supported, specify an additional library path in which libBlocksRuntime can be found. This is not required on OS X, where the Blocks runtime is included in libSystem, but is required on FreeBSD.
The following options are likely to only be useful when building libdispatch on
OS X as a replacement for /usr/lib/system/libdispatch.dylib:
`--disable-libdispatch-init-constructor`
Do not tag libdispatch's init routine as __constructor, in which case it must be run manually before libdispatch routines can be called. This is the default when building on OS X. For /usr/lib/system/libdispatch.dylib the init routine is called automatically during process start.
`--enable-apple-tsd-optimizations`
Use a non-portable allocation scheme for pthread per-thread data (TSD) keys when building libdispatch for /usr/lib/system on OS X. This should not be used on other OS's, or on OS X when building a stand-alone library.
#### Typical configuration commands
The following command lines create the configuration required to build
libdispatch for /usr/lib/system on OS X El Capitan:
clangpath=$(dirname `xcrun --find clang`)
sudo mkdir -p "$clangpath/../local/lib/clang/enable_objc_gc"
LIBTOOLIZE=glibtoolize sh autogen.sh
cflags='-arch x86_64 -arch i386 -g -Os'
./configure CFLAGS="$cflags" OBJCFLAGS="$cflags" CXXFLAGS="$cflags" \
--prefix=/usr --libdir=/usr/lib/system --disable-static \
--enable-apple-tsd-optimizations \
--with-apple-libpthread-source=/path/to/10.11.0/libpthread-137.1.1 \
--with-apple-libplatform-source=/path/to/10.11.0/libplatform-73.1.1 \
--with-apple-xnu-source=/path/to/10.11.0/xnu-3247.1.106 \
make check
### Building and installing for FreeBSD
Typical configuration line for FreeBSD 8.x and 9.x to build libdispatch with
clang and blocks support:
```
cmake -G Ninja -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DBlocksRuntime_INCLUDE_DIR=/usr/local/include -DBlocksRuntime_LIBRARIES=/usr/local/lib/libBlocksRuntime.so <path-to-source>
ninja
ninja test
```
### Building for android
Note that this assumes that you are building on Linux. It requires that you
have the android NDK available. It has been tested against API Level 21.
```
cmake -G Ninja -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_SYSTEM_NAME=Android -DCMAKE_SYSTEM_VERSION=21 -DCMAKE_ANDROID_NDK=<path to android NDK> <path-to-source>
ninja
```
### Building and installing for Linux
Note that libdispatch development and testing is done only
on Ubuntu; currently supported versions are 14.04, 15.10 and 16.04.
1. The first thing to do is install required packages:
`sudo apt-get install cmake ninja-build clang systemtap-sdt-dev libbsd-dev linux-libc-dev`
Note: compiling libdispatch requires clang 3.8 or better and
the gold linker. If the default clang on your Ubuntu version is
too old, see http://apt.llvm.org/ to install a newer version.
On older Ubuntu releases, you may need to install binutils-gold
to get the gold linker.
2. Build
```
cmake -G Ninja -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ <path-to-source>
ninja
ninja install
```

211
Telegram/ThirdParty/dispatch/LICENSE vendored Normal file
View File

@@ -0,0 +1,211 @@
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.
### Runtime Library Exception to the Apache 2.0 License: ###
As an exception, if you use this Software to compile your source code and
portions of this Software are embedded into the binary product as a result,
you may redistribute such product without providing attribution as would
otherwise be required by Sections 4(a), 4(b) and 4(d) of the License.

436
Telegram/ThirdParty/dispatch/PATCHES vendored Normal file
View File

@@ -0,0 +1,436 @@
The libdispatch project exists in a parallel open source repository at:
http://github.com/apple/swift-corelibs-libdispatch
Externally contributed changes are synchronized back to the internal repository
via pull request of the result of `git am` of the contributed patch series.
Internal changes are synchronized from the internal darwin/trunk branch to the
external repository via `gi am` on the github darwin/trunk branch and merge to
github master.
Key:
APPLIED: change set was applied to internal repository.
INTERNAL: change set originated internally (i.e. already applied).
SKIPPED: change set was skipped.
svn revisions until r218 from legacy open source repository at
http://svn.macosforge.org/repository/libdispatch/trunk
[ 1] SKIPPED
[ 2] SKIPPED
[ 3] INTERNAL rdar://problem/7148356
[ 4] APPLIED rdar://problem/7323245
[ 5] APPLIED rdar://problem/7323245
[ 6] APPLIED rdar://problem/7323245
[ 7] APPLIED rdar://problem/7323245
[ 8] APPLIED rdar://problem/7323245
[ 9] APPLIED rdar://problem/7323245
[ 10] APPLIED rdar://problem/7323245
[ 11] APPLIED rdar://problem/7323245
[ 12] APPLIED rdar://problem/7323245
[ 13] SKIPPED
[ 14] APPLIED rdar://problem/7323245
[ 15] APPLIED rdar://problem/7323245
[ 16] APPLIED rdar://problem/7323245
[ 17] APPLIED rdar://problem/7323245
[ 18] APPLIED rdar://problem/7323245
[ 19] APPLIED rdar://problem/7323245
[ 20] APPLIED rdar://problem/7323245
[ 21] APPLIED rdar://problem/7323245
[ 22] APPLIED rdar://problem/7323245
[ 23] APPLIED rdar://problem/7323245
[ 24] APPLIED rdar://problem/7323245
[ 25] APPLIED rdar://problem/7323245
[ 26] APPLIED rdar://problem/7323245
[ 27] APPLIED rdar://problem/7323245
[ 28] APPLIED rdar://problem/7323245
[ 29] APPLIED rdar://problem/7323245
[ 30] SKIPPED
[ 31] APPLIED rdar://problem/7323245
[ 32] APPLIED rdar://problem/7323245
[ 33] APPLIED rdar://problem/7323245
[ 34] APPLIED rdar://problem/7323245
[ 35] SKIPPED
[ 36] APPLIED rdar://problem/7323245
[ 37] APPLIED rdar://problem/7323245
[ 38] APPLIED rdar://problem/7323245
[ 39] APPLIED rdar://problem/7323245
[ 40] APPLIED rdar://problem/7323245
[ 41] APPLIED rdar://problem/7323245
[ 42] APPLIED rdar://problem/7323245
[ 43] APPLIED rdar://problem/7323245
[ 44] APPLIED rdar://problem/7323245
[ 45] APPLIED rdar://problem/7323245
[ 46] APPLIED rdar://problem/7323245
[ 47] APPLIED rdar://problem/7323245
[ 48] APPLIED rdar://problem/7323245
[ 49] APPLIED rdar://problem/7323245
[ 50] APPLIED rdar://problem/7323245
[ 51] APPLIED rdar://problem/7323245
[ 52] APPLIED rdar://problem/7323245
[ 53] APPLIED rdar://problem/7323245
[ 54] APPLIED rdar://problem/7323245
[ 55] APPLIED rdar://problem/7323245
[ 56] APPLIED rdar://problem/7323245
[ 57] APPLIED rdar://problem/7323245
[ 58] APPLIED rdar://problem/7323245
[ 59] APPLIED rdar://problem/7323245
[ 60] APPLIED rdar://problem/7323245
[ 61] APPLIED rdar://problem/7323245
[ 62] APPLIED rdar://problem/7323245
[ 63] APPLIED rdar://problem/7323245
[ 64] APPLIED rdar://problem/7323245
[ 65] APPLIED rdar://problem/7323245
[ 66] APPLIED rdar://problem/7323245
[ 67] APPLIED rdar://problem/7323245
[ 68] APPLIED rdar://problem/7323245
[ 69] APPLIED rdar://problem/7323245
[ 70] APPLIED rdar://problem/7323245
[ 71] INTERNAL
[ 72] INTERNAL
[ 73] APPLIED rdar://problem/7531526
[ 74] APPLIED rdar://problem/7531526
[ 75]
[ 76]
[ 77]
[ 78]
[ 79] APPLIED rdar://problem/7531526
[ 80] APPLIED rdar://problem/7531526
[ 81] APPLIED rdar://problem/7531526
[ 82] APPLIED rdar://problem/7531526
[ 83] APPLIED rdar://problem/7531526
[ 84] APPLIED rdar://problem/7531526
[ 85]
[ 86]
[ 87] APPLIED rdar://problem/7531526
[ 88] APPLIED rdar://problem/7531526
[ 89] APPLIED rdar://problem/7531526
[ 90]
[ 91]
[ 92]
[ 93]
[ 94]
[ 95]
[ 96] APPLIED rdar://problem/7531526
[ 97] APPLIED rdar://problem/7531526
[ 98]
[ 99]
[ 100]
[ 101]
[ 102]
[ 103] APPLIED rdar://problem/7531526
[ 104] APPLIED rdar://problem/7531526
[ 105]
[ 106] APPLIED rdar://problem/7531526
[ 107] SKIPPED
[ 108] SKIPPED
[ 109] SKIPPED
[ 110] SKIPPED
[ 111] SKIPPED
[ 112] APPLIED rdar://problem/7531526
[ 113] SKIPPED
[ 114] APPLIED rdar://problem/7531526
[ 115] APPLIED rdar://problem/7531526
[ 116] APPLIED rdar://problem/7531526
[ 117] SKIPPED
[ 118] APPLIED rdar://problem/7531526
[ 119] SKIPPED
[ 120] APPLIED rdar://problem/7531526
[ 121] SKIPPED
[ 122] SKIPPED
[ 123] SKIPPED
[ 124] SKIPPED
[ 125] APPLIED rdar://problem/7531526
[ 126] SKIPPED
[ 127] APPLIED rdar://problem/7531526
[ 128]
[ 129]
[ 130]
[ 131]
[ 132]
[ 133]
[ 134]
[ 135]
[ 136]
[ 137] APPLIED rdar://problem/7647055
[ 138] SKIPPED
[ 139] APPLIED rdar://problem/7531526
[ 140] APPLIED rdar://problem/7531526
[ 141] APPLIED rdar://problem/7531526
[ 142] APPLIED rdar://problem/7531526
[ 143]
[ 144] APPLIED rdar://problem/7531526
[ 145] APPLIED rdar://problem/7531526
[ 146] APPLIED rdar://problem/7531526
[ 147]
[ 148]
[ 149]
[ 150]
[ 151] APPLIED rdar://problem/7531526
[ 152] APPLIED rdar://problem/7531526
[ 153]
[ 154] APPLIED rdar://problem/7531526
[ 155]
[ 156]
[ 157] APPLIED rdar://problem/7531526
[ 158]
[ 159]
[ 160]
[ 161]
[ 162] APPLIED rdar://problem/7531526
[ 163] APPLIED rdar://problem/7531526
[ 164]
[ 165]
[ 166] APPLIED rdar://problem/7531526
[ 167] APPLIED rdar://problem/7531526
[ 168]
[ 169] APPLIED rdar://problem/7531526
[ 170] APPLIED rdar://problem/7531526
[ 171] APPLIED rdar://problem/7531526
[ 172] APPLIED rdar://problem/7531526
[ 173] APPLIED rdar://problem/7531526
[ 174] APPLIED rdar://problem/7531526
[ 175] APPLIED rdar://problem/7531526
[ 176] APPLIED rdar://problem/7531526
[ 177] APPLIED rdar://problem/7531526
[ 178]
[ 179] APPLIED rdar://problem/7531526
[ 180] APPLIED rdar://problem/7531526
[ 181]
[ 182]
[ 183] INTERNAL rdar://problem/7581831
[ 202] INTERNAL libdispatch-187.5
[ 212] INTERNAL libdispatch-228.18
[ 213] INTERNAL rdar://problem/11754320
[ 216] INTERNAL libdispatch-339.1.9
[ 217] INTERNAL libdispatch-442.1.4
[ 218] INTERNAL libdispatch-500.1.5
github commits starting with 29bdc2f from
http://github.com/apple/swift-corelibs-libdispatch
[29bdc2f] INTERNAL libdispatch-500.1.5
[a60acd6] APPLIED rdar://23661056
[39ac720] APPLIED rdar://23705483
[acd56f6] APPLIED rdar://23754944
[394d9a1] APPLIED rdar://23772602
[3691f26] APPLIED rdar://23868354
[8904f45] APPLIED rdar://23868354
[6dbebd6] APPLIED rdar://23868354
[b2ccfeb] APPLIED rdar://23868354
[e7ca00f] APPLIED rdar://23868354
[35eb408] APPLIED rdar://25159995
[32411c2] APPLIED rdar://25159995
[31586d5] APPLIED rdar://25159995
[50faff5] APPLIED rdar://25159995
[3ce4e3d] APPLIED rdar://25159995
[b647aee] APPLIED rdar://25159995
[ab7e16c] APPLIED rdar://25159995
[cef2960] APPLIED rdar://25159995
[dfa43cd] APPLIED rdar://25159995
[8b9c3a9] APPLIED rdar://25159995
[fefb6cf] APPLIED rdar://25159995
[1a9c57f] APPLIED rdar://25159995
[c04488a] APPLIED rdar://25159995
[f1d58d1] APPLIED rdar://25159995
[be83e85] APPLIED rdar://25159995
[79fbb13] APPLIED rdar://25159995
[6ead519] APPLIED rdar://25159995
[1fa1513] APPLIED rdar://25159995
[4a6ec51] APPLIED rdar://25159995
[bc16cc9] APPLIED rdar://25159995
[954ace4] APPLIED rdar://25159995
[5ea30b5] APPLIED rdar://26822213
[9f1e778] APPLIED rdar://26822213
[3339b81] APPLIED rdar://26822213
[4fa8d8d] APPLIED rdar://26822213
[e922531] APPLIED rdar://26822213
[195cbcf] APPLIED rdar://27303844
[5b893c8] APPLIED rdar://27303844
[92689ed] APPLIED rdar://27303844
[ecc14fa] APPLIED rdar://27303844
[2dbf83c] APPLIED rdar://27303844
[78b9e82] APPLIED rdar://27303844
[2c0e5ee] APPLIED rdar://27303844
[5ee237f] APPLIED rdar://27600964
[77299ec] APPLIED rdar://27600964
[57c5c28] APPLIED rdar://27600964
[f8423ec] APPLIED rdar://27600964
[325f73d] APPLIED rdar://27600964
[b84e87e] APPLIED rdar://27600964
[ae71a91] APPLIED rdar://27600964
[8669dea] APPLIED rdar://27600964
[a8d0327] APPLIED rdar://27600964
[2e4e6af] APPLIED rdar://27600964
[2457fb2] APPLIED rdar://27600964
[4d58038] APPLIED rdar://27600964
[98d0a05] APPLIED rdar://27600964
[8976101] APPLIED rdar://27600964
[0d9ea5f] APPLIED rdar://28486911
[e7e9a32] APPLIED rdar://28486911
[44174d9] APPLIED rdar://28486911
[6402cb7] APPLIED rdar://28486911
[e2d5eb5] APPLIED rdar://28486911
[758bb7f] APPLIED rdar://28486911
[4c588e9] APPLIED rdar://28486911
[1300d06] APPLIED rdar://28486911
[ae1f7e8] APPLIED rdar://28486911
[40a9bfb] APPLIED rdar://28486911
[6366081] APPLIED rdar://28486911
[81d1d0c] APPLIED rdar://28486911
[5526122] APPLIED rdar://28486911
[1a7ff3f] APPLIED rdar://28486911
[e905735] APPLIED rdar://28486911
[7fe8323] APPLIED rdar://28486911
[6249878] APPLIED rdar://28486911
[20792fe] APPLIED rdar://28486911
[3639fbe] APPLIED rdar://28486911
[bda3baf] APPLIED rdar://28486911
[8803d07] APPLIED rdar://28486911
[d04a0df] APPLIED rdar://28486911
[69d2a6a] APPLIED rdar://28486911
[367bd95] APPLIED rdar://28486911
[152985f] APPLIED rdar://28486911
[ba7802e] APPLIED rdar://28486911
[92773e0] APPLIED rdar://30568673
[548a1b9] APPLIED rdar://30568673
[b628e5c] APPLIED rdar://30568673
[a055ddb] APPLIED rdar://30568673
[012f48b] APPLIED rdar://30568673
[353adba] APPLIED rdar://30568673
[eb730eb] APPLIED rdar://30568673
[ac16fbb] APPLIED rdar://30568673
[967876e] APPLIED rdar://30568673
[44c2291] APPLIED rdar://30568673
[ceb1fac] APPLIED rdar://30568673
[c95febb] APPLIED rdar://30568673
[b6e9cf4] APPLIED rdar://30568673
[e199473] APPLIED rdar://30568673
[3767ac7] APPLIED rdar://30568673
[10eb0e4] APPLIED rdar://30568673
[787dd92] APPLIED rdar://30568673
[ba4cac5] APPLIED rdar://30568673
[7974138] APPLIED rdar://30568673
[cd12dcb] APPLIED rdar://32283666
[ff05109] APPLIED rdar://32283666
[73315ee] APPLIED rdar://32283666
[fcc1924] APPLIED rdar://32283666
[272e818] APPLIED rdar://32283666
[b6f8908] APPLIED rdar://32283666
[a6c16d0] APPLIED rdar://32283666
[1cc64e1] APPLIED rdar://32283666
[d137aa4] APPLIED rdar://32283666
[a69853f] APPLIED rdar://32283666
[eea0667] APPLIED rdar://32283666
[f84d21d] APPLIED rdar://32283666
[3da8398] APPLIED rdar://32283666
[2df80a3] APPLIED rdar://32283666
[97a2f06] APPLIED rdar://32283666
[f76b8f5] APPLIED rdar://32283666
[3828fbb] APPLIED rdar://32283666
[5e8789e] APPLIED rdar://32283666
[3fba60a] APPLIED rdar://32283666
[d6eb245] APPLIED rdar://32283666
[0b6c22e] APPLIED rdar://33531111
[5a3c02a] APPLIED rdar://33531111
[22df1e7] APPLIED rdar://33531111
[21273de] APPLIED rdar://33531111
[dc1857c] APPLIED rdar://33531111
[56f36b6] APPLIED rdar://33531111
[c87c6bb] APPLIED rdar://33531111
[b791d23] APPLIED rdar://33531111
[c2d0c49] APPLIED rdar://33531111
[1d25040] APPLIED rdar://33531111
[ab89c6c] APPLIED rdar://33531111
[e591e7e] APPLIED rdar://33531111
[ded5bab] APPLIED rdar://33531111
[ce90d0c] APPLIED rdar://33531111
[69c8f3e] APPLIED rdar://33531111
[23a3a84] APPLIED rdar://33531111
[79b7529] APPLIED rdar://33531111
[f8e71eb] APPLIED rdar://33531111
[8947dcf] APPLIED rdar://33531111
[5ad9208] APPLIED rdar://33531111
[698d085] APPLIED rdar://33531111
[ce1ce45] APPLIED rdar://35017478
[291f34d] APPLIED rdar://35017478
[666df60] APPLIED rdar://35017478
[80dd736] APPLIED rdar://35017478
[0fd5a69] APPLIED rdar://35017478
[0e35ed9] APPLIED rdar://35017478
[70ce56b] APPLIED rdar://35017478
[40fc1f3] APPLIED rdar://35017478
[9ec74ed] APPLIED rdar://35017478
[7f330ed] APPLIED rdar://35017478
[947b51c] APPLIED rdar://35017478
[295f676] APPLIED rdar://35017478
[48196a2] APPLIED rdar://35017478
[a28fc2b] APPLIED rdar://35017478
[791ce5d] APPLIED rdar://35017478
[0d0a998] APPLIED rdar://35017478
[29329b5] APPLIED rdar://35017478
[141403a] APPLIED rdar://35017478
[b7f1beb] APPLIED rdar://35017478
[7ef9cde] APPLIED rdar://35017478
[12c9ca8] APPLIED rdar://35017478
[6d6dc2e] APPLIED rdar://40252515
[4a9833d] APPLIED rdar://40252515
[f88e382] APPLIED rdar://40252515
[bfa9aa7] APPLIED rdar://40252515
[44f3640] APPLIED rdar://40252515
[3b06f54] APPLIED rdar://40252515
[e245cbe] APPLIED rdar://40252515
[2a539d6] APPLIED rdar://40252515
[e52c174] APPLIED rdar://40252515
[723bd98] APPLIED rdar://40252515
[7e7a579] APPLIED rdar://40252515
[244a5fe] APPLIED rdar://40252515
[8b72f76] APPLIED rdar://40252515
[f3531a2] APPLIED rdar://40252515
[5cf8acb] APPLIED rdar://40252515
[dc01e36] APPLIED rdar://40252515
[2d6d1fd] APPLIED rdar://40252515
[fdd671d] APPLIED rdar://40252515
[698220e] APPLIED rdar://40252515
[9c792ac] APPLIED rdar://40252515
[b5ec5d8] APPLIED rdar://40252515
[9295346] APPLIED rdar://40252515
[bbf03ca] APPLIED rdar://40252515
[8d3aa22] APPLIED rdar://40252515
[f151b33] APPLIED rdar://40252515
[f6e6917] APPLIED rdar://40252515
[f83b5a4] APPLIED rdar://40252515
[c4d6402] APPLIED rdar://40252515
[1457de8] APPLIED rdar://40252515
[c025baa] APPLIED rdar://40252515
[a618b46] APPLIED rdar://40252515
[e723a8e] APPLIED rdar://44568645
[4ac77b7] APPLIED rdar://44568645
[03696d7] APPLIED rdar://44568645
[44f67b2] APPLIED rdar://44568645
[b15ee59] APPLIED rdar://44568645
[d29ed37] APPLIED rdar://44568645
[65ebc0c] APPLIED rdar://44568645
[93c64d8] APPLIED rdar://44568645
[1271df6] APPLIED rdar://44568645
[84ac6ac] APPLIED rdar://44568645
[30d3c8c] APPLIED rdar://44568645
[12ff819] APPLIED rdar://44568645
[82342ee] APPLIED rdar://44568645
[b13a51e] APPLIED rdar://44568645
[6bf3065] APPLIED rdar://44568645
[631821c] APPLIED rdar://44568645
[e764f34] APPLIED rdar://44568645
[ff1daf8] APPLIED rdar://44568645
[b863538] APPLIED rdar://44568645
[ba3933d] APPLIED rdar://44568645
[9c48a80] APPLIED rdar://44568645
[5f49e8b] APPLIED rdar://44568645
[653a523] APPLIED rdar://44568645
[ac5f4c4] APPLIED rdar://44568645
[57139c6] APPLIED rdar://44568645
[ba74b6a] APPLIED rdar://44568645
[3975b58] APPLIED rdar://44568645
[81dc900] APPLIED rdar://44568645
[6162a1d] APPLIED rdar://44568645

24
Telegram/ThirdParty/dispatch/README.md vendored Normal file
View File

@@ -0,0 +1,24 @@
# Grand Central Dispatch
Grand Central Dispatch (GCD or libdispatch) provides comprehensive support for concurrent code execution on multicore hardware.
libdispatch is currently available on all Darwin platforms. This project aims to make a modern version of libdispatch available on all other Swift platforms. To do this, we will implement as much of the portable subset of the API as possible, using the existing open source C implementation.
libdispatch on Darwin is a combination of logic in the `xnu` kernel alongside the user-space Library. The kernel has the most information available to balance workload across the entire system. As a first step, however, we believe it is useful to bring up the basic functionality of the library using user-space pthread primitives on Linux. Eventually, a Linux kernel module could be developed to support more informed thread scheduling.
## Project Status
A port of libdispatch to Linux has been completed. On Linux, since Swift 3, swift-corelibs-libdispatch has been included in all Swift releases and is used by other swift-corelibs projects.
Opportunities to contribute and on-going work include:
1. Develop a test suite for the Swift APIs of libdispatch.
2. Enhance libdispatch as needed to support Swift language evolution and the needs of the other Core Libraries projects.
## Build and Install
For detailed instructions on building and installing libdispatch, see [INSTALL.md](INSTALL.md)
## Testing
For detailed instructions on testing libdispatch, see [TESTING.md](TESTING.md)

27
Telegram/ThirdParty/dispatch/TESTING.md vendored Normal file
View File

@@ -0,0 +1,27 @@
## Testing libdispatch
### Running tests
A C-based test suite can be found in the tests subdirectory.
It uses the automake testing harness to execute the tests.
A default set of tests that are always expected to pass can
be executed by doing
```
make check
```
An extended test suite that includes some tests that may fail
occasionally can be enabled at configure time:
```
./configure --enable-extended-test-suite
make check
```
### Additional prerequisites
A few test cases require additional packages to be installed.
In particular, several IO tests assume /usr/bin/vi is available
as an input file and will fail if it is not present.

View File

@@ -0,0 +1,259 @@
/* Define if building pthread work queues from source */
#cmakedefine01 DISPATCH_USE_INTERNAL_WORKQUEUE
/* Enable usage of thread local storage via _Thread_local */
#cmakedefine01 DISPATCH_USE_THREAD_LOCAL_STORAGE
/* Define to 1 if you have the declaration of `CLOCK_MONOTONIC', and to 0 if
you don't. */
#cmakedefine01 HAVE_DECL_CLOCK_MONOTONIC
/* Define to 1 if you have the declaration of `CLOCK_REALTIME', and to 0 if
you don't. */
#cmakedefine01 HAVE_DECL_CLOCK_REALTIME
/* Define to 1 if you have the declaration of `CLOCK_UPTIME', and to 0 if you
don't. */
#cmakedefine01 HAVE_DECL_CLOCK_UPTIME
/* Define to 1 if you have the declaration of `CLOCK_UPTIME_FAST', and to 0 if
you don't. */
#cmakedefine01 HAVE_DECL_CLOCK_UPTIME_FAST
/* Define to 1 if you have the declaration of `CLOCK_MONOTONIC_COARSE', and to
0 if you don't. */
#cmakedefine01 HAVE_CLOCK_MONOTONIC_COARSE
/* Define to 1 if you have the declaration of `FD_COPY', and to 0 if you
don't. */
#cmakedefine01 HAVE_DECL_FD_COPY
/* Define to 1 if you have the declaration of `NOTE_LOWAT', and to 0 if you
don't. */
#cmakedefine01 HAVE_DECL_NOTE_LOWAT
/* Define to 1 if you have the declaration of `NOTE_NONE', and to 0 if you
don't. */
#cmakedefine01 HAVE_DECL_NOTE_NONE
/* Define to 1 if you have the declaration of `NOTE_REAP', and to 0 if you
don't. */
#cmakedefine01 HAVE_DECL_NOTE_REAP
/* Define to 1 if you have the declaration of `NOTE_REVOKE', and to 0 if you
don't. */
#cmakedefine01 HAVE_DECL_NOTE_REVOKE
/* Define to 1 if you have the declaration of `NOTE_SIGNAL', and to 0 if you
don't. */
#cmakedefine01 HAVE_DECL_NOTE_SIGNAL
/* Define to 1 if you have the declaration of `POSIX_SPAWN_START_SUSPENDED',
and to 0 if you don't. */
#cmakedefine01 HAVE_DECL_POSIX_SPAWN_START_SUSPENDED
/* Define to 1 if you have the declaration of `program_invocation_short_name',
and to 0 if you don't. */
#cmakedefine01 HAVE_DECL_PROGRAM_INVOCATION_SHORT_NAME
/* Define to 1 if you have the declaration of `SIGEMT', and to 0 if you don't.
*/
#cmakedefine01 HAVE_DECL_SIGEMT
/* Define to 1 if you have the declaration of `VQ_DESIRED_DISK', and to 0 if
you don't. */
#cmakedefine01 HAVE_DECL_VQ_DESIRED_DISK
/* Define to 1 if you have the declaration of `VQ_NEARLOWDISK', and to 0 if
you don't. */
#cmakedefine01 HAVE_DECL_VQ_NEARLOWDISK
/* Define to 1 if you have the declaration of `VQ_QUOTA', and to 0 if you
don't. */
#cmakedefine01 HAVE_DECL_VQ_QUOTA
/* Define to 1 if you have the declaration of `VQ_UPDATE', and to 0 if you
don't. */
#cmakedefine01 HAVE_DECL_VQ_UPDATE
/* Define to 1 if you have the declaration of `VQ_VERYLOWDISK', and to 0 if
you don't. */
#cmakedefine01 HAVE_DECL_VQ_VERYLOWDISK
/* Define to 1 if you have the declaration of `VQ_FREE_SPACE_CHANGE', and to 0 if
you don't. */
#cmakedefine01 HAVE_DECL_VQ_FREE_SPACE_CHANGE
/* Define to 1 if you have the <dlfcn.h> header file. */
#cmakedefine01 HAVE_DLFCN_H
/* Define to 1 if you have the <fcntl.h> header file. */
#cmakedefine01 HAVE_FCNTL_H
/* Define to 1 if you have the `getprogname' function. */
#cmakedefine01 HAVE_GETPROGNAME
/* Define to 1 if you have the <inttypes.h> header file. */
#cmakedefine01 HAVE_INTTYPES_H
/* Define if Apple leaks program is present */
#cmakedefine HAVE_LEAKS
/* Define to 1 if you have the <libkern/OSAtomic.h> header file. */
#cmakedefine HAVE_LIBKERN_OSATOMIC_H
/* Define to 1 if you have the <libkern/OSCrossEndian.h> header file. */
#cmakedefine HAVE_LIBKERN_OSCROSSENDIAN_H
/* Define to 1 if you have the <libproc_internal.h> header file. */
#cmakedefine HAVE_LIBPROC_INTERNAL_H
/* Define if mach is present */
#cmakedefine HAVE_MACH
/* Define to 1 if you have the `mach_absolute_time' function. */
#cmakedefine HAVE_MACH_ABSOLUTE_TIME
/* Define to 1 if you have the `mach_approximate_time' function. */
#cmakedefine HAVE_MACH_APPROXIMATE_TIME
/* Define to 1 if you have the `mach_port_construct' function. */
#cmakedefine HAVE_MACH_PORT_CONSTRUCT
/* Define to 1 if you have the `malloc_create_zone' function. */
#cmakedefine HAVE_MALLOC_CREATE_ZONE
/* Define to 1 if you have the <malloc/malloc.h> header file. */
#cmakedefine HAVE_MALLOC_MALLOC_H
/* Define to 1 if you have the <memory.h> header file. */
#cmakedefine01 HAVE_MEMORY_H
/* Define if __builtin_trap marked noreturn */
#cmakedefine01 HAVE_NORETURN_BUILTIN_TRAP
/* Define if you have the Objective-C runtime */
#cmakedefine HAVE_OBJC
/* Define to 1 if you have the `posix_fadvise' function. */
#cmakedefine HAVE_POSIX_FADVISE
/* Define to 1 if you have the `posix_spawnp' function. */
#cmakedefine HAVE_POSIX_SPAWNP
/* Define to 1 if you have the `pthread_key_init_np' function. */
#cmakedefine HAVE_PTHREAD_KEY_INIT_NP
/* Define to 1 if you have the `pthread_attr_setcpupercent_np' function. */
#cmakedefine HAVE_PTHREAD_ATTR_SETCPUPERCENT_NP
/* Define to 1 if you have the <pthread_machdep.h> header file. */
#cmakedefine HAVE_PTHREAD_MACHDEP_H
/* Define to 1 if you have the `pthread_main_np' function. */
#cmakedefine01 HAVE_PTHREAD_MAIN_NP
/* Define to 1 if you have the `pthread_yield_np' function. */
#cmakedefine01 HAVE_PTHREAD_YIELD_NP
/* Define to 1 if you have the <pthread_np.h> header file. */
#cmakedefine01 HAVE_PTHREAD_NP_H
/* Define to 1 if you have the <pthread/qos.h> header file. */
#cmakedefine HAVE_PTHREAD_QOS_H
/* Define if pthread work queues are present */
#cmakedefine01 HAVE_PTHREAD_WORKQUEUES
/* Define to 1 if you have the <pthread_workqueue.h> header file. */
#cmakedefine HAVE_PTHREAD_WORKQUEUE_H
/* Define to 1 if you have the <pthread/workqueue_private.h> header file. */
#cmakedefine HAVE_PTHREAD_WORKQUEUE_PRIVATE_H
/* Define to 1 if you have the <stdint.h> header file. */
#cmakedefine01 HAVE_STDINT_H
/* Define to 1 if you have the <stdlib.h> header file. */
#cmakedefine01 HAVE_STDLIB_H
/* Define to 1 if you have the <strings.h> header file. */
#cmakedefine01 HAVE_STRINGS_H
/* Define to 1 if you have the <string.h> header file. */
#cmakedefine01 HAVE_STRING_H
/* Define to 1 if you have the `strlcpy' function. */
#cmakedefine01 HAVE_STRLCPY
/* Define if building for Swift */
#undef HAVE_SWIFT
/* Define to 1 if you have the `sysconf' function. */
#cmakedefine01 HAVE_SYSCONF
/* Define to 1 if you have the <sys/guarded.h> header file. */
#cmakedefine HAVE_SYS_GUARDED_H
/* Define to 1 if you have the <sys/stat.h> header file. */
#cmakedefine01 HAVE_SYS_STAT_H
/* Define to 1 if you have the <sys/types.h> header file. */
#cmakedefine01 HAVE_SYS_TYPES_H
/* Define to 1 if you have the <TargetConditionals.h> header file. */
#cmakedefine HAVE_TARGETCONDITIONALS_H
/* Define to 1 if you have the `_pthread_workqueue_init' function. */
#cmakedefine HAVE__PTHREAD_WORKQUEUE_INIT
/* Define to use non-portable pthread TSD optimizations for Mac OS X) */
#cmakedefine USE_APPLE_TSD_OPTIMIZATIONS
/* Define to tag libdispatch_init as a constructor */
#cmakedefine01 USE_LIBDISPATCH_INIT_CONSTRUCTOR
/* Define to use Mach semaphores */
#cmakedefine USE_MACH_SEM
/* Define to use POSIX semaphores */
#cmakedefine01 USE_POSIX_SEM
/* Enable extensions on AIX 3, Interix. */
#ifndef _ALL_SOURCE
#cmakedefine01 _ALL_SOURCE
#endif
/* Enable GNU extensions on systems that have them. */
#ifndef _GNU_SOURCE
#cmakedefine _GNU_SOURCE
#endif
/* Enable threading extensions on Solaris. */
#ifndef _POSIX_PTHREAD_SEMANTICS
#cmakedefine01 _POSIX_PTHREAD_SEMANTICS
#endif
/* Enable extensions on HP NonStop. */
#ifndef _TANDEM_SOURCE
#cmakedefine01 _TANDEM_SOURCE
#endif
/* Enable general extensions on Solaris. */
#ifndef __EXTENSIONS__
#cmakedefine01 __EXTENSIONS__
#endif
/* Version number of package */
#define VERSION "${PROJECT_VERSION}"
/* Define to 1 if on MINIX. */
#cmakedefine _MINIX
/* Define to 2 if the system does not provide POSIX.1 features except with
this defined. */
#cmakedefine _POSIX_1_SOURCE
/* Define to 1 if you need to in order for `stat' and other things to work. */
#cmakedefine _POSIX_SOURCE
/* Define if using Darwin $NOCANCEL */
#cmakedefine __DARWIN_NON_CANCELABLE

View File

@@ -0,0 +1,7 @@
set(DISPATCH_EXPORTS_FILE ${CMAKE_CURRENT_BINARY_DIR}/dispatchExports.cmake)
configure_file(dispatchConfig.cmake.in
${CMAKE_CURRENT_BINARY_DIR}/dispatchConfig.cmake)
get_property(DISPATCH_EXPORTS GLOBAL PROPERTY DISPATCH_EXPORTS)
export(TARGETS ${DISPATCH_EXPORTS} FILE ${DISPATCH_EXPORTS_FILE})

View File

@@ -0,0 +1,5 @@
# clang-cl interprets paths starting with /U as macro undefines, so we need to
# put a -- before the input file path to force it to be treated as a path.
string(REPLACE "-c <SOURCE>" "-c -- <SOURCE>" CMAKE_C_COMPILE_OBJECT "${CMAKE_C_COMPILE_OBJECT}")
string(REPLACE "-c <SOURCE>" "-c -- <SOURCE>" CMAKE_CXX_COMPILE_OBJECT "${CMAKE_CXX_COMPILE_OBJECT}")

View File

@@ -0,0 +1,26 @@
function(dtrace_usdt_probe script)
set(options)
set(single_parameter_options TARGET_NAME OUTPUT_SOURCES)
set(multiple_parameter_options)
cmake_parse_arguments("" "${options}" "${single_parameter_options}" "${multiple_parameter_options}" ${ARGN})
get_filename_component(script_we ${script} NAME_WE)
add_custom_command(OUTPUT
${CMAKE_CURRENT_BINARY_DIR}/${script_we}.h
COMMAND
${dtrace_EXECUTABLE} -h -s ${script} -o ${CMAKE_CURRENT_BINARY_DIR}/${script_we}.h
DEPENDS
${script})
add_custom_target(dtrace-usdt-header-${script_we}
DEPENDS
${CMAKE_CURRENT_BINARY_DIR}/${script_we}.h)
if(_TARGET_NAME)
set(${_TARGET_NAME} dtrace-usdt-header-${script_we} PARENT_SCOPE)
endif()
if(_OUTPUT_SOURCES)
set(${_OUTPUT_SOURCES} ${CMAKE_CURRENT_BINARY_DIR}/${script_we}.h PARENT_SCOPE)
endif()
endfunction()

View File

@@ -0,0 +1,43 @@
set(WITH_APPLE_PTHREAD_SOURCE "" CACHE PATH "Path to Apple's libpthread")
set(WITH_APPLE_LIBPLATFORM_SOURCE "" CACHE PATH "Path to Apple's libplatform")
set(WITH_APPLE_LIBCLOSURE_SOURCE "" CACHE PATH "Path to Apple's libclosure")
set(WITH_APPLE_XNU_SOURCE "" CACHE PATH "Path to Apple's XNU")
set(WITH_APPLE_OBJC4_SOURCE "" CACHE PATH "Path to Apple's ObjC4")
if(WITH_APPLE_PTHREAD_SOURCE)
include_directories(SYSTEM "${WITH_APPLE_PTHREAD_SOURCE}")
endif()
if(WITH_APPLE_LIBPLATFORM_SOURCE)
include_directories(SYSTEM "${WITH_APPLE_LIBPLATFORM_SOURCE}/include")
endif()
if(WITH_APPLE_LIBCLOSURE_SOURCE)
include_directories(SYSTEM "${WITH_APPLE_LIBCLOSURE_SOURCE}")
endif()
if(WITH_APPLE_XNU_SOURCE)
# FIXME(compnerd) this should use -idirafter
include_directories("${WITH_APPLE_XNU_SOURCE}/libkern")
include_directories(SYSTEM
"${WITH_APPLE_XNU_SOURCE}/bsd"
"${WITH_APPLE_XNU_SOURCE}/libsyscall"
"${WITH_APPLE_XNU_SOURCE}/libsyscall/wrappers/libproc")
# hack for xnu/bsd/sys/event.h EVFILT_SOCK declaration
add_definitions(-DPRIVATE=1)
endif()
if(IS_DIRECTORY "/System/Library/Frameworks/System.framework/PrivateHeaders")
include_directories(SYSTEM
"/System/Library/Frameworks/System.framework/PrivateHeaders")
endif()
option(ENABLE_APPLE_TSD_OPTIMIZATIONS "use non-portable pthread TSD optimizations" OFF)
if(ENABLE_APPLE_TSD_OPTIMIZATIONS)
set(USE_APPLE_TSD_OPTIMIZATIONS 1)
else()
set(USE_APPLE_TSD_OPTIMIZATIONS 0)
endif()
# TODO(compnerd) link in libpthread headers

View File

@@ -0,0 +1,84 @@
if("${CMAKE_C_SIMULATE_ID}" STREQUAL "MSVC")
# TODO: someone needs to provide the msvc equivalent warning flags
elseif(WIN32)
# Tareting Windows but using a non-MSVC compiler. Set -fms-extensions
# so that we can use __popcnt64
add_compile_options($<$<OR:$<COMPILE_LANGUAGE:C>,$<COMPILE_LANGUAGE:CXX>>:-fms-extensions>)
else()
add_compile_options($<$<OR:$<COMPILE_LANGUAGE:C>,$<COMPILE_LANGUAGE:CXX>>:-Werror>)
add_compile_options($<$<OR:$<COMPILE_LANGUAGE:C>,$<COMPILE_LANGUAGE:CXX>>:-Wall>)
add_compile_options($<$<OR:$<COMPILE_LANGUAGE:C>,$<COMPILE_LANGUAGE:CXX>>:-Wextra>)
add_compile_options($<$<OR:$<COMPILE_LANGUAGE:C>,$<COMPILE_LANGUAGE:CXX>>:-Warray-bounds-pointer-arithmetic>)
add_compile_options($<$<OR:$<COMPILE_LANGUAGE:C>,$<COMPILE_LANGUAGE:CXX>>:-Wassign-enum>)
add_compile_options($<$<OR:$<COMPILE_LANGUAGE:C>,$<COMPILE_LANGUAGE:CXX>>:-Watomic-properties>)
add_compile_options($<$<OR:$<COMPILE_LANGUAGE:C>,$<COMPILE_LANGUAGE:CXX>>:-Wcomma>)
add_compile_options($<$<OR:$<COMPILE_LANGUAGE:C>,$<COMPILE_LANGUAGE:CXX>>:-Wconditional-uninitialized>)
add_compile_options($<$<OR:$<COMPILE_LANGUAGE:C>,$<COMPILE_LANGUAGE:CXX>>:-Wconversion>)
add_compile_options($<$<OR:$<COMPILE_LANGUAGE:C>,$<COMPILE_LANGUAGE:CXX>>:-Wcovered-switch-default>)
add_compile_options($<$<OR:$<COMPILE_LANGUAGE:C>,$<COMPILE_LANGUAGE:CXX>>:-Wdate-time>)
add_compile_options($<$<OR:$<COMPILE_LANGUAGE:C>,$<COMPILE_LANGUAGE:CXX>>:-Wdeprecated>)
add_compile_options($<$<OR:$<COMPILE_LANGUAGE:C>,$<COMPILE_LANGUAGE:CXX>>:-Wdocumentation>)
add_compile_options($<$<OR:$<COMPILE_LANGUAGE:C>,$<COMPILE_LANGUAGE:CXX>>:-Wdouble-promotion>)
add_compile_options($<$<OR:$<COMPILE_LANGUAGE:C>,$<COMPILE_LANGUAGE:CXX>>:-Wduplicate-enum>)
add_compile_options($<$<OR:$<COMPILE_LANGUAGE:C>,$<COMPILE_LANGUAGE:CXX>>:-Wexpansion-to-defined>)
add_compile_options($<$<OR:$<COMPILE_LANGUAGE:C>,$<COMPILE_LANGUAGE:CXX>>:-Wfloat-equal>)
add_compile_options($<$<OR:$<COMPILE_LANGUAGE:C>,$<COMPILE_LANGUAGE:CXX>>:-Widiomatic-parentheses>)
add_compile_options($<$<OR:$<COMPILE_LANGUAGE:C>,$<COMPILE_LANGUAGE:CXX>>:-Winfinite-recursion>)
add_compile_options($<$<OR:$<COMPILE_LANGUAGE:C>,$<COMPILE_LANGUAGE:CXX>>:-Wmissing-prototypes>)
add_compile_options($<$<OR:$<COMPILE_LANGUAGE:C>,$<COMPILE_LANGUAGE:CXX>>:-Wnewline-eof>)
add_compile_options($<$<OR:$<COMPILE_LANGUAGE:C>,$<COMPILE_LANGUAGE:CXX>>:-Wnullable-to-nonnull-conversion>)
add_compile_options($<$<OR:$<COMPILE_LANGUAGE:C>,$<COMPILE_LANGUAGE:CXX>>:-Wobjc-interface-ivars>)
add_compile_options($<$<OR:$<COMPILE_LANGUAGE:C>,$<COMPILE_LANGUAGE:CXX>>:-Wover-aligned>)
add_compile_options($<$<OR:$<COMPILE_LANGUAGE:C>,$<COMPILE_LANGUAGE:CXX>>:-Wpacked>)
add_compile_options($<$<OR:$<COMPILE_LANGUAGE:C>,$<COMPILE_LANGUAGE:CXX>>:-Wpointer-arith>)
add_compile_options($<$<OR:$<COMPILE_LANGUAGE:C>,$<COMPILE_LANGUAGE:CXX>>:-Wselector>)
add_compile_options($<$<OR:$<COMPILE_LANGUAGE:C>,$<COMPILE_LANGUAGE:CXX>>:-Wshadow>)
add_compile_options($<$<OR:$<COMPILE_LANGUAGE:C>,$<COMPILE_LANGUAGE:CXX>>:-Wshorten-64-to-32>)
add_compile_options($<$<OR:$<COMPILE_LANGUAGE:C>,$<COMPILE_LANGUAGE:CXX>>:-Wsign-conversion>)
add_compile_options($<$<OR:$<COMPILE_LANGUAGE:C>,$<COMPILE_LANGUAGE:CXX>>:-Wstatic-in-inline>)
add_compile_options($<$<OR:$<COMPILE_LANGUAGE:C>,$<COMPILE_LANGUAGE:CXX>>:-Wsuper-class-method-mismatch>)
add_compile_options($<$<OR:$<COMPILE_LANGUAGE:C>,$<COMPILE_LANGUAGE:CXX>>:-Wswitch>)
add_compile_options($<$<OR:$<COMPILE_LANGUAGE:C>,$<COMPILE_LANGUAGE:CXX>>:-Wunguarded-availability>)
add_compile_options($<$<OR:$<COMPILE_LANGUAGE:C>,$<COMPILE_LANGUAGE:CXX>>:-Wunreachable-code>)
add_compile_options($<$<OR:$<COMPILE_LANGUAGE:C>,$<COMPILE_LANGUAGE:CXX>>:-Wunused>)
add_compile_options($<$<OR:$<COMPILE_LANGUAGE:C>,$<COMPILE_LANGUAGE:CXX>>:-Wno-unknown-warning-option>)
add_compile_options($<$<OR:$<COMPILE_LANGUAGE:C>,$<COMPILE_LANGUAGE:CXX>>:-Wno-trigraphs>)
add_compile_options($<$<OR:$<COMPILE_LANGUAGE:C>,$<COMPILE_LANGUAGE:CXX>>:-Wno-four-char-constants>)
add_compile_options($<$<OR:$<COMPILE_LANGUAGE:C>,$<COMPILE_LANGUAGE:CXX>>:-Wno-disabled-macro-expansion>)
add_compile_options($<$<OR:$<COMPILE_LANGUAGE:C>,$<COMPILE_LANGUAGE:CXX>>:-Wno-pedantic>)
add_compile_options($<$<OR:$<COMPILE_LANGUAGE:C>,$<COMPILE_LANGUAGE:CXX>>:-Wno-bad-function-cast>)
add_compile_options($<$<OR:$<COMPILE_LANGUAGE:C>,$<COMPILE_LANGUAGE:CXX>>:-Wno-c++-compat>)
add_compile_options($<$<OR:$<COMPILE_LANGUAGE:C>,$<COMPILE_LANGUAGE:CXX>>:-Wno-c++98-compat>)
add_compile_options($<$<OR:$<COMPILE_LANGUAGE:C>,$<COMPILE_LANGUAGE:CXX>>:-Wno-c++98-compat-pedantic>)
add_compile_options($<$<OR:$<COMPILE_LANGUAGE:C>,$<COMPILE_LANGUAGE:CXX>>:-Wno-cast-align>)
add_compile_options($<$<OR:$<COMPILE_LANGUAGE:C>,$<COMPILE_LANGUAGE:CXX>>:-Wno-cast-qual>)
add_compile_options($<$<OR:$<COMPILE_LANGUAGE:C>,$<COMPILE_LANGUAGE:CXX>>:-Wno-documentation-unknown-command>)
add_compile_options($<$<OR:$<COMPILE_LANGUAGE:C>,$<COMPILE_LANGUAGE:CXX>>:-Wno-format-nonliteral>)
add_compile_options($<$<OR:$<COMPILE_LANGUAGE:C>,$<COMPILE_LANGUAGE:CXX>>:-Wno-missing-variable-declarations>)
add_compile_options($<$<OR:$<COMPILE_LANGUAGE:C>,$<COMPILE_LANGUAGE:CXX>>:-Wno-old-style-cast>)
add_compile_options($<$<OR:$<COMPILE_LANGUAGE:C>,$<COMPILE_LANGUAGE:CXX>>:-Wno-padded>)
add_compile_options($<$<OR:$<COMPILE_LANGUAGE:C>,$<COMPILE_LANGUAGE:CXX>>:-Wno-reserved-id-macro>)
add_compile_options($<$<OR:$<COMPILE_LANGUAGE:C>,$<COMPILE_LANGUAGE:CXX>>:-Wno-shift-sign-overflow>)
add_compile_options($<$<OR:$<COMPILE_LANGUAGE:C>,$<COMPILE_LANGUAGE:CXX>>:-Wno-undef>)
add_compile_options($<$<OR:$<COMPILE_LANGUAGE:C>,$<COMPILE_LANGUAGE:CXX>>:-Wno-unreachable-code-aggressive>)
add_compile_options($<$<OR:$<COMPILE_LANGUAGE:C>,$<COMPILE_LANGUAGE:CXX>>:-Wno-unused-macros>)
add_compile_options($<$<OR:$<COMPILE_LANGUAGE:C>,$<COMPILE_LANGUAGE:CXX>>:-Wno-used-but-marked-unused>)
add_compile_options($<$<OR:$<COMPILE_LANGUAGE:C>,$<COMPILE_LANGUAGE:CXX>>:-Wno-void-pointer-to-int-cast>)
add_compile_options($<$<OR:$<COMPILE_LANGUAGE:C>,$<COMPILE_LANGUAGE:CXX>>:-Wno-vla>)
if(CMAKE_SYSTEM_NAME STREQUAL Android)
add_compile_options($<$<OR:$<COMPILE_LANGUAGE:C>,$<COMPILE_LANGUAGE:CXX>>:-Wno-incompatible-function-pointer-types>)
add_compile_options($<$<OR:$<COMPILE_LANGUAGE:C>,$<COMPILE_LANGUAGE:CXX>>:-Wno-implicit-function-declaration>)
add_compile_options($<$<OR:$<COMPILE_LANGUAGE:C>,$<COMPILE_LANGUAGE:CXX>>:-Wno-conversion>)
add_compile_options($<$<OR:$<COMPILE_LANGUAGE:C>,$<COMPILE_LANGUAGE:CXX>>:-Wno-int-conversion>)
add_compile_options($<$<OR:$<COMPILE_LANGUAGE:C>,$<COMPILE_LANGUAGE:CXX>>:-Wno-shorten-64-to-32>)
endif()
add_compile_options($<$<OR:$<COMPILE_LANGUAGE:C>,$<COMPILE_LANGUAGE:CXX>>:-Wno-error=assign-enum>)
# Should re-enable after rdar://133498289 is fixed (ie. fixing the one mismatched cast in apply.c)
add_compile_options($<$<OR:$<COMPILE_LANGUAGE:C>,$<COMPILE_LANGUAGE:CXX>>:-Wno-cast-function-type-mismatch>)
add_compile_options($<$<OR:$<COMPILE_LANGUAGE:C>,$<COMPILE_LANGUAGE:CXX>>:-Wno-error=unknown-warning-option>)
endif()

View File

@@ -0,0 +1,44 @@
set(DISPATCH_USE_SANITIZER "" CACHE STRING
"Define the sanitizer used to build binaries and tests.")
if(CMAKE_SYSTEM_NAME STREQUAL Darwin AND DISPATCH_USE_SANITIZER)
message(FATAL_ERROR "building libdispatch with sanitization is not supported on Darwin")
endif()
if(DISPATCH_USE_SANITIZER)
# TODO(compnerd) ensure that the compiler supports these options before adding
# them. At the moment, assume that this will just be used with a GNU
# compatible driver and that the options are spelt correctly in light of that.
add_compile_options("-fno-omit-frame-pointer")
if(CMAKE_BUILD_TYPE MATCHES "Debug")
add_compile_options("-O1")
elseif(NOT CMAKE_BUILD_TYPE MATCHES "Debug" AND
NOT CMAKE_BUILD_TYPE MATCHES "RelWithDebInfo")
add_compile_options("-gline-tables-only")
endif()
if(LLVM_USE_SANITIZER STREQUAL "Address")
add_compile_options("-fsanitize=address")
elseif(DISPATCH_USE_SANITIZER MATCHES "Memory(WithOrigins)?")
add_compile_options("-fsanitize=memory")
if(DISPATCH_USE_SANITIZER STREQUAL "MemoryWithOrigins")
add_compile_options("-fsanitize-memory-track-origins")
endif()
elseif(DISPATCH_USE_SANITIZER STREQUAL "Undefined")
add_compile_options("-fsanitize=undefined")
add_compile_options("-fno-sanitize=vptr,function")
add_compile_options("-fno-sanitize-recover=all")
elseif(DISPATCH_USE_SANITIZER STREQUAL "Thread")
add_compile_options("-fsanitize=thread")
elseif(DISPATCH_USE_SANITIZER STREQUAL "Address;Undefined" OR
DISPATCH_USE_SANITIZER STREQUAL "Undefined;Address")
add_compile_options("-fsanitize=address,undefined")
add_compile_options("-fno-sanitize=vptr,function")
add_compile_options("-fno-sanitize-recover=all")
elseif(DISPATCH_USE_SANITIZER STREQUAL "Leaks")
add_compile_options("-fsanitize=leak")
else()
message(FATAL_ERROR "unsupported value of DISPATCH_USE_SANITIZER: ${DISPATCH_USE_SANITIZER}")
endif()
endif()

View File

@@ -0,0 +1,74 @@
function(dispatch_windows_arch_spelling arch var)
if(${arch} STREQUAL i686)
set(${var} x86 PARENT_SCOPE)
elseif(${arch} STREQUAL x86_64 OR ${arch} STREQUAL AMD64)
set(${var} x64 PARENT_SCOPE)
elseif(${arch} STREQUAL armv7)
set(${var} arm PARENT_SCOPE)
elseif(${arch} STREQUAL aarch64 OR ${arch} STREQUAL ARM64)
set(${var} arm64 PARENT_SCOPE)
else()
message(FATAL_ERROR "do not know MSVC spelling for ARCH: `${arch}`")
endif()
endfunction()
function(dispatch_verify_windows_environment_variables)
set(VCToolsInstallDir $ENV{VCToolsInstallDir})
set(UniversalCRTSdkDir $ENV{UniversalCRTSdkDir})
set(UCRTVersion $ENV{UCRTVersion})
if("${VCToolsInstallDir}" STREQUAL "")
message(SEND_ERROR "VCToolsInstallDir environment variable must be set")
endif()
if("${UniversalCRTSdkDir}" STREQUAL "")
message(SEND_ERROR "UniversalCRTSdkDir environment variable must be set")
endif()
if("${UCRTVersion}" STREQUAL "")
message(SEND_ERROR "UCRTVersion environment variable must be set")
endif()
endfunction()
function(dispatch_windows_include_for_arch arch var)
dispatch_verify_windows_environment_variables()
set(paths
"$ENV{VCToolsInstallDir}/include"
"$ENV{UniversalCRTSdkDir}/Include/$ENV{UCRTVersion}/ucrt"
"$ENV{UniversalCRTSdkDir}/Include/$ENV{UCRTVersion}/shared"
"$ENV{UniversalCRTSdkDir}/Include/$ENV{UCRTVersion}/um")
set(${var} ${paths} PARENT_SCOPE)
endfunction()
function(dispatch_windows_lib_for_arch arch var)
dispatch_verify_windows_environment_variables()
dispatch_windows_arch_spelling(${arch} ARCH)
set(paths)
if(${ARCH} STREQUAL x86)
list(APPEND paths "$ENV{VCToolsInstallDir}/Lib")
else()
list(APPEND paths "$ENV{VCToolsInstallDir}/Lib/${ARCH}")
endif()
list(APPEND paths
"$ENV{UniversalCRTSdkDir}/Lib/$ENV{UCRTVersion}/ucrt/${ARCH}"
"$ENV{UniversalCRTSdkDir}/Lib/$ENV{UCRTVersion}/um/${ARCH}")
set(${var} ${paths} PARENT_SCOPE)
endfunction()
function(dispatch_windows_generate_sdk_vfs_overlay flags)
dispatch_verify_windows_environment_variables()
get_filename_component(VCToolsInstallDir $ENV{VCToolsInstallDir} ABSOLUTE)
get_filename_component(UniversalCRTSdkDir $ENV{UniversalCRTSdkDir} ABSOLUTE)
set(UCRTVersion $ENV{UCRTVersion})
# TODO(compnerd) use a target to avoid re-creating this file all the time
configure_file("${PROJECT_SOURCE_DIR}/utils/WindowsSDKVFSOverlay.yaml.in"
"${PROJECT_BINARY_DIR}/windows-sdk-vfs-overlay.yaml"
@ONLY)
set(${flags}
-ivfsoverlay;"${PROJECT_BINARY_DIR}/windows-sdk-vfs-overlay.yaml"
PARENT_SCOPE)
endfunction()

View File

@@ -0,0 +1,48 @@
#.rst:
# FindBlocksRuntime
# -----------------
#
# Find libBlocksRuntime library and headers.
#
# The module defines the following variables:
#
# ##
#
# BlocksRuntime_FOUND - true if libBlocksRuntime was found
# BlocksRuntime_INCLUDE_DIR - include search path
# BlocksRuntime_LIBRARIES - libraries to link
if(BlocksRuntime_INCLUDE_DIR AND BlocksRuntime_LIBRARIES)
set(BlocksRuntime_FOUND TRUE)
else()
find_path(BlocksRuntime_INCLUDE_DIR
NAMES
Blocks.h
HINTS
${CMAKE_INSTALL_FULL_INCLUDEDIR})
find_library(BlocksRuntime_LIBRARIES
NAMES
BlocksRuntime libBlocksRuntime
HINTS
${CMAKE_INSTALL_FULL_LIBDIR})
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(BlocksRuntime
REQUIRED_VARS
BlocksRuntime_LIBRARIES
BlocksRuntime_INCLUDE_DIR)
mark_as_advanced(BlocksRuntime_LIBRARIES BlocksRuntime_INCLUDE_DIR)
endif()
if(BlocksRuntime_FOUND)
if(NOT TARGET BlocksRuntime::BlocksRuntime)
add_library(BlocksRuntime::BlocksRuntime UNKNOWN IMPORTED)
set_target_properties(BlocksRuntime::BlocksRuntime
PROPERTIES
IMPORTED_LOCATION
${BlocksRuntime_LIBRARIES}
INTERFACE_INCLUDE_DIRECTORIES
${BlocksRuntime_INCLUDE_DIR})
endif()
endif()

View File

@@ -0,0 +1,39 @@
#.rst:
# FindLibRT
# ---------
#
# Find librt library and headers.
#
# The mdoule defines the following variables:
#
# ::
#
# LibRT_FOUND - true if librt was found
# LibRT_INCLUDE_DIR - include search path
# LibRT_LIBRARIES - libraries to link
if(UNIX)
find_path(LibRT_INCLUDE_DIR
NAMES
time.h)
find_library(LibRT_LIBRARIES rt)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(LibRT
REQUIRED_VARS
LibRT_LIBRARIES
LibRT_INCLUDE_DIR)
if(LibRT_FOUND)
if(NOT TARGET RT::rt)
add_library(RT::rt UNKNOWN IMPORTED)
set_target_properties(RT::rt
PROPERTIES
IMPORTED_LOCATION ${LibRT_LIBRARIES}
INTERFACE_INCLUDE_DIRECTORIES ${LibRT_INCLUDE_DIR})
endif()
endif()
mark_as_advanced(LibRT_LIBRARIES LibRT_INCLUDE_DIR)
endif()

View File

@@ -0,0 +1,41 @@
# Returns the current achitecture name in a variable
#
# Usage:
# get_swift_host_arch(result_var_name)
#
# If the current architecture is supported by Swift, sets ${result_var_name}
# with the sanitized host architecture name derived from CMAKE_SYSTEM_PROCESSOR.
function(get_swift_host_arch result_var_name)
if("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "x86_64")
set("${result_var_name}" "x86_64" PARENT_SCOPE)
elseif ("${CMAKE_SYSTEM_PROCESSOR}" MATCHES "AArch64|aarch64|arm64|ARM64")
if(CMAKE_SYSTEM_NAME MATCHES Darwin)
set("${result_var_name}" "arm64" PARENT_SCOPE)
else()
set("${result_var_name}" "aarch64" PARENT_SCOPE)
endif()
elseif("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "ppc64")
set("${result_var_name}" "powerpc64" PARENT_SCOPE)
elseif("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "ppc64le")
set("${result_var_name}" "powerpc64le" PARENT_SCOPE)
elseif("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "s390x")
set("${result_var_name}" "s390x" PARENT_SCOPE)
elseif("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "armv6l")
set("${result_var_name}" "armv6" PARENT_SCOPE)
elseif("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "armv7-a")
set("${result_var_name}" "armv7" PARENT_SCOPE)
elseif("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "armv7l")
set("${result_var_name}" "armv7" PARENT_SCOPE)
elseif("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "AMD64")
set("${result_var_name}" "x86_64" PARENT_SCOPE)
elseif("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "IA64")
set("${result_var_name}" "itanium" PARENT_SCOPE)
elseif("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "x86")
set("${result_var_name}" "i686" PARENT_SCOPE)
elseif("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "i686")
set("${result_var_name}" "i686" PARENT_SCOPE)
else()
message(FATAL_ERROR "Unrecognized architecture on host system: ${CMAKE_SYSTEM_PROCESSOR}")
endif()
endfunction()

View File

@@ -0,0 +1,7 @@
set(DISPATCH_HAS_SWIFT_SDK_OVERLAY @ENABLE_SWIFT@)
if(NOT TARGET dispatch)
include(@DISPATCH_EXPORTS_FILE@)
endif()

View File

@@ -0,0 +1,35 @@
if(CMAKE_SYSTEM_NAME STREQUAL Darwin)
set(DISPATCH_MODULE_MAP ${PROJECT_SOURCE_DIR}/dispatch/darwin/module.modulemap)
elseif(BUILD_SHARED_LIBS)
set(DISPATCH_MODULE_MAP ${PROJECT_SOURCE_DIR}/dispatch/generic/module.modulemap)
else()
set(DISPATCH_MODULE_MAP ${PROJECT_SOURCE_DIR}/dispatch/generic_static/module.modulemap)
endif()
configure_file(dispatch-vfs.yaml.in
${CMAKE_BINARY_DIR}/dispatch-vfs-overlay.yaml
@ONLY)
install(FILES
base.h
block.h
data.h
dispatch.h
group.h
introspection.h
io.h
object.h
once.h
queue.h
semaphore.h
source.h
time.h
DESTINATION
"${INSTALL_DISPATCH_HEADERS_DIR}")
if(ENABLE_SWIFT)
install(FILES
${DISPATCH_MODULE_MAP}
DESTINATION
"${INSTALL_DISPATCH_HEADERS_DIR}")
endif()

View File

@@ -0,0 +1,326 @@
/*
* Copyright (c) 2008-2012 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
#ifndef __has_builtin
#define __has_builtin(x) 0
#endif
#ifndef __has_include
#define __has_include(x) 0
#endif
#ifndef __has_feature
#define __has_feature(x) 0
#endif
#ifndef __has_attribute
#define __has_attribute(x) 0
#endif
#ifndef __has_extension
#define __has_extension(x) 0
#endif
#if __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__ && __clang_major__ < 3
// 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_CONST __attribute__((__const__))
#define DISPATCH_WARN_RESULT __attribute__((__warn_unused_result__))
#define DISPATCH_MALLOC __attribute__((__malloc__))
#define DISPATCH_ALWAYS_INLINE __attribute__((__always_inline__))
#define DISPATCH_UNAVAILABLE __attribute__((__unavailable__))
#define DISPATCH_UNAVAILABLE_MSG(msg) __attribute__((__unavailable__(msg)))
#elif defined(_MSC_VER)
#define DISPATCH_NORETURN __declspec(noreturn)
#define DISPATCH_NOTHROW __declspec(nothrow)
#define DISPATCH_NONNULL1
#define DISPATCH_NONNULL2
#define DISPATCH_NONNULL3
#define DISPATCH_NONNULL4
#define DISPATCH_NONNULL5
#define DISPATCH_NONNULL6
#define DISPATCH_NONNULL7
#define DISPATCH_NONNULL_ALL
#define DISPATCH_SENTINEL
#define DISPATCH_PURE
#define DISPATCH_CONST
#if (_MSC_VER >= 1700)
#define DISPATCH_WARN_RESULT _Check_return_
#else
#define DISPATCH_WARN_RESULT
#endif
#define DISPATCH_MALLOC
#define DISPATCH_ALWAYS_INLINE __forceinline
#define DISPATCH_UNAVAILABLE
#define DISPATCH_UNAVAILABLE_MSG(msg)
#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_CONST
/*! @parseOnly */
#define DISPATCH_WARN_RESULT
/*! @parseOnly */
#define DISPATCH_MALLOC
/*! @parseOnly */
#define DISPATCH_ALWAYS_INLINE
/*! @parseOnly */
#define DISPATCH_UNAVAILABLE
/*! @parseOnly */
#define DISPATCH_UNAVAILABLE_MSG(msg)
#endif
#if defined(__cplusplus)
# if __cplusplus >= 201703L
# define DISPATCH_FALLTHROUGH [[fallthrough]]
# elif __cplusplus >= 201103L
# if defined(__clang__)
# define DISPATCH_FALLTHROUGH [[clang::fallthrough]]
# elif defined(__GNUC__) && __GNUC__ >= 7
# define DISPATCH_FALLTHROUGH [[gnu::fallthrough]]
# else
# define DISPATCH_FALLTHROUGH
# endif
# else
# define DISPATCH_FALLTHROUGH
# endif
#elif defined(__GNUC__) && __GNUC__ >= 7
# define DISPATCH_FALLTHROUGH __attribute__((__fallthrough__))
#elif defined(__clang__)
# if __has_attribute(fallthrough) && __clang_major__ >= 5
# define DISPATCH_FALLTHROUGH __attribute__((__fallthrough__))
# else
# define DISPATCH_FALLTHROUGH
# endif
#else
# define DISPATCH_FALLTHROUGH
#endif
#ifdef __linux__
#define DISPATCH_LINUX_UNAVAILABLE() \
DISPATCH_UNAVAILABLE_MSG( \
"This interface is unavailable on linux systems")
#else
#define DISPATCH_LINUX_UNAVAILABLE()
#endif
#ifdef __FreeBSD__
#define DISPATCH_FREEBSD_UNAVAILABLE() \
DISPATCH_UNAVAILABLE_MSG( \
"This interface is unavailable on FreeBSD systems")
#else
#define DISPATCH_FREEBSD_UNAVAILABLE()
#endif
#ifndef DISPATCH_ALIAS_V2
#if TARGET_OS_MAC
#define DISPATCH_ALIAS_V2(sym) __asm__("_" #sym "$V2")
#else
#define DISPATCH_ALIAS_V2(sym)
#endif
#endif
#if defined(_WIN32)
#if defined(__DISPATCH_BUILDING_DISPATCH__)
#if defined(__cplusplus)
#define DISPATCH_EXPORT extern "C" __declspec(dllexport)
#else
#define DISPATCH_EXPORT extern __declspec(dllexport)
#endif
#else
#if defined(__cplusplus)
#define DISPATCH_EXPORT extern "C" __declspec(dllimport)
#else
#define DISPATCH_EXPORT extern __declspec(dllimport)
#endif
#endif
#elif __GNUC__
#define DISPATCH_EXPORT extern __attribute__((visibility("default")))
#else
#define DISPATCH_EXPORT extern
#endif
#if __GNUC__
#define DISPATCH_INLINE static __inline__
#else
#define DISPATCH_INLINE static inline
#endif
#if __GNUC__
#define DISPATCH_EXPECT(x, v) __builtin_expect((x), (v))
#define dispatch_compiler_barrier() __asm__ __volatile__("" ::: "memory")
#else
#define DISPATCH_EXPECT(x, v) (x)
#define dispatch_compiler_barrier() do { } while (0)
#endif
#if __has_attribute(not_tail_called)
#define DISPATCH_NOT_TAIL_CALLED __attribute__((__not_tail_called__))
#else
#define DISPATCH_NOT_TAIL_CALLED
#endif
#if __has_builtin(__builtin_assume)
#define DISPATCH_COMPILER_CAN_ASSUME(expr) __builtin_assume(expr)
#else
#define DISPATCH_COMPILER_CAN_ASSUME(expr) ((void)(expr))
#endif
#if __has_attribute(noescape)
#define DISPATCH_NOESCAPE __attribute__((__noescape__))
#else
#define DISPATCH_NOESCAPE
#endif
#if __has_attribute(cold)
#define DISPATCH_COLD __attribute__((__cold__))
#else
#define DISPATCH_COLD
#endif
#if __has_feature(assume_nonnull)
#define DISPATCH_ASSUME_NONNULL_BEGIN _Pragma("clang assume_nonnull begin")
#define DISPATCH_ASSUME_NONNULL_END _Pragma("clang assume_nonnull end")
#else
#define DISPATCH_ASSUME_NONNULL_BEGIN
#define DISPATCH_ASSUME_NONNULL_END
#endif
#if !__has_feature(nullability)
#ifndef _Nullable
#define _Nullable
#endif
#ifndef _Nonnull
#define _Nonnull
#endif
#ifndef _Null_unspecified
#define _Null_unspecified
#endif
#endif
#ifndef DISPATCH_RETURNS_RETAINED_BLOCK
#if __has_attribute(ns_returns_retained)
#define DISPATCH_RETURNS_RETAINED_BLOCK __attribute__((__ns_returns_retained__))
#else
#define DISPATCH_RETURNS_RETAINED_BLOCK
#endif
#endif
#if __has_feature(objc_fixed_enum) || __has_extension(cxx_strong_enums) || defined(_WIN32)
#define DISPATCH_ENUM(name, type, ...) \
typedef enum : type { __VA_ARGS__ } name##_t
#else
#define DISPATCH_ENUM(name, type, ...) \
enum { __VA_ARGS__ }; typedef type name##_t
#endif
#if __has_feature(enumerator_attributes)
#define DISPATCH_ENUM_API_AVAILABLE(...) API_AVAILABLE(__VA_ARGS__)
#define DISPATCH_ENUM_API_DEPRECATED(...) API_DEPRECATED(__VA_ARGS__)
#define DISPATCH_ENUM_API_DEPRECATED_WITH_REPLACEMENT(...) \
API_DEPRECATED_WITH_REPLACEMENT(__VA_ARGS__)
#else
#define DISPATCH_ENUM_API_AVAILABLE(...)
#define DISPATCH_ENUM_API_DEPRECATED(...)
#define DISPATCH_ENUM_API_DEPRECATED_WITH_REPLACEMENT(...)
#endif
#if defined(SWIFT_SDK_OVERLAY_DISPATCH_EPOCH) && \
SWIFT_SDK_OVERLAY_DISPATCH_EPOCH >= 2
#define DISPATCH_SWIFT3_OVERLAY 1
#else
#define DISPATCH_SWIFT3_OVERLAY 0
#endif // SWIFT_SDK_OVERLAY_DISPATCH_EPOCH >= 2
#if __has_feature(attribute_availability_swift)
#define DISPATCH_SWIFT_UNAVAILABLE(_msg) \
__attribute__((__availability__(swift, unavailable, message=_msg)))
#else
#define DISPATCH_SWIFT_UNAVAILABLE(_msg)
#endif
#if DISPATCH_SWIFT3_OVERLAY
#define DISPATCH_SWIFT3_UNAVAILABLE(_msg) DISPATCH_SWIFT_UNAVAILABLE(_msg)
#else
#define DISPATCH_SWIFT3_UNAVAILABLE(_msg)
#endif
#if __has_attribute(swift_private)
#define DISPATCH_REFINED_FOR_SWIFT __attribute__((__swift_private__))
#else
#define DISPATCH_REFINED_FOR_SWIFT
#endif
#if __has_attribute(swift_name)
#define DISPATCH_SWIFT_NAME(_name) __attribute__((__swift_name__(#_name)))
#else
#define DISPATCH_SWIFT_NAME(_name)
#endif
#ifndef __cplusplus
#define DISPATCH_TRANSPARENT_UNION __attribute__((__transparent_union__))
#else
#define DISPATCH_TRANSPARENT_UNION
#endif
typedef void (*dispatch_function_t)(void *_Nullable);
#endif /* __DISPATCH_BASE__ */

View File

@@ -0,0 +1,428 @@
/*
* Copyright (c) 2014 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_BLOCK__
#define __DISPATCH_BLOCK__
#ifndef __DISPATCH_INDIRECT__
#error "Please #include <dispatch/dispatch.h> instead of this file directly."
#include <dispatch/base.h> // for HeaderDoc
#endif
#ifdef __BLOCKS__
/*!
* @group Dispatch block objects
*/
DISPATCH_ASSUME_NONNULL_BEGIN
__BEGIN_DECLS
/*!
* @typedef dispatch_block_flags_t
* Flags to pass to the dispatch_block_create* functions.
*
* @const DISPATCH_BLOCK_BARRIER
* Flag indicating that a dispatch block object should act as a barrier block
* when submitted to a DISPATCH_QUEUE_CONCURRENT queue.
* See dispatch_barrier_async() for details.
* This flag has no effect when the dispatch block object is invoked directly.
*
* @const DISPATCH_BLOCK_DETACHED
* Flag indicating that a dispatch block object should execute disassociated
* from current execution context attributes such as os_activity_t
* and properties of the current IPC request (if any). With regard to QoS class,
* the behavior is the same as for DISPATCH_BLOCK_NO_QOS. If invoked directly,
* the block object will remove the other attributes from the calling thread for
* the duration of the block body (before applying attributes assigned to the
* block object, if any). If submitted to a queue, the block object will be
* executed with the attributes of the queue (or any attributes specifically
* assigned to the block object).
*
* @const DISPATCH_BLOCK_ASSIGN_CURRENT
* Flag indicating that a dispatch block object should be assigned the execution
* context attributes that are current at the time the block object is created.
* This applies to attributes such as QOS class, os_activity_t and properties of
* the current IPC request (if any). If invoked directly, the block object will
* apply these attributes to the calling thread for the duration of the block
* body. If the block object is submitted to a queue, this flag replaces the
* default behavior of associating the submitted block instance with the
* execution context attributes that are current at the time of submission.
* If a specific QOS class is assigned with DISPATCH_BLOCK_NO_QOS_CLASS or
* dispatch_block_create_with_qos_class(), that QOS class takes precedence over
* the QOS class assignment indicated by this flag.
*
* @const DISPATCH_BLOCK_NO_QOS_CLASS
* Flag indicating that a dispatch block object should be not be assigned a QOS
* class. If invoked directly, the block object will be executed with the QOS
* class of the calling thread. If the block object is submitted to a queue,
* this replaces the default behavior of associating the submitted block
* instance with the QOS class current at the time of submission.
* This flag is ignored if a specific QOS class is assigned with
* dispatch_block_create_with_qos_class().
*
* @const DISPATCH_BLOCK_INHERIT_QOS_CLASS
* Flag indicating that execution of a dispatch block object submitted to a
* queue should prefer the QOS class assigned to the queue over the QOS class
* assigned to the block (resp. associated with the block at the time of
* submission). The latter will only be used if the queue in question does not
* have an assigned QOS class, as long as doing so does not result in a QOS
* class lower than the QOS class inherited from the queue's target queue.
* This flag is the default when a dispatch block object is submitted to a queue
* for asynchronous execution and has no effect when the dispatch block object
* is invoked directly. It is ignored if DISPATCH_BLOCK_ENFORCE_QOS_CLASS is
* also passed.
*
* @const DISPATCH_BLOCK_ENFORCE_QOS_CLASS
* Flag indicating that execution of a dispatch block object submitted to a
* queue should prefer the QOS class assigned to the block (resp. associated
* with the block at the time of submission) over the QOS class assigned to the
* queue, as long as doing so will not result in a lower QOS class.
* This flag is the default when a dispatch block object is submitted to a queue
* for synchronous execution or when the dispatch block object is invoked
* directly.
*/
DISPATCH_ENUM(dispatch_block_flags, unsigned long,
DISPATCH_BLOCK_BARRIER
DISPATCH_ENUM_API_AVAILABLE(macos(10.10), ios(8.0)) = 0x1,
DISPATCH_BLOCK_DETACHED
DISPATCH_ENUM_API_AVAILABLE(macos(10.10), ios(8.0)) = 0x2,
DISPATCH_BLOCK_ASSIGN_CURRENT
DISPATCH_ENUM_API_AVAILABLE(macos(10.10), ios(8.0)) = 0x4,
DISPATCH_BLOCK_NO_QOS_CLASS
DISPATCH_ENUM_API_AVAILABLE(macos(10.10), ios(8.0)) = 0x8,
DISPATCH_BLOCK_INHERIT_QOS_CLASS
DISPATCH_ENUM_API_AVAILABLE(macos(10.10), ios(8.0)) = 0x10,
DISPATCH_BLOCK_ENFORCE_QOS_CLASS
DISPATCH_ENUM_API_AVAILABLE(macos(10.10), ios(8.0)) = 0x20,
);
/*!
* @function dispatch_block_create
*
* @abstract
* Create a new dispatch block object on the heap from an existing block and
* the given flags.
*
* @discussion
* The provided block is Block_copy'ed to the heap and retained by the newly
* created dispatch block object.
*
* The returned dispatch block object is intended to be submitted to a dispatch
* queue with dispatch_async() and related functions, but may also be invoked
* directly. Both operations can be performed an arbitrary number of times but
* only the first completed execution of a dispatch block object can be waited
* on with dispatch_block_wait() or observed with dispatch_block_notify().
*
* If the returned dispatch block object is submitted to a dispatch queue, the
* submitted block instance will be associated with the QOS class current at the
* time of submission, unless one of the following flags assigned a specific QOS
* class (or no QOS class) at the time of block creation:
* - DISPATCH_BLOCK_ASSIGN_CURRENT
* - DISPATCH_BLOCK_NO_QOS_CLASS
* - DISPATCH_BLOCK_DETACHED
* The QOS class the block object will be executed with also depends on the QOS
* class assigned to the queue and which of the following flags was specified or
* defaulted to:
* - DISPATCH_BLOCK_INHERIT_QOS_CLASS (default for asynchronous execution)
* - DISPATCH_BLOCK_ENFORCE_QOS_CLASS (default for synchronous execution)
* See description of dispatch_block_flags_t for details.
*
* If the returned dispatch block object is submitted directly to a serial queue
* and is configured to execute with a specific QOS class, the system will make
* a best effort to apply the necessary QOS overrides to ensure that blocks
* submitted earlier to the serial queue are executed at that same QOS class or
* higher.
*
* @param flags
* Configuration flags for the block object.
* Passing a value that is not a bitwise OR of flags from dispatch_block_flags_t
* results in NULL being returned.
*
* @param block
* The block to create the dispatch block object from.
*
* @result
* The newly created dispatch block object, or NULL.
* When not building with Objective-C ARC, must be released with a -[release]
* message or the Block_release() function.
*/
API_AVAILABLE(macos(10.10), ios(8.0))
DISPATCH_EXPORT DISPATCH_NONNULL2 DISPATCH_RETURNS_RETAINED_BLOCK
DISPATCH_WARN_RESULT DISPATCH_NOTHROW
dispatch_block_t
dispatch_block_create(dispatch_block_flags_t flags, dispatch_block_t block);
/*!
* @function dispatch_block_create_with_qos_class
*
* @abstract
* Create a new dispatch block object on the heap from an existing block and
* the given flags, and assign it the specified QOS class and relative priority.
*
* @discussion
* The provided block is Block_copy'ed to the heap and retained by the newly
* created dispatch block object.
*
* The returned dispatch block object is intended to be submitted to a dispatch
* queue with dispatch_async() and related functions, but may also be invoked
* directly. Both operations can be performed an arbitrary number of times but
* only the first completed execution of a dispatch block object can be waited
* on with dispatch_block_wait() or observed with dispatch_block_notify().
*
* If invoked directly, the returned dispatch block object will be executed with
* the assigned QOS class as long as that does not result in a lower QOS class
* than what is current on the calling thread.
*
* If the returned dispatch block object is submitted to a dispatch queue, the
* QOS class it will be executed with depends on the QOS class assigned to the
* block, the QOS class assigned to the queue and which of the following flags
* was specified or defaulted to:
* - DISPATCH_BLOCK_INHERIT_QOS_CLASS: default for asynchronous execution
* - DISPATCH_BLOCK_ENFORCE_QOS_CLASS: default for synchronous execution
* See description of dispatch_block_flags_t for details.
*
* If the returned dispatch block object is submitted directly to a serial queue
* and is configured to execute with a specific QOS class, the system will make
* a best effort to apply the necessary QOS overrides to ensure that blocks
* submitted earlier to the serial queue are executed at that same QOS class or
* higher.
*
* @param flags
* Configuration flags for the new block object.
* Passing a value that is not a bitwise OR of flags from dispatch_block_flags_t
* results in NULL being returned.
*
* @param qos_class
* A QOS class value:
* - QOS_CLASS_USER_INTERACTIVE
* - QOS_CLASS_USER_INITIATED
* - QOS_CLASS_DEFAULT
* - QOS_CLASS_UTILITY
* - QOS_CLASS_BACKGROUND
* - QOS_CLASS_UNSPECIFIED
* Passing QOS_CLASS_UNSPECIFIED is equivalent to specifying the
* DISPATCH_BLOCK_NO_QOS_CLASS flag. Passing any other value results in NULL
* being returned.
*
* @param relative_priority
* A relative priority within the QOS class. This value is a negative
* offset from the maximum supported scheduler priority for the given class.
* Passing a value greater than zero or less than QOS_MIN_RELATIVE_PRIORITY
* results in NULL being returned.
*
* @param block
* The block to create the dispatch block object from.
*
* @result
* The newly created dispatch block object, or NULL.
* When not building with Objective-C ARC, must be released with a -[release]
* message or the Block_release() function.
*/
API_AVAILABLE(macos(10.10), ios(8.0))
DISPATCH_EXPORT DISPATCH_NONNULL4 DISPATCH_RETURNS_RETAINED_BLOCK
DISPATCH_WARN_RESULT DISPATCH_NOTHROW
dispatch_block_t
dispatch_block_create_with_qos_class(dispatch_block_flags_t flags,
dispatch_qos_class_t qos_class, int relative_priority,
dispatch_block_t block);
/*!
* @function dispatch_block_perform
*
* @abstract
* Create, synchronously execute and release a dispatch block object from the
* specified block and flags.
*
* @discussion
* Behaves identically to the sequence
* <code>
* dispatch_block_t b = dispatch_block_create(flags, block);
* b();
* Block_release(b);
* </code>
* but may be implemented more efficiently internally by not requiring a copy
* to the heap of the specified block or the allocation of a new block object.
*
* @param flags
* Configuration flags for the temporary block object.
* The result of passing a value that is not a bitwise OR of flags from
* dispatch_block_flags_t is undefined.
*
* @param block
* The block to create the temporary block object from.
*/
API_AVAILABLE(macos(10.10), ios(8.0))
DISPATCH_EXPORT DISPATCH_NONNULL2 DISPATCH_NOTHROW
void
dispatch_block_perform(dispatch_block_flags_t flags,
DISPATCH_NOESCAPE dispatch_block_t block);
/*!
* @function dispatch_block_wait
*
* @abstract
* Wait synchronously until execution of the specified dispatch block object has
* completed or until the specified timeout has elapsed.
*
* @discussion
* This function will return immediately if execution of the block object has
* already completed.
*
* It is not possible to wait for multiple executions of the same block object
* with this interface; use dispatch_group_wait() for that purpose. A single
* dispatch block object may either be waited on once and executed once,
* or it may be executed any number of times. The behavior of any other
* combination is undefined. Submission to a dispatch queue counts as an
* execution, even if cancellation (dispatch_block_cancel) means the block's
* code never runs.
*
* The result of calling this function from multiple threads simultaneously
* with the same dispatch block object is undefined, but note that doing so
* would violate the rules described in the previous paragraph.
*
* If this function returns indicating that the specified timeout has elapsed,
* then that invocation does not count as the one allowed wait.
*
* If at the time this function is called, the specified dispatch block object
* has been submitted directly to a serial queue, the system will make a best
* effort to apply the necessary QOS overrides to ensure that the block and any
* blocks submitted earlier to that serial queue are executed at the QOS class
* (or higher) of the thread calling dispatch_block_wait().
*
* @param block
* The dispatch block object to wait on.
* The result of passing NULL or a block object not returned by one of the
* dispatch_block_create* functions 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 (the dispatch block object completed within the
* specified timeout) or non-zero on error (i.e. timed out).
*/
API_AVAILABLE(macos(10.10), ios(8.0))
DISPATCH_EXPORT DISPATCH_NONNULL1 DISPATCH_NOTHROW
intptr_t
dispatch_block_wait(dispatch_block_t block, dispatch_time_t timeout);
/*!
* @function dispatch_block_notify
*
* @abstract
* Schedule a notification block to be submitted to a queue when the execution
* of a specified dispatch block object has completed.
*
* @discussion
* This function will submit the notification block immediately if execution of
* the observed block object has already completed.
*
* It is not possible to be notified of multiple executions of the same block
* object with this interface, use dispatch_group_notify() for that purpose.
*
* A single dispatch block object may either be observed one or more times
* and executed once, or it may be executed any number of times. The behavior
* of any other combination is undefined. Submission to a dispatch queue
* counts as an execution, even if cancellation (dispatch_block_cancel) means
* the block's code never runs.
*
* If multiple notification blocks are scheduled for a single block object,
* there is no defined order in which the notification blocks will be submitted
* to their associated queues.
*
* @param block
* The dispatch block object to observe.
* The result of passing NULL or a block object not returned by one of the
* dispatch_block_create* functions is undefined.
*
* @param queue
* The queue to which the supplied notification block will be submitted when
* the observed block completes.
*
* @param notification_block
* The notification block to submit when the observed block object completes.
*/
API_AVAILABLE(macos(10.10), ios(8.0))
DISPATCH_EXPORT DISPATCH_NONNULL_ALL DISPATCH_NOTHROW
void
dispatch_block_notify(dispatch_block_t block, dispatch_queue_t queue,
dispatch_block_t notification_block);
/*!
* @function dispatch_block_cancel
*
* @abstract
* Asynchronously cancel the specified dispatch block object.
*
* @discussion
* Cancellation causes any future execution of the dispatch block object to
* return immediately, but does not affect any execution of the block object
* that is already in progress.
*
* Release of any resources associated with the block object will be delayed
* until execution of the block object is next attempted (or any execution
* already in progress completes).
*
* NOTE: care needs to be taken to ensure that a block object that may be
* canceled does not capture any resources that require execution of the
* block body in order to be released (e.g. memory allocated with
* malloc(3) that the block body calls free(3) on). Such resources will
* be leaked if the block body is never executed due to cancellation.
*
* @param block
* The dispatch block object to cancel.
* The result of passing NULL or a block object not returned by one of the
* dispatch_block_create* functions is undefined.
*/
API_AVAILABLE(macos(10.10), ios(8.0))
DISPATCH_EXPORT DISPATCH_NONNULL_ALL DISPATCH_NOTHROW
void
dispatch_block_cancel(dispatch_block_t block);
/*!
* @function dispatch_block_testcancel
*
* @abstract
* Tests whether the given dispatch block object has been canceled.
*
* @param block
* The dispatch block object to test.
* The result of passing NULL or a block object not returned by one of the
* dispatch_block_create* functions is undefined.
*
* @result
* Non-zero if canceled and zero if not canceled.
*/
API_AVAILABLE(macos(10.10), ios(8.0))
DISPATCH_EXPORT DISPATCH_NONNULL_ALL DISPATCH_WARN_RESULT DISPATCH_PURE
DISPATCH_NOTHROW
intptr_t
dispatch_block_testcancel(dispatch_block_t block);
__END_DECLS
DISPATCH_ASSUME_NONNULL_END
#endif // __BLOCKS__
#endif // __DISPATCH_BLOCK__

View File

@@ -0,0 +1,9 @@
module Dispatch [system] [extern_c] {
umbrella header "dispatch.h"
export *
}
module DispatchIntrospection [system] [extern_c] {
header "introspection.h"
export *
}

View File

@@ -0,0 +1,278 @@
/*
* Copyright (c) 2009-2013 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_DATA__
#define __DISPATCH_DATA__
#ifndef __DISPATCH_INDIRECT__
#error "Please #include <dispatch/dispatch.h> instead of this file directly."
#include <dispatch/base.h> // for HeaderDoc
#endif
DISPATCH_ASSUME_NONNULL_BEGIN
__BEGIN_DECLS
/*! @header
* Dispatch data objects describe contiguous or sparse regions of memory that
* may be managed by the system or by the application.
* Dispatch data objects are immutable, any direct access to memory regions
* represented by dispatch objects must not modify that memory.
*/
/*!
* @typedef dispatch_data_t
* A dispatch object representing memory regions.
*/
DISPATCH_DATA_DECL(dispatch_data);
/*!
* @var dispatch_data_empty
* @discussion The singleton dispatch data object representing a zero-length
* memory region.
*/
#define dispatch_data_empty \
DISPATCH_GLOBAL_OBJECT(dispatch_data_t, _dispatch_data_empty)
API_AVAILABLE(macos(10.7), ios(5.0))
DISPATCH_EXPORT struct dispatch_data_s _dispatch_data_empty;
/*!
* @const DISPATCH_DATA_DESTRUCTOR_DEFAULT
* @discussion The default destructor for dispatch data objects.
* Used at data object creation to indicate that the supplied buffer should
* be copied into internal storage managed by the system.
*/
#define DISPATCH_DATA_DESTRUCTOR_DEFAULT NULL
#ifdef __BLOCKS__
/*! @parseOnly */
#define DISPATCH_DATA_DESTRUCTOR_TYPE_DECL(name) \
DISPATCH_EXPORT const dispatch_block_t _dispatch_data_destructor_##name
#else
#define DISPATCH_DATA_DESTRUCTOR_TYPE_DECL(name) \
DISPATCH_EXPORT const dispatch_function_t \
_dispatch_data_destructor_##name
#endif /* __BLOCKS__ */
/*!
* @const DISPATCH_DATA_DESTRUCTOR_FREE
* @discussion The destructor for dispatch data objects created from a malloc'd
* buffer. Used at data object creation to indicate that the supplied buffer
* was allocated by the malloc() family and should be destroyed with free(3).
*/
#define DISPATCH_DATA_DESTRUCTOR_FREE (_dispatch_data_destructor_free)
API_AVAILABLE(macos(10.7), ios(5.0))
DISPATCH_DATA_DESTRUCTOR_TYPE_DECL(free);
/*!
* @const DISPATCH_DATA_DESTRUCTOR_MUNMAP
* @discussion The destructor for dispatch data objects that have been created
* from buffers that require deallocation with munmap(2).
*/
#define DISPATCH_DATA_DESTRUCTOR_MUNMAP (_dispatch_data_destructor_munmap)
API_AVAILABLE(macos(10.9), ios(7.0))
DISPATCH_DATA_DESTRUCTOR_TYPE_DECL(munmap);
#ifdef __BLOCKS__
/*!
* @function dispatch_data_create
* Creates a dispatch data object from the given contiguous buffer of memory. If
* a non-default destructor is provided, ownership of the buffer remains with
* the caller (i.e. the bytes will not be copied). The last release of the data
* object will result in the invocation of the specified destructor on the
* specified queue to free the buffer.
*
* If the DISPATCH_DATA_DESTRUCTOR_FREE destructor is provided the buffer will
* be freed via free(3) and the queue argument ignored.
*
* If the DISPATCH_DATA_DESTRUCTOR_DEFAULT destructor is provided, data object
* creation will copy the buffer into internal memory managed by the system.
*
* @param buffer A contiguous buffer of data.
* @param size The size of the contiguous buffer of data.
* @param queue The queue to which the destructor should be submitted.
* @param destructor The destructor responsible for freeing the data when it
* is no longer needed.
* @result A newly created dispatch data object.
*/
API_AVAILABLE(macos(10.7), ios(5.0))
DISPATCH_EXPORT DISPATCH_RETURNS_RETAINED DISPATCH_WARN_RESULT DISPATCH_NOTHROW
dispatch_data_t
dispatch_data_create(const void *buffer,
size_t size,
dispatch_queue_t _Nullable queue,
dispatch_block_t _Nullable destructor);
#endif /* __BLOCKS__ */
/*!
* @function dispatch_data_get_size
* Returns the logical size of the memory region(s) represented by the specified
* dispatch data object.
*
* @param data The dispatch data object to query.
* @result The number of bytes represented by the data object.
*/
API_AVAILABLE(macos(10.7), ios(5.0))
DISPATCH_EXPORT DISPATCH_PURE DISPATCH_NONNULL1 DISPATCH_NOTHROW
size_t
dispatch_data_get_size(dispatch_data_t data);
/*!
* @function dispatch_data_create_map
* Maps the memory represented by the specified dispatch data object as a single
* contiguous memory region and returns a new data object representing it.
* If non-NULL references to a pointer and a size variable are provided, they
* are filled with the location and extent of that region. These allow direct
* read access to the represented memory, but are only valid until the returned
* object is released. Under ARC, if that object is held in a variable with
* automatic storage, care needs to be taken to ensure that it is not released
* by the compiler before memory access via the pointer has been completed.
*
* @param data The dispatch data object to map.
* @param buffer_ptr A pointer to a pointer variable to be filled with the
* location of the mapped contiguous memory region, or
* NULL.
* @param size_ptr A pointer to a size_t variable to be filled with the
* size of the mapped contiguous memory region, or NULL.
* @result A newly created dispatch data object.
*/
API_AVAILABLE(macos(10.7), ios(5.0))
DISPATCH_EXPORT DISPATCH_NONNULL1 DISPATCH_RETURNS_RETAINED
DISPATCH_WARN_RESULT DISPATCH_NOTHROW
dispatch_data_t
dispatch_data_create_map(dispatch_data_t data,
const void *_Nullable *_Nullable buffer_ptr,
size_t *_Nullable size_ptr);
/*!
* @function dispatch_data_create_concat
* Returns a new dispatch data object representing the concatenation of the
* specified data objects. Those objects may be released by the application
* after the call returns (however, the system might not deallocate the memory
* region(s) described by them until the newly created object has also been
* released).
*
* @param data1 The data object representing the region(s) of memory to place
* at the beginning of the newly created object.
* @param data2 The data object representing the region(s) of memory to place
* at the end of the newly created object.
* @result A newly created object representing the concatenation of the
* data1 and data2 objects.
*/
API_AVAILABLE(macos(10.7), ios(5.0))
DISPATCH_EXPORT DISPATCH_NONNULL_ALL DISPATCH_RETURNS_RETAINED
DISPATCH_WARN_RESULT DISPATCH_NOTHROW
dispatch_data_t
dispatch_data_create_concat(dispatch_data_t data1, dispatch_data_t data2);
/*!
* @function dispatch_data_create_subrange
* Returns a new dispatch data object representing a subrange of the specified
* data object, which may be released by the application after the call returns
* (however, the system might not deallocate the memory region(s) described by
* that object until the newly created object has also been released).
*
* @param data The data object representing the region(s) of memory to
* create a subrange of.
* @param offset The offset into the data object where the subrange
* starts.
* @param length The length of the range.
* @result A newly created object representing the specified
* subrange of the data object.
*/
API_AVAILABLE(macos(10.7), ios(5.0))
DISPATCH_EXPORT DISPATCH_NONNULL1 DISPATCH_RETURNS_RETAINED
DISPATCH_WARN_RESULT DISPATCH_NOTHROW
dispatch_data_t
dispatch_data_create_subrange(dispatch_data_t data,
size_t offset,
size_t length);
#ifdef __BLOCKS__
/*!
* @typedef dispatch_data_applier_t
* A block to be invoked for every contiguous memory region in a data object.
*
* @param region A data object representing the current region.
* @param offset The logical offset of the current region to the start
* of the data object.
* @param buffer The location of the memory for the current region.
* @param size The size of the memory for the current region.
* @result A Boolean indicating whether traversal should continue.
*/
typedef bool (^dispatch_data_applier_t)(dispatch_data_t region,
size_t offset,
const void *buffer,
size_t size);
/*!
* @function dispatch_data_apply
* Traverse the memory regions represented by the specified dispatch data object
* in logical order and invoke the specified block once for every contiguous
* memory region encountered.
*
* Each invocation of the block is passed a data object representing the current
* region and its logical offset, along with the memory location and extent of
* the region. These allow direct read access to the memory region, but are only
* valid until the passed-in region object is released. Note that the region
* object is released by the system when the block returns, it is the
* responsibility of the application to retain it if the region object or the
* associated memory location are needed after the block returns.
*
* @param data The data object to traverse.
* @param applier The block to be invoked for every contiguous memory
* region in the data object.
* @result A Boolean indicating whether traversal completed
* successfully.
*/
API_AVAILABLE(macos(10.7), ios(5.0))
DISPATCH_EXPORT DISPATCH_NONNULL_ALL DISPATCH_NOTHROW
bool
dispatch_data_apply(dispatch_data_t data,
DISPATCH_NOESCAPE dispatch_data_applier_t applier);
#endif /* __BLOCKS__ */
/*!
* @function dispatch_data_copy_region
* Finds the contiguous memory region containing the specified location among
* the regions represented by the specified object and returns a copy of the
* internal dispatch data object representing that region along with its logical
* offset in the specified object.
*
* @param data The dispatch data object to query.
* @param location The logical position in the data object to query.
* @param offset_ptr A pointer to a size_t variable to be filled with the
* logical offset of the returned region object to the
* start of the queried data object.
* @result A newly created dispatch data object.
*/
API_AVAILABLE(macos(10.7), ios(5.0))
DISPATCH_EXPORT DISPATCH_NONNULL1 DISPATCH_NONNULL3 DISPATCH_RETURNS_RETAINED
DISPATCH_WARN_RESULT DISPATCH_NOTHROW
dispatch_data_t
dispatch_data_copy_region(dispatch_data_t data,
size_t location,
size_t *offset_ptr);
__END_DECLS
DISPATCH_ASSUME_NONNULL_END
#endif /* __DISPATCH_DATA__ */

View File

@@ -0,0 +1,11 @@
---
version: 0
case-sensitive: false
use-external-names: false
roots:
- name: "@CMAKE_CURRENT_SOURCE_DIR@"
type: directory
contents:
- name: module.modulemap
type: file
external-contents: "@DISPATCH_MODULE_MAP@"

View File

@@ -0,0 +1,80 @@
/*
* Copyright (c) 2008-2013 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__
#ifdef __APPLE__
#include <Availability.h>
#include <os/availability.h>
#include <TargetConditionals.h>
#include <os/base.h>
#elif defined(_WIN32)
#include <os/generic_win_base.h>
#elif defined(__unix__)
#include <os/generic_unix_base.h>
#endif
#include <sys/types.h>
#include <stddef.h>
#include <stdint.h>
#include <stdbool.h>
#include <stdarg.h>
#include <string.h>
#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__))
#include <unistd.h>
#endif
#include <fcntl.h>
#if defined(_WIN32)
#include <time.h>
#endif
#if (defined(__linux__) || defined(__FreeBSD__)) && defined(__has_feature)
#if __has_feature(modules)
#if !defined(__arm__)
#include <stdio.h> // for off_t (to match Glibc.modulemap)
#endif
#endif
#endif
#define DISPATCH_API_VERSION 20180109
#ifndef __DISPATCH_BUILDING_DISPATCH__
#ifndef __DISPATCH_INDIRECT__
#define __DISPATCH_INDIRECT__
#endif
#include <os/object.h>
#include <dispatch/base.h>
#include <dispatch/time.h>
#include <dispatch/object.h>
#include <dispatch/queue.h>
#include <dispatch/block.h>
#include <dispatch/source.h>
#include <dispatch/group.h>
#include <dispatch/semaphore.h>
#include <dispatch/once.h>
#include <dispatch/data.h>
#include <dispatch/io.h>
#undef __DISPATCH_INDIRECT__
#endif /* !__DISPATCH_BUILDING_DISPATCH__ */
#endif /* __DISPATCH_PUBLIC__ */

View File

@@ -0,0 +1,18 @@
module Dispatch {
requires blocks
export *
link "dispatch"
link "BlocksRuntime"
}
module DispatchIntrospection [system] [extern_c] {
header "introspection.h"
export *
}
module CDispatch [system] [extern_c] {
umbrella header "dispatch.h"
export *
requires blocks
link "dispatch"
}

View File

@@ -0,0 +1,19 @@
module Dispatch {
requires blocks
export *
link "dispatch"
link "BlocksRuntime"
link "DispatchStubs"
}
module DispatchIntrospection [system] [extern_c] {
header "introspection.h"
export *
}
module CDispatch [system] [extern_c] {
umbrella header "dispatch.h"
export *
requires blocks
link "dispatch"
}

View File

@@ -0,0 +1,279 @@
/*
* Copyright (c) 2008-2013 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
DISPATCH_ASSUME_NONNULL_BEGIN
/*!
* @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.
*/
API_AVAILABLE(macos(10.6), ios(4.0))
DISPATCH_EXPORT DISPATCH_MALLOC DISPATCH_RETURNS_RETAINED DISPATCH_WARN_RESULT
DISPATCH_NOTHROW
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__
API_AVAILABLE(macos(10.6), ios(4.0))
DISPATCH_EXPORT DISPATCH_NONNULL_ALL DISPATCH_NOTHROW
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().
*/
API_AVAILABLE(macos(10.6), ios(4.0))
DISPATCH_EXPORT DISPATCH_NONNULL1 DISPATCH_NONNULL2 DISPATCH_NONNULL4
DISPATCH_NOTHROW
void
dispatch_group_async_f(dispatch_group_t group,
dispatch_queue_t queue,
void *_Nullable context,
dispatch_function_t work);
/*!
* @function dispatch_group_wait
*
* @abstract
* Wait synchronously until all the blocks associated with a group have
* completed or until the specified timeout has elapsed.
*
* @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.
*
* 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 multiple 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).
*/
API_AVAILABLE(macos(10.6), ios(4.0))
DISPATCH_EXPORT DISPATCH_NONNULL_ALL DISPATCH_NOTHROW
intptr_t
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 all the blocks associated
* with a group 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__
API_AVAILABLE(macos(10.6), ios(4.0))
DISPATCH_EXPORT DISPATCH_NONNULL_ALL DISPATCH_NOTHROW
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 all the blocks
* associated with a group 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().
*/
API_AVAILABLE(macos(10.6), ios(4.0))
DISPATCH_EXPORT DISPATCH_NONNULL1 DISPATCH_NONNULL2 DISPATCH_NONNULL4
DISPATCH_NOTHROW
void
dispatch_group_notify_f(dispatch_group_t group,
dispatch_queue_t queue,
void *_Nullable 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.
*/
API_AVAILABLE(macos(10.6), ios(4.0))
DISPATCH_EXPORT DISPATCH_NONNULL_ALL DISPATCH_NOTHROW
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
* group 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.
*/
API_AVAILABLE(macos(10.6), ios(4.0))
DISPATCH_EXPORT DISPATCH_NONNULL_ALL DISPATCH_NOTHROW
void
dispatch_group_leave(dispatch_group_t group);
__END_DECLS
DISPATCH_ASSUME_NONNULL_END
#endif /* __DISPATCH_GROUP__ */

View File

@@ -0,0 +1,188 @@
/*
* Copyright (c) 2013 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_INTROSPECTION__
#define __DISPATCH_INTROSPECTION__
#include <dispatch/dispatch.h>
DISPATCH_ASSUME_NONNULL_BEGIN
/*!
* @header
*
* @abstract
* Interposable introspection hooks for libdispatch.
*
* @discussion
* These hooks are only available in the introspection version of the library,
* loaded by running a process with the environment variable
* DYLD_LIBRARY_PATH=/usr/lib/system/introspection
*/
__BEGIN_DECLS
/*!
* @function dispatch_introspection_hook_queue_create
*
* @abstract
* Interposable hook function called when a dispatch queue was created.
*
* @param queue
* The newly created dispatch queue.
*/
API_AVAILABLE(macos(10.9), ios(7.0))
DISPATCH_EXPORT
void
dispatch_introspection_hook_queue_create(dispatch_queue_t queue);
/*!
* @function dispatch_introspection_hook_queue_destroy
*
* @abstract
* Interposable hook function called when a dispatch queue is about to be
* destroyed.
*
* @param queue
* The dispatch queue about to be destroyed.
*/
API_AVAILABLE(macos(10.9), ios(7.0))
DISPATCH_EXPORT
void
dispatch_introspection_hook_queue_destroy(dispatch_queue_t queue);
/*!
* @function dispatch_introspection_hook_queue_item_enqueue
*
* @abstract
* Interposable hook function called when an item is about to be enqueued onto
* a dispatch queue.
*
* @param queue
* The dispatch queue enqueued onto.
*
* @param item
* The object about to be enqueued.
*/
API_AVAILABLE(macos(10.9), ios(7.0))
DISPATCH_EXPORT
void
dispatch_introspection_hook_queue_item_enqueue(dispatch_queue_t queue,
dispatch_object_t item);
/*!
* @function dispatch_introspection_hook_queue_item_dequeue
*
* @abstract
* Interposable hook function called when an item was dequeued from a dispatch
* queue.
*
* @param queue
* The dispatch queue dequeued from.
*
* @param item
* The dequeued object.
*/
API_AVAILABLE(macos(10.9), ios(7.0))
DISPATCH_EXPORT
void
dispatch_introspection_hook_queue_item_dequeue(dispatch_queue_t queue,
dispatch_object_t item);
/*!
* @function dispatch_introspection_hook_queue_item_complete
*
* @abstract
* Interposable hook function called when an item previously dequeued from a
* dispatch queue has completed processing.
*
* @discussion
* The object pointer value passed to this function must be treated as a value
* only. It is intended solely for matching up with an earlier call to a
* dequeue hook function and must NOT be dereferenced.
*
* @param item
* Opaque dentifier for completed item. Must NOT be dereferenced.
*/
API_AVAILABLE(macos(10.10), ios(7.1))
DISPATCH_EXPORT
void
dispatch_introspection_hook_queue_item_complete(dispatch_object_t item);
/*!
* @function dispatch_introspection_hook_queue_callout_begin
*
* @abstract
* Interposable hook function called when a client function is about to be
* called out to on a dispatch queue.
*
* @param queue
* The dispatch queue the callout is performed on.
*
* @param context
* The context parameter passed to the function. For a callout to a block,
* this is a pointer to the block object.
*
* @param function
* The client function about to be called out to. For a callout to a block,
* this is the block object's invoke function.
*/
API_AVAILABLE(macos(10.9), ios(7.0))
DISPATCH_EXPORT
void
dispatch_introspection_hook_queue_callout_begin(dispatch_queue_t queue,
void *_Nullable context, dispatch_function_t function);
/*!
* @function dispatch_introspection_hook_queue_callout_end
*
* @abstract
* Interposable hook function called after a client function has returned from
* a callout on a dispatch queue.
*
* @param queue
* The dispatch queue the callout was performed on.
*
* @param context
* The context parameter passed to the function. For a callout to a block,
* this is a pointer to the block object.
*
* @param function
* The client function that was called out to. For a callout to a block,
* this is the block object's invoke function.
*/
API_AVAILABLE(macos(10.9), ios(7.0))
DISPATCH_EXPORT
void
dispatch_introspection_hook_queue_callout_end(dispatch_queue_t queue,
void *_Nullable context, dispatch_function_t function);
__END_DECLS
DISPATCH_ASSUME_NONNULL_END
#endif /* __DISPATCH_INTROSPECTION__ */

View File

@@ -0,0 +1,597 @@
/*
* Copyright (c) 2009-2013 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_IO__
#define __DISPATCH_IO__
#ifndef __DISPATCH_INDIRECT__
#error "Please #include <dispatch/dispatch.h> instead of this file directly."
#include <dispatch/base.h> // for HeaderDoc
#endif
DISPATCH_ASSUME_NONNULL_BEGIN
__BEGIN_DECLS
/*! @header
* Dispatch I/O provides both stream and random access asynchronous read and
* write operations on file descriptors. One or more dispatch I/O channels may
* be created from a file descriptor as either the DISPATCH_IO_STREAM type or
* DISPATCH_IO_RANDOM type. Once a channel has been created the application may
* schedule asynchronous read and write operations.
*
* The application may set policies on the dispatch I/O channel to indicate the
* desired frequency of I/O handlers for long-running operations.
*
* Dispatch I/O also provides a memory management model for I/O buffers that
* avoids unnecessary copying of data when pipelined between channels. Dispatch
* I/O monitors the overall memory pressure and I/O access patterns for the
* application to optimize resource utilization.
*/
/*!
* @typedef dispatch_fd_t
* Native file descriptor type for the platform.
*/
#if defined(_WIN32)
typedef intptr_t dispatch_fd_t;
#else
typedef int dispatch_fd_t;
#endif
/*!
* @functiongroup Dispatch I/O Convenience API
* Convenience wrappers around the dispatch I/O channel API, with simpler
* callback handler semantics and no explicit management of channel objects.
* File descriptors passed to the convenience API are treated as streams, and
* scheduling multiple operations on one file descriptor via the convenience API
* may incur more overhead than by using the dispatch I/O channel API directly.
*/
#ifdef __BLOCKS__
/*!
* @function dispatch_read
* Schedule a read operation for asynchronous execution on the specified file
* descriptor. The specified handler is enqueued with the data read from the
* file descriptor when the operation has completed or an error occurs.
*
* The data object passed to the handler will be automatically released by the
* system when the handler returns. It is the responsibility of the application
* to retain, concatenate or copy the data object if it is needed after the
* handler returns.
*
* The data object passed to the handler will only contain as much data as is
* currently available from the file descriptor (up to the specified length).
*
* If an unrecoverable error occurs on the file descriptor, the handler will be
* enqueued with the appropriate error code along with a data object of any data
* that could be read successfully.
*
* An invocation of the handler with an error code of zero and an empty data
* object indicates that EOF was reached.
*
* The system takes control of the file descriptor until the handler is
* enqueued, and during this time file descriptor flags such as O_NONBLOCK will
* be modified by the system on behalf of the application. It is an error for
* the application to modify a file descriptor directly while it is under the
* control of the system, but it may create additional dispatch I/O convenience
* operations or dispatch I/O channels associated with that file descriptor.
*
* @param fd The file descriptor from which to read the data.
* @param length The length of data to read from the file descriptor,
* or SIZE_MAX to indicate that all of the data currently
* available from the file descriptor should be read.
* @param queue The dispatch queue to which the handler should be
* submitted.
* @param handler The handler to enqueue when data is ready to be
* delivered.
* param data The data read from the file descriptor.
* param error An errno condition for the read operation or
* zero if the read was successful.
*/
API_AVAILABLE(macos(10.7), ios(5.0))
DISPATCH_EXPORT DISPATCH_NONNULL3 DISPATCH_NONNULL4 DISPATCH_NOTHROW
void
dispatch_read(dispatch_fd_t fd,
size_t length,
dispatch_queue_t queue,
void (^handler)(dispatch_data_t data, int error));
/*!
* @function dispatch_write
* Schedule a write operation for asynchronous execution on the specified file
* descriptor. The specified handler is enqueued when the operation has
* completed or an error occurs.
*
* If an unrecoverable error occurs on the file descriptor, the handler will be
* enqueued with the appropriate error code along with the data that could not
* be successfully written.
*
* An invocation of the handler with an error code of zero indicates that the
* data was fully written to the channel.
*
* The system takes control of the file descriptor until the handler is
* enqueued, and during this time file descriptor flags such as O_NONBLOCK will
* be modified by the system on behalf of the application. It is an error for
* the application to modify a file descriptor directly while it is under the
* control of the system, but it may create additional dispatch I/O convenience
* operations or dispatch I/O channels associated with that file descriptor.
*
* @param fd The file descriptor to which to write the data.
* @param data The data object to write to the file descriptor.
* @param queue The dispatch queue to which the handler should be
* submitted.
* @param handler The handler to enqueue when the data has been written.
* param data The data that could not be written to the I/O
* channel, or NULL.
* param error An errno condition for the write operation or
* zero if the write was successful.
*/
API_AVAILABLE(macos(10.7), ios(5.0))
DISPATCH_EXPORT DISPATCH_NONNULL2 DISPATCH_NONNULL3 DISPATCH_NONNULL4
DISPATCH_NOTHROW
void
dispatch_write(dispatch_fd_t fd,
dispatch_data_t data,
dispatch_queue_t queue,
void (^handler)(dispatch_data_t _Nullable data, int error));
#endif /* __BLOCKS__ */
/*!
* @functiongroup Dispatch I/O Channel API
*/
/*!
* @typedef dispatch_io_t
* A dispatch I/O channel represents the asynchronous I/O policy applied to a
* file descriptor. I/O channels are first class dispatch objects and may be
* retained and released, suspended and resumed, etc.
*/
DISPATCH_DECL(dispatch_io);
/*!
* @typedef dispatch_io_type_t
* The type of a dispatch I/O channel:
*
* @const DISPATCH_IO_STREAM A dispatch I/O channel representing a stream of
* bytes. Read and write operations on a channel of this type are performed
* serially (in order of creation) and read/write data at the file pointer
* position that is current at the time the operation starts executing.
* Operations of different type (read vs. write) may be performed simultaneously.
* Offsets passed to operations on a channel of this type are ignored.
*
* @const DISPATCH_IO_RANDOM A dispatch I/O channel representing a random
* access file. Read and write operations on a channel of this type may be
* performed concurrently and read/write data at the specified offset. Offsets
* are interpreted relative to the file pointer position current at the time the
* I/O channel is created. Attempting to create a channel of this type for a
* file descriptor that is not seekable will result in an error.
*/
#define DISPATCH_IO_STREAM 0
#define DISPATCH_IO_RANDOM 1
typedef unsigned long dispatch_io_type_t;
#ifdef __BLOCKS__
/*!
* @function dispatch_io_create
* Create a dispatch I/O channel associated with a file descriptor. The system
* takes control of the file descriptor until the channel is closed, an error
* occurs on the file descriptor or all references to the channel are released.
* At that time the specified cleanup handler will be enqueued and control over
* the file descriptor relinquished.
*
* While a file descriptor is under the control of a dispatch I/O channel, file
* descriptor flags such as O_NONBLOCK will be modified by the system on behalf
* of the application. It is an error for the application to modify a file
* descriptor directly while it is under the control of a dispatch I/O channel,
* but it may create additional channels associated with that file descriptor.
*
* @param type The desired type of I/O channel (DISPATCH_IO_STREAM
* or DISPATCH_IO_RANDOM).
* @param fd The file descriptor to associate with the I/O channel.
* @param queue The dispatch queue to which the handler should be submitted.
* @param cleanup_handler The handler to enqueue when the system
* relinquishes control over the file descriptor.
* param error An errno condition if control is relinquished
* because channel creation failed, zero otherwise.
* @result The newly created dispatch I/O channel or NULL if an error
* occurred (invalid type specified).
*/
API_AVAILABLE(macos(10.7), ios(5.0))
DISPATCH_EXPORT DISPATCH_MALLOC DISPATCH_RETURNS_RETAINED DISPATCH_WARN_RESULT
DISPATCH_NOTHROW
dispatch_io_t
dispatch_io_create(dispatch_io_type_t type,
dispatch_fd_t fd,
dispatch_queue_t queue,
void (^cleanup_handler)(int error));
/*!
* @function dispatch_io_create_with_path
* Create a dispatch I/O channel associated with a path name. The specified
* path, oflag and mode parameters will be passed to open(2) when the first I/O
* operation on the channel is ready to execute and the resulting file
* descriptor will remain open and under the control of the system until the
* channel is closed, an error occurs on the file descriptor or all references
* to the channel are released. At that time the file descriptor will be closed
* and the specified cleanup handler will be enqueued.
*
* @param type The desired type of I/O channel (DISPATCH_IO_STREAM
* or DISPATCH_IO_RANDOM).
* @param path The absolute path to associate with the I/O channel.
* @param oflag The flags to pass to open(2) when opening the file at
* path.
* @param mode The mode to pass to open(2) when creating the file at
* path (i.e. with flag O_CREAT), zero otherwise.
* @param queue The dispatch queue to which the handler should be
* submitted.
* @param cleanup_handler The handler to enqueue when the system
* has closed the file at path.
* param error An errno condition if control is relinquished
* because channel creation or opening of the
* specified file failed, zero otherwise.
* @result The newly created dispatch I/O channel or NULL if an error
* occurred (invalid type or non-absolute path specified).
*/
API_AVAILABLE(macos(10.7), ios(5.0))
DISPATCH_EXPORT DISPATCH_NONNULL2 DISPATCH_MALLOC DISPATCH_RETURNS_RETAINED
DISPATCH_WARN_RESULT DISPATCH_NOTHROW
dispatch_io_t
dispatch_io_create_with_path(dispatch_io_type_t type,
const char *path, int oflag, mode_t mode,
dispatch_queue_t queue,
void (^cleanup_handler)(int error));
/*!
* @function dispatch_io_create_with_io
* Create a new dispatch I/O channel from an existing dispatch I/O channel.
* The new channel inherits the file descriptor or path name associated with
* the existing channel, but not its channel type or policies.
*
* If the existing channel is associated with a file descriptor, control by the
* system over that file descriptor is extended until the new channel is also
* closed, an error occurs on the file descriptor, or all references to both
* channels are released. At that time the specified cleanup handler will be
* enqueued and control over the file descriptor relinquished.
*
* While a file descriptor is under the control of a dispatch I/O channel, file
* descriptor flags such as O_NONBLOCK will be modified by the system on behalf
* of the application. It is an error for the application to modify a file
* descriptor directly while it is under the control of a dispatch I/O channel,
* but it may create additional channels associated with that file descriptor.
*
* @param type The desired type of I/O channel (DISPATCH_IO_STREAM
* or DISPATCH_IO_RANDOM).
* @param io The existing channel to create the new I/O channel from.
* @param queue The dispatch queue to which the handler should be submitted.
* @param cleanup_handler The handler to enqueue when the system
* relinquishes control over the file descriptor
* (resp. closes the file at path) associated with
* the existing channel.
* param error An errno condition if control is relinquished
* because channel creation failed, zero otherwise.
* @result The newly created dispatch I/O channel or NULL if an error
* occurred (invalid type specified).
*/
API_AVAILABLE(macos(10.7), ios(5.0))
DISPATCH_EXPORT DISPATCH_NONNULL2 DISPATCH_MALLOC DISPATCH_RETURNS_RETAINED
DISPATCH_WARN_RESULT DISPATCH_NOTHROW
dispatch_io_t
dispatch_io_create_with_io(dispatch_io_type_t type,
dispatch_io_t io,
dispatch_queue_t queue,
void (^cleanup_handler)(int error));
/*!
* @typedef dispatch_io_handler_t
* The prototype of I/O handler blocks for dispatch I/O operations.
*
* @param done A flag indicating whether the operation is complete.
* @param data The data object to be handled.
* @param error An errno condition for the operation.
*/
typedef void (^dispatch_io_handler_t)(bool done, dispatch_data_t _Nullable data,
int error);
/*!
* @function dispatch_io_read
* Schedule a read operation for asynchronous execution on the specified I/O
* channel. The I/O handler is enqueued one or more times depending on the
* general load of the system and the policy specified on the I/O channel.
*
* Any data read from the channel is described by the dispatch data object
* passed to the I/O handler. This object will be automatically released by the
* system when the I/O handler returns. It is the responsibility of the
* application to retain, concatenate or copy the data object if it is needed
* after the I/O handler returns.
*
* Dispatch I/O handlers are not reentrant. The system will ensure that no new
* I/O handler instance is invoked until the previously enqueued handler block
* has returned.
*
* An invocation of the I/O handler with the done flag set indicates that the
* read operation is complete and that the handler will not be enqueued again.
*
* If an unrecoverable error occurs on the I/O channel's underlying file
* descriptor, the I/O handler will be enqueued with the done flag set, the
* appropriate error code and a NULL data object.
*
* An invocation of the I/O handler with the done flag set, an error code of
* zero and an empty data object indicates that EOF was reached.
*
* @param channel The dispatch I/O channel from which to read the data.
* @param offset The offset relative to the channel position from which
* to start reading (only for DISPATCH_IO_RANDOM).
* @param length The length of data to read from the I/O channel, or
* SIZE_MAX to indicate that data should be read until EOF
* is reached.
* @param queue The dispatch queue to which the I/O handler should be
* submitted.
* @param io_handler The I/O handler to enqueue when data is ready to be
* delivered.
* param done A flag indicating whether the operation is complete.
* param data An object with the data most recently read from the
* I/O channel as part of this read operation, or NULL.
* param error An errno condition for the read operation or zero if
* the read was successful.
*/
API_AVAILABLE(macos(10.7), ios(5.0))
DISPATCH_EXPORT DISPATCH_NONNULL1 DISPATCH_NONNULL4 DISPATCH_NONNULL5
DISPATCH_NOTHROW
void
dispatch_io_read(dispatch_io_t channel,
off_t offset,
size_t length,
dispatch_queue_t queue,
dispatch_io_handler_t io_handler);
/*!
* @function dispatch_io_write
* Schedule a write operation for asynchronous execution on the specified I/O
* channel. The I/O handler is enqueued one or more times depending on the
* general load of the system and the policy specified on the I/O channel.
*
* Any data remaining to be written to the I/O channel is described by the
* dispatch data object passed to the I/O handler. This object will be
* automatically released by the system when the I/O handler returns. It is the
* responsibility of the application to retain, concatenate or copy the data
* object if it is needed after the I/O handler returns.
*
* Dispatch I/O handlers are not reentrant. The system will ensure that no new
* I/O handler instance is invoked until the previously enqueued handler block
* has returned.
*
* An invocation of the I/O handler with the done flag set indicates that the
* write operation is complete and that the handler will not be enqueued again.
*
* If an unrecoverable error occurs on the I/O channel's underlying file
* descriptor, the I/O handler will be enqueued with the done flag set, the
* appropriate error code and an object containing the data that could not be
* written.
*
* An invocation of the I/O handler with the done flag set and an error code of
* zero indicates that the data was fully written to the channel.
*
* @param channel The dispatch I/O channel on which to write the data.
* @param offset The offset relative to the channel position from which
* to start writing (only for DISPATCH_IO_RANDOM).
* @param data The data to write to the I/O channel. The data object
* will be retained by the system until the write operation
* is complete.
* @param queue The dispatch queue to which the I/O handler should be
* submitted.
* @param io_handler The I/O handler to enqueue when data has been delivered.
* param done A flag indicating whether the operation is complete.
* param data An object of the data remaining to be
* written to the I/O channel as part of this write
* operation, or NULL.
* param error An errno condition for the write operation or zero
* if the write was successful.
*/
API_AVAILABLE(macos(10.7), ios(5.0))
DISPATCH_EXPORT DISPATCH_NONNULL1 DISPATCH_NONNULL3 DISPATCH_NONNULL4
DISPATCH_NONNULL5 DISPATCH_NOTHROW
void
dispatch_io_write(dispatch_io_t channel,
off_t offset,
dispatch_data_t data,
dispatch_queue_t queue,
dispatch_io_handler_t io_handler);
#endif /* __BLOCKS__ */
/*!
* @typedef dispatch_io_close_flags_t
* The type of flags you can set on a dispatch_io_close() call
*
* @const DISPATCH_IO_STOP Stop outstanding operations on a channel when
* the channel is closed.
*/
#define DISPATCH_IO_STOP 0x1
typedef unsigned long dispatch_io_close_flags_t;
/*!
* @function dispatch_io_close
* Close the specified I/O channel to new read or write operations; scheduling
* operations on a closed channel results in their handler returning an error.
*
* If the DISPATCH_IO_STOP flag is provided, the system will make a best effort
* to interrupt any outstanding read and write operations on the I/O channel,
* otherwise those operations will run to completion normally.
* Partial results of read and write operations may be returned even after a
* channel is closed with the DISPATCH_IO_STOP flag.
* The final invocation of an I/O handler of an interrupted operation will be
* passed an ECANCELED error code, as will the I/O handler of an operation
* scheduled on a closed channel.
*
* @param channel The dispatch I/O channel to close.
* @param flags The flags for the close operation.
*/
API_AVAILABLE(macos(10.7), ios(5.0))
DISPATCH_EXPORT DISPATCH_NONNULL1 DISPATCH_NOTHROW
void
dispatch_io_close(dispatch_io_t channel, dispatch_io_close_flags_t flags);
#ifdef __BLOCKS__
/*!
* @function dispatch_io_barrier
* Schedule a barrier operation on the specified I/O channel; all previously
* scheduled operations on the channel will complete before the provided
* barrier block is enqueued onto the global queue determined by the channel's
* target queue, and no subsequently scheduled operations will start until the
* barrier block has returned.
*
* If multiple channels are associated with the same file descriptor, a barrier
* operation scheduled on any of these channels will act as a barrier across all
* channels in question, i.e. all previously scheduled operations on any of the
* channels will complete before the barrier block is enqueued, and no
* operations subsequently scheduled on any of the channels will start until the
* barrier block has returned.
*
* While the barrier block is running, it may safely operate on the channel's
* underlying file descriptor with fsync(2), lseek(2) etc. (but not close(2)).
*
* @param channel The dispatch I/O channel to schedule the barrier on.
* @param barrier The barrier block.
*/
API_AVAILABLE(macos(10.7), ios(5.0))
DISPATCH_EXPORT DISPATCH_NONNULL_ALL DISPATCH_NOTHROW
void
dispatch_io_barrier(dispatch_io_t channel, dispatch_block_t barrier);
#endif /* __BLOCKS__ */
/*!
* @function dispatch_io_get_descriptor
* Returns the file descriptor underlying a dispatch I/O channel.
*
* Will return -1 for a channel closed with dispatch_io_close() and for a
* channel associated with a path name that has not yet been open(2)ed.
*
* If called from a barrier block scheduled on a channel associated with a path
* name that has not yet been open(2)ed, this will trigger the channel open(2)
* operation and return the resulting file descriptor.
*
* @param channel The dispatch I/O channel to query.
* @result The file descriptor underlying the channel, or -1.
*/
API_AVAILABLE(macos(10.7), ios(5.0))
DISPATCH_EXPORT DISPATCH_NONNULL_ALL DISPATCH_WARN_RESULT DISPATCH_NOTHROW
dispatch_fd_t
dispatch_io_get_descriptor(dispatch_io_t channel);
/*!
* @function dispatch_io_set_high_water
* Set a high water mark on the I/O channel for all operations.
*
* The system will make a best effort to enqueue I/O handlers with partial
* results as soon the number of bytes processed by an operation (i.e. read or
* written) reaches the high water mark.
*
* The size of data objects passed to I/O handlers for this channel will never
* exceed the specified high water mark.
*
* The default value for the high water mark is unlimited (i.e. SIZE_MAX).
*
* @param channel The dispatch I/O channel on which to set the policy.
* @param high_water The number of bytes to use as a high water mark.
*/
API_AVAILABLE(macos(10.7), ios(5.0))
DISPATCH_EXPORT DISPATCH_NONNULL1 DISPATCH_NOTHROW
void
dispatch_io_set_high_water(dispatch_io_t channel, size_t high_water);
/*!
* @function dispatch_io_set_low_water
* Set a low water mark on the I/O channel for all operations.
*
* The system will process (i.e. read or write) at least the low water mark
* number of bytes for an operation before enqueueing I/O handlers with partial
* results.
*
* The size of data objects passed to intermediate I/O handler invocations for
* this channel (i.e. excluding the final invocation) will never be smaller than
* the specified low water mark, except if the channel has an interval with the
* DISPATCH_IO_STRICT_INTERVAL flag set or if EOF or an error was encountered.
*
* I/O handlers should be prepared to receive amounts of data significantly
* larger than the low water mark in general. If an I/O handler requires
* intermediate results of fixed size, set both the low and and the high water
* mark to that size.
*
* The default value for the low water mark is unspecified, but must be assumed
* to be such that intermediate handler invocations may occur.
* If I/O handler invocations with partial results are not desired, set the
* low water mark to SIZE_MAX.
*
* @param channel The dispatch I/O channel on which to set the policy.
* @param low_water The number of bytes to use as a low water mark.
*/
API_AVAILABLE(macos(10.7), ios(5.0))
DISPATCH_EXPORT DISPATCH_NONNULL1 DISPATCH_NOTHROW
void
dispatch_io_set_low_water(dispatch_io_t channel, size_t low_water);
/*!
* @typedef dispatch_io_interval_flags_t
* Type of flags to set on dispatch_io_set_interval()
*
* @const DISPATCH_IO_STRICT_INTERVAL Enqueue I/O handlers at a channel's
* interval setting even if the amount of data ready to be delivered is inferior
* to the low water mark (or zero).
*/
#define DISPATCH_IO_STRICT_INTERVAL 0x1
typedef unsigned long dispatch_io_interval_flags_t;
/*!
* @function dispatch_io_set_interval
* Set a nanosecond interval at which I/O handlers are to be enqueued on the
* I/O channel for all operations.
*
* This allows an application to receive periodic feedback on the progress of
* read and write operations, e.g. for the purposes of displaying progress bars.
*
* If the amount of data ready to be delivered to an I/O handler at the interval
* is inferior to the channel low water mark, the handler will only be enqueued
* if the DISPATCH_IO_STRICT_INTERVAL flag is set.
*
* Note that the system may defer enqueueing interval I/O handlers by a small
* unspecified amount of leeway in order to align with other system activity for
* improved system performance or power consumption.
*
* @param channel The dispatch I/O channel on which to set the policy.
* @param interval The interval in nanoseconds at which delivery of the I/O
* handler is desired.
* @param flags Flags indicating desired data delivery behavior at
* interval time.
*/
API_AVAILABLE(macos(10.7), ios(5.0))
DISPATCH_EXPORT DISPATCH_NONNULL1 DISPATCH_NOTHROW
void
dispatch_io_set_interval(dispatch_io_t channel,
uint64_t interval,
dispatch_io_interval_flags_t flags);
__END_DECLS
DISPATCH_ASSUME_NONNULL_END
#endif /* __DISPATCH_IO__ */

View File

@@ -0,0 +1,550 @@
/*
* Copyright (c) 2008-2012 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
DISPATCH_ASSUME_NONNULL_BEGIN
/*!
* @typedef dispatch_object_t
*
* @abstract
* Abstract base type for all dispatch objects.
* The details of the type definition are language-specific.
*
* @discussion
* Dispatch objects are reference counted via calls to dispatch_retain() and
* dispatch_release().
*/
#if OS_OBJECT_USE_OBJC
/*
* By default, dispatch objects are declared as Objective-C types when building
* with an Objective-C compiler. This allows them to participate in ARC, in RR
* management by the Blocks runtime and in leaks checking by the static
* analyzer, and enables them to be added to Cocoa collections.
* See <os/object.h> for details.
*/
OS_OBJECT_DECL_CLASS(dispatch_object);
#if OS_OBJECT_SWIFT3
#define DISPATCH_DECL(name) OS_OBJECT_DECL_SUBCLASS_SWIFT(name, dispatch_object)
#define DISPATCH_DECL_SUBCLASS(name, base) OS_OBJECT_DECL_SUBCLASS_SWIFT(name, base)
#else // OS_OBJECT_SWIFT3
#define DISPATCH_DECL(name) OS_OBJECT_DECL_SUBCLASS(name, dispatch_object)
#define DISPATCH_DECL_SUBCLASS(name, base) OS_OBJECT_DECL_SUBCLASS(name, base)
DISPATCH_INLINE DISPATCH_ALWAYS_INLINE DISPATCH_NONNULL_ALL DISPATCH_NOTHROW
void
_dispatch_object_validate(dispatch_object_t object)
{
void *isa = *(void *volatile*)(OS_OBJECT_BRIDGE void*)object;
(void)isa;
}
#endif // OS_OBJECT_SWIFT3
#define DISPATCH_GLOBAL_OBJECT(type, object) ((OS_OBJECT_BRIDGE type)&(object))
#define DISPATCH_RETURNS_RETAINED OS_OBJECT_RETURNS_RETAINED
#elif defined(__cplusplus) && !defined(__DISPATCH_BUILDING_DISPATCH__)
/*
* 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;
#define DISPATCH_DECL(name) \
typedef struct name##_s : public dispatch_object_s {} *name##_t
#define DISPATCH_DECL_SUBCLASS(name, base) \
typedef struct name##_s : public base##_s {} *name##_t
#define DISPATCH_GLOBAL_OBJECT(type, object) (static_cast<type>(&(object)))
#define DISPATCH_RETURNS_RETAINED
#else /* Plain C */
#ifndef __DISPATCH_BUILDING_DISPATCH__
typedef union {
struct _os_object_s *_os_obj;
struct dispatch_object_s *_do;
struct dispatch_queue_s *_dq;
struct dispatch_queue_attr_s *_dqa;
struct dispatch_group_s *_dg;
struct dispatch_source_s *_ds;
struct dispatch_mach_s *_dm;
struct dispatch_mach_msg_s *_dmsg;
struct dispatch_semaphore_s *_dsema;
struct dispatch_data_s *_ddata;
struct dispatch_io_s *_dchannel;
} dispatch_object_t DISPATCH_TRANSPARENT_UNION;
#endif // !__DISPATCH_BUILDING_DISPATCH__
#define DISPATCH_DECL(name) typedef struct name##_s *name##_t
#define DISPATCH_DECL_SUBCLASS(name, base) typedef base##_t name##_t
#define DISPATCH_GLOBAL_OBJECT(type, object) ((type)&(object))
#define DISPATCH_RETURNS_RETAINED
#endif
#if OS_OBJECT_SWIFT3 && OS_OBJECT_USE_OBJC
#define DISPATCH_SOURCE_TYPE_DECL(name) \
DISPATCH_EXPORT struct dispatch_source_type_s \
_dispatch_source_type_##name; \
OS_OBJECT_DECL_PROTOCOL(dispatch_source_##name, <OS_dispatch_source>); \
OS_OBJECT_CLASS_IMPLEMENTS_PROTOCOL( \
dispatch_source, dispatch_source_##name)
#define DISPATCH_SOURCE_DECL(name) \
DISPATCH_DECL(name); \
OS_OBJECT_DECL_PROTOCOL(name, <NSObject>); \
OS_OBJECT_CLASS_IMPLEMENTS_PROTOCOL(name, name)
#ifndef DISPATCH_DATA_DECL
#define DISPATCH_DATA_DECL(name) OS_OBJECT_DECL_SWIFT(name)
#endif // DISPATCH_DATA_DECL
#else
#define DISPATCH_SOURCE_DECL(name) \
DISPATCH_DECL(name);
#define DISPATCH_DATA_DECL(name) DISPATCH_DECL(name)
#define DISPATCH_SOURCE_TYPE_DECL(name) \
DISPATCH_EXPORT const struct dispatch_source_type_s \
_dispatch_source_type_##name
#endif
#ifdef __BLOCKS__
/*!
* @typedef dispatch_block_t
*
* @abstract
* The type of blocks submitted to dispatch queues, which take no arguments
* and have no return value.
*
* @discussion
* When not building with Objective-C ARC, a block object allocated on or
* copied to the heap must be released with a -[release] message or the
* Block_release() function.
*
* The declaration of a block literal allocates storage on the stack.
* Therefore, this is an invalid construct:
* <code>
* dispatch_block_t block;
* if (x) {
* block = ^{ printf("true\n"); };
* } else {
* block = ^{ printf("false\n"); };
* }
* block(); // unsafe!!!
* </code>
*
* What is happening behind the scenes:
* <code>
* if (x) {
* struct Block __tmp_1 = ...; // setup details
* block = &__tmp_1;
* } else {
* struct Block __tmp_2 = ...; // setup details
* block = &__tmp_2;
* }
* </code>
*
* 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.
*
* Instead, the block literal must be copied to the heap with the Block_copy()
* function or by sending it a -[copy] message.
*/
typedef void (^dispatch_block_t)(void);
#endif // __BLOCKS__
__BEGIN_DECLS
/*!
* @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.
*/
API_AVAILABLE(macos(10.6), ios(4.0))
DISPATCH_EXPORT DISPATCH_NONNULL_ALL DISPATCH_NOTHROW
DISPATCH_SWIFT_UNAVAILABLE("Can't be used with ARC")
void
dispatch_retain(dispatch_object_t object);
#if OS_OBJECT_USE_OBJC_RETAIN_RELEASE
#undef dispatch_retain
#define dispatch_retain(object) \
__extension__({ dispatch_object_t _o = (object); \
_dispatch_object_validate(_o); (void)[_o retain]; })
#endif
/*!
* @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.
*/
API_AVAILABLE(macos(10.6), ios(4.0))
DISPATCH_EXPORT DISPATCH_NONNULL_ALL DISPATCH_NOTHROW
DISPATCH_SWIFT_UNAVAILABLE("Can't be used with ARC")
void
dispatch_release(dispatch_object_t object);
#if OS_OBJECT_USE_OBJC_RETAIN_RELEASE
#undef dispatch_release
#define dispatch_release(object) \
__extension__({ dispatch_object_t _o = (object); \
_dispatch_object_validate(_o); [_o release]; })
#endif
/*!
* @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.
*/
API_AVAILABLE(macos(10.6), ios(4.0))
DISPATCH_EXPORT DISPATCH_NONNULL_ALL DISPATCH_PURE DISPATCH_WARN_RESULT
DISPATCH_NOTHROW
void *_Nullable
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.
*
*/
API_AVAILABLE(macos(10.6), ios(4.0))
DISPATCH_EXPORT DISPATCH_NOTHROW
void
dispatch_set_context(dispatch_object_t object, void *_Nullable context);
/*!
* @function dispatch_set_finalizer_f
*
* @abstract
* Set the finalizer function for a dispatch object.
*
* @param object
* The dispatch object to modify.
* The result of passing NULL in this parameter is undefined.
*
* @param finalizer
* 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.
*/
API_AVAILABLE(macos(10.6), ios(4.0))
DISPATCH_EXPORT DISPATCH_NOTHROW
void
dispatch_set_finalizer_f(dispatch_object_t object,
dispatch_function_t _Nullable finalizer);
/*!
* @function dispatch_activate
*
* @abstract
* Activates the specified dispatch object.
*
* @discussion
* Dispatch objects such as queues and sources may be created in an inactive
* state. Objects in this state have to be activated before any blocks
* associated with them will be invoked.
*
* The target queue of inactive objects can be changed using
* dispatch_set_target_queue(). Change of target queue is no longer permitted
* once an initially inactive object has been activated.
*
* Calling dispatch_activate() on an active object has no effect.
* Releasing the last reference count on an inactive object is undefined.
*
* @param object
* The object to be activated.
* The result of passing NULL in this parameter is undefined.
*/
API_AVAILABLE(macos(10.12), ios(10.0), tvos(10.0), watchos(3.0))
DISPATCH_EXPORT DISPATCH_NONNULL_ALL DISPATCH_NOTHROW
void
dispatch_activate(dispatch_object_t object);
/*!
* @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.
*/
API_AVAILABLE(macos(10.6), ios(4.0))
DISPATCH_EXPORT 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.
*
* @discussion
* Dispatch objects can be suspended with dispatch_suspend(), which increments
* an internal suspension count. dispatch_resume() is the inverse operation,
* and consumes suspension counts. When the last suspension count is consumed,
* blocks associated with the object will be invoked again.
*
* For backward compatibility reasons, dispatch_resume() on an inactive and not
* otherwise suspended dispatch source object has the same effect as calling
* dispatch_activate(). For new code, using dispatch_activate() is preferred.
*
* If the specified object has zero suspension count and is not an inactive
* source, this function will result in an assertion and the process being
* terminated.
*
* @param object
* The object to be resumed.
* The result of passing NULL in this parameter is undefined.
*/
API_AVAILABLE(macos(10.6), ios(4.0))
DISPATCH_EXPORT DISPATCH_NONNULL_ALL DISPATCH_NOTHROW
void
dispatch_resume(dispatch_object_t object);
#ifdef __BLOCKS__
/*!
* @function dispatch_wait
*
* @abstract
* Wait synchronously for an object or until the specified timeout has elapsed.
*
* @discussion
* Type-generic macro that maps to dispatch_block_wait, dispatch_group_wait or
* dispatch_semaphore_wait, depending on the type of the first argument.
* See documentation for these functions for more details.
* This function is unavailable for any other object type.
*
* @param object
* The object 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 or non-zero on error (i.e. timed out).
*/
DISPATCH_UNAVAILABLE
DISPATCH_EXPORT DISPATCH_NONNULL1 DISPATCH_NOTHROW
intptr_t
dispatch_wait(void *object, dispatch_time_t timeout);
#if __has_extension(c_generic_selections)
#define dispatch_wait(object, timeout) \
_Generic((object), \
dispatch_block_t:dispatch_block_wait, \
dispatch_group_t:dispatch_group_wait, \
dispatch_semaphore_t:dispatch_semaphore_wait \
)((object),(timeout))
#endif
/*!
* @function dispatch_notify
*
* @abstract
* Schedule a notification block to be submitted to a queue when the execution
* of a specified object has completed.
*
* @discussion
* Type-generic macro that maps to dispatch_block_notify or
* dispatch_group_notify, depending on the type of the first argument.
* See documentation for these functions for more details.
* This function is unavailable for any other object type.
*
* @param object
* The object to observe.
* The result of passing NULL in this parameter is undefined.
*
* @param queue
* The queue to which the supplied notification block will be submitted when
* the observed object completes.
*
* @param notification_block
* The block to submit when the observed object completes.
*/
DISPATCH_UNAVAILABLE
DISPATCH_EXPORT DISPATCH_NONNULL_ALL DISPATCH_NOTHROW
void
dispatch_notify(void *object, dispatch_object_t queue,
dispatch_block_t notification_block);
#if __has_extension(c_generic_selections)
#define dispatch_notify(object, queue, notification_block) \
_Generic((object), \
dispatch_block_t:dispatch_block_notify, \
dispatch_group_t:dispatch_group_notify \
)((object),(queue), (notification_block))
#endif
/*!
* @function dispatch_cancel
*
* @abstract
* Cancel the specified object.
*
* @discussion
* Type-generic macro that maps to dispatch_block_cancel or
* dispatch_source_cancel, depending on the type of the first argument.
* See documentation for these functions for more details.
* This function is unavailable for any other object type.
*
* @param object
* The object to cancel.
* The result of passing NULL in this parameter is undefined.
*/
DISPATCH_UNAVAILABLE
DISPATCH_EXPORT DISPATCH_NONNULL_ALL DISPATCH_NOTHROW
void
dispatch_cancel(void *object);
#if __has_extension(c_generic_selections)
#define dispatch_cancel(object) \
_Generic((object), \
dispatch_block_t:dispatch_block_cancel, \
dispatch_source_t:dispatch_source_cancel \
)((object))
#endif
/*!
* @function dispatch_testcancel
*
* @abstract
* Test whether the specified object has been canceled
*
* @discussion
* Type-generic macro that maps to dispatch_block_testcancel or
* dispatch_source_testcancel, depending on the type of the first argument.
* See documentation for these functions for more details.
* This function is unavailable for any other object type.
*
* @param object
* The object to test.
* The result of passing NULL in this parameter is undefined.
*
* @result
* Non-zero if canceled and zero if not canceled.
*/
DISPATCH_UNAVAILABLE
DISPATCH_EXPORT DISPATCH_NONNULL_ALL DISPATCH_WARN_RESULT DISPATCH_PURE
DISPATCH_NOTHROW
intptr_t
dispatch_testcancel(void *object);
#if __has_extension(c_generic_selections)
#define dispatch_testcancel(object) \
_Generic((object), \
dispatch_block_t:dispatch_block_testcancel, \
dispatch_source_t:dispatch_source_testcancel \
)((object))
#endif
#endif // __BLOCKS__
/*!
* @function dispatch_debug
*
* @abstract
* Programmatically log debug information about a dispatch object.
*
* @discussion
* Programmatically log debug information about a dispatch object. By default,
* the log output is sent to syslog at notice level. In the debug version of
* the library, the log output is sent to a file in /var/tmp.
* The log output destination can be configured via the LIBDISPATCH_LOG
* environment variable, valid values are: YES, NO, syslog, stderr, file.
*
* This function is deprecated and will be removed in a future release.
* Objective-C callers may use -debugDescription instead.
*
* @param object
* The object to introspect.
*
* @param message
* The message to log above and beyond the introspection.
*/
API_DEPRECATED("unsupported interface", macos(10.6,10.9), ios(4.0,6.0))
DISPATCH_EXPORT DISPATCH_NONNULL2 DISPATCH_NOTHROW DISPATCH_COLD
__attribute__((__format__(printf,2,3)))
void
dispatch_debug(dispatch_object_t object, const char *message, ...);
API_DEPRECATED("unsupported interface", macos(10.6,10.9), ios(4.0,6.0))
DISPATCH_EXPORT DISPATCH_NONNULL2 DISPATCH_NOTHROW DISPATCH_COLD
__attribute__((__format__(printf,2,0)))
void
dispatch_debugv(dispatch_object_t object, const char *message, va_list ap);
__END_DECLS
DISPATCH_ASSUME_NONNULL_END
#endif /* __DISPATCH_OBJECT__ */

View File

@@ -0,0 +1,125 @@
/*
* Copyright (c) 2008-2010 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
DISPATCH_ASSUME_NONNULL_BEGIN
__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.
*/
DISPATCH_SWIFT3_UNAVAILABLE("Use lazily initialized globals instead")
typedef intptr_t dispatch_once_t;
#if defined(__x86_64__) || defined(__i386__) || defined(__s390x__)
#define DISPATCH_ONCE_INLINE_FASTPATH 1
#elif defined(__APPLE__)
#define DISPATCH_ONCE_INLINE_FASTPATH 1
#else
#define DISPATCH_ONCE_INLINE_FASTPATH 0
#endif
/*!
* @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__
API_AVAILABLE(macos(10.6), ios(4.0))
DISPATCH_EXPORT DISPATCH_NONNULL_ALL DISPATCH_NOTHROW
DISPATCH_SWIFT3_UNAVAILABLE("Use lazily initialized globals instead")
void
dispatch_once(dispatch_once_t *predicate,
DISPATCH_NOESCAPE dispatch_block_t block);
#if DISPATCH_ONCE_INLINE_FASTPATH
DISPATCH_INLINE DISPATCH_ALWAYS_INLINE DISPATCH_NONNULL_ALL DISPATCH_NOTHROW
DISPATCH_SWIFT3_UNAVAILABLE("Use lazily initialized globals instead")
void
_dispatch_once(dispatch_once_t *predicate,
DISPATCH_NOESCAPE dispatch_block_t block)
{
if (DISPATCH_EXPECT(*predicate, ~0l) != ~0l) {
dispatch_once(predicate, block);
} else {
dispatch_compiler_barrier();
}
DISPATCH_COMPILER_CAN_ASSUME(*predicate == ~0l);
}
#undef dispatch_once
#define dispatch_once _dispatch_once
#endif
#endif // DISPATCH_ONCE_INLINE_FASTPATH
API_AVAILABLE(macos(10.6), ios(4.0))
DISPATCH_EXPORT DISPATCH_NONNULL1 DISPATCH_NONNULL3 DISPATCH_NOTHROW
DISPATCH_SWIFT3_UNAVAILABLE("Use lazily initialized globals instead")
void
dispatch_once_f(dispatch_once_t *predicate, void *_Nullable context,
dispatch_function_t function);
#if DISPATCH_ONCE_INLINE_FASTPATH
DISPATCH_INLINE DISPATCH_ALWAYS_INLINE DISPATCH_NONNULL1 DISPATCH_NONNULL3
DISPATCH_NOTHROW
DISPATCH_SWIFT3_UNAVAILABLE("Use lazily initialized globals instead")
void
_dispatch_once_f(dispatch_once_t *predicate, void *_Nullable context,
dispatch_function_t function)
{
if (DISPATCH_EXPECT(*predicate, ~0l) != ~0l) {
dispatch_once_f(predicate, context, function);
} else {
dispatch_compiler_barrier();
}
DISPATCH_COMPILER_CAN_ASSUME(*predicate == ~0l);
}
#undef dispatch_once_f
#define dispatch_once_f _dispatch_once_f
#endif // DISPATCH_ONCE_INLINE_FASTPATH
__END_DECLS
DISPATCH_ASSUME_NONNULL_END
#endif /* __DISPATCH_ONCE__ */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,117 @@
/*
* Copyright (c) 2008-2013 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
DISPATCH_ASSUME_NONNULL_BEGIN
/*!
* @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 greater 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.
*/
API_AVAILABLE(macos(10.6), ios(4.0))
DISPATCH_EXPORT DISPATCH_MALLOC DISPATCH_RETURNS_RETAINED DISPATCH_WARN_RESULT
DISPATCH_NOTHROW
dispatch_semaphore_t
dispatch_semaphore_create(intptr_t 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 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.
*/
API_AVAILABLE(macos(10.6), ios(4.0))
DISPATCH_EXPORT DISPATCH_NONNULL_ALL DISPATCH_NOTHROW
intptr_t
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.
*/
API_AVAILABLE(macos(10.6), ios(4.0))
DISPATCH_EXPORT DISPATCH_NONNULL_ALL DISPATCH_NOTHROW
intptr_t
dispatch_semaphore_signal(dispatch_semaphore_t dsema);
__END_DECLS
DISPATCH_ASSUME_NONNULL_END
#endif /* __DISPATCH_SEMAPHORE__ */

View File

@@ -0,0 +1,773 @@
/*
* Copyright (c) 2008-2013 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
#if TARGET_OS_MAC
#include <mach/port.h>
#include <mach/message.h>
#endif
#if !defined(_WIN32)
#include <signal.h>
#endif
DISPATCH_ASSUME_NONNULL_BEGIN
/*!
* @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_SOURCE_DECL(dispatch_source)
__BEGIN_DECLS
/*!
* @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 identifier, etc.), and how the mask argument 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)
API_AVAILABLE(macos(10.6), ios(4.0))
DISPATCH_SOURCE_TYPE_DECL(data_add);
/*!
* @const DISPATCH_SOURCE_TYPE_DATA_OR
* @discussion A dispatch source that coalesces data obtained via calls to
* dispatch_source_merge_data(). A bitwise OR 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_OR (&_dispatch_source_type_data_or)
API_AVAILABLE(macos(10.6), ios(4.0))
DISPATCH_SOURCE_TYPE_DECL(data_or);
/*!
* @const DISPATCH_SOURCE_TYPE_DATA_REPLACE
* @discussion A dispatch source that tracks data obtained via calls to
* dispatch_source_merge_data(). Newly obtained data values replace existing
* data values not yet delivered to the source handler
*
* A data value of zero will cause the source handler to not be invoked.
*
* The handle is unused (pass zero for now).
* The mask is unused (pass zero for now).
*/
#define DISPATCH_SOURCE_TYPE_DATA_REPLACE (&_dispatch_source_type_data_replace)
API_AVAILABLE(macos(10.13), ios(11.0), tvos(11.0), watchos(4.0))
DISPATCH_SOURCE_TYPE_DECL(data_replace);
/*!
* @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)
API_AVAILABLE(macos(10.6), ios(4.0)) DISPATCH_LINUX_UNAVAILABLE()
DISPATCH_SOURCE_TYPE_DECL(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)
API_AVAILABLE(macos(10.6), ios(4.0)) DISPATCH_LINUX_UNAVAILABLE()
DISPATCH_SOURCE_TYPE_DECL(mach_recv);
/*!
* @const DISPATCH_SOURCE_TYPE_MEMORYPRESSURE
* @discussion A dispatch source that monitors the system for changes in
* memory pressure condition.
* The handle is unused (pass zero for now).
* The mask is a mask of desired events from
* dispatch_source_memorypressure_flags_t.
*/
#define DISPATCH_SOURCE_TYPE_MEMORYPRESSURE \
(&_dispatch_source_type_memorypressure)
API_AVAILABLE(macos(10.9), ios(8.0)) DISPATCH_LINUX_UNAVAILABLE()
DISPATCH_SOURCE_TYPE_DECL(memorypressure);
/*!
* @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)
API_AVAILABLE(macos(10.6), ios(4.0)) DISPATCH_LINUX_UNAVAILABLE()
DISPATCH_SOURCE_TYPE_DECL(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)
API_AVAILABLE(macos(10.6), ios(4.0))
DISPATCH_SOURCE_TYPE_DECL(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)
API_AVAILABLE(macos(10.6), ios(4.0))
DISPATCH_SOURCE_TYPE_DECL(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 specifies which flags from dispatch_source_timer_flags_t to apply.
*/
#define DISPATCH_SOURCE_TYPE_TIMER (&_dispatch_source_type_timer)
API_AVAILABLE(macos(10.6), ios(4.0))
DISPATCH_SOURCE_TYPE_DECL(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)
API_AVAILABLE(macos(10.6), ios(4.0)) DISPATCH_LINUX_UNAVAILABLE()
DISPATCH_SOURCE_TYPE_DECL(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)
API_AVAILABLE(macos(10.6), ios(4.0))
DISPATCH_SOURCE_TYPE_DECL(write);
/*!
* @typedef dispatch_source_mach_send_flags_t
* Type of dispatch_source_mach_send flags
*
* @constant DISPATCH_MACH_SEND_DEAD
* The receive right corresponding to the given send right was destroyed.
*/
#define DISPATCH_MACH_SEND_DEAD 0x1
typedef unsigned long dispatch_source_mach_send_flags_t;
/*!
* @typedef dispatch_source_memorypressure_flags_t
* Type of dispatch_source_memorypressure flags
*
* @constant DISPATCH_MEMORYPRESSURE_NORMAL
* The system memory pressure condition has returned to normal.
*
* @constant DISPATCH_MEMORYPRESSURE_WARN
* The system memory pressure condition has changed to warning.
*
* @constant DISPATCH_MEMORYPRESSURE_CRITICAL
* The system memory pressure condition has changed to critical.
*
* @discussion
* Elevated memory pressure is a system-wide condition that applications
* registered for this source should react to by changing their future memory
* use behavior, e.g. by reducing cache sizes of newly initiated operations
* until memory pressure returns back to normal.
* NOTE: applications should NOT traverse and discard existing caches for past
* operations when the system memory pressure enters an elevated state, as that
* is likely to trigger VM operations that will further aggravate system memory
* pressure.
*/
#define DISPATCH_MEMORYPRESSURE_NORMAL 0x01
#define DISPATCH_MEMORYPRESSURE_WARN 0x02
#define DISPATCH_MEMORYPRESSURE_CRITICAL 0x04
typedef unsigned long dispatch_source_memorypressure_flags_t;
/*!
* @typedef dispatch_source_proc_flags_t
* Type of dispatch_source_proc flags
*
* @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.
*/
#define DISPATCH_PROC_EXIT 0x80000000
#define DISPATCH_PROC_FORK 0x40000000
#define DISPATCH_PROC_EXEC 0x20000000
#define DISPATCH_PROC_SIGNAL 0x08000000
typedef unsigned long dispatch_source_proc_flags_t;
/*!
* @typedef dispatch_source_vnode_flags_t
* Type of dispatch_source_vnode flags
*
* @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.
*
* @constant DISPATCH_VNODE_FUNLOCK
* The filesystem object was unlocked.
*/
#define DISPATCH_VNODE_DELETE 0x1
#define DISPATCH_VNODE_WRITE 0x2
#define DISPATCH_VNODE_EXTEND 0x4
#define DISPATCH_VNODE_ATTRIB 0x8
#define DISPATCH_VNODE_LINK 0x10
#define DISPATCH_VNODE_RENAME 0x20
#define DISPATCH_VNODE_REVOKE 0x40
#define DISPATCH_VNODE_FUNLOCK 0x100
typedef unsigned long dispatch_source_vnode_flags_t;
/*!
* @typedef dispatch_source_timer_flags_t
* Type of dispatch_source_timer flags
*
* @constant DISPATCH_TIMER_STRICT
* Specifies that the system should make a best effort to strictly observe the
* leeway value specified for the timer via dispatch_source_set_timer(), even
* if that value is smaller than the default leeway value that would be applied
* to the timer otherwise. A minimal amount of leeway will be applied to the
* timer even if this flag is specified.
*
* CAUTION: Use of this flag may override power-saving techniques employed by
* the system and cause higher power consumption, so it must be used with care
* and only when absolutely necessary.
*/
#define DISPATCH_TIMER_STRICT 0x1
typedef unsigned long dispatch_source_timer_flags_t;
/*!
* @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 an inactive state. After creating the
* source and setting any desired attributes (i.e. the handler, context, etc.),
* a call must be made to dispatch_activate() in order to begin event delivery.
*
* Calling dispatch_set_target_queue() on a source once it has been activated
* is not allowed (see dispatch_activate() and dispatch_set_target_queue()).
*
* For backward compatibility reasons, dispatch_resume() on an inactive,
* and not otherwise suspended source has the same effect as calling
* dispatch_activate(). For new code, using dispatch_activate() is preferred.
*
* @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 submitted.
* If queue is DISPATCH_TARGET_QUEUE_DEFAULT, the source will submit the event
* handler block to the default priority global queue.
*
* @result
* The newly created dispatch source. Or NULL if invalid arguments are passed.
*/
API_AVAILABLE(macos(10.6), ios(4.0))
DISPATCH_EXPORT DISPATCH_MALLOC DISPATCH_RETURNS_RETAINED DISPATCH_WARN_RESULT
DISPATCH_NOTHROW
dispatch_source_t
dispatch_source_create(dispatch_source_type_t type,
uintptr_t handle,
uintptr_t mask,
dispatch_queue_t _Nullable 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__
API_AVAILABLE(macos(10.6), ios(4.0))
DISPATCH_EXPORT DISPATCH_NONNULL1 DISPATCH_NOTHROW
void
dispatch_source_set_event_handler(dispatch_source_t source,
dispatch_block_t _Nullable 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 context of
* the dispatch source current at the time the event handler was set.
*/
API_AVAILABLE(macos(10.6), ios(4.0))
DISPATCH_EXPORT DISPATCH_NONNULL1 DISPATCH_NOTHROW
void
dispatch_source_set_event_handler_f(dispatch_source_t source,
dispatch_function_t _Nullable 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:
* Source cancellation and a cancellation handler are 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 is invoked 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__
API_AVAILABLE(macos(10.6), ios(4.0))
DISPATCH_EXPORT DISPATCH_NONNULL1 DISPATCH_NOTHROW
void
dispatch_source_set_cancel_handler(dispatch_source_t source,
dispatch_block_t _Nullable 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.
*/
API_AVAILABLE(macos(10.6), ios(4.0))
DISPATCH_EXPORT DISPATCH_NONNULL1 DISPATCH_NOTHROW
void
dispatch_source_set_cancel_handler_f(dispatch_source_t source,
dispatch_function_t _Nullable 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.
*/
API_AVAILABLE(macos(10.6), ios(4.0))
DISPATCH_EXPORT 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.
*/
API_AVAILABLE(macos(10.6), ios(4.0))
DISPATCH_EXPORT DISPATCH_NONNULL_ALL DISPATCH_WARN_RESULT DISPATCH_PURE
DISPATCH_NOTHROW
intptr_t
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_DATA_REPLACE: 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_MEMORYPRESSURE n/a
* 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)
*/
API_AVAILABLE(macos(10.6), ios(4.0))
DISPATCH_EXPORT 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_DATA_REPLACE: n/a
* DISPATCH_SOURCE_TYPE_MACH_SEND: dispatch_source_mach_send_flags_t
* DISPATCH_SOURCE_TYPE_MACH_RECV: n/a
* DISPATCH_SOURCE_TYPE_MEMORYPRESSURE dispatch_source_memorypressure_flags_t
* 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: dispatch_source_timer_flags_t
* DISPATCH_SOURCE_TYPE_VNODE: dispatch_source_vnode_flags_t
* DISPATCH_SOURCE_TYPE_WRITE: n/a
*/
API_AVAILABLE(macos(10.6), ios(4.0))
DISPATCH_EXPORT DISPATCH_NONNULL_ALL DISPATCH_WARN_RESULT DISPATCH_PURE
DISPATCH_NOTHROW
uintptr_t
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_DATA_REPLACE: application defined data
* DISPATCH_SOURCE_TYPE_MACH_SEND: dispatch_source_mach_send_flags_t
* DISPATCH_SOURCE_TYPE_MACH_RECV: n/a
* DISPATCH_SOURCE_TYPE_MEMORYPRESSURE dispatch_source_memorypressure_flags_t
* 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
*/
API_AVAILABLE(macos(10.6), ios(4.0))
DISPATCH_EXPORT DISPATCH_NONNULL_ALL DISPATCH_WARN_RESULT DISPATCH_PURE
DISPATCH_NOTHROW
uintptr_t
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,
* DISPATCH_SOURCE_TYPE_DATA_OR or DISPATCH_SOURCE_TYPE_DATA_REPLACE,
* 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.
*/
API_AVAILABLE(macos(10.6), ios(4.0))
DISPATCH_EXPORT DISPATCH_NONNULL_ALL DISPATCH_NOTHROW
void
dispatch_source_merge_data(dispatch_source_t source, uintptr_t value);
/*!
* @function dispatch_source_set_timer
*
* @abstract
* Sets a start time, interval, and leeway value for a timer source.
*
* @discussion
* Once this function returns, any pending source data accumulated for the
* previous timer values has been cleared; the next fire of the timer will
* occur at 'start', and every 'interval' nanoseconds thereafter until the
* timer source is canceled.
*
* Any fire of the timer may be delayed by the system in order to improve power
* consumption and system performance. The upper limit to the allowable delay
* may be configured with the 'leeway' argument, the lower limit is under the
* control of the system.
*
* For the initial timer fire at 'start', the upper limit to the allowable
* delay is set to 'leeway' nanoseconds. For the subsequent timer fires at
* 'start' + N * 'interval', the upper limit is MIN('leeway','interval'/2).
*
* The lower limit to the allowable delay may vary with process state such as
* visibility of application UI. If the specified timer source was created with
* a mask of DISPATCH_TIMER_STRICT, the system will make a best effort to
* strictly observe the provided 'leeway' value even if it is smaller than the
* current lower limit. Note that a minimal amount of delay is to be expected
* even if this flag is specified.
*
* The 'start' argument also determines which clock will be used for the timer:
* If 'start' is DISPATCH_TIME_NOW or was created with dispatch_time(3), the
* timer is based on up time (which is obtained from mach_absolute_time() on
* Apple platforms). If 'start' was created with dispatch_walltime(3), the
* timer is based on gettimeofday(3).
*
* Calling this function has no effect if the timer source has already been
* canceled.
*
* @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. Use DISPATCH_TIME_FOREVER for a
* one-shot timer.
*
* @param leeway
* The nanosecond leeway for the timer.
*/
API_AVAILABLE(macos(10.6), ios(4.0))
DISPATCH_EXPORT DISPATCH_NONNULL_ALL DISPATCH_NOTHROW
void
dispatch_source_set_timer(dispatch_source_t source,
dispatch_time_t start,
uint64_t interval,
uint64_t leeway);
/*!
* @function dispatch_source_set_registration_handler
*
* @abstract
* Sets the registration handler block for the given dispatch source.
*
* @discussion
* The registration handler (if specified) will be submitted to the source's
* target queue once the corresponding kevent() has been registered with the
* system, following the initial dispatch_resume() of the source.
*
* If a source is already registered when the registration handler is set, the
* registration handler will be invoked immediately.
*
* @param source
* The dispatch source to modify.
* The result of passing NULL in this parameter is undefined.
*
* @param handler
* The registration handler block to submit to the source's target queue.
*/
#ifdef __BLOCKS__
API_AVAILABLE(macos(10.7), ios(4.3))
DISPATCH_EXPORT DISPATCH_NONNULL1 DISPATCH_NOTHROW
void
dispatch_source_set_registration_handler(dispatch_source_t source,
dispatch_block_t _Nullable handler);
#endif /* __BLOCKS__ */
/*!
* @function dispatch_source_set_registration_handler_f
*
* @abstract
* Sets the registration handler function for the given dispatch source.
*
* @discussion
* See dispatch_source_set_registration_handler() for more details.
*
* @param source
* The dispatch source to modify.
* The result of passing NULL in this parameter is undefined.
*
* @param handler
* The registration handler function to submit to the source's target queue.
* The context parameter passed to the registration handler function is the
* current context of the dispatch source at the time the handler call is made.
*/
API_AVAILABLE(macos(10.7), ios(4.3))
DISPATCH_EXPORT DISPATCH_NONNULL1 DISPATCH_NOTHROW
void
dispatch_source_set_registration_handler_f(dispatch_source_t source,
dispatch_function_t _Nullable handler);
__END_DECLS
DISPATCH_ASSUME_NONNULL_END
#endif /* __DISPATCH_SOURCE__ */

View File

@@ -0,0 +1,135 @@
/*
* Copyright (c) 2008-2011 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>
// <rdar://problem/6368156&7563559>
#if TARGET_OS_MAC
#include <mach/clock_types.h>
#endif
DISPATCH_ASSUME_NONNULL_BEGIN
#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
#ifdef NSEC_PER_MSEC
#undef NSEC_PER_MSEC
#endif
#define NSEC_PER_SEC 1000000000ull
#define NSEC_PER_MSEC 1000000ull
#define USEC_PER_SEC 1000000ull
#define NSEC_PER_USEC 1000ull
__BEGIN_DECLS
struct timespec;
/*!
* @typedef dispatch_time_t
*
* @abstract
* A 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;
enum {
DISPATCH_WALLTIME_NOW DISPATCH_ENUM_API_AVAILABLE(macos(10.14), ios(12.0), tvos(12.0), watchos(5.0)) = ~1ull,
};
#define DISPATCH_TIME_NOW (0ull)
#define DISPATCH_TIME_FOREVER (~0ull)
/*!
* @function dispatch_time
*
* @abstract
* Create a dispatch_time_t relative to the current value of the default or
* wall time clock, or modify an existing dispatch_time_t.
*
* @discussion
* On Apple platforms, the default clock is based on mach_absolute_time().
*
* @param when
* An optional dispatch_time_t to add nanoseconds to. If DISPATCH_TIME_NOW is
* passed, then dispatch_time() will use the default clock (which is based on
* mach_absolute_time() on Apple platforms). If DISPATCH_WALLTIME_NOW is used,
* dispatch_time() will use the value returned by gettimeofday(3).
* dispatch_time(DISPATCH_WALLTIME_NOW, delta) is equivalent to
* dispatch_walltime(NULL, delta).
*
* @param delta
* Nanoseconds to add.
*
* @result
* A new dispatch_time_t.
*/
API_AVAILABLE(macos(10.6), ios(4.0))
DISPATCH_EXPORT DISPATCH_WARN_RESULT 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 timespec to add time to. If NULL is passed, then
* dispatch_walltime() will use the result of gettimeofday(3).
* dispatch_walltime(NULL, delta) returns the same value as
* dispatch_time(DISPATCH_WALLTIME_NOW, delta).
*
* @param delta
* Nanoseconds to add.
*
* @result
* A new dispatch_time_t.
*/
API_AVAILABLE(macos(10.6), ios(4.0))
DISPATCH_EXPORT DISPATCH_WARN_RESULT DISPATCH_NOTHROW
dispatch_time_t
dispatch_walltime(const struct timespec *_Nullable when, int64_t delta);
__END_DECLS
DISPATCH_ASSUME_NONNULL_END
#endif /* __DISPATCH_TIME__ */

View File

@@ -0,0 +1,23 @@
# TODO(compnerd) add symlinks
if(NOT ENABLE_SWIFT)
install(FILES
dispatch.3
dispatch_after.3
dispatch_api.3
dispatch_apply.3
dispatch_async.3
dispatch_data_create.3
dispatch_group_create.3
dispatch_io_create.3
dispatch_io_read.3
dispatch_object.3
dispatch_once.3
dispatch_queue_create.3
dispatch_read.3
dispatch_semaphore_create.3
dispatch_source_create.3
dispatch_time.3
DESTINATION
"${CMAKE_INSTALL_FULL_MANDIR}/man3")
endif()

View File

@@ -0,0 +1,43 @@
.\" Copyright (c) 2008-2012 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_after 3 ,
.Xr dispatch_api 3 ,
.Xr dispatch_apply 3 ,
.Xr dispatch_async 3 ,
.Xr dispatch_data_create 3 ,
.Xr dispatch_group_create 3 ,
.Xr dispatch_io_create 3 ,
.Xr dispatch_io_read 3 ,
.Xr dispatch_object 3 ,
.Xr dispatch_once 3 ,
.Xr dispatch_queue_create 3 ,
.Xr dispatch_semaphore_create 3 ,
.Xr dispatch_source_create 3 ,
.Xr dispatch_time 3

View File

@@ -0,0 +1,69 @@
.\" Copyright (c) 2008-2010 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 .
Submission of the block may be delayed by the system in order to improve power consumption and system performance.
The system applies a leeway (see
.Xr dispatch_source_set_timer 3 )
that is equal to one tenth of the interval between
.Fa when
and the time at which the function is called, with the leeway capped to at least one millisecond and at most one minute.
.Pp
For a more detailed description about submitting blocks to queues, see
.Xr dispatch_async 3 .
.Sh CAVEATS
.Fn dispatch_after
retains the passed queue.
.Pp
Specifying
.Vt DISPATCH_TIME_NOW
as the
.Fa when
parameter
is supported, but is not as efficient as calling
.Fn dispatch_async .
.Pp
The result of passing
.Vt DISPATCH_TIME_FOREVER
as the
.Fa when
parameter is undefined.
.Pp
.Sh FUNDAMENTALS
The
.Fn dispatch_after
function is a wrapper around
.Fn dispatch_after_f .
.Sh SEE ALSO
.Xr dispatch 3 ,
.Xr dispatch_async 3 ,
.Xr dispatch_time 3

View File

@@ -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

View File

@@ -0,0 +1,122 @@
.\" Copyright (c) 2008-2017 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
size_t iterations = 10;
// 'idx' is zero indexed, just like:
// for (idx = 0; idx < iterations; idx++)
dispatch_apply(iterations, DISPATCH_APPLY_AUTO, ^(size_t idx) {
printf("%zu\\n", idx);
});
.Ed
.Pp
Although any queue can be used, it is strongly recommended to use
.Vt DISPATCH_APPLY_AUTO
as the
.Vt queue
argument to both
.Fn dispatch_apply
and
.Fn dispatch_apply_f ,
as shown in the example above, since this allows the system to automatically use worker threads
that match the configuration of the current thread as closely as possible.
No assumptions should be made about which global concurrent queue will be used.
.Pp
Like a "for (;;)" loop, the
.Fn dispatch_apply
function is synchronous.
If asynchronous behavior is desired, 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, DISPATCH_APPLY_AUTO, ^(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 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).
.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
.Fn dispatch_apply
and
.Fn dispatch_apply_f
attempt to quickly create enough worker threads to efficiently iterate work in parallel.
By contrast, a loop that passes work items individually to
.Fn dispatch_async
or
.Fn dispatch_async_f
will incur more overhead and does not express the desired parallel execution semantics to
the system, so may not create an optimal number of worker threads for a parallel workload.
For this reason, prefer to use
.Fn dispatch_apply
or
.Fn dispatch_apply_f
when parallel execution is important.
.Pp
The
.Fn dispatch_apply
function is a wrapper around
.Fn dispatch_apply_f .
.Sh CAVEATS
Unlike
.Fn dispatch_async ,
a block submitted to
.Fn dispatch_apply
is expected to be either independent or dependent
.Em only
on work already performed in lower-indexed invocations of the block. If
the block's index dependency is non-linear, it is recommended to
use a for-loop around invocations of
.Fn dispatch_async .
.Sh SEE ALSO
.Xr dispatch 3 ,
.Xr dispatch_async 3 ,
.Xr dispatch_queue_create 3

View File

@@ -0,0 +1,235 @@
.\" Copyright (c) 2008-2012 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 background 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 synchronous 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 3 ,
.Xr dispatch_apply 3 ,
.Xr dispatch_once 3 ,
.Xr dispatch_queue_create 3 ,
.Xr dispatch_semaphore_create 3

View File

@@ -0,0 +1,59 @@
.\" 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
.Ft uint64_t
.Fo dispatch_benchmark_f
.Fa "size_t count" "void *context" "void (*function)(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

View File

@@ -0,0 +1,220 @@
.\" Copyright (c) 2010-2012 Apple Inc. All rights reserved.
.Dd December 1, 2010
.Dt dispatch_data_create 3
.Os Darwin
.Sh NAME
.Nm dispatch_data_create ,
.Nm dispatch_data_create_concat ,
.Nm dispatch_data_create_subrange ,
.Nm dispatch_data_create_map ,
.Nm dispatch_data_apply ,
.Nm dispatch_data_copy_region ,
.Nm dispatch_data_get_size
.Nd create and manipulate dispatch data objects
.Sh SYNOPSIS
.Fd #include <dispatch/dispatch.h>
.Ft dispatch_data_t
.Fo dispatch_data_create
.Fa "const void* buffer"
.Fa "size_t size"
.Fa "dispatch_queue_t queue"
.Fa "dispatch_block_t destructor"
.Fc
.Ft dispatch_data_t
.Fo dispatch_data_create_concat
.Fa "dispatch_data_t data1"
.Fa "dispatch_data_t data2"
.Fc
.Ft dispatch_data_t
.Fo dispatch_data_create_subrange
.Fa "dispatch_data_t data"
.Fa "size_t offset"
.Fa "size_t length"
.Fc
.Ft dispatch_data_t
.Fo dispatch_data_create_map
.Fa "dispatch_data_t data"
.Fa "const void **buffer_ptr"
.Fa "size_t *size_ptr"
.Fc
.Ft bool
.Fo dispatch_data_apply
.Fa "dispatch_data_t data"
.Fa "bool (^applier)(dispatch_data_t, size_t, const void *, size_t)"
.Fc
.Ft dispatch_data_t
.Fo dispatch_data_copy_region
.Fa "dispatch_data_t data"
.Fa "size_t location"
.Fa "size_t *offset_ptr"
.Fc
.Ft size_t
.Fo dispatch_data_get_size
.Fa "dispatch_data_t data"
.Fc
.Vt dispatch_data_t dispatch_data_empty ;
.Sh DESCRIPTION
Dispatch data objects are opaque containers of bytes that represent one or more
regions of memory. They are created either from memory buffers managed by the
application or the system or from other dispatch data objects. Dispatch data
objects are immutable and the memory regions they represent are required to
remain unchanged for the lifetime of all data objects that reference them.
Dispatch data objects avoid copying the represented memory as much as possible.
Multiple data objects can represent the same memory regions or subsections
thereof.
.Sh CREATION
The
.Fn dispatch_data_create
function creates a new dispatch data object of given
.Fa size
from a
.Fa buffer .
The provided
.Fa destructor
block will be submitted to the specified
.Fa queue
when the object reaches the end of its lifecycle, indicating that the system no
longer references the
.Fa buffer .
This allows the application to deallocate
the associated storage. The
.Fa queue
argument is ignored if one of the following predefined destructors is passed:
.Bl -tag -width DISPATCH_DATA_DESTRUCTOR_DEFAULT -compact -offset indent
.It DISPATCH_DATA_DESTRUCTOR_FREE
indicates that the provided buffer can be deallocated with
.Xr free 3
directly.
.It DISPATCH_DATA_DESTRUCTOR_DEFAULT
indicates that the provided buffer is not managed by the application and should
be copied into memory managed and automatically deallocated by the system.
.El
.Pp
The
.Fn dispatch_data_create_concat
function creates a new data object representing the concatenation of the memory
regions represented by the provided data objects.
.Pp
The
.Fn dispatch_data_create_subrange
function creates a new data object representing the sub-region of the provided
.Fa data
object specified by the
.Fa offset
and
.Fa length
parameters.
.Pp
The
.Fn dispatch_data_create_map
function creates a new data object by mapping the memory represented by the
provided
.Fa data
object as a single contiguous memory region (moving or copying memory as
necessary). If the
.Fa buffer_ptr
and
.Fa size_ptr
references are not
.Dv NULL ,
they are filled with the location and extent of the contiguous region, allowing
direct read access to the mapped memory. These values are valid only as long as
the newly created object has not been released.
.Sh ACCESS
The
.Fn dispatch_data_apply
function provides read access to represented memory without requiring it to be
mapped as a single contiguous region. It traverses the memory regions
represented by the
.Fa data
argument in logical order, invokes the specified
.Fa applier
block for each region and returns a boolean indicating whether traversal
completed successfully. The
.Fa applier
block is passed the following arguments for each memory region and returns a
boolean indicating whether traversal should continue:
.Bl -tag -width "dispatch_data_t rgn" -compact -offset indent
.It Fa "dispatch_data_t rgn"
data object representing the region
.It Fa "size_t offset"
logical position of the region in
.Fa data
.It Vt "const void *loc"
memory location of the region
.It Vt "size_t size"
extent of the region
.El
The
.Fa rgn
data object is released by the system when the
.Fa applier
block returns.
The associated memory location
.Fa loc
is valid only as long as
.Fa rgn
has not been deallocated; if
.Fa loc
is needed outside of the
.Fa applier
block, the
.Fa rgn
object must be retained in the block.
.Pp
The
.Fn dispatch_data_copy_region
function finds the contiguous memory region containing the logical position
specified by the
.Fa location
argument among the regions represented by the provided
.Fa data
object and returns a newly created copy of the data object representing that
region. The variable specified by the
.Fa offset_ptr
argument is filled with the logical position where the returned object starts
in the
.Fa data
object.
.Pp
The
.Fn dispatch_data_get_size
function returns the logical size of the memory region or regions represented
by the provided
.Fa data
object.
.Sh EMPTY DATA OBJECT
The
.Vt dispatch_data_empty
object is the global singleton object representing a zero-length memory region.
It is a valid input to any dispatch_data functions that take data object
parameters.
.Sh MEMORY MODEL
Dispatch data objects are retained and released via calls to
.Fn dispatch_retain
and
.Fn dispatch_release .
Data objects passed as arguments to a dispatch data
.Sy create
or
.Sy copy
function can be released when the function returns. The newly created object
holds implicit references to their constituent memory regions as necessary.
.Pp
The functions
.Fn dispatch_data_create_map
and
.Fn dispatch_data_apply
return an interior pointer to represented memory that is only valid as long as
an associated object has not been released. When Objective-C Automated
Reference Counting is enabled, care needs to be taken if that object is held in
a variable with automatic storage. It may need to be annotated with the
.Li objc_precise_lifetime
attribute, or stored in a
.Li __strong
instance variable instead, to ensure that the object is not released
prematurely before memory accesses via the interor pointer have been completed.
.Sh SEE ALSO
.Xr dispatch 3 ,
.Xr dispatch_object 3 ,
.Xr dispatch_io_read 3

View File

@@ -0,0 +1,180 @@
.\" Copyright (c) 2008-2012 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 CAVEATS
In order to ensure deterministic behavior, it is recommended to call
.Fn dispatch_group_wait
only once all blocks have been submitted to the group. If it is later
determined that new blocks should be run, it is recommended not to reuse an
already-running group, but to create a new group.
.Pp
.Fn dispatch_group_wait
returns as soon as there are exactly zero
.Em enqueued or running
blocks associated with a group (more precisely, as soon as every
.Fn dispatch_group_enter
call has been balanced by a
.Fn dispatch_group_leave
call). If one thread waits for a group while another thread submits
new blocks to the group, then the count of associated blocks might
momentarily reach zero before all blocks have been submitted. If this happens,
.Fn dispatch_group_wait
will return too early: some blocks associated with the group have finished,
but some have not yet been submitted or run.
.Pp
However, as a special case, a block associated with a group may submit new
blocks associated with its own group. In this case, the behavior is
deterministic: a waiting thread will
.Em not
wake up until the newly submitted blocks have also finished.
.Pp
All of the foregoing also applies to
.Fn dispath_group_notify
as well, with "block to be submitted" substituted for "waiting thread".
.Sh SEE ALSO
.Xr dispatch 3 ,
.Xr dispatch_async 3 ,
.Xr dispatch_object 3 ,
.Xr dispatch_queue_create 3 ,
.Xr dispatch_semaphore_create 3 ,
.Xr dispatch_time 3

View File

@@ -0,0 +1,282 @@
.\" Copyright (c) 2010-2013 Apple Inc. All rights reserved.
.Dd December 1, 2010
.Dt dispatch_io_create 3
.Os Darwin
.Sh NAME
.Nm dispatch_io_create ,
.Nm dispatch_io_create_with_path ,
.Nm dispatch_io_close ,
.Nm dispatch_io_set_high_water ,
.Nm dispatch_io_set_low_water ,
.Nm dispatch_io_set_interval ,
.Nm dispatch_io_barrier
.Nd open, close and configure dispatch I/O channels
.Sh SYNOPSIS
.Fd #include <dispatch/dispatch.h>
.Ft dispatch_io_t
.Fo dispatch_io_create
.Fa "dispatch_io_type_t type"
.Fa "int fd"
.Fa "dispatch_queue_t queue"
.Fa "void (^cleanup_handler)(int error)"
.Fc
.Ft dispatch_io_t
.Fo dispatch_io_create_with_path
.Fa "dispatch_io_type_t type"
.Fa "const char *path"
.Fa "int oflag"
.Fa "mode_t mode"
.Fa "dispatch_queue_t queue"
.Fa "void (^cleanup_handler)(int error)"
.Fc
.Ft void
.Fo dispatch_io_close
.Fa "dispatch_io_t channel"
.Fa "dispatch_io_close_flags_t flags"
.Fc
.Ft void
.Fo dispatch_io_set_high_water
.Fa "dispatch_io_t channel"
.Fa "size_t high_water"
.Fc
.Ft void
.Fo dispatch_io_set_low_water
.Fa "dispatch_io_t channel"
.Fa "size_t low_water"
.Fc
.Ft void
.Fo dispatch_io_set_interval
.Fa "dispatch_io_t channel"
.Fa "uint64_t interval"
.Fa "dispatch_io_interval_flags_t flags"
.Fc
.Ft void
.Fo dispatch_io_barrier
.Fa "dispatch_io_t channel"
.Fa "void (^barrier)(void)"
.Fc
.Sh DESCRIPTION
The dispatch I/O framework is an API for asynchronous read and write I/O
operations. It is an application of the ideas and idioms present in the
.Xr dispatch 3
framework to device I/O. Dispatch I/O enables an application to more easily
avoid blocking I/O operations and allows it to more directly express its I/O
requirements than by using the raw POSIX file API. Dispatch I/O will make a
best effort to optimize how and when asynchronous I/O operations are performed
based on the capabilities of the targeted device.
.Pp
This page provides details on how to create and configure dispatch I/O
channels. Reading from and writing to these channels is covered in the
.Xr dispatch_io_read 3
page. The dispatch I/O framework also provides the convenience functions
.Xr dispatch_read 3
and
.Xr dispatch_write 3
for uses that do not require the full functionality provided by I/O channels.
.Sh FUNDAMENTALS
A dispatch I/O channel represents the asynchronous I/O policy applied to a file
descriptor and encapsulates it for the purposes of ownership tracking while
I/O operations are ongoing.
.Sh CHANNEL TYPES
Dispatch I/O channels can have one of the following types:
.Bl -tag -width DISPATCH_IO_STREAM -compact -offset indent
.It DISPATCH_IO_STREAM
channels that represent a stream of bytes and do not support reads and writes
at arbitrary offsets, such as pipes or sockets. Channels of this type perform
read and write operations sequentially at the current file pointer position and
ignore any offset specified. Depending on the underlying file descriptor, read
operations may be performed simultaneously with write operations.
.It DISPATCH_IO_RANDOM
channels that represent random access files on disk. Only supported for
seekable file descriptors and paths. Channels of this type may perform
submitted read and write operations concurrently at the specified offset
(interpreted relative to the position of the file pointer when the channel was
created).
.El
.Sh CHANNEL OPENING AND CLOSING
The
.Fn dispatch_io_create
and
.Fn dispatch_io_create_with_path
functions create a dispatch I/O channel of provided
.Fa type
from a file descriptor
.Fa fd
or an absolute pathname, respectively. They can be thought of as analogous to
the
.Xr fdopen 3
POSIX function and the
.Xr fopen 3
function in the standard C library. For a channel created from a pathname, the
provided
.Fa path ,
.Fa oflag
and
.Fa mode
parameters will be passed to
.Xr open 2
when the first I/O operation on the channel is ready to execute.
.Pp
The provided
.Fa cleanup_handler
block will be submitted to the specified
.Fa queue
when all I/O operations on the channel have completed and it is closed or
reaches the end of its lifecycle. If an error occurs during channel creation,
the
.Fa cleanup_handler
block will be submitted immediately and passed an
.Fa error
parameter with the POSIX error encountered. If an invalid
.Fa type
or a non-absolute
.Fa path
argument is specified, these functions will return NULL and the
.Fa cleanup_handler
will not be invoked. After successfully creating a dispatch I/O channel from a
file descriptor, the application must take care not to modify that file
descriptor until the associated
.Fa cleanup_handler
is invoked, see
.Sx "FILEDESCRIPTOR OWNERSHIP"
for details.
.Pp
The
.Fn dispatch_io_close
function closes a dispatch I/O channel to new submissions of I/O operations. If
.Dv DISPATCH_IO_STOP
is passed in the
.Fa flags
parameter, the system will in addition not perform the I/O operations already
submitted to the channel that are still pending and will make a best effort to
interrupt any ongoing operations. Handlers for operations so affected will be
passed the
.Er ECANCELED
error code, along with any partial results.
.Sh CHANNEL CONFIGURATION
Dispatch I/O channels have high-water mark, low-water mark and interval
configuration settings that determine if and when partial results from I/O
operations are delivered via their associated I/O handlers.
.Pp
The
.Fn dispatch_io_set_high_water
and
.Fn dispatch_io_set_low_water
functions configure the water mark settings of a
.Fa channel .
The system will read
or write at least the number of bytes specified by
.Fa low_water
before submitting an I/O handler with partial results, and will make a best
effort to submit an I/O handler as soon as the number of bytes read or written
reaches
.Fa high_water .
.Pp
The
.Fn dispatch_io_set_interval
function configures the time
.Fa interval
at which I/O handlers are submitted (measured in nanoseconds). If
.Dv DISPATCH_IO_STRICT_INTERVAL
is passed in the
.Fa flags
parameter, the interval will be strictly observed even if there is an
insufficient amount of data to deliver; otherwise delivery will be skipped for
intervals where the amount of available data is inferior to the channel's
low-water mark. Note that the system may defer enqueueing interval I/O handlers
by a small unspecified amount of leeway in order to align with other system
activity for improved system performance or power consumption.
.Pp
.Sh DATA DELIVERY
The size of data objects passed to I/O handlers for a channel will never be
larger than the high-water mark set on the channel; it will also never be
smaller than the low-water mark, except in the following cases:
.Bl -dash -offset indent -compact
.It
the final handler invocation for an I/O operation
.It
EOF was encountered
.It
the channel has an interval with the
.Dv DISPATCH_IO_STRICT_INTERVAL
flag set
.El
Bear in mind that dispatch I/O channels will typically deliver amounts of data
significantly higher than the low-water mark. The default value for the
low-water mark is unspecified, but must be assumed to allow intermediate
handler invocations. The default value for the high-water mark is
unlimited (i.e.\&
.Dv SIZE_MAX ) .
Channels that require intermediate results of fixed size should have both the
low-water and the high-water mark set to that size. Channels that do not wish
to receive any intermediate results should have the low-water mark set to
.Dv SIZE_MAX .
.Pp
.Sh FILEDESCRIPTOR OWNERSHIP
When an application creates a dispatch I/O channel from a file descriptor with
the
.Fn dispatch_io_create
function, the system takes control of that file descriptor until the channel is
closed, an error occurs on the file descriptor or all references to the channel
are released. At that time the channel's cleanup handler will be enqueued and
control over the file descriptor relinquished, making it safe for the
application to
.Xr close 2
the file descriptor. While a file descriptor is under the control of a dispatch
I/O channel, file descriptor flags such as
.Dv O_NONBLOCK
will be modified by the system on behalf of the application. It is an error for
the application to modify a file descriptor directly while it is under the
control of a dispatch I/O channel, but it may create further I/O channels
from that file descriptor or use the
.Xr dispatch_read 3
and
.Xr dispatch_write 3
convenience functions with that file descriptor. If multiple I/O channels have
been created from the same file descriptor, all the associated cleanup handlers
will be submitted together once the last channel has been closed resp.\& all
references to those channels have been released. If convenience functions have
also been used on that file descriptor, submission of their handlers will be
tied to the submission of the channel cleanup handlers as well.
.Pp
.Sh BARRIER OPERATIONS
The
.Fn dispatch_io_barrier
function schedules a barrier operation on an I/O channel. The specified barrier
block will be run once, after all current I/O operations (such as
.Xr read 2 or
.Xr write 2 )
on the underlying
file descriptor have finished. No new I/O operations will start until the
barrier block finishes.
.Pp
The barrier block may operate on the underlying file descriptor with functions
like
.Xr fsync 2
or
.Xr lseek 2 .
As discussed in the
.Sx FILEDESCRIPTOR OWNERSHIP
section, the barrier block must not
.Xr close 2
the file descriptor, and if it changes any flags on the file descriptor, it
must restore them before finishing.
.Pp
There is no synchronization between a barrier block and any
.Xr dispatch_io_read 3
or
.Xr dispatch_io_write 3
handler blocks; they may be running at the same time. The barrier block itself
is responsible for any required synchronization.
.Sh MEMORY MODEL
Dispatch I/O channel objects are retained and released via calls to
.Fn dispatch_retain
and
.Fn dispatch_release .
.Sh SEE ALSO
.Xr dispatch 3 ,
.Xr dispatch_io_read 3 ,
.Xr dispatch_object 3 ,
.Xr dispatch_read 3 ,
.Xr fopen 3 ,
.Xr open 2

View File

@@ -0,0 +1,151 @@
.\" Copyright (c) 2010 Apple Inc. All rights reserved.
.Dd December 1, 2010
.Dt dispatch_io_read 3
.Os Darwin
.Sh NAME
.Nm dispatch_io_read ,
.Nm dispatch_io_write
.Nd submit read and write operations to dispatch I/O channels
.Sh SYNOPSIS
.Fd #include <dispatch/dispatch.h>
.Ft void
.Fo dispatch_io_read
.Fa "dispatch_io_t channel"
.Fa "off_t offset"
.Fa "size_t length"
.Fa "dispatch_queue_t queue"
.Fa "void (^handler)(bool done, dispatch_data_t data, int error)"
.Fc
.Ft void
.Fo dispatch_io_write
.Fa "dispatch_io_t channel"
.Fa "off_t offset"
.Fa "dispatch_data_t data"
.Fa "dispatch_queue_t queue"
.Fa "void (^handler)(bool done, dispatch_data_t data, int error)"
.Fc
.Sh DESCRIPTION
The dispatch I/O framework is an API for asynchronous read and write I/O
operations. It is an application of the ideas and idioms present in the
.Xr dispatch 3
framework to device I/O. Dispatch I/O enables an application to more easily
avoid blocking I/O operations and allows it to more directly express its I/O
requirements than by using the raw POSIX file API. Dispatch I/O will make a
best effort to optimize how and when asynchronous I/O operations are performed
based on the capabilities of the targeted device.
.Pp
This page provides details on how to read from and write to dispatch I/O
channels. Creation and configuration of these channels is covered in the
.Xr dispatch_io_create 3
page. The dispatch I/O framework also provides the convenience functions
.Xr dispatch_read 3
and
.Xr dispatch_write 3
for uses that do not require the full functionality provided by I/O channels.
.Pp
.Sh FUNDAMENTALS
The
.Fn dispatch_io_read
and
.Fn dispatch_io_write
functions are used to perform asynchronous read and write operations on
dispatch I/O channels. They can be thought of as asynchronous versions of the
.Xr fread 3
and
.Xr fwrite 3
functions in the standard C library.
.Sh READ OPERATIONS
The
.Fn dispatch_io_read
function schedules an I/O read operation on the specified dispatch I/O
.Va channel .
As results from the read operation become available, the provided
.Va handler
block will be submitted to the specified
.Va queue .
The block will be passed a dispatch data object representing the data that has
been read since the handler's previous invocation.
.Pp
The
.Va offset
parameter indicates where the read operation should begin. For a channel of
.Dv DISPATCH_IO_RANDOM
type it is interpreted relative to the position of the file pointer when the
channel was created, for a channel of
.Dv DISPATCH_IO_STREAM
type it is ignored and the read operation will begin at the current file
pointer position.
.Pp
The
.Va length
parameter indicates the number of bytes that should be read from the I/O
channel. Pass
.Dv SIZE_MAX
to keep reading until EOF is encountered (for a channel created from a
disk-based file this happens when reading past the end of the physical file).
.Sh WRITE OPERATIONS
The
.Fn dispatch_io_write
function schedules an I/O write operation on the specified dispatch I/O
.Va channel .
As the write operation progresses, the provided
.Va handler
block will be submitted to the specified
.Va queue .
The block will be passed a dispatch data object representing the data that
remains to be written as part of this I/O operation.
.Pp
The
.Va offset
parameter indicates where the write operation should begin. It is interpreted
as for read operations above.
.Pp
The
.Va data
parameter specifies the location and amount of data to be written, encapsulated
as a dispatch data object. The object is retained by the system until the write
operation is complete.
.Sh I/O HANDLER BLOCKS
Dispatch I/O handler blocks submitted to a channel via the
.Fn dispatch_io_read
or
.Fn dispatch_io_write
functions will be executed one or more times depending on system load and the
channel's configuration settings (see
.Xr dispatch_io_create 3
for details). The handler block need not be reentrant safe,
no new I/O handler instance is submitted until the previously enqueued handler
block has returned.
.Pp
The dispatch
.Va data
object passed to an I/O handler block will be released by the system when the
block returns, if access to the memory buffer it represents is needed outside
of the handler, the handler block must retain the data object or create a new
(e.g.\& concatenated) data object from it (see
.Xr dispatch_data_create 3
for details).
.Pp
Once an I/O handler block is invoked with the
.Va done
flag set, the associated I/O operation is complete and that handler block will
not be run again. If an unrecoverable error occurs while performing the I/O
operation, the handler block will be submitted with the
.Va done
flag set and the appropriate POSIX error code in the
.Va error
parameter. An invocation of a handler block with the
.Va done
flag set, zero
.Va error
and
.Va data
set to
.Vt dispatch_data_empty
indicates that the I/O operation has encountered EOF.
.Sh SEE ALSO
.Xr dispatch 3 ,
.Xr dispatch_data_create 3 ,
.Xr dispatch_io_create 3 ,
.Xr dispatch_read 3 ,
.Xr fread 3

View File

@@ -0,0 +1,190 @@
.\" Copyright (c) 2008-2012 Apple Inc. All rights reserved.
.Dd March 1, 2012
.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_activate
.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.
.Sh MEMORY MANAGEMENT
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.
.Ss INTEGRATION WITH OBJECTIVE-C
.Bd -filled -offset indent
When building with an Objective-C or Objective-C++ compiler, dispatch objects
are declared as Objective-C types. This results in the following differences
compared to building as plain C/C++:
.Bl -dash
.It
if Objective-C Automated Reference Counting is enabled, dispatch objects are
memory managed by the Objective-C runtime and explicit calls to the
.Fn dispatch_retain
and
.Fn dispatch_release
functions will produce build errors.
.Pp
.Em Note :
when ARC is enabled, care needs to be taken with dispatch API returning an
interior pointer that is only valid as long as an associated object has not
been released. If that object is held in a variable with automatic storage, it
may need to be annotated with the
.Li objc_precise_lifetime
attribute, or stored in a
.Li __strong
instance variable instead, to ensure that the object is not prematurely
released. The functions returning interior pointers are
.Xr dispatch_data_create_map 3
and
.Xr dispatch_data_apply 3 .
.It
the Blocks runtime automatically retains and releases dispatch objects captured
by blocks upon
.Fn Block_copy
and
.Fn Block_release ,
e.g.\& as performed during asynchronous execution of a block via
.Xr dispatch_async 3 .
.Pp
.Em Note :
retain cycles may be encountered if dispatch source objects are captured by
their handler blocks; these cycles can be broken by declaring the captured
object
.Li __weak
or by calling
.Xr dispatch_source_cancel 3
to cause its handler blocks to be released explicitly.
.It
dispatch objects can be added directly to Cocoa collections, and their
lifetime is tracked by the Objective-C static analyzer.
.El
.Pp
Integration of dispatch objects with Objective-C requires targeting Mac\ OS\ X
10.8 or later, and is disabled when building for the legacy Objective-C runtime.
It can also be disabled manually by using compiler options to define the
.Dv OS_OBJECT_USE_OBJC
preprocessor macro to
.Li 0 .
.Ed
.Pp
.Em Important :
When building with a plain C/C++ compiler or when integration with Objective-C
is disabled, dispatch objects are
.Em not
automatically retained and released when captured by a block. Therefore, when a
dispatch object is captured by a block that will be executed asynchronously,
the object must be manually retained and released:
.Pp
.Bd -literal -offset indent
dispatch_retain(object);
dispatch_async(queue, ^{
do_something_with_object(object);
dispatch_release(object);
});
.Ed
.Sh ACTIVATION
Dispatch objects such as queues and sources may be created in an inactive
state. Objects in this state must be activated before any blocks
associated with them will be invoked. Calling
.Fn dispatch_activate
on an active object has no effect.
.Pp
Changing attributes such as the target queue or a source handler is no longer permitted
once the object has been activated (see
.Xr dispatch_set_target_queue 3 ,
.Xr dispatch_source_set_event_handler 3 ).
.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. Other dispatch objects do not support suspension.
.Pp
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. Suspending an object causes it
to be retained and resuming an object causes it to be released. 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
an inactive or suspended state is undefined.
.Sh CONTEXT POINTERS
Dispatch objects support supplemental context pointers. The value of the
context pointer 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 that is invoked
asynchronously if the context pointer is not NULL when the last
reference to the object is released.
This gives the
application an opportunity to free the context data associated with the object.
The finalizer will be run on the object's target queue.
.Sh SEE ALSO
.Xr dispatch 3 ,
.Xr dispatch_async 3 ,
.Xr dispatch_group_create 3 ,
.Xr dispatch_queue_create 3 ,
.Xr dispatch_semaphore_create 3 ,
.Xr dispatch_set_target_queue 3 ,
.Xr dispatch_source_cancel 3 ,
.Xr dispatch_source_create 3

View File

@@ -0,0 +1,46 @@
.\" 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 .
.Sh SEE ALSO
.Xr dispatch 3

View File

@@ -0,0 +1,371 @@
.\" Copyright (c) 2008-2012 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_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.
Queues created with the
.Dv DISPATCH_QUEUE_SERIAL
attribute wait for the previously dequeued block to complete before dequeuing
the next block. A queue with this FIFO completion behavior is usually simply
described as a "serial queue." All memory writes performed by a block dispatched
to a serial queue are guaranteed to be visible to subsequent blocks dispatched
to the same queue. Queues are not bound to any specific thread of execution and
blocks submitted to independent queues may execute concurrently.
.Pp
Queues created with the
.Dv DISPATCH_QUEUE_CONCURRENT
attribute may execute dequeued blocks concurrently and support barrier blocks
submitted with the dispatch barrier API.
.Sh CREATION
Queues are created with the
.Fn dispatch_queue_create
function. 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. If a label is provided, it is copied.
By convention, clients should pass a reverse DNS style label. For example:
.Pp
.Bd -literal -offset indent
my_queue = dispatch_queue_create("com.example.subsystem.taskXYZ",
DISPATCH_QUEUE_SERIAL);
.Ed
.Pp
The
.Fa attr
argument specifies the type of queue to create and must be either
.Dv DISPATCH_QUEUE_SERIAL
or
.Dv DISPATCH_QUEUE_CONCURRENT .
.Pp
The
.Fn dispatch_queue_get_label
function returns the label provided when the given
.Fa queue
was created (or an empty C string if no label was provided at creation).
Passing the constant
.Dv DISPATCH_CURRENT_QUEUE_LABEL
to
.Fn dispatch_queue_get_label
returns the label of the current queue.
.Sh SUSPENSION
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 the
.Fn dispatch_get_main_queue
function.
.Pp
Programs must call
.Fn dispatch_main
at the end of
.Fn main
in order to process blocks submitted to the main queue. (See the
.Sx COMPATIBILITY
section for exceptions.) The
.Fn dispatch_main
function never returns.
.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). Four global concurrent queues are
provided, representing the following priority bands:
.Bl -bullet -compact -offset indent
.It
DISPATCH_QUEUE_PRIORITY_HIGH
.It
DISPATCH_QUEUE_PRIORITY_DEFAULT
.It
DISPATCH_QUEUE_PRIORITY_LOW
.It
DISPATCH_QUEUE_PRIORITY_BACKGROUND
.El
.Pp
The priority of a global concurrent queue controls the scheduling priority of
the threads created by the system to invoke the blocks submitted to that queue.
Global queues with lower priority will be scheduled for execution after all
global queues with higher priority have been scheduled. Additionally, items on
the background priority global queue will execute on threads with background
state as described in
.Xr setpriority 2
(i.e.\& disk I/O is throttled and the thread's scheduling priority is set to
lowest value).
.Pp
Use the
.Fn dispatch_get_global_queue
function to obtain the global queue of given priority. The
.Fa flags
argument is reserved for future use and must be zero. Passing any value other
than zero may result in a NULL return value.
.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.
.Pp
The new target queue is retained by the given object before the previous target
queue is released. The new target queue setting will take effect between block
executions on the object, but not in the middle of any existing block executions
(non-preemptive).
.Pp
The default target queue of all dispatch objects created by the application is
the default priority global concurrent queue. To reset an object's target queue
to the default, pass the
.Dv DISPATCH_TARGET_QUEUE_DEFAULT
constant to
.Fn dispatch_set_target_queue .
.Pp
The priority of a dispatch queue is inherited from 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.
.Pp
Blocks submitted to a serial queue whose target queue is another serial queue
will not be invoked concurrently with blocks submitted to the target queue or
to any other queue with that same target queue.
.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 target queue of a dispatch I/O channel specifies the priority of the global
queue where its I/O operations are executed. See
.Xr dispatch_io_create 3
for more information about dispatch I/O channels.
.Pp
For all other dispatch object types, the only function of the target queue is
to determine where an object's finalizer function is invoked.
.Pp
The result of passing the main queue or a global concurrent queue as 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 DEPRECATED FUNCTIONS
The following functions are deprecated and will be removed in a future release:
.Bl -item
.It
.Ft dispatch_queue_t
.Fn dispatch_get_current_queue void ;
.El
.Pp
.Fn dispatch_get_current_queue
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. In all other cases, the default target queue will be returned.
.Pp
The use of
.Fn dispatch_get_current_queue
is strongly discouraged except for debugging and logging purposes. Code must not
make any assumptions about the queue returned, unless it is one of the global
queues or a queue the code has itself created. 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. This function is deprecated and will be removed in a future
release.
.Pp
It is equally unsafe for code to assume that synchronous execution onto a queue
is safe from deadlock if that queue is not the one returned by
.Fn dispatch_get_current_queue .
.Pp
The result of
.Fn dispatch_get_main_queue
may or may not equal the result of
.Fn dispatch_get_current_queue
when called on the main thread. Comparing the two is not a valid way to test
whether code is executing on the main thread. Foundation/AppKit programs should
use [NSThread isMainThread]. POSIX programs may use
.Xr pthread_main_np 3 .
.Pp
.Fn dispatch_get_current_queue
may return a queue owned by a different subsystem which has already had all
external references to it released. While such a queue will continue to exist
until all blocks submitted to it have completed, attempting to retain it is
forbidden and will trigger an assertion. If Objective-C Automatic Reference
Counting is enabled, any use of the object returned by
.Fn dispatch_get_current_queue
will cause retain calls to be automatically generated, so the use of
.Fn dispatch_get_current_queue
for any reason in code built with ARC is particularly strongly discouraged.
.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.
However, blocks submitted to the main queue in applications using
.Fn dispatch_main
are not guaranteed to execute on the main thread.
.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 process will be terminated with an uncaught exception.
.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
.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 3 ,
.Xr dispatch_async 3 ,
.Xr dispatch_object 3 ,
.Xr dispatch_source_create 3

View File

@@ -0,0 +1,123 @@
.\" Copyright (c) 2010 Apple Inc. All rights reserved.
.Dd December 1, 2010
.Dt dispatch_read 3
.Os Darwin
.Sh NAME
.Nm dispatch_read ,
.Nm dispatch_write
.Nd asynchronously read from and write to file descriptors
.Sh SYNOPSIS
.Fd #include <dispatch/dispatch.h>
.Ft void
.Fo dispatch_read
.Fa "int fd"
.Fa "size_t length"
.Fa "dispatch_queue_t queue"
.Fa "void (^handler)(dispatch_data_t data, int error)"
.Fc
.Ft void
.Fo dispatch_write
.Fa "int fd"
.Fa "dispatch_data_t data"
.Fa "dispatch_queue_t queue"
.Fa "void (^handler)(dispatch_data_t data, int error))"
.Fc
.Sh DESCRIPTION
The
.Fn dispatch_read
and
.Fn dispatch_write
functions asynchronously read from and write to POSIX file descriptors. They
can be thought of as asynchronous, callback-based versions of the
.Fn fread
and
.Fn fwrite
functions provided by the standard C library. They are convenience functions
based on the
.Xr dispatch_io_read 3
and
.Xr dispatch_io_write 3
functions, intended for simple one-shot read or write requests. Multiple
request on the same file desciptor are better handled with the full underlying
dispatch I/O channel functions.
.Sh BEHAVIOR
The
.Fn dispatch_read
function schedules an asynchronous read operation on the file descriptor
.Va fd .
Once the file descriptor is readable, the system will read as much data as is
currently available, up to the specified
.Va length ,
starting at the current file pointer position. The given
.Va handler
block will be submitted to
.Va queue
when the operation completes or an error occurs. The block will be passed a
dispatch
.Va data
object with the result of the read operation. If an error occurred while
reading from the file descriptor, the
.Va error
parameter to the block will be set to the appropriate POSIX error code and
.Va data
will contain any data that could be read successfully. If the file pointer
position is at end-of-file, emtpy
.Va data
and zero
.Va error
will be passed to the handler block.
.Pp
The
.Fn dispatch_write
function schedules an asynchronous write operation on the file descriptor
.Va fd .
The system will attempt to write the entire contents of the provided
.Va data
object to
.Va fd
at the current file pointer position. The given
.Va handler
block will be submitted to
.Va queue
when the operation completes or an error occurs. If the write operation
completed successfully, the
.Va error
parameter to the block will be set to zero, otherwise it will be set to the
appropriate POSIX error code and the
.Va data
parameter will contain any data that could not be written.
.Sh CAVEATS
The
.Va data
object passed to a
.Va handler
block is released by the system when the block returns. If
.Va data
is needed outside of the handler block, it must concatenate, copy, or retain
it.
.Pp
Once an asynchronous read or write operation has been submitted on a file
descriptor
.Va fd ,
the system takes control of that file descriptor until the
.Va handler
block is executed. During this time the application must not manipulate
.Va fd
directly, in particular it is only safe to close
.Va fd
from the handler block (or after it has returned).
.Pp
If multiple asynchronous read or write operations are submitted to the same
file descriptor, they will be performed in order, but their handlers will only
be submitted once all operations have completed and control over the file
descriptor has been relinquished. For details on this and on the interaction
with dispatch I/O channels created from the same file descriptor, see
.Sx FILEDESCRIPTOR OWNERSHIP
in
.Xr dispatch_io_create 3 .
.Sh SEE ALSO
.Xr dispatch 3 ,
.Xr dispatch_data_create 3 ,
.Xr dispatch_io_create 3 ,
.Xr dispatch_io_read 3 ,
.Xr fread 3

View File

@@ -0,0 +1,121 @@
.\" Copyright (c) 2008-2012 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.
.Pp
The
.Fn dispatch_semaphore_wait
function decrements the semaphore. If the resulting value is less than zero,
it waits for a signal from a thread that increments the semaphore by calling
.Fn dispatch_semaphore_signal
before returning.
The
.Fa timeout
parameter is creatable with the
.Xr dispatch_time 3
or
.Xr dispatch_walltime 3
functions. If the timeout is reached without a signal being received, the semaphore
is re-incremented before the function returns.
.Pp
The
.Fn dispatch_semaphore_signal
function increments the counting semaphore. If the previous value was less than zero,
it wakes one of the threads that are waiting in
.Fn dispatch_semaphore_wait
before returning.
.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
Unbalanced dispatch semaphores cannot be released.
For a given semaphore, calls to
.Fn dispatch_semaphore_signal
and
.Fn dispatch_semaphore_wait
must be balanced before
.Fn dispatch_release
is called on it.
.Sh SEE ALSO
.Xr dispatch 3 ,
.Xr dispatch_object 3

View File

@@ -0,0 +1,587 @@
.\" Copyright (c) 2008-2013 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_registration_handler
.Fa "dispatch_source_t source"
.Fa "void (^block)(void)"
.Fc
.Ft void
.Fo dispatch_source_set_registration_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 long
.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. The
.Fa queue
parameter specifies the target queue of the new source object, it will
be retained by the source object. Pass the
.Dv DISPATCH_TARGET_QUEUE_DEFAULT
constant to use the default target queue (the default priority global
concurrent queue).
.Pp
Newly created sources are created in a suspended state. After the source has
been configured by setting an event handler, cancellation handler, registration
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_DATA_REPLACE
.It
DISPATCH_SOURCE_TYPE_MACH_SEND
.It
DISPATCH_SOURCE_TYPE_MACH_RECV
.It
DISPATCH_SOURCE_TYPE_MEMORYPRESSURE
.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 ,
.Vt DISPATCH_SOURCE_TYPE_DATA_OR
and
.Vt DISPATCH_SOURCE_TYPE_DATA_REPLACE
source types. The result of using this function with any other source type is
undefined. Data merging is performed according to the source type:
.Bl -tag -width "XXDISPATCH_SOURCE_TYPE_DATA_REPLACE" -compact -offset indent
.It \(bu DISPATCH_SOURCE_TYPE_DATA_ADD
.Vt data
is atomically added to the source's data
.It \(bu DISPATCH_SOURCE_TYPE_DATA_OR
.Vt data
is atomically bitwise ORed into the source's data
.It \(bu DISPATCH_SOURCE_TYPE_DATA_REPLACE
.Vt data
atomically replaces the source's data.
.El
.Pp
If the source data value resulting from the merge operation is 0, the source
handler will not be invoked. This can happen if:
.Bl -bullet -compact -offset indent
.It
the atomic addition wraps for sources of type
.Vt DISPATCH_SOURCE_TYPE_DATA_ADD ,
.It
0 is merged for sources of type
.Vt DISPATCH_SOURCE_TYPE_DATA_REPLACE .
.El
.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. If a source
is resumed with no event handler block set, events will be quietly ignored.
If the event handler block is changed while the source is suspended, or from a
block running on a serial queue that is the source's target queue, then the next
event handler invocation will use the new block.
.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 handler is set, the dispatch source will perform a
.Fn Block_copy
on the
.Fa handler
block.
.Pp
To unset the event handler, call
.Fn dispatch_source_set_event_handler_f
and pass NULL as
.Fa function .
This unsets the event handler regardless of whether the handler
was a function pointer or a block. Registration and cancellation handlers
(see below) may be unset in the same way, but as noted below, a cancellation
handler may be required.
.Sh REGISTRATION
When
.Fn dispatch_resume
is called on a suspended or newly created source, there may be a brief delay
before the source is ready to receive events from the underlying system handle.
During this delay, the event handler will not be invoked, and events will be
missed.
.Pp
Once the dispatch source is registered with the underlying system and is ready
to process all events its optional registration handler will be submitted to
its target queue. This registration handler may be specified via
.Fn dispatch_source_set_registration_handler .
.Pp
The event handler will not be called until the registration handler finishes.
If the source is canceled (see below) before it is registered,
its registration handler will not be called.
.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). If a source is canceled
before the first time it is resumed, its event handler will never be called.
(In this case, note that the source must be resumed before it can be released.)
.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
closed 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 ,
.Vt DISPATCH_SOURCE_TYPE_DATA_REPLACE
.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
atomic bitwise OR, or direct replacement (based on the source's type), and the
event handler block will be submitted to the source's target queue. The
.Fa data
is application defined. These sources have no
.Fa handle
or
.Fa mask
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
is a bitmask that indicates which of the events in the
.Fa mask
were observed. Note that because this source type will request notifications on
the provided port, it should not be mixed with the use of
.Fn mach_port_request_notification
on the same port.
.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_MEMORYPRESSURE
.Pp
Sources of this type monitor the system memory pressure condition for state
changes. The
.Fa handle
is unused and should be zero. The
.Fa mask
may be one or more of the following:
.Bl -tag -width "XXDISPATCH_MEMORYPRESSURE_CRITICAL" -compact -offset indent
.It \(bu DISPATCH_MEMORYPRESSURE_NORMAL
The system memory pressure condition has returned to normal.
.It \(bu DISPATCH_MEMORYPRESSURE_WARN
The system memory pressure condition has changed to warning.
.It \(bu DISPATCH_MEMORYPRESSURE_CRITICAL
The system memory pressure condition has changed to critical.
.El
.Pp
The data returned by
.Fn dispatch_source_get_data
indicates which of the events in the
.Fa mask
were observed.
.Pp
Elevated memory pressure is a system-wide condition that applications
registered for this source should react to by changing their future memory use
behavior, e.g. by reducing cache sizes of newly initiated operations until
memory pressure returns back to normal.
.Pp
However, applications should
.Em NOT
traverse and discard existing caches for past operations when the system memory
pressure enters an elevated state, as that is likely to trigger VM operations
that will further aggravate system memory pressure.
.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_SIGNAL
A signal was delivered to the process.
.El
.Pp
The data returned by
.Fn dispatch_source_get_data
is a bitmask that 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 fcntl 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. The
.Fa handle
argument is unused and should be zero.
.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 timer parameters are configured with the
.Fn dispatch_source_set_timer
function. Once this function returns, any pending source data accumulated for
the previous timer parameters has been cleared; the next fire of the timer will
occur at
.Fa start ,
and every
.Fa interval
nanoseconds thereafter until the timer source is canceled.
.Pp
Any fire of the timer may be delayed by the system in order to improve power
consumption and system performance. The upper limit to the allowable delay may
be configured with the
.Fa leeway
argument, the lower limit is under the control of the system.
.Pp
For the initial timer fire at
.Fa start ,
the upper limit to the allowable delay is set to
.Fa leeway
nanoseconds. For the subsequent timer fires at
.Fa start
.Li "+ N *"
.Fa interval ,
the upper limit is
.Li MIN(
.Fa leeway ,
.Fa interval
.Li "/ 2 )" .
.Pp
The lower limit to the allowable delay may vary with process state such as
visibility of application UI. If the specified timer source was created with a
.Fa mask
of
.Vt DISPATCH_TIMER_STRICT ,
the system will make a best effort to strictly observe the provided
.Fa leeway
value even if it is smaller than the current lower limit. Note that a minimal
amount of delay is to be expected even if this flag is specified.
.Pp
The
.Fa start
argument also determines which clock will be used for the timer: If
.Fa start
is
.Vt DISPATCH_TIME_NOW
or was created with
.Xr dispatch_time 3 ,
the timer is based on up time (which is obtained from
.Fn mach_absolute_time
on Apple platforms).
If
.Fa start
was created with
.Xr dispatch_walltime 3 ,
the timer is based on
.Xr gettimeofday 3 .
.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.
.It \(bu DISPATCH_VNODE_FUNLOCK
The referenced file was unlocked by
.Xr flock 2
or
.Xr close 2 .
.El
.Pp
The data returned by
.Fn dispatch_source_get_data
is a bitmask that 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 fcntl 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

View File

@@ -0,0 +1,130 @@
.\" Copyright (c) 2008-2013 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 = 0ull ;
.Vt static const dispatch_time_t DISPATCH_WALLTIME_NOW = ~1ull ;
.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 ,
.Vt DISPATCH_WALLTIME_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 or is
.Vt DISPATCH_WALLTIME_NOW ,
then the returned value is relative to the wall clock.
Otherwise, if
.Fa base
is
.Vt DISPATCH_TIME_NOW ,
then the current time of the default host clock is used. On Apple platforms,
the value of the default host clock is obtained from
.Vt mach_absolute_time() .
.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.
.Vt dispatch_walltime(NULL, offset)
is equivalent to
.Vt dispatch_time(DISPATCH_WALLTIME_NOW, offset) .
.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, relative to the default clock:
.Bd -literal -offset indent
milestone = dispatch_time(DISPATCH_TIME_NOW, 2 * NSEC_PER_SEC);
.Ed
.Pp
Create a milestone two seconds in the future, in wall clock time:
.Bd -literal -offset indent
milestone = dispatch_time(DISPATCH_WALLTIME_NOW, 2 * 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
.Pp
Use a negative delta to create a milestone an hour before the one above:
.Bd -literal -offset indent
milestone = dispatch_walltime(&ts, -60 * 60 * NSEC_PER_SEC);
.Ed
.Sh RETURN VALUE
These functions return an abstract value for use with
.Fn dispatch_after ,
.Fn dispatch_group_wait ,
.Fn dispatch_semaphore_wait ,
or
.Fn dispatch_source_set_timer .
.Sh SEE ALSO
.Xr dispatch 3 ,
.Xr dispatch_after 3 ,
.Xr dispatch_group_create 3 ,
.Xr dispatch_semaphore_create 3

View File

@@ -0,0 +1,12 @@
# TODO(compnerd) ensure that object_private.h voucher_activity_private.h
# voucher_private.h are included in the source tarball
install(FILES
generic_base.h
generic_unix_base.h
generic_win_base.h
object.h
DESTINATION
"${INSTALL_OS_HEADERS_DIR}")

View File

@@ -0,0 +1,161 @@
/*
* Copyright (c) 2015 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 __FIREHOSE_BUFFER_PRIVATE__
#define __FIREHOSE_BUFFER_PRIVATE__
#if OS_FIREHOSE_SPI
#ifdef KERNEL
#include <stdint.h>
#else
#include <os/base.h>
#include <os/availability.h>
#include <os/base_private.h>
#include <dispatch/dispatch.h>
#endif
#define OS_FIREHOSE_SPI_VERSION 20180226
/*!
* @group Firehose SPI
* SPI intended for logd only
* Layout of structs is subject to change without notice
*/
#define FIREHOSE_BUFFER_LIBTRACE_HEADER_SIZE 2048ul
#define FIREHOSE_BUFFER_KERNEL_MIN_CHUNK_COUNT 16
#define FIREHOSE_BUFFER_KERNEL_MAX_CHUNK_COUNT 64
typedef struct firehose_buffer_range_s {
uint16_t fbr_offset; // offset from the start of the buffer
uint16_t fbr_length;
} *firehose_buffer_range_t;
#ifdef KERNEL
typedef struct firehose_chunk_s *firehose_chunk_t;
// implemented by the kernel
extern void __firehose_buffer_push_to_logd(firehose_buffer_t fb, bool for_io);
extern void __firehose_critical_region_enter(void);
extern void __firehose_critical_region_leave(void);
extern void __firehose_allocate(vm_offset_t *addr, vm_size_t size);
extern uint8_t __firehose_buffer_kernel_chunk_count;
extern uint8_t __firehose_num_kernel_io_pages;
#define FIREHOSE_BUFFER_KERNEL_DEFAULT_CHUNK_COUNT FIREHOSE_BUFFER_KERNEL_MIN_CHUNK_COUNT
#define FIREHOSE_BUFFER_KERNEL_DEFAULT_IO_PAGES 8
#define FIREHOSE_BUFFER_KERNEL_CHUNK_COUNT __firehose_buffer_kernel_chunk_count
#define FIREHOSE_BUFFER_CHUNK_PREALLOCATED_COUNT (__firehose_buffer_kernel_chunk_count - 1) // the first chunk is the header
// exported for the kernel
firehose_tracepoint_t
__firehose_buffer_tracepoint_reserve(uint64_t stamp, firehose_stream_t stream,
uint16_t pubsize, uint16_t privsize, uint8_t **privptr);
void
__firehose_buffer_tracepoint_flush(firehose_tracepoint_t vat,
firehose_tracepoint_id_u vatid);
firehose_buffer_t
__firehose_buffer_create(size_t *size);
void
__firehose_merge_updates(firehose_push_reply_t update);
int
__firehose_kernel_configuration_valid(uint8_t chunk_count, uint8_t io_pages);
#else
#define __firehose_critical_region_enter()
#define __firehose_critical_region_leave()
OS_EXPORT
const uint32_t _firehose_spi_version;
OS_ALWAYS_INLINE
static inline const uint8_t *
_firehose_tracepoint_reader_init(firehose_chunk_t fc, const uint8_t **endptr)
{
const uint8_t *start = fc->fc_data;
const uint8_t *end = fc->fc_start + fc->fc_pos.fcp_next_entry_offs;
if (end > fc->fc_start + FIREHOSE_CHUNK_SIZE) {
end = start;
}
*endptr = end;
return start;
}
OS_ALWAYS_INLINE
static inline firehose_tracepoint_t
_firehose_tracepoint_reader_next(const uint8_t **ptr, const uint8_t *end)
{
const uint16_t ft_size = offsetof(struct firehose_tracepoint_s, ft_data);
struct ft_unaligned_s {
struct firehose_tracepoint_s ft;
} __attribute__((packed, aligned(1))) *uft;
do {
uft = (struct ft_unaligned_s *)*ptr;
if (uft->ft.ft_data >= end) {
// reached the end
return NULL;
}
if (!uft->ft.ft_length) {
// tracepoint write didn't even start
return NULL;
}
if (uft->ft.ft_length > end - uft->ft.ft_data) {
// invalid length
return NULL;
}
*ptr += roundup(ft_size + uft->ft.ft_length, 8);
// test whether write of the tracepoint was finished
} while (os_unlikely(uft->ft.ft_id.ftid_value == 0));
return (firehose_tracepoint_t)uft;
}
#define firehose_tracepoint_foreach(ft, fbc) \
for (const uint8_t *end, *p = _firehose_tracepoint_reader_init(fbc, &end); \
((ft) = _firehose_tracepoint_reader_next(&p, end)); )
OS_ALWAYS_INLINE
static inline bool
firehose_buffer_range_validate(firehose_chunk_t fc, firehose_tracepoint_t ft,
firehose_buffer_range_t range)
{
if (range->fbr_offset + range->fbr_length > FIREHOSE_CHUNK_SIZE) {
return false;
}
if (fc->fc_start + range->fbr_offset < ft->ft_data + ft->ft_length) {
return false;
}
return true;
}
#endif // !KERNEL
#endif // OS_FIREHOSE_SPI
#endif // __FIREHOSE_BUFFER_PRIVATE__

View File

@@ -0,0 +1,484 @@
/*
* Copyright (c) 2015 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 __FIREHOSE_SERVER_PRIVATE__
#define __FIREHOSE_SERVER_PRIVATE__
#include <os/base.h>
#include <dispatch/dispatch.h>
#include "firehose_buffer_private.h"
#if OS_FIREHOSE_SPI
/*!
* @group Firehose SPI
* SPI intended for logd only
*/
#pragma mark - Firehose Client
/*!
* @typedef firehose_client_t
*
* @abstract
* Represents a firehose client.
*
* @discussion
* Firehose client objects are os_object_t's, and it's legal to retain/release
* them with os_retain / os_release.
*/
OS_OBJECT_DECL_CLASS(firehose_client);
/*!
* @typedef firehose_event_t
*
* @const FIREHOSE_EVENT_NONE
* Never passed to callbacks, meaningful for
* firehose_client_metadata_stream_peek.
*
* @const FIREHOSE_EVENT_CLIENT_CONNECTED
* A new client has connected
*
* This is the first event delivered, and no event is delivered until
* the handler of that event returns
*
* The `page` argument is really a firehose_client_connected_info_t. The
* `fc_pos` argument is not meaningful.
*
* @const FIREHOSE_EVENT_CLIENT_DIED
* The specified client is gone and will not flush new buffers
*
* This is the last event delivered, it is never called before all other
* event handlers have returned. This event is generated even when a
* FIREHOSE_EVENT_CLIENT_CORRUPTED event has been generated.
*
* @const FIREHOSE_EVENT_IO_BUFFER_RECEIVED
* A new buffer needs to be pushed; `page` is set to that buffer, and `fc_pos`
* to its chunk position header.
*
* This event can be sent concurrently wrt FIREHOSE_EVENT_MEM_BUFFER_RECEIVED
* events.
*
* @const FIREHOSE_EVENT_MEM_BUFFER_RECEIVED
* A new buffer needs to be pushed; `page` is set to that buffer, and `fc_pos`
* to its chunk position header.
*
* This event can be sent concurrently wrt FIREHOSE_EVENT_IO_BUFFER_RECEIVED
* events.
*
* @const FIREHOSE_EVENT_CLIENT_CORRUPTED
* This event is received when a client is found being corrupted.
* `page` is set to the buffer header page, and `fc_pos` is not meaningful. When
* this event is received, logs have likely been lost for this client.
*
* This buffer isn't really a proper firehose buffer page, but its content may
* be useful for debugging purposes.
*
* @const FIREHOSE_EVENT_CLIENT_FINALIZE
* This event is received when a firehose client structure is about to be
* destroyed. Only firehose_client_get_context() can ever be called with
* the passed firehose client. The `page` argument is NULL for this event, and
* the `fc_pos` argument is not meaningful.
*
* The event is sent from the context that is dropping the last refcount
* of the client.
*/
OS_ENUM(firehose_event, unsigned long,
FIREHOSE_EVENT_NONE = 0,
FIREHOSE_EVENT_CLIENT_CONNECTED,
FIREHOSE_EVENT_CLIENT_DIED,
FIREHOSE_EVENT_IO_BUFFER_RECEIVED,
FIREHOSE_EVENT_MEM_BUFFER_RECEIVED,
FIREHOSE_EVENT_CLIENT_CORRUPTED,
FIREHOSE_EVENT_CLIENT_FINALIZE,
);
#define FIREHOSE_CLIENT_CONNECTED_INFO_VERSION 1
/*!
* @typedef firehose_client_connected_info
*
* @abstract
* Type of the data passed to CLIENT_CONNECTED events.
*/
typedef struct firehose_client_connected_info_s {
unsigned long fcci_version;
// version 1
const void *fcci_data;
size_t fcci_size;
} *firehose_client_connected_info_t;
/*!
* @function firehose_client_get_unique_pid
*
* @abstract
* Returns the unique pid of the specified firehose client
*
* @param client
* The specified client.
*
* @param pid
* The pid for this client.
*
* @returns
* The unique pid of the specified client.
*/
OS_NOTHROW OS_NONNULL1
uint64_t
firehose_client_get_unique_pid(firehose_client_t client, pid_t *pid);
/*!
* @function firehose_client_get_pid_version
*
* @abstract
* Returns the pid version for that client.
*
* @param client
* The specified client.
*/
OS_NOTHROW OS_NONNULL1
int
firehose_client_get_pid_version(firehose_client_t client);
/*!
* @function firehose_client_get_euid
*
* @abstract
* Returns the EUID for that client as discovered at connect time.
*
* @param client
* The specified client.
*/
OS_NOTHROW OS_NONNULL1
uid_t
firehose_client_get_euid(firehose_client_t client);
/*!
* @function firehose_client_get_metadata_buffer
*
* @abstract
* Returns the metadata buffer for the specified firehose client
*
* @param client
* The specified client.
*
* @param size
* The size of the metadata buffer.
*
* @returns
* The pointer to the buffer.
*/
OS_NOTHROW OS_NONNULL_ALL
void *
firehose_client_get_metadata_buffer(firehose_client_t client, size_t *size);
/*!
* @function firehose_client_get_context
*
* @abstract
* Gets the context for the specified client.
*
* @param client
* The specified client.
*
* @returns
* The context set for the client with firehose_client_set_context
*/
OS_NOTHROW OS_NONNULL1
void *
firehose_client_get_context(firehose_client_t client);
/*!
* @function firehose_client_set_strings_cached
*
* @abstract
* Marks a given client as having strings cached already.
*
* @param client
* The specified client.
*/
OS_NOTHROW OS_NONNULL1
void
firehose_client_set_strings_cached(firehose_client_t client);
/*!
* @function firehose_client_set_context
*
* @abstract
* Sets the context for the specified client.
*
* @discussion
* Setting the context exchanges the context pointer, but the client must
* ensure proper synchronization with possible getters.
*
* The lifetime of the context is under the control of the API user,
* it is suggested to destroy the context when the CLIENT_DIED event is
* received.
*
* @param client
* The specified client.
*
* @param ctxt
* The new context to set.
*
* @returns
* The previous context set for the client.
*/
OS_NOTHROW OS_NONNULL1
void *
firehose_client_set_context(firehose_client_t client, void *ctxt);
/*!
* @function firehose_client_initiate_quarantine
*
* @abstract
* Starts the procedure to move the given client to the high volume quarantine
*
* @discussion
* When the client is in the high volume quarantine, their firehose chunks
* have the fcp_quarantined bit set to 1.
*
* @param client
* The specified client.
*/
OS_NOTHROW OS_NONNULL1
void
firehose_client_initiate_quarantine(firehose_client_t client);
/*!
* @function firehose_client_metadata_stream_peek
*
* @abstract
* Peek at the metadata stream in flight buffers for a given client
*
* @discussion
* This function should never be called from the context of a snapshot
* handler.
*
* @param client
* The specified client
*
* @param context
* If this function is called synchronously from the handler passed to
* firehose_server_init, then `context` should be the event being processed.
* Else pass FIREHOSE_EVENT_NONE.
*
* @param peek_should_start
* Handler that is called prior to peeking to solve the race of metadata
* buffers not beeing processed yet at first lookup time, and being processed
* before the peek enumeration starts.
*
* If the handler returns false, then the enumeration doesn't start.
* If the race cannot happen, pass NULL.
*
* @param peek
* Handler that will receive all the live metadata buffers for this process.
* If the handler returns false, the enumeration is interrupted.
*/
OS_NOTHROW OS_NONNULL1 OS_NONNULL4
void
firehose_client_metadata_stream_peek(firehose_client_t client,
firehose_event_t context, OS_NOESCAPE bool (^peek_should_start)(void),
OS_NOESCAPE bool (^peek)(firehose_chunk_t fbc));
#pragma mark - Firehose Server
/*!
* @typedef firehose_handler_t
*
* @abstract
* Type of the handler block for firehose_server_init()
*/
typedef void (^firehose_handler_t)(firehose_client_t client,
firehose_event_t event, firehose_chunk_t page,
firehose_chunk_pos_u fc_pos);
/*!
* @function firehose_server_init
*
* @abstract
* Initializes the firehose MiG server
*
* @discussion
* Initializes the firehose MiG server by boostrap registering the services
* and creating dispatch_sources for the same.
*/
OS_NOTHROW
void
firehose_server_init(mach_port_t firehose_comm_port,
firehose_handler_t handler);
/*!
* @function firehose_server_assert_spi_version
*
* @abstract
* Checks that libdispatch and firehose components all match
*
* @discussion
* Will assert that all the components have the same SPI versions
*/
OS_NOTHROW
void
firehose_server_assert_spi_version(uint32_t spi_version);
/*!
* @function firehose_server_has_ever_flushed_pages
*
* @abstract
* Checks whether the firehose server has ever flushed any pages this boot.
*
* @discussion
* Must be called after firehose_server_init() and before calling
* firehose_server_resume().
*/
OS_NOTHROW
bool
firehose_server_has_ever_flushed_pages(void);
/*!
* @function firehose_server_resume
*
* @abstract
* Allows firehose events to flow
*
* @discussion
* Must be called after firehose_server_init()
*/
OS_NOTHROW
void
firehose_server_resume(void);
/*!
* @function firehose_server_cancel
*
* @abstract
* Cancels the server, disconnects all clients, and prevents new connections.
*/
OS_NOTHROW
void
firehose_server_cancel(void);
/*!
* @function firehose_server_set_logging_prefs
*
* @abstract
* Publishes a new preferences buffer.
*
* @description
* The server will take ownership of this buffer and will
* call munmap() on the previous one that was stored.
*/
OS_NOTHROW
void
firehose_server_set_logging_prefs(void *pointer, size_t length,
os_block_t block);
/*!
* @typedef firehose_server_queue_t
*
* @abstract
* Values to pass to firehose_server_get_queue()
*/
OS_ENUM(firehose_server_queue, unsigned long,
FIREHOSE_SERVER_QUEUE_UNKNOWN,
FIREHOSE_SERVER_QUEUE_IO,
FIREHOSE_SERVER_QUEUE_MEMORY,
);
/*!
* @function firehose_server_copy_queue
*
* @abstract
* Returns internal queues to the firehose server subsystem.
*/
OS_NOTHROW OS_OBJECT_RETURNS_RETAINED
dispatch_queue_t
firehose_server_copy_queue(firehose_server_queue_t which);
/*!
* @function firehose_server_quarantined_suspend
*
* @abstract
* Suspends processing of quarantined clients until
* firehose_server_quarantined_resume() is called for the same queue.
*
* @discussion
* Suspending processing of quarantined clients causes firehose_snapshot()
* to block until the processing is enabled again.
*
* However if this is used to pace the processing, it is a good idea to disable
* this pacing until the snapshot has completed.
*
* Similarly, quarantine suspension must be off during shutdown.
*/
OS_NOTHROW
void
firehose_server_quarantined_suspend(firehose_server_queue_t q);
/*!
* @function firehose_server_quarantined_resume
*
* @abstract
* Resumes processing of quarantined clients.
*/
OS_NOTHROW
void
firehose_server_quarantined_resume(firehose_server_queue_t q);
#pragma mark - Firehose Snapshot
/*!
* @typedef firehose_snapshot_event
*/
OS_ENUM(firehose_snapshot_event, unsigned long,
FIREHOSE_SNAPSHOT_EVENT_IO_START = 1,
FIREHOSE_SNAPSHOT_EVENT_MEM_START,
FIREHOSE_SNAPSHOT_EVENT_IO_BUFFER,
FIREHOSE_SNAPSHOT_EVENT_MEM_BUFFER,
FIREHOSE_SNAPSHOT_EVENT_COMPLETE,
);
/*!
* @typedef firehose_snapshot_handler_t
*
* @abstract
* Type of the handler block for firehose_snapshot
*/
typedef void (^firehose_snapshot_handler_t)(firehose_client_t client,
firehose_snapshot_event_t event, firehose_chunk_t page,
firehose_chunk_pos_u fc_pos);
/*!
* @function firehose_snapshot
*
* @abstract
* Gather a snapshot for the current firehose state.
*
* @discussion
* This function can be called several times, in which case snapshots are taken
* one after the other. If coalescing is desired, it has to be built around this
* call.
*/
OS_NOTHROW
void
firehose_snapshot(firehose_snapshot_handler_t handler);
#endif // OS_FIREHOSE_SPI
#endif // __FIREHOSE_SERVER_PRIVATE__

View File

@@ -0,0 +1,34 @@
/*
* Copyright (c) 2011-2014 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 __OS_GENERIC_BASE__
#define __OS_GENERIC_BASE__
#if !defined(__BEGIN_DECLS) && !defined(__END_DECLS)
#if defined(__cplusplus)
#define __BEGIN_DECLS extern "C" {
#define __END_DECLS }
#else
#define __BEGIN_DECLS
#define __END_DECLS
#endif
#endif
#endif /* __OS_GENERIC_BASE__ */

View File

@@ -0,0 +1,130 @@
/*
* This source file is part of the Swift.org open source project
*
* Copyright (c) 2015 Apple Inc. and the Swift project authors
*
* Licensed under Apache License v2.0 with Runtime Library Exception
*
* See https://swift.org/LICENSE.txt for license information
* See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
*
*/
#ifndef __OS_GENERIC_UNIX_BASE__
#define __OS_GENERIC_UNIX_BASE__
#include <os/generic_base.h>
#if __has_include(<sys/sysmacros.h>)
#include <sys/sysmacros.h>
#endif
#if defined(__FreeBSD__)
#include <libutil.h>
#include <fcntl.h>
#endif
#include <sys/param.h>
#if __has_include(<sys/cdefs.h>)
#include <sys/cdefs.h>
#endif
#ifndef API_AVAILABLE
#define API_AVAILABLE(...)
#endif
#ifndef API_DEPRECATED
#define API_DEPRECATED(...)
#endif
#ifndef API_UNAVAILABLE
#define API_UNAVAILABLE(...)
#endif
#ifndef API_DEPRECATED_WITH_REPLACEMENT
#define API_DEPRECATED_WITH_REPLACEMENT(...)
#endif
#if __GNUC__
#define OS_EXPECT(x, v) __builtin_expect((x), (v))
#define OS_UNUSED __attribute__((__unused__))
#else
#define OS_EXPECT(x, v) (x)
#define OS_UNUSED
#endif
#ifndef os_likely
#define os_likely(x) OS_EXPECT(!!(x), 1)
#endif
#ifndef os_unlikely
#define os_unlikely(x) OS_EXPECT(!!(x), 0)
#endif
#if __has_feature(assume_nonnull)
#define OS_ASSUME_NONNULL_BEGIN _Pragma("clang assume_nonnull begin")
#define OS_ASSUME_NONNULL_END _Pragma("clang assume_nonnull end")
#else
#define OS_ASSUME_NONNULL_BEGIN
#define OS_ASSUME_NONNULL_END
#endif
#if __has_builtin(__builtin_assume)
#define OS_COMPILER_CAN_ASSUME(expr) __builtin_assume(expr)
#else
#define OS_COMPILER_CAN_ASSUME(expr) ((void)(expr))
#endif
#if __has_feature(attribute_availability_swift)
// equivalent to __SWIFT_UNAVAILABLE from Availability.h
#define OS_SWIFT_UNAVAILABLE(_msg) \
__attribute__((__availability__(swift, unavailable, message=_msg)))
#else
#define OS_SWIFT_UNAVAILABLE(_msg)
#endif
#if __has_attribute(swift_private)
# define OS_REFINED_FOR_SWIFT __attribute__((__swift_private__))
#else
# define OS_REFINED_FOR_SWIFT
#endif
#if __has_attribute(swift_name)
# define OS_SWIFT_NAME(_name) __attribute__((__swift_name__(#_name)))
#else
# define OS_SWIFT_NAME(_name)
#endif
#define __OS_STRINGIFY(s) #s
#define OS_STRINGIFY(s) __OS_STRINGIFY(s)
#define __OS_CONCAT(x, y) x ## y
#define OS_CONCAT(x, y) __OS_CONCAT(x, y)
#if __has_feature(objc_fixed_enum) || __has_extension(cxx_strong_enums)
#define OS_ENUM(_name, _type, ...) \
typedef enum : _type { __VA_ARGS__ } _name##_t
#else
#define OS_ENUM(_name, _type, ...) \
enum { __VA_ARGS__ }; typedef _type _name##_t
#endif
/*
* Stub out misc linking and compilation attributes
*/
#ifdef OS_EXPORT
#undef OS_EXPORT
#endif
#define OS_EXPORT
#ifdef OS_WARN_RESULT_NEEDS_RELEASE
#undef OS_WARN_RESULT_NEEDS_RELEASE
#endif
#ifdef OS_WARN_RESULT
#undef OS_WARN_RESULT
#endif
#define OS_WARN_RESULT
#ifdef OS_NOTHROW
#undef OS_NOTHROW
#endif
#define OS_NOTHROW
#endif /* __OS_GENERIC_UNIX_BASE__ */

View File

@@ -0,0 +1,128 @@
/*
* This source file is part of the Swift.org open source project
*
* Copyright (c) 2015 Apple Inc. and the Swift project authors
*
* Licensed under Apache License v2.0 with Runtime Library Exception
*
* See https://swift.org/LICENSE.txt for license information
* See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
*
*/
#ifndef __OS_GENERIC_WIN_BASE__
#define __OS_GENERIC_WIN_BASE__
#include <os/generic_base.h>
// Unices provide `roundup` via sys/param.h
#define roundup(x, y) ((((x) + ((y) - 1)) / (y)) * (y))
// Unices provide `MAX` via sys/param.h
#define MAX(a,b) (((a)>(b))?(a):(b))
// Unices provide `MIN` via sys/param.h
#define MIN(a,b) (((a)<(b))?(a):(b))
// Unices provide `howmany` via sys/param.h
#define howmany(x, y) (((x) + ((y) - 1)) / (y))
#ifndef HAVE_MODE_T
typedef int mode_t;
#endif
typedef void pthread_attr_t;
#ifndef API_AVAILABLE
#define API_AVAILABLE(...)
#endif
#ifndef API_DEPRECATED
#define API_DEPRECATED(...)
#endif
#ifndef API_UNAVAILABLE
#define API_UNAVAILABLE(...)
#endif
#ifndef API_DEPRECATED_WITH_REPLACEMENT
#define API_DEPRECATED_WITH_REPLACEMENT(...)
#endif
#if !defined(__has_attribute)
#define __has_attribute(attibute) 0
#endif
#if !defined(__has_builtin)
#define __has_builtin(builtin) 0
#endif
#if !defined(__has_feature)
#define __has_feature(feature) 0
#endif
#if __has_builtin(__builtin_expect)
#define OS_EXPECT(expression, value) __builtin_expect((expression), (value))
#else
#define OS_EXPECT(expression, value) (expression)
#endif
#if __has_attribute(__unused__)
#define OS_UNUSED __attribute__((__unused__))
#else
#define OS_UNUSED
#endif
#ifndef os_likely
#define os_likely(expression) OS_EXPECT(!!(expression), 1)
#endif
#ifndef os_unlikely
#define os_unlikely(expression) OS_EXPECT(!!(expression), 0)
#endif
#if __has_feature(assume_nonnull)
#define OS_ASSUME_NONNULL_BEGIN _Pragma("clang assume_nonnull begin")
#define OS_ASSUME_NONNULL_END _Pragma("clang assume_nonnull end")
#else
#define OS_ASSUME_NONNULL_BEGIN
#define OS_ASSUME_NONNULL_END
#endif
#if __has_builtin(__builtin_assume)
#define OS_COMPILER_CAN_ASSUME(expr) __builtin_assume(expr)
#else
#define OS_COMPILER_CAN_ASSUME(expr) ((void)(expr))
#endif
#if __has_feature(attribute_availability_swift)
// equivalent to __SWIFT_UNAVAILABLE from Availability.h
#define OS_SWIFT_UNAVAILABLE(msg) \
__attribute__((__availability__(swift, unavailable, message = msg)))
#else
#define OS_SWIFT_UNAVAILABLE(msg)
#endif
#define __OS_STRINGIFY(s) #s
#define OS_STRINGIFY(s) __OS_STRINGIFY(s)
#if __has_feature(objc_fixed_enum) || __has_extension(cxx_strong_enums)
#define OS_ENUM(name, type, ...) typedef enum : type { __VA_ARGS__ } name##_t
#else
#define OS_ENUM(name, type, ...) \
enum { __VA_ARGS__ }; \
typedef type name##_t
#endif
#ifdef OS_EXPORT
#undef OS_EXPORT
#endif
#define OS_EXPORT __declspec(dllexport)
#ifdef OS_WARN_RESULT_NEEDS_RELEASE
#undef OS_WARN_RESULT_NEEDS_RELEASE
#endif
#ifdef OS_WARN_RESULT
#undef OS_WARN_RESULT
#endif
#define OS_WARN_RESULT
#ifdef OS_NOTHROW
#undef OS_NOTHROW
#endif
#define OS_NOTHROW
#endif

272
Telegram/ThirdParty/dispatch/os/object.h vendored Normal file
View File

@@ -0,0 +1,272 @@
/*
* Copyright (c) 2011-2014 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 __OS_OBJECT__
#define __OS_OBJECT__
#ifdef __APPLE__
#include <Availability.h>
#include <os/availability.h>
#include <TargetConditionals.h>
#include <os/base.h>
#elif defined(_WIN32)
#include <os/generic_win_base.h>
#elif defined(__unix__)
#include <os/generic_unix_base.h>
#endif
/*!
* @header
*
* @preprocinfo
* By default, libSystem objects such as GCD and XPC objects are declared as
* Objective-C types when building with an Objective-C compiler. This allows
* them to participate in ARC, in RR management by the Blocks runtime and in
* leaks checking by the static analyzer, and enables them to be added to Cocoa
* collections.
*
* NOTE: this requires explicit cancellation of dispatch sources and xpc
* connections whose handler blocks capture the source/connection object,
* resp. ensuring that such captures do not form retain cycles (e.g. by
* declaring the source as __weak).
*
* To opt-out of this default behavior, add -DOS_OBJECT_USE_OBJC=0 to your
* compiler flags.
*
* This mode requires a platform with the modern Objective-C runtime, the
* Objective-C GC compiler option to be disabled, and at least a Mac OS X 10.8
* or iOS 6.0 deployment target.
*/
#ifndef OS_OBJECT_HAVE_OBJC_SUPPORT
#if !defined(__OBJC__) || defined(__OBJC_GC__)
# define OS_OBJECT_HAVE_OBJC_SUPPORT 0
#elif !defined(TARGET_OS_MAC) || !TARGET_OS_MAC
# define OS_OBJECT_HAVE_OBJC_SUPPORT 0
#elif TARGET_OS_IOS && __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_6_0
# define OS_OBJECT_HAVE_OBJC_SUPPORT 0
#elif TARGET_OS_MAC && !TARGET_OS_IPHONE
# if __MAC_OS_X_VERSION_MIN_REQUIRED < __MAC_10_8
# define OS_OBJECT_HAVE_OBJC_SUPPORT 0
# elif defined(__i386__) && __MAC_OS_X_VERSION_MIN_REQUIRED < __MAC_10_12
# define OS_OBJECT_HAVE_OBJC_SUPPORT 0
# else
# define OS_OBJECT_HAVE_OBJC_SUPPORT 1
# endif
#else
# define OS_OBJECT_HAVE_OBJC_SUPPORT 1
#endif
#endif // OS_OBJECT_HAVE_OBJC_SUPPORT
#if OS_OBJECT_HAVE_OBJC_SUPPORT
#if defined(__swift__) && __swift__ && !OS_OBJECT_USE_OBJC
#define OS_OBJECT_USE_OBJC 1
#endif
#ifndef OS_OBJECT_USE_OBJC
#define OS_OBJECT_USE_OBJC 1
#endif
#elif defined(OS_OBJECT_USE_OBJC) && OS_OBJECT_USE_OBJC
/* Unsupported platform for OS_OBJECT_USE_OBJC=1 */
#undef OS_OBJECT_USE_OBJC
#define OS_OBJECT_USE_OBJC 0
#else
#define OS_OBJECT_USE_OBJC 0
#endif
#ifndef OS_OBJECT_SWIFT3
#if defined(SWIFT_SDK_OVERLAY_DISPATCH_EPOCH) && \
SWIFT_SDK_OVERLAY_DISPATCH_EPOCH >= 2
#define OS_OBJECT_SWIFT3 1
#else
#define OS_OBJECT_SWIFT3 0
#endif // SWIFT_SDK_OVERLAY_DISPATCH_EPOCH >= 2
#endif // OS_OBJECT_SWIFT3
#if OS_OBJECT_USE_OBJC
#import <objc/NSObject.h>
#if __has_attribute(objc_independent_class)
#define OS_OBJC_INDEPENDENT_CLASS __attribute__((objc_independent_class))
#endif // __has_attribute(objc_independent_class)
#ifndef OS_OBJC_INDEPENDENT_CLASS
#define OS_OBJC_INDEPENDENT_CLASS
#endif
#define OS_OBJECT_CLASS(name) OS_##name
#define OS_OBJECT_DECL_PROTOCOL(name, ...) \
@protocol OS_OBJECT_CLASS(name) __VA_ARGS__ \
@end
#define OS_OBJECT_CLASS_IMPLEMENTS_PROTOCOL_IMPL(name, proto) \
@interface name () <proto> \
@end
#define OS_OBJECT_CLASS_IMPLEMENTS_PROTOCOL(name, proto) \
OS_OBJECT_CLASS_IMPLEMENTS_PROTOCOL_IMPL( \
OS_OBJECT_CLASS(name), OS_OBJECT_CLASS(proto))
#define OS_OBJECT_DECL_IMPL(name, ...) \
OS_OBJECT_DECL_PROTOCOL(name, __VA_ARGS__) \
typedef NSObject<OS_OBJECT_CLASS(name)> \
* OS_OBJC_INDEPENDENT_CLASS name##_t
#define OS_OBJECT_DECL_BASE(name, ...) \
@interface OS_OBJECT_CLASS(name) : __VA_ARGS__ \
- (instancetype)init OS_SWIFT_UNAVAILABLE("Unavailable in Swift"); \
@end
#define OS_OBJECT_DECL_IMPL_CLASS(name, ...) \
OS_OBJECT_DECL_BASE(name, ## __VA_ARGS__) \
typedef OS_OBJECT_CLASS(name) \
* OS_OBJC_INDEPENDENT_CLASS name##_t
#define OS_OBJECT_DECL(name, ...) \
OS_OBJECT_DECL_IMPL(name, <NSObject>)
#define OS_OBJECT_DECL_SUBCLASS(name, super) \
OS_OBJECT_DECL_IMPL(name, <OS_OBJECT_CLASS(super)>)
#if __has_attribute(ns_returns_retained)
#define OS_OBJECT_RETURNS_RETAINED __attribute__((__ns_returns_retained__))
#else
#define OS_OBJECT_RETURNS_RETAINED
#endif
#if __has_attribute(ns_consumed)
#define OS_OBJECT_CONSUMED __attribute__((__ns_consumed__))
#else
#define OS_OBJECT_CONSUMED
#endif
#if __has_feature(objc_arc)
#define OS_OBJECT_BRIDGE __bridge
#define OS_WARN_RESULT_NEEDS_RELEASE
#else
#define OS_OBJECT_BRIDGE
#define OS_WARN_RESULT_NEEDS_RELEASE OS_WARN_RESULT
#endif
#if __has_attribute(objc_runtime_visible) && \
((defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && \
__MAC_OS_X_VERSION_MIN_REQUIRED < __MAC_10_12) || \
(defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && \
!defined(__TV_OS_VERSION_MIN_REQUIRED) && \
!defined(__WATCH_OS_VERSION_MIN_REQUIRED) && \
__IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_10_0) || \
(defined(__TV_OS_VERSION_MIN_REQUIRED) && \
__TV_OS_VERSION_MIN_REQUIRED < __TVOS_10_0) || \
(defined(__WATCH_OS_VERSION_MIN_REQUIRED) && \
__WATCH_OS_VERSION_MIN_REQUIRED < __WATCHOS_3_0))
/*
* To provide backward deployment of ObjC objects in Swift on pre-10.12
* SDKs, OS_object classes can be marked as OS_OBJECT_OBJC_RUNTIME_VISIBLE.
* When compiling with a deployment target earlier than OS X 10.12 (iOS 10.0,
* tvOS 10.0, watchOS 3.0) the Swift compiler will only refer to this type at
* runtime (using the ObjC runtime).
*/
#define OS_OBJECT_OBJC_RUNTIME_VISIBLE __attribute__((objc_runtime_visible))
#else
#define OS_OBJECT_OBJC_RUNTIME_VISIBLE
#endif
#ifndef OS_OBJECT_USE_OBJC_RETAIN_RELEASE
#if defined(__clang_analyzer__)
#define OS_OBJECT_USE_OBJC_RETAIN_RELEASE 1
#elif __has_feature(objc_arc) && !OS_OBJECT_SWIFT3
#define OS_OBJECT_USE_OBJC_RETAIN_RELEASE 1
#else
#define OS_OBJECT_USE_OBJC_RETAIN_RELEASE 0
#endif
#endif
#if OS_OBJECT_SWIFT3
#define OS_OBJECT_DECL_SWIFT(name) \
OS_EXPORT OS_OBJECT_OBJC_RUNTIME_VISIBLE \
OS_OBJECT_DECL_IMPL_CLASS(name, NSObject)
#define OS_OBJECT_DECL_SUBCLASS_SWIFT(name, super) \
OS_EXPORT OS_OBJECT_OBJC_RUNTIME_VISIBLE \
OS_OBJECT_DECL_IMPL_CLASS(name, OS_OBJECT_CLASS(super))
OS_EXPORT OS_OBJECT_OBJC_RUNTIME_VISIBLE
OS_OBJECT_DECL_BASE(object, NSObject);
#endif // OS_OBJECT_SWIFT3
#else
/*! @parseOnly */
#define OS_OBJECT_RETURNS_RETAINED
/*! @parseOnly */
#define OS_OBJECT_CONSUMED
/*! @parseOnly */
#define OS_OBJECT_BRIDGE
/*! @parseOnly */
#define OS_WARN_RESULT_NEEDS_RELEASE OS_WARN_RESULT
/*! @parseOnly */
#define OS_OBJECT_OBJC_RUNTIME_VISIBLE
#define OS_OBJECT_USE_OBJC_RETAIN_RELEASE 0
#endif
#if OS_OBJECT_SWIFT3
#define OS_OBJECT_DECL_CLASS(name) \
OS_OBJECT_DECL_SUBCLASS_SWIFT(name, object)
#elif OS_OBJECT_USE_OBJC
#define OS_OBJECT_DECL_CLASS(name) \
OS_OBJECT_DECL(name)
#else
#define OS_OBJECT_DECL_CLASS(name) \
typedef struct name##_s *name##_t
#endif
#define OS_OBJECT_GLOBAL_OBJECT(type, object) ((OS_OBJECT_BRIDGE type)&(object))
__BEGIN_DECLS
/*!
* @function os_retain
*
* @abstract
* Increment the reference count of an os_object.
*
* @discussion
* On a platform with the modern Objective-C runtime this is exactly equivalent
* to sending the object the -[retain] message.
*
* @param object
* The object to retain.
*
* @result
* The retained object.
*/
API_AVAILABLE(macos(10.10), ios(8.0))
OS_EXPORT OS_SWIFT_UNAVAILABLE("Can't be used with ARC")
void*
os_retain(void *object);
#if OS_OBJECT_USE_OBJC
#undef os_retain
#define os_retain(object) [object retain]
#endif
/*!
* @function os_release
*
* @abstract
* Decrement the reference count of a os_object.
*
* @discussion
* On a platform with the modern Objective-C runtime this is exactly equivalent
* to sending the object the -[release] message.
*
* @param object
* The object to release.
*/
API_AVAILABLE(macos(10.10), ios(8.0))
OS_EXPORT
void OS_SWIFT_UNAVAILABLE("Can't be used with ARC")
os_release(void *object);
#if OS_OBJECT_USE_OBJC
#undef os_release
#define os_release(object) [object release]
#endif
__END_DECLS
#endif

View File

@@ -0,0 +1,205 @@
/*
* Copyright (c) 2011-2012 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 __OS_OBJECT_PRIVATE__
#define __OS_OBJECT_PRIVATE__
#include <os/object.h>
#include <stddef.h>
#include <stdint.h>
#if __GNUC__
#define OS_OBJECT_NOTHROW __attribute__((__nothrow__))
#define OS_OBJECT_NONNULL __attribute__((__nonnull__))
#define OS_OBJECT_WARN_RESULT __attribute__((__warn_unused_result__))
#define OS_OBJECT_MALLOC __attribute__((__malloc__))
#ifndef OS_OBJECT_EXPORT
#define OS_OBJECT_EXPORT extern __attribute__((visibility("default")))
#endif
#else
/*! @parseOnly */
#define OS_OBJECT_NOTHROW
/*! @parseOnly */
#define OS_OBJECT_NONNULL
/*! @parseOnly */
#define OS_OBJECT_WARN_RESULT
/*! @parseOnly */
#define OS_OBJECT_MALLOC
#ifndef OS_OBJECT_EXPORT
/*! @parseOnly */
#define OS_OBJECT_EXPORT extern
#endif
#endif
#if OS_OBJECT_USE_OBJC && __has_feature(objc_arc)
#define _OS_OBJECT_OBJC_ARC 1
#else
#define _OS_OBJECT_OBJC_ARC 0
#endif
#define _OS_OBJECT_GLOBAL_REFCNT INT_MAX
#define _OS_OBJECT_HEADER(isa, ref_cnt, xref_cnt) \
isa; /* must be pointer-sized */ \
int volatile ref_cnt; \
int volatile xref_cnt
#if OS_OBJECT_HAVE_OBJC_SUPPORT
#define OS_OBJECT_CLASS_SYMBOL(name) OS_##name##_class
#if TARGET_OS_MAC && !TARGET_OS_SIMULATOR && defined(__i386__)
#define OS_OBJECT_HAVE_OBJC1 1
#define OS_OBJECT_HAVE_OBJC2 0
#define OS_OBJC_CLASS_RAW_SYMBOL_NAME(name) \
".objc_class_name_" OS_STRINGIFY(name)
#define _OS_OBJECT_CLASS_HEADER() \
const void *_os_obj_objc_isa
#else
#define OS_OBJECT_HAVE_OBJC1 0
#define OS_OBJECT_HAVE_OBJC2 1
#define OS_OBJC_CLASS_RAW_SYMBOL_NAME(name) "_OBJC_CLASS_$_" OS_STRINGIFY(name)
// Must match size of compiler-generated OBJC_CLASS structure rdar://10640168
#define _OS_OBJECT_CLASS_HEADER() \
void *_os_obj_objc_class_t[5]
#endif
#define OS_OBJECT_OBJC_CLASS_DECL(name) \
extern void *OS_OBJECT_CLASS_SYMBOL(name) \
__asm__(OS_OBJC_CLASS_RAW_SYMBOL_NAME(OS_OBJECT_CLASS(name)))
#else
#define OS_OBJECT_HAVE_OBJC1 0
#define OS_OBJECT_HAVE_OBJC2 0
#define _OS_OBJECT_CLASS_HEADER() \
void (*_os_obj_xref_dispose)(_os_object_t); \
void (*_os_obj_dispose)(_os_object_t)
#endif
#define OS_OBJECT_CLASS(name) OS_##name
#if OS_OBJECT_USE_OBJC && OS_OBJECT_SWIFT3
@interface OS_OBJECT_CLASS(object) (OSObjectPrivate)
- (void)_xref_dispose;
- (void)_dispose;
@end
OS_OBJECT_DECL_PROTOCOL(object, <NSObject>);
typedef OS_OBJECT_CLASS(object) *_os_object_t;
#define _OS_OBJECT_DECL_SUBCLASS_INTERFACE(name, super) \
@interface OS_OBJECT_CLASS(name) : OS_OBJECT_CLASS(super) \
<OS_OBJECT_CLASS(name)> \
@end
#define _OS_OBJECT_DECL_PROTOCOL(name, super) \
OS_OBJECT_DECL_PROTOCOL(name, <OS_OBJECT_CLASS(super)>)
#define _OS_OBJECT_CLASS_IMPLEMENTS_PROTOCOL(name, super) \
OS_OBJECT_CLASS_IMPLEMENTS_PROTOCOL(name, super)
#elif OS_OBJECT_USE_OBJC
API_AVAILABLE(macos(10.8), ios(6.0))
OS_OBJECT_EXPORT
@interface OS_OBJECT_CLASS(object) : NSObject
- (void)_xref_dispose;
- (void)_dispose;
@end
typedef OS_OBJECT_CLASS(object) *_os_object_t;
#define _OS_OBJECT_DECL_SUBCLASS_INTERFACE(name, super) \
@interface OS_OBJECT_CLASS(name) : OS_OBJECT_CLASS(super) \
<OS_OBJECT_CLASS(name)> \
@end
#else
#define _OS_OBJECT_DECL_SUBCLASS_INTERFACE(name, super)
#define _OS_OBJECT_DECL_PROTOCOL(name, super)
#define _OS_OBJECT_CLASS_IMPLEMENTS_PROTOCOL(name, super)
typedef struct _os_object_s *_os_object_t;
#endif
OS_ASSUME_NONNULL_BEGIN
__BEGIN_DECLS
#if !_OS_OBJECT_OBJC_ARC
API_AVAILABLE(macos(10.8), ios(6.0))
OS_OBJECT_EXPORT OS_OBJECT_MALLOC OS_OBJECT_WARN_RESULT OS_OBJECT_NOTHROW
OS_SWIFT_UNAVAILABLE("Unavailable in Swift")
_os_object_t
_os_object_alloc(const void *cls, size_t size);
API_AVAILABLE(macos(10.8), ios(6.0))
OS_OBJECT_EXPORT OS_OBJECT_MALLOC OS_OBJECT_WARN_RESULT OS_OBJECT_NOTHROW
OS_SWIFT_UNAVAILABLE("Unavailable in Swift")
_os_object_t
_os_object_alloc_realized(const void *cls, size_t size);
API_AVAILABLE(macos(10.8), ios(6.0))
OS_OBJECT_EXPORT OS_OBJECT_NONNULL OS_OBJECT_NOTHROW
OS_SWIFT_UNAVAILABLE("Unavailable in Swift")
void _os_object_dealloc(_os_object_t object);
API_AVAILABLE(macos(10.8), ios(6.0))
OS_OBJECT_EXPORT OS_OBJECT_NONNULL OS_OBJECT_NOTHROW
OS_SWIFT_UNAVAILABLE("Unavailable in Swift")
_os_object_t
_os_object_retain(_os_object_t object);
API_AVAILABLE(macos(10.8), ios(6.0))
OS_OBJECT_EXPORT OS_OBJECT_NONNULL OS_OBJECT_NOTHROW
OS_SWIFT_UNAVAILABLE("Unavailable in Swift")
_os_object_t
_os_object_retain_with_resurrect(_os_object_t obj);
API_AVAILABLE(macos(10.8), ios(6.0))
OS_OBJECT_EXPORT OS_OBJECT_NONNULL OS_OBJECT_NOTHROW
OS_SWIFT_UNAVAILABLE("Unavailable in Swift")
void
_os_object_release(_os_object_t object);
API_AVAILABLE(macos(10.8), ios(6.0))
OS_OBJECT_EXPORT OS_OBJECT_NONNULL OS_OBJECT_NOTHROW
OS_SWIFT_UNAVAILABLE("Unavailable in Swift")
_os_object_t
_os_object_retain_internal(_os_object_t object);
API_AVAILABLE(macos(10.8), ios(6.0))
OS_OBJECT_EXPORT OS_OBJECT_NONNULL OS_OBJECT_NOTHROW
OS_SWIFT_UNAVAILABLE("Unavailable in Swift")
void
_os_object_release_internal(_os_object_t object);
API_AVAILABLE(macos(10.13), ios(11.0), tvos(11.0), watchos(4.0))
OS_OBJECT_EXPORT OS_OBJECT_NONNULL OS_OBJECT_NOTHROW
OS_SWIFT_UNAVAILABLE("Unavailable in Swift")
_os_object_t
_os_object_retain_internal_n(_os_object_t object, uint16_t n);
API_AVAILABLE(macos(10.13), ios(11.0), tvos(11.0), watchos(4.0))
OS_OBJECT_EXPORT OS_OBJECT_NONNULL OS_OBJECT_NOTHROW
OS_SWIFT_UNAVAILABLE("Unavailable in Swift")
void
_os_object_release_internal_n(_os_object_t object, uint16_t n);
#endif // !_OS_OBJECT_OBJC_ARC
__END_DECLS
OS_ASSUME_NONNULL_END
#endif

View File

@@ -0,0 +1,373 @@
/*
* Copyright (c) 2013-2015 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 __OS_VOUCHER_ACTIVITY_PRIVATE__
#define __OS_VOUCHER_ACTIVITY_PRIVATE__
#if OS_VOUCHER_ACTIVITY_SPI
#if __has_include(<mach/mach_time.h>)
#include <mach/mach_time.h>
#include <firehose/tracepoint_private.h>
#endif
#if __APPLE__
#include <os/base.h>
#include <os/availability.h>
#endif
#include <sys/uio.h>
#include <os/object.h>
#include "voucher_private.h"
#define OS_VOUCHER_ACTIVITY_SPI_VERSION 20161003
#if OS_VOUCHER_WEAK_IMPORT
#define OS_VOUCHER_EXPORT OS_EXPORT OS_WEAK_IMPORT
#else
#define OS_VOUCHER_EXPORT OS_EXPORT
#endif
__BEGIN_DECLS
/*!
* @const VOUCHER_CURRENT
* Shorthand for the currently adopted voucher
*
* This value can only be used as an argument to functions, and is never
* actually returned. It looks enough like a tagged pointer object that ARC
* won't crash if this is assigned to a temporary variable.
*/
#define VOUCHER_CURRENT ((OS_OBJECT_BRIDGE voucher_t)(void *)~2ul)
/*!
* @function voucher_get_activity_id
*
* @abstract
* Returns the activity_id associated with the specified voucher at the time
* of the call.
*
* @discussion
* When the passed voucher is VOUCHER_CURRENT this returns the current
* activity ID.
*
* @param voucher
* The specified voucher.
*
* @param parent_id
* An out parameter to return the parent ID of the returned activity ID.
*
* @result
* The current activity identifier, if any. When 0 is returned, parent_id will
* also always be 0.
*/
API_AVAILABLE(macos(10.12), ios(10.0), tvos(10.0), watchos(3.0))
OS_VOUCHER_EXPORT OS_NOTHROW
firehose_activity_id_t
voucher_get_activity_id(voucher_t voucher, firehose_activity_id_t *parent_id);
/*!
* @function voucher_get_activity_id_and_creator
*
* @abstract
* Returns the activity_id associated with the specified voucher at the time
* of the call.
*
* @discussion
* When the passed voucher is VOUCHER_CURRENT this returns the current
* activity ID.
*
* @param voucher
* The specified voucher.
*
* @param creator_pid
* The unique pid of the process that created the returned activity ID if any.
*
* @param parent_id
* An out parameter to return the parent ID of the returned activity ID.
*
* @result
* The current activity identifier, if any. When 0 is returned, parent_id will
* also always be 0.
*/
API_AVAILABLE(macos(10.12), ios(10.0), tvos(10.0), watchos(3.0))
OS_VOUCHER_EXPORT OS_NOTHROW
firehose_activity_id_t
voucher_get_activity_id_and_creator(voucher_t voucher, uint64_t *creator_pid,
firehose_activity_id_t *parent_id);
/*!
* @function voucher_activity_create_with_data
*
* @abstract
* Creates a voucher object with a new activity identifier.
*
* @discussion
* As part of voucher transport, activities are automatically propagated by the
* system to other threads and processes (across IPC).
*
* When a voucher with an activity identifier is applied to a thread, work
* on that thread is done on behalf of this activity.
*
* @param trace_id
* Tracepoint identifier returned by voucher_activity_trace_id(), intended for
* identification of the automatic tracepoint generated as part of creating the
* new activity.
*
* @param base
* The base voucher used to create the activity. If the base voucher has an
* activity identifier, then the created activity will be parented to that one.
* If the passed in base has no activity identifier, the activity identifier
* will be a top-level one, on behalf of the process that created the base
* voucher.
*
* If base is VOUCHER_NONE, the activity is a top-level one, on behalf of the
* current process.
*
* If base is VOUCHER_CURRENT, then the activity is naturally based on the
* one currently applied to the current thread (the one voucher_copy() would
* return).
*
* @param flags
* See voucher_activity_flag_t documentation for effect.
*
* @param pubdata
* Pointer to packed buffer of tracepoint data.
*
* @param publen
* Length of data at 'pubdata'.
*
* @result
* A new voucher with an activity identifier.
*/
API_AVAILABLE(macos(10.12.4), ios(10.3), tvos(10.2), watchos(3.2))
OS_VOUCHER_EXPORT OS_OBJECT_RETURNS_RETAINED OS_WARN_RESULT OS_NOTHROW
voucher_t
voucher_activity_create_with_data(firehose_tracepoint_id_t *trace_id,
voucher_t base, firehose_activity_flags_t flags,
const void *pubdata, size_t publen);
API_DEPRECATED_WITH_REPLACEMENT("voucher_activity_create_with_data",
macos(10.12,10.12.4), ios(10.0,10.3), tvos(10.0,10.2), watchos(3.0,3.2))
OS_VOUCHER_EXPORT OS_OBJECT_RETURNS_RETAINED OS_WARN_RESULT OS_NOTHROW
voucher_t
voucher_activity_create_with_location(firehose_tracepoint_id_t *trace_id,
voucher_t base, firehose_activity_flags_t flags, uint64_t location);
/*!
* @group Voucher Activity Trace SPI
* SPI intended for libtrace only
*/
/*!
* @function voucher_activity_id_allocate
*
* @abstract
* Allocate a new system-wide unique activity ID.
*
* @param flags
* The bottom-most 8 bits of the flags will be used to generate the ID.
* See firehose_activity_flags_t.
*/
API_AVAILABLE(macos(10.13), ios(11.0), tvos(11.0), watchos(4.0))
OS_VOUCHER_EXPORT OS_NOTHROW
firehose_activity_id_t
voucher_activity_id_allocate(firehose_activity_flags_t flags);
/*!
* @function voucher_activity_flush
*
* @abstract
* Force flushing the specified stream.
*
* @discussion
* This maks all the buffers currently being written to as full, so that
* their current content is pushed in a timely fashion.
*
* When this call returns, the actual flush may or may not yet have happened.
*
* @param stream
* The stream to flush.
*/
API_AVAILABLE(macos(10.12), ios(10.0), tvos(10.0), watchos(3.0))
OS_VOUCHER_EXPORT OS_NOTHROW
void
voucher_activity_flush(firehose_stream_t stream);
/*!
* @function voucher_activity_trace
*
* @abstract
* Add a tracepoint to the specified stream.
*
* @param stream
* The stream to trace this entry into.
*
* @param trace_id
* Tracepoint identifier returned by voucher_activity_trace_id()
*
* @param timestamp
* The mach_approximate_time()/mach_absolute_time() value for this tracepoint.
*
* @param pubdata
* Pointer to packed buffer of tracepoint data.
*
* @param publen
* Length of data at 'pubdata'.
*/
API_AVAILABLE(macos(10.12), ios(10.0), tvos(10.0), watchos(3.0))
OS_VOUCHER_EXPORT OS_NOTHROW OS_NONNULL4
firehose_tracepoint_id_t
voucher_activity_trace(firehose_stream_t stream,
firehose_tracepoint_id_t trace_id, uint64_t timestamp,
const void *pubdata, size_t publen);
/*!
* @function voucher_activity_trace_v
*
* @abstract
* Add a tracepoint to the specified stream, with private data.
*
* @param stream
* The stream to trace this entry into.
*
* @param trace_id
* Tracepoint identifier returned by voucher_activity_trace_id()
*
* @param timestamp
* The mach_approximate_time()/mach_absolute_time() value for this tracepoint.
*
* @param iov
* Array of `struct iovec` pointing to the data to layout.
* The total size of this iovec must span exactly `publen + privlen` bytes.
* The `publen` boundary must coincide with the end of an iovec (each iovec
* must either be pure public or pure private data).
*
* @param publen
* Total length of data to read from the iovec for the public data.
*
* @param privlen
* Length of data to read from the iovec after the public data for the private
* data.
*/
API_AVAILABLE(macos(10.12.4), ios(10.3), tvos(10.2), watchos(3.2))
OS_VOUCHER_EXPORT OS_NOTHROW OS_NONNULL4
firehose_tracepoint_id_t
voucher_activity_trace_v(firehose_stream_t stream,
firehose_tracepoint_id_t trace_id, uint64_t timestamp,
const struct iovec *iov, size_t publen, size_t privlen);
#define VOUCHER_ACTIVITY_TRACE_FLAG_UNRELIABLE 0x01
API_AVAILABLE(macos(10.14), ios(12.0), tvos(12.0), watchos(5.0))
OS_VOUCHER_EXPORT OS_NOTHROW OS_NONNULL4
firehose_tracepoint_id_t
voucher_activity_trace_v_2(firehose_stream_t stream,
firehose_tracepoint_id_t trace_id, uint64_t timestamp,
const struct iovec *iov, size_t publen, size_t privlen, uint32_t flags);
typedef const struct voucher_activity_hooks_s {
#define VOUCHER_ACTIVITY_HOOKS_VERSION 5
long vah_version;
mach_port_t (*vah_get_logd_port)(void);
dispatch_mach_handler_function_t vah_debug_channel_handler;
kern_return_t (*vah_get_reconnect_info)(mach_vm_address_t *, mach_vm_size_t *);
void (*vah_metadata_init)(void *metadata_buffer, size_t size);
void (*vah_quarantine_starts)(void);
} *voucher_activity_hooks_t;
/*!
* @function voucher_activity_initialize_4libtrace
*
* @abstract
* Configure upcall hooks for libtrace.
*
* @param hooks
* A pointer to a voucher_activity_hooks_s structure.
*/
API_AVAILABLE(macos(10.12), ios(10.0), tvos(10.0), watchos(3.0))
OS_VOUCHER_EXPORT OS_NOTHROW OS_NONNULL_ALL
void
voucher_activity_initialize_4libtrace(voucher_activity_hooks_t hooks);
/*!
* @function voucher_activity_get_metadata_buffer
*
* @abstract
* Return address and length of buffer in the process trace memory area
* reserved for libtrace metadata.
*
* @param length
* Pointer to size_t variable, filled with length of metadata buffer.
*
* @result
* Address of metadata buffer.
*/
API_AVAILABLE(macos(10.10), ios(8.0))
OS_VOUCHER_EXPORT OS_WARN_RESULT OS_NOTHROW OS_NONNULL_ALL
void *
voucher_activity_get_metadata_buffer(size_t *length);
/*!
* @function voucher_activity_get_logging_preferences
*
* @abstract
* Return address and length of vm_map()ed configuration data for the logging
* subsystem.
*
* @discussion
* The data must be deallocated with vm_deallocate().
*
* @param length
* Pointer to size_t variable, filled with length of preferences buffer.
*
* @result
* Address of preferences buffer, returns NULL on error.
*/
API_AVAILABLE(macos(10.14), ios(12.0), tvos(12.0), watchos(5.0), bridgeos(3.0))
OS_VOUCHER_EXPORT OS_WARN_RESULT OS_NOTHROW OS_NONNULL_ALL
void *
voucher_activity_get_logging_preferences(size_t *length);
/*!
* @function voucher_activity_should_send_strings
*
* @abstract
* Returns whether the client should send the strings or not.
*/
API_AVAILABLE(macos(10.14), ios(12.0), tvos(12.0), watchos(5.0), bridgeos(4.0))
OS_VOUCHER_EXPORT OS_WARN_RESULT OS_NOTHROW
bool
voucher_activity_should_send_strings(void);
/*!
* @function voucher_get_activity_id_4dyld
*
* @abstract
* Return the current voucher activity ID. Available for the dyld client stub
* only.
*/
API_AVAILABLE(macos(10.12), ios(10.0), tvos(10.0), watchos(3.0))
OS_VOUCHER_EXPORT OS_WARN_RESULT OS_NOTHROW
firehose_activity_id_t
voucher_get_activity_id_4dyld(void);
__END_DECLS
#endif // OS_VOUCHER_ACTIVITY_SPI
#endif // __OS_VOUCHER_ACTIVITY_PRIVATE__

View File

@@ -0,0 +1,641 @@
/*
* Copyright (c) 2013-2014 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 __OS_VOUCHER_PRIVATE__
#define __OS_VOUCHER_PRIVATE__
#if __APPLE__
#include <os/base.h>
#include <os/availability.h>
#endif
#if __has_include(<mach/mach.h>)
#include <os/object.h>
#include <mach/mach.h>
#endif
#if __has_include(<bank/bank_types.h>)
#include <bank/bank_types.h>
#endif
#if __has_include(<sys/persona.h>)
#include <sys/persona.h>
#endif
#ifndef __DISPATCH_BUILDING_DISPATCH__
#include <dispatch/dispatch.h>
#endif /* !__DISPATCH_BUILDING_DISPATCH__ */
#define OS_VOUCHER_SPI_VERSION 20150630
#if OS_VOUCHER_WEAK_IMPORT
#define OS_VOUCHER_EXPORT OS_EXPORT OS_WEAK_IMPORT
#else
#define OS_VOUCHER_EXPORT OS_EXPORT
#endif
DISPATCH_ASSUME_NONNULL_BEGIN
__BEGIN_DECLS
/*!
* @group Voucher Transport SPI
* SPI intended for clients that need to transport vouchers.
*/
/*!
* @typedef voucher_t
*
* @abstract
* Vouchers are immutable sets of key/value attributes that can be adopted on a
* thread in the current process or sent to another process.
*
* @discussion
* Voucher objects are os_objects (c.f. <os/object.h>). They are memory-managed
* with the os_retain()/os_release() functions or -[retain]/-[release] methods.
*/
OS_OBJECT_DECL_CLASS(voucher);
/*!
* @const VOUCHER_NULL
* Represents the empty base voucher with no attributes.
*/
#define VOUCHER_NULL ((voucher_t)0)
/*!
* @const VOUCHER_INVALID
* Represents an invalid voucher
*/
#define VOUCHER_INVALID ((voucher_t)-1)
/*!
* @function voucher_adopt
*
* @abstract
* Adopt the specified voucher on the current thread and return the voucher
* that had been adopted previously.
*
* @discussion
* Adopted vouchers are automatically carried forward by the system to other
* threads and processes (across IPC).
*
* Consumes a reference to the specified voucher.
* Returns a reference to the previous voucher.
*
* @param voucher
* The voucher object to adopt on the current thread.
*
* @result
* The previously adopted voucher object.
*/
API_AVAILABLE(macos(10.10), ios(8.0))
OS_VOUCHER_EXPORT OS_OBJECT_RETURNS_RETAINED OS_WARN_RESULT_NEEDS_RELEASE
OS_NOTHROW
voucher_t _Nullable
voucher_adopt(voucher_t _Nullable voucher OS_OBJECT_CONSUMED);
/*!
* @function voucher_copy
*
* @abstract
* Returns a reference to the voucher that had been adopted previously on the
* current thread (or carried forward by the system).
*
* @result
* The currently adopted voucher object.
*/
API_AVAILABLE(macos(10.10), ios(8.0))
OS_VOUCHER_EXPORT OS_OBJECT_RETURNS_RETAINED OS_WARN_RESULT OS_NOTHROW
voucher_t _Nullable
voucher_copy(void);
/*!
* @function voucher_copy_without_importance
*
* @abstract
* Returns a reference to a voucher object with all the properties of the
* voucher that had been adopted previously on the current thread, but
* without the importance properties that are frequently attached to vouchers
* carried with IPC requests. Importance properties may elevate the scheduling
* of threads that adopt or retain the voucher while they service the request.
* See xpc_transaction_begin(3) for further details on importance.
*
* @result
* A copy of the currently adopted voucher object, with importance removed.
*/
API_AVAILABLE(macos(10.10), ios(8.0))
OS_VOUCHER_EXPORT OS_OBJECT_RETURNS_RETAINED OS_WARN_RESULT OS_NOTHROW
voucher_t _Nullable
voucher_copy_without_importance(void);
/*!
* @function voucher_replace_default_voucher
*
* @abstract
* Replace process attributes of default voucher (used for IPC by this process
* when no voucher is adopted on the sending thread) with the process attributes
* of the voucher adopted on the current thread.
*
* @discussion
* This allows a daemon to indicate from the context of an incoming IPC request
* that all future outgoing IPC from the process should be marked as acting
* "on behalf of" the sending process of the current IPC request (as long as the
* thread sending that outgoing IPC is not itself in the direct context of an
* IPC request, i.e. no voucher is adopted).
*
* If no voucher is adopted on the current thread or the current voucher does
* not contain any process attributes, the default voucher is reset to the
* default process attributes for the current process.
*
* CAUTION: Do NOT use this SPI without contacting the Darwin Runtime team.
*/
API_AVAILABLE(macos(10.10), ios(8.0))
OS_VOUCHER_EXPORT OS_NOTHROW
void
voucher_replace_default_voucher(void);
/*!
* @function voucher_decrement_importance_count4CF
*
* @abstract
* Decrement external importance count of the mach voucher in the specified
* voucher object.
*
* @discussion
* This is only intended for use by CoreFoundation to explicitly manage the
* App Nap state of an application following reception of a de-nap IPC message.
*
* CAUTION: Do NOT use this SPI without contacting the Darwin Runtime team.
*/
API_AVAILABLE(macos(10.10), ios(8.0))
OS_VOUCHER_EXPORT OS_NOTHROW
void
voucher_decrement_importance_count4CF(voucher_t _Nullable voucher);
/*!
* @group Voucher dispatch block SPI
*/
/*!
* @typedef dispatch_block_flags_t
* SPI Flags to pass to the dispatch_block_create* functions.
*
* @const DISPATCH_BLOCK_NO_VOUCHER
* Flag indicating that a dispatch block object should not be assigned a voucher
* object. If invoked directly, the block object will be executed with the
* voucher adopted on the calling thread. If the block object is submitted to a
* queue, this replaces the default behavior of associating the submitted block
* instance with the voucher adopted at the time of submission.
* This flag is ignored if used with the dispatch_block_create_with_voucher*()
* functions.
*
*/
#define DISPATCH_BLOCK_NO_VOUCHER (0x40ul)
#define DISPATCH_BLOCK_IF_LAST_RESET_QUEUE_QOS_OVERRIDE (0x80ul)
/*!
* @function dispatch_block_create_with_voucher
*
* @abstract
* Create a new dispatch block object on the heap from an existing block and
* the given flags, and assign it the specified voucher object.
*
* @discussion
* The provided block is Block_copy'ed to the heap, it and the specified voucher
* object are retained by the newly created dispatch block object.
*
* The returned dispatch block object is intended to be submitted to a dispatch
* queue with dispatch_async() and related functions, but may also be invoked
* directly. Both operations can be performed an arbitrary number of times but
* only the first completed execution of a dispatch block object can be waited
* on with dispatch_block_wait() or observed with dispatch_block_notify().
*
* The returned dispatch block will be executed with the specified voucher
* adopted for the duration of the block body.
*
* If the returned dispatch block object is submitted to a dispatch queue, the
* submitted block instance will be associated with the QOS class current at the
* time of submission, unless one of the following flags assigned a specific QOS
* class (or no QOS class) at the time of block creation:
* - DISPATCH_BLOCK_ASSIGN_CURRENT
* - DISPATCH_BLOCK_NO_QOS_CLASS
* - DISPATCH_BLOCK_DETACHED
* The QOS class the block object will be executed with also depends on the QOS
* class assigned to the queue and which of the following flags was specified or
* defaulted to:
* - DISPATCH_BLOCK_INHERIT_QOS_CLASS (default for asynchronous execution)
* - DISPATCH_BLOCK_ENFORCE_QOS_CLASS (default for synchronous execution)
* See description of dispatch_block_flags_t for details.
*
* If the returned dispatch block object is submitted directly to a serial queue
* and is configured to execute with a specific QOS class, the system will make
* a best effort to apply the necessary QOS overrides to ensure that blocks
* submitted earlier to the serial queue are executed at that same QOS class or
* higher.
*
* @param flags
* Configuration flags for the block object.
* Passing a value that is not a bitwise OR of flags from dispatch_block_flags_t
* results in NULL being returned. The DISPATCH_BLOCK_NO_VOUCHER flag is
* ignored.
*
* @param voucher
* A voucher object or NULL.
*
* @param block
* The block to create the dispatch block object from.
*
* @result
* The newly created dispatch block object, or NULL.
* When not building with Objective-C ARC, must be released with a -[release]
* message or the Block_release() function.
*/
API_AVAILABLE(macos(10.10), ios(8.0))
DISPATCH_EXPORT DISPATCH_NONNULL3 DISPATCH_RETURNS_RETAINED_BLOCK
DISPATCH_WARN_RESULT DISPATCH_NOTHROW
dispatch_block_t
dispatch_block_create_with_voucher(dispatch_block_flags_t flags,
voucher_t _Nullable voucher, dispatch_block_t block);
/*!
* @function dispatch_block_create_with_voucher_and_qos_class
*
* @abstract
* Create a new dispatch block object on the heap from an existing block and
* the given flags, and assign it the specified voucher object, QOS class and
* relative priority.
*
* @discussion
* The provided block is Block_copy'ed to the heap, it and the specified voucher
* object are retained by the newly created dispatch block object.
*
* The returned dispatch block object is intended to be submitted to a dispatch
* queue with dispatch_async() and related functions, but may also be invoked
* directly. Both operations can be performed an arbitrary number of times but
* only the first completed execution of a dispatch block object can be waited
* on with dispatch_block_wait() or observed with dispatch_block_notify().
*
* The returned dispatch block will be executed with the specified voucher
* adopted for the duration of the block body.
*
* If invoked directly, the returned dispatch block object will be executed with
* the assigned QOS class as long as that does not result in a lower QOS class
* than what is current on the calling thread.
*
* If the returned dispatch block object is submitted to a dispatch queue, the
* QOS class it will be executed with depends on the QOS class assigned to the
* block, the QOS class assigned to the queue and which of the following flags
* was specified or defaulted to:
* - DISPATCH_BLOCK_INHERIT_QOS_CLASS: default for asynchronous execution
* - DISPATCH_BLOCK_ENFORCE_QOS_CLASS: default for synchronous execution
* See description of dispatch_block_flags_t for details.
*
* If the returned dispatch block object is submitted directly to a serial queue
* and is configured to execute with a specific QOS class, the system will make
* a best effort to apply the necessary QOS overrides to ensure that blocks
* submitted earlier to the serial queue are executed at that same QOS class or
* higher.
*
* @param flags
* Configuration flags for the block object.
* Passing a value that is not a bitwise OR of flags from dispatch_block_flags_t
* results in NULL being returned. The DISPATCH_BLOCK_NO_VOUCHER and
* DISPATCH_BLOCK_NO_QOS flags are ignored.
*
* @param voucher
* A voucher object or NULL.
*
* @param qos_class
* A QOS class value:
* - QOS_CLASS_USER_INTERACTIVE
* - QOS_CLASS_USER_INITIATED
* - QOS_CLASS_DEFAULT
* - QOS_CLASS_UTILITY
* - QOS_CLASS_BACKGROUND
* - QOS_CLASS_UNSPECIFIED
* Passing QOS_CLASS_UNSPECIFIED is equivalent to specifying the
* DISPATCH_BLOCK_NO_QOS_CLASS flag. Passing any other value results in NULL
* being returned.
*
* @param relative_priority
* A relative priority within the QOS class. This value is a negative
* offset from the maximum supported scheduler priority for the given class.
* Passing a value greater than zero or less than QOS_MIN_RELATIVE_PRIORITY
* results in NULL being returned.
*
* @param block
* The block to create the dispatch block object from.
*
* @result
* The newly created dispatch block object, or NULL.
* When not building with Objective-C ARC, must be released with a -[release]
* message or the Block_release() function.
*/
API_AVAILABLE(macos(10.10), ios(8.0))
DISPATCH_EXPORT DISPATCH_NONNULL5 DISPATCH_RETURNS_RETAINED_BLOCK
DISPATCH_WARN_RESULT DISPATCH_NOTHROW
dispatch_block_t
dispatch_block_create_with_voucher_and_qos_class(dispatch_block_flags_t flags,
voucher_t _Nullable voucher, dispatch_qos_class_t qos_class,
int relative_priority, dispatch_block_t block);
/*!
* @group Voucher dispatch queue SPI
*/
/*!
* @function dispatch_queue_create_with_accounting_override_voucher
*
* @abstract
* Deprecated, do not use, will abort process if called.
*/
API_DEPRECATED("removed SPI", \
macos(10.11,10.13), ios(9.0,11.0), watchos(2.0,4.0), tvos(9.0,11.0))
DISPATCH_EXPORT DISPATCH_MALLOC DISPATCH_RETURNS_RETAINED DISPATCH_WARN_RESULT
DISPATCH_NOTHROW
dispatch_queue_t
dispatch_queue_create_with_accounting_override_voucher(
const char *_Nullable label,
dispatch_queue_attr_t _Nullable attr,
voucher_t _Nullable voucher);
#if __has_include(<mach/mach.h>)
/*!
* @group Voucher Mach SPI
* SPI intended for clients that need to interact with mach messages or mach
* voucher ports directly.
*/
/*!
* @function voucher_create_with_mach_msg
*
* @abstract
* Creates a new voucher object from a mach message carrying a mach voucher port
*
* @discussion
* Ownership of the mach voucher port in the message is transfered to the new
* voucher object and the message header mach voucher field is cleared.
*
* @param msg
* The mach message to query.
*
* @result
* The newly created voucher object or NULL if the message was not carrying a
* mach voucher.
*/
API_AVAILABLE(macos(10.10), ios(8.0))
OS_VOUCHER_EXPORT OS_OBJECT_RETURNS_RETAINED OS_WARN_RESULT OS_NOTHROW
voucher_t _Nullable
voucher_create_with_mach_msg(mach_msg_header_t *msg);
/*!
* @function voucher_kvoucher_debug
*
* @abstract
* Writes a human-readable representation of a voucher to a memory buffer.
*
* @discussion
* The formatted representation of the voucher is written starting at a given
* offset in the buffer. If the remaining space in the buffer is too small, the
* output is truncated. Nothing is written before buf[offset] or at or beyond
* buf[bufsize].
*
* @param task
* The task port for the task that owns the voucher port.
*
* @param voucher
* The voucher port name.
*
* @param buf
* The buffer to which the formatted representation of the voucher should be
* written.
*
* @param bufsiz
* The size of the buffer.
*
* @param offset
* The offset of the first byte in the buffer to be used for output.
*
* @param prefix
* A string to be written at the start of each line of formatted output.
* Typically used to generate leading whitespace for indentation. Use NULL if
* no prefix is required.
*
* @param max_hex_data
* The maximum number of bytes of hex data to be formatted for voucher content
* that is not of type MACH_VOUCHER_ATTR_KEY_ATM, MACH_VOUCHER_ATTR_KEY_BANK
* or MACH_VOUCHER_ATTR_KEY_IMPORTANCE.
*
* @result
* The offset of the first byte in the buffer following the formatted voucher
* representation.
*/
API_AVAILABLE(macos(10.14), ios(12.0), tvos(12.0), watchos(5.0))
OS_VOUCHER_EXPORT OS_WARN_RESULT OS_NOTHROW DISPATCH_COLD
size_t
voucher_kvoucher_debug(mach_port_t task, mach_port_name_t voucher, char *buf,
size_t bufsiz, size_t offset, char * _Nullable prefix,
size_t max_hex_data) ;
/*!
* @group Voucher Persona SPI
* SPI intended for clients that need to interact with personas.
*/
struct proc_persona_info;
/*!
* @function voucher_get_current_persona
*
* @abstract
* Returns the persona identifier for the current thread.
*
* @discussion
* Retrieve the persona identifier from the currently adopted voucher.
*
* If the thread has not adopted a voucher, or the current voucher does not
* contain persona information, this function returns the persona identifier
* of the current process.
*
* If the process is not running under a persona, then this returns
* PERSONA_ID_NONE.
*
* @result
* The persona identifier for the current voucher,
* or the persona identifier of the current process
* or PERSONA_ID_NONE
*/
API_AVAILABLE(macos(10.14), ios(9.2))
OS_VOUCHER_EXPORT OS_WARN_RESULT OS_NOTHROW
uid_t
voucher_get_current_persona(void);
/*!
* @function voucher_get_current_persona_originator_info
*
* @abstract
* Retrieve the originator process persona info for the currently adopted
* voucher.
*
* @discussion
* If there is no currently adopted voucher, or no PERSONA_TOKEN attribute
* in that voucher, this function fails.
*
* @param persona_info
* The proc_persona_info structure to fill in case of success
*
* @result
* 0 on success: currently adopted voucher has a PERSONA_TOKEN
* -1 on failure: persona_info is untouched/uninitialized
*/
API_AVAILABLE(macos(10.14), ios(9.2))
OS_VOUCHER_EXPORT OS_WARN_RESULT OS_NOTHROW OS_NONNULL1
int
voucher_get_current_persona_originator_info(
struct proc_persona_info *persona_info);
/*!
* @function voucher_get_current_persona_proximate_info
*
* @abstract
* Retrieve the proximate process persona info for the currently adopted
* voucher.
*
* @discussion
* If there is no currently adopted voucher, or no PERSONA_TOKEN attribute
* in that voucher, this function fails.
*
* @param persona_info
* The proc_persona_info structure to fill in case of success
*
* @result
* 0 on success: currently adopted voucher has a PERSONA_TOKEN
* -1 on failure: persona_info is untouched/uninitialized
*/
API_AVAILABLE(macos(10.14), ios(9.2))
OS_VOUCHER_EXPORT OS_WARN_RESULT OS_NOTHROW OS_NONNULL1
int
voucher_get_current_persona_proximate_info(
struct proc_persona_info *persona_info);
/*!
* @function voucher_copy_with_persona_mach_voucher
*
* @abstract
* Creates a copy of the currently adopted voucher and replaces its
* persona information with the one passed in the specified mach voucher
*
* @discussion
* If the specified mach voucher is not one returned from
* mach_voucher_persona_for_originator() (called on behalf
* of the current process), this function will fail
*
* @param persona_mach_voucher
* mach voucher containing the new persona information
*
* @result
* On success, a copy of the current voucher with the new
* persona information
* On failure, VOUCHER_INVALID
*/
API_AVAILABLE(macos(10.14), ios(12))
OS_VOUCHER_EXPORT OS_OBJECT_RETURNS_RETAINED OS_WARN_RESULT OS_NOTHROW
voucher_t _Nullable
voucher_copy_with_persona_mach_voucher(
mach_voucher_t persona_mach_voucher);
/*!
* @function mach_voucher_persona_self
*
* @abstract
* Creates a mach voucher containing the persona information of the
* current process that can be sent as a mach port descriptor in a message
*
* @discussion
* The returned mach voucher has been pre-processed so that it can be sent
* in a message
*
* @param persona_mach_voucher
* If successful, a reference to the newly created mach voucher
*
* @result
* KERN_SUCCESS: a mach voucher ready to be sent in a message is
* successfully created
* KERN_RESOURCE_SHORTAGE: mach voucher creation failed due to
* lack of free space
*/
API_AVAILABLE(macos(10.14), ios(12))
OS_VOUCHER_EXPORT OS_WARN_RESULT OS_NOTHROW OS_NONNULL1
kern_return_t
mach_voucher_persona_self(mach_voucher_t *persona_mach_voucher);
/*!
* @function mach_voucher_persona_for_originator
*
* @abstract
* Creates a mach voucher on behalf of the originator process by copying
* the persona information from the specified mach voucher and then
* updating the persona identifier to the specified value
*
* @discussion
* Should be called by a privileged process on behalf of the originator process.
* The newly created mach voucher should be returned to the originator in a
* message. The originator's thread can adopt the new persona by passing
* this mach voucher to voucher_copy_with_persona_mach_voucher().
*
* @param persona_id
* The new persona identifier to be set in the mach voucher
*
* @param originator_persona_mach_voucher
* A mach voucher received from the originator, where it was created using
* mach_voucher_persona_self()
*
* @param originator_unique_pid
* Unique pid of the originator process
*
* @param persona_mach_voucher
* If successful, a reference to the newly created mach voucher
*
* @result
* KERN_SUCCESS: a mach voucher ready to be returned to the
* originator was successfully created
* KERN_NO_ACCESS: process does not have privilege to carry
* out this operation
* KERN_INVALID_ARGUMENT: specified persona identifier is invalid
* KERN_INVALID_CAPABILITY: originator_unique_pid does not
* match the specified voucher originator's unique pid
* KERN_RESOURCE_SHORTAGE: mach voucher creation failed due to
* lack of free space
*/
API_AVAILABLE(macos(10.14), ios(12))
OS_VOUCHER_EXPORT OS_WARN_RESULT OS_NOTHROW OS_NONNULL4
kern_return_t
mach_voucher_persona_for_originator(uid_t persona_id,
mach_voucher_t originator_persona_mach_voucher,
uint64_t originator_unique_pid, mach_voucher_t *persona_mach_voucher);
#endif // __has_include(<mach/mach.h>)
__END_DECLS
DISPATCH_ASSUME_NONNULL_END
#endif // __OS_VOUCHER_PRIVATE__
#if OS_VOUCHER_ACTIVITY_SPI
#include "voucher_activity_private.h"
#endif

View File

@@ -0,0 +1,21 @@
# TODO(compnerd) ensure that benchmark.h data_private.h introduction_private.h
# io_private.h layout_private.h mach_private.h private.h queue_private.h
# source_private.h are included in the source tarball
if (INSTALL_PRIVATE_HEADERS)
install(FILES
benchmark.h
data_private.h
introspection_private.h
io_private.h
layout_private.h
mach_private.h
private.h
queue_private.h
source_private.h
time_private.h
workloop_private.h
DESTINATION
"${INSTALL_DISPATCH_HEADERS_DIR}")
endif()

View File

@@ -0,0 +1,89 @@
/*
* 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/private.h> instead of this file directly."
#include <dispatch/base.h> // for HeaderDoc
#endif
DISPATCH_ASSUME_NONNULL_BEGIN
__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__
API_AVAILABLE(macos(10.6), ios(4.0))
DISPATCH_EXPORT DISPATCH_NONNULL2 DISPATCH_NOTHROW
uint64_t
dispatch_benchmark(size_t count, dispatch_block_t block);
#endif
API_AVAILABLE(macos(10.6), ios(4.0))
DISPATCH_EXPORT DISPATCH_NONNULL3 DISPATCH_NOTHROW
uint64_t
dispatch_benchmark_f(size_t count, void *_Nullable ctxt,
dispatch_function_t func);
__END_DECLS
DISPATCH_ASSUME_NONNULL_END
#endif

View File

@@ -0,0 +1,10 @@
module DispatchPrivate [system] [extern_c] {
umbrella header "private.h"
exclude header "mach_private.h"
export *
}
module DispatchIntrospectionPrivate [system] [extern_c] {
header "introspection_private.h"
export *
}

View File

@@ -0,0 +1,325 @@
/*
* Copyright (c) 2011-2013 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_DATA_PRIVATE__
#define __DISPATCH_DATA_PRIVATE__
#ifndef __DISPATCH_INDIRECT__
#error "Please #include <dispatch/dispatch.h> instead of this file directly."
#include <dispatch/base.h> // for HeaderDoc
#endif
DISPATCH_ASSUME_NONNULL_BEGIN
__BEGIN_DECLS
/*!
* @const DISPATCH_DATA_DESTRUCTOR_NONE
* @discussion The destructor for dispatch data objects that require no buffer
* memory management. This can be used to allow a data object to efficiently
* encapsulate buffers that should not be copied or freed by the system.
*/
#define DISPATCH_DATA_DESTRUCTOR_NONE (_dispatch_data_destructor_none)
API_AVAILABLE(macos(10.8), ios(6.0))
DISPATCH_DATA_DESTRUCTOR_TYPE_DECL(none);
/*!
* @const DISPATCH_DATA_DESTRUCTOR_VM_DEALLOCATE
* @discussion The destructor for dispatch data objects that have been created
* from buffers that require deallocation using vm_deallocate.
*/
#define DISPATCH_DATA_DESTRUCTOR_VM_DEALLOCATE \
(_dispatch_data_destructor_vm_deallocate)
API_AVAILABLE(macos(10.8), ios(6.0)) DISPATCH_LINUX_UNAVAILABLE()
DISPATCH_DATA_DESTRUCTOR_TYPE_DECL(vm_deallocate);
/*!
* @function dispatch_data_create_f
* Creates a dispatch data object from the given contiguous buffer of memory. If
* a non-default destructor is provided, ownership of the buffer remains with
* the caller (i.e. the bytes will not be copied). The last release of the data
* object will result in the invocation of the specified destructor function on
* specified queue to free the buffer (passed as the context parameter).
*
* If the DISPATCH_DATA_DESTRUCTOR_FREE destructor is provided the buffer will
* be freed via free(3) and the queue argument ignored.
*
* If the DISPATCH_DATA_DESTRUCTOR_DEFAULT destructor is provided, data object
* creation will copy the buffer into internal memory managed by the system.
*
* @param buffer A contiguous buffer of data.
* @param size The size of the contiguous buffer of data.
* @param queue The queue to which the destructor should be submitted.
* @param destructor The destructor function responsible for freeing the
* data buffer when it is no longer needed.
* @result A newly created dispatch data object.
*/
API_AVAILABLE(macos(10.9), ios(7.0))
DISPATCH_EXPORT DISPATCH_RETURNS_RETAINED DISPATCH_WARN_RESULT DISPATCH_NOTHROW
dispatch_data_t
dispatch_data_create_f(const void *buffer,
size_t size,
dispatch_queue_t _Nullable queue,
dispatch_function_t _Nullable destructor);
/*!
* @function dispatch_data_create_alloc
* Creates a dispatch data object representing a newly allocated memory region
* of the given size. If a non-NULL reference to a pointer is provided, it is
* filled with the location of the memory region.
*
* It is the responsibility of the application to ensure that the data object
* becomes immutable (i.e. the returned memory region is not further modified)
* once the dispatch data object is passed to other API.
*
* @param size The size of the required allocation.
* @param buffer_ptr A pointer to a pointer variable to be filled with the
* location of the newly allocated memory region, or NULL.
* @result A newly created dispatch data object.
*/
API_AVAILABLE(macos(10.9), ios(6.0))
DISPATCH_EXPORT DISPATCH_RETURNS_RETAINED
DISPATCH_WARN_RESULT DISPATCH_NOTHROW
dispatch_data_t
dispatch_data_create_alloc(size_t size, void *_Nullable *_Nullable buffer_ptr);
/*!
* @typedef dispatch_data_applier_function_t
* A function to be invoked for every contiguous memory region in a data object.
*
* @param context Application-defined context parameter.
* @param region A data object representing the current region.
* @param offset The logical offset of the current region to the start
* of the data object.
* @param buffer The location of the memory for the current region.
* @param size The size of the memory for the current region.
* @result A Boolean indicating whether traversal should continue.
*/
typedef bool (*dispatch_data_applier_function_t)(void *_Nullable context,
dispatch_data_t region, size_t offset, const void *buffer, size_t size);
/*!
* @function dispatch_data_apply_f
* Traverse the memory regions represented by the specified dispatch data object
* in logical order and invoke the specified function once for every contiguous
* memory region encountered.
*
* Each invocation of the function is passed a data object representing the
* current region and its logical offset, along with the memory location and
* extent of the region. These allow direct read access to the memory region,
* but are only valid until the passed-in region object is released. Note that
* the region object is released by the system when the function returns, it is
* the responsibility of the application to retain it if the region object or
* the associated memory location are needed after the function returns.
*
* @param data The data object to traverse.
* @param context The application-defined context to pass to the function.
* @param applier The function to be invoked for every contiguous memory
* region in the data object.
* @result A Boolean indicating whether traversal completed
* successfully.
*/
API_AVAILABLE(macos(10.9), ios(6.0))
DISPATCH_EXPORT DISPATCH_NONNULL_ALL DISPATCH_NOTHROW
bool
dispatch_data_apply_f(dispatch_data_t data, void *_Nullable context,
dispatch_data_applier_function_t applier);
#if TARGET_OS_MAC
/*!
* @function dispatch_data_make_memory_entry
* Return a mach memory entry for the memory regions represented by the
* specified dispatch data object.
*
* For data objects created with the DISPATCH_DATA_DESTRUCTOR_VM_DEALLOCATE
* destructor, directly makes a memory entry from the represented region;
* otherwise, makes a memory entry from newly allocated pages containing a copy
* of the represented memory regions.
*
* @param data The data object to make a memory entry for.
* @result A mach port for the newly made memory entry, or
* MACH_PORT_NULL if an error occurred.
*/
API_AVAILABLE(macos(10.9), ios(6.0))
DISPATCH_EXPORT DISPATCH_NONNULL_ALL DISPATCH_NOTHROW
mach_port_t
dispatch_data_make_memory_entry(dispatch_data_t data);
#endif
/*!
* @functiongroup Dispatch data transform SPI
*/
/*!
* @typedef dispatch_data_format_type_t
*
* @abstract
* Data formats are used to specify the input and output types of data supplied
* to dispatch_data_create_transform.
*/
typedef const struct dispatch_data_format_type_s *dispatch_data_format_type_t;
#define DISPATCH_DATA_FORMAT_TYPE_DECL(name) \
DISPATCH_EXPORT const struct dispatch_data_format_type_s \
_dispatch_data_format_type_##name
/*!
* @const DISPATCH_DATA_FORMAT_TYPE_NONE
* @discussion A data format denoting that the given input or output format is,
* or should be, comprised of raw data bytes with no given encoding.
*/
#define DISPATCH_DATA_FORMAT_TYPE_NONE (&_dispatch_data_format_type_none)
API_AVAILABLE(macos(10.8), ios(6.0))
DISPATCH_DATA_FORMAT_TYPE_DECL(none);
/*!
* @const DISPATCH_DATA_FORMAT_TYPE_BASE32
* @discussion A data format denoting that the given input or output format is,
* or should be, encoded in Base32 (RFC 4648) format. On input, this format will
* skip whitespace characters. Cannot be used in conjunction with UTF format
* types.
*/
#define DISPATCH_DATA_FORMAT_TYPE_BASE32 (&_dispatch_data_format_type_base32)
API_AVAILABLE(macos(10.8), ios(6.0))
DISPATCH_DATA_FORMAT_TYPE_DECL(base32);
/*!
* @const DISPATCH_DATA_FORMAT_TYPE_BASE32HEX
* @discussion A data format denoting that the given input or output format is,
* or should be, encoded in Base32Hex (RFC 4648) format. On input, this format
* will skip whitespace characters. Cannot be used in conjunction with UTF
* format types.
*/
#define DISPATCH_DATA_FORMAT_TYPE_BASE32HEX \
(&_dispatch_data_format_type_base32hex)
API_AVAILABLE(macos(10.9), ios(7.0))
DISPATCH_DATA_FORMAT_TYPE_DECL(base32hex);
/*!
* @const DISPATCH_DATA_FORMAT_TYPE_BASE64
* @discussion A data format denoting that the given input or output format is,
* or should be, encoded in Base64 (RFC 4648) format. On input, this format will
* skip whitespace characters. Cannot be used in conjunction with UTF format
* types.
*/
#define DISPATCH_DATA_FORMAT_TYPE_BASE64 (&_dispatch_data_format_type_base64)
API_AVAILABLE(macos(10.8), ios(6.0))
DISPATCH_DATA_FORMAT_TYPE_DECL(base64);
/*!
* @const DISPATCH_DATA_FORMAT_TYPE_UTF8
* @discussion A data format denoting that the given input or output format is,
* or should be, encoded in UTF-8 format. Is only valid when used in conjunction
* with other UTF format types.
*/
#define DISPATCH_DATA_FORMAT_TYPE_UTF8 (&_dispatch_data_format_type_utf8)
API_AVAILABLE(macos(10.8), ios(6.0))
DISPATCH_DATA_FORMAT_TYPE_DECL(utf8);
/*!
* @const DISPATCH_DATA_FORMAT_TYPE_UTF16LE
* @discussion A data format denoting that the given input or output format is,
* or should be, encoded in UTF-16LE format. Is only valid when used in
* conjunction with other UTF format types.
*/
#define DISPATCH_DATA_FORMAT_TYPE_UTF16LE (&_dispatch_data_format_type_utf16le)
API_AVAILABLE(macos(10.8), ios(6.0))
DISPATCH_DATA_FORMAT_TYPE_DECL(utf16le);
/*!
* @const DISPATCH_DATA_FORMAT_TYPE_UTF16BE
* @discussion A data format denoting that the given input or output format is,
* or should be, encoded in UTF-16BE format. Is only valid when used in
* conjunction with other UTF format types.
*/
#define DISPATCH_DATA_FORMAT_TYPE_UTF16BE (&_dispatch_data_format_type_utf16be)
API_AVAILABLE(macos(10.8), ios(6.0))
DISPATCH_DATA_FORMAT_TYPE_DECL(utf16be);
/*!
* @const DISPATCH_DATA_FORMAT_TYPE_UTFANY
* @discussion A data format denoting that dispatch_data_create_transform should
* attempt to automatically detect the input type based on the presence of a
* byte order mark character at the beginning of the data. In the absence of a
* BOM, the data will be assumed to be in UTF-8 format. Only valid as an input
* format.
*/
#define DISPATCH_DATA_FORMAT_TYPE_UTF_ANY (&_dispatch_data_format_type_utf_any)
API_AVAILABLE(macos(10.8), ios(6.0))
DISPATCH_DATA_FORMAT_TYPE_DECL(utf_any);
/*!
* @function dispatch_data_create_transform
* Returns a new dispatch data object after transforming the given data object
* from the supplied format, into the given output format.
*
* @param data
* The data object representing the region(s) of memory to transform.
* @param input_type
* Flags specifying the input format of the source dispatch_data_t
*
* @param output_type
* Flags specifying the expected output format of the resulting transformation.
*
* @result
* A newly created dispatch data object, dispatch_data_empty if no has been
* produced, or NULL if an error occurred.
*/
API_AVAILABLE(macos(10.8), ios(6.0))
DISPATCH_EXPORT DISPATCH_NONNULL_ALL DISPATCH_RETURNS_RETAINED
DISPATCH_WARN_RESULT DISPATCH_NOTHROW
dispatch_data_t
dispatch_data_create_with_transform(dispatch_data_t data,
dispatch_data_format_type_t input_type,
dispatch_data_format_type_t output_type);
/*!
* @function dispatch_data_get_flattened_bytes_4libxpc
*
* Similar to dispatch_data_create_map() but attaches it to the passed in
* dispatch data.
*
* The returned mapping, if not NULL, has the size returned by
* dispatch_data_get_size() for the specified object, and its lifetime is tied
* to the one of the dispatch data itself.
*
* @discussion
* This interface is reserved for XPC usage and is not considered stable ABI.
*
*
* @result
* A newly created linear mapping for this data object, may return NULL if
* making the dispatch data contiguous failed to allocate memory.
*/
API_AVAILABLE(macos(10.14), ios(12.0), tvos(12.0), watchos(5.0), bridgeos(4.0))
const void *_Nullable
dispatch_data_get_flattened_bytes_4libxpc(dispatch_data_t data);
__END_DECLS
DISPATCH_ASSUME_NONNULL_END
#endif // __DISPATCH_DATA_PRIVATE__

View File

@@ -0,0 +1,10 @@
module DispatchPrivate [system] [extern_c] {
umbrella header "private.h"
exclude header "mach_private.h"
export *
}
module DispatchIntrospectionPrivate [system] [extern_c] {
header "introspection_private.h"
export *
}

View File

@@ -0,0 +1,871 @@
/*
* Copyright (c) 2012-2013 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_INTROSPECTION_PRIVATE__
#define __DISPATCH_INTROSPECTION_PRIVATE__
/*!
* @header
*
* @abstract
* Introspection SPI for libdispatch.
*
* @discussion
* This SPI is only available in the introspection version of the library,
* loaded by running a process with the environment variable
* DYLD_LIBRARY_PATH=/usr/lib/system/introspection
*
* NOTE: most of these functions are _not_ exported from the shared library,
* the unexported functions are intended to only be called from a debugger
* context while the rest of the process is suspended.
*/
#ifndef __BEGIN_DECLS
#if defined(__cplusplus)
#define __BEGIN_DECLS extern "C" {
#define __END_DECLS }
#else
#define __BEGIN_DECLS
#define __END_DECLS
#endif
#endif
__BEGIN_DECLS
#ifndef __DISPATCH_INDIRECT__
/*
* Typedefs of opaque types, for direct inclusion of header in lldb expressions
*/
typedef __typeof__(sizeof(int)) size_t;
typedef struct _opaque_pthread_t *pthread_t;
typedef void (*dispatch_function_t)(void *);
typedef struct Block_layout *dispatch_block_t;
typedef struct dispatch_continuation_s *dispatch_continuation_t;
typedef struct dispatch_queue_s *dispatch_queue_t;
typedef struct dispatch_source_s *dispatch_source_t;
typedef struct dispatch_group_s *dispatch_group_t;
typedef struct dispatch_object_s *dispatch_object_t;
#ifndef API_AVAILABLE
#define API_AVAILABLE(...)
#endif
#ifndef DISPATCH_EXPORT
#define DISPATCH_EXPORT extern
#endif
#endif // __DISPATCH_INDIRECT__
/*!
* @typedef dispatch_introspection_versions_s
*
* @abstract
* A structure of version and size information of introspection structures.
*
* @field introspection_version
* Version of overall dispatch_introspection SPI.
*
* @field hooks_version
* Version of dispatch_introspection_hooks_s structure.
* Version 2 adds the queue_item_complete member.
*
* @field hooks_size
* Size of dispatch_introspection_hooks_s structure.
*
* @field queue_item_version
* Version of dispatch_introspection_queue_item_s structure.
*
* @field queue_item_size
* Size of dispatch_introspection_queue_item_s structure.
*
* @field queue_block_version
* Version of dispatch_introspection_queue_block_s structure.
*
* @field queue_block_size
* Size of dispatch_introspection_queue_block_s structure.
*
* @field queue_function_version
* Version of dispatch_introspection_queue_function_s structure.
*
* @field queue_function_size
* Size of dispatch_introspection_queue_function_s structure.
*
* @field queue_thread_version
* Version of dispatch_introspection_queue_thread_s structure.
*
* @field queue_thread_size
* Size of dispatch_introspection_queue_thread_s structure.
*
* @field object_version
* Version of dispatch_introspection_object_s structure.
*
* @field object_size
* Size of dispatch_introspection_object_s structure.
*
* @field queue_version
* Version of dispatch_introspection_queue_s structure.
*
* @field queue_size
* Size of dispatch_introspection_queue_s structure.
*
* @field source_version
* Version of dispatch_introspection_source_s structure.
*
* @field source_size
* Size of dispatch_introspection_source_s structure.
*/
API_AVAILABLE(macos(10.9), ios(7.0))
DISPATCH_EXPORT const struct dispatch_introspection_versions_s {
unsigned long introspection_version;
unsigned long hooks_version;
size_t hooks_size;
unsigned long queue_item_version;
size_t queue_item_size;
unsigned long queue_block_version;
size_t queue_block_size;
unsigned long queue_function_version;
size_t queue_function_size;
unsigned long queue_thread_version;
size_t queue_thread_size;
unsigned long object_version;
size_t object_size;
unsigned long queue_version;
size_t queue_size;
unsigned long source_version;
size_t source_size;
} dispatch_introspection_versions;
/*!
* @typedef dispatch_introspection_queue_block_s
*
* @abstract
* A structure of introspection information for a block item enqueued on a
* dispatch queue.
*
* @field continuation
* Pointer to enqueued item.
*
* @field target_queue
* Target queue of item (may be different to the queue the item is currently
* enqueued on).
*
* @field block
* Block for enqueued item.
*
* @field block_invoke
* Function pointer of block for enqueued item.
*
* @field group
* Group containing enqueued item (may be NULL).
*
* @field waiter
* Thread waiting for completion of enqueued item (NULL if sync == 0).
*
* @field barrier
* Item is a barrier on the queue (all items on serial queues are barriers).
*
* @field sync
* Item was enqueued by a dispatch_sync/dispatch_barrier_sync.
*
* @field apply
* Item is part of a dispatch_apply.
*/
typedef struct dispatch_introspection_queue_block_s {
dispatch_continuation_t continuation;
dispatch_queue_t target_queue;
dispatch_block_t block;
dispatch_function_t block_invoke;
dispatch_group_t group;
pthread_t waiter;
unsigned long barrier:1,
sync:1,
apply:1;
} dispatch_introspection_queue_block_s;
typedef dispatch_introspection_queue_block_s
*dispatch_introspection_queue_block_t;
/*!
* @typedef dispatch_introspection_queue_function_s
*
* @abstract
* A structure of introspection information for a function & context pointer
* item enqueued on a dispatch queue.
*
* @field continuation
* Pointer to enqueued item.
*
* @field target_queue
* Target queue of item (may be different to the queue the item is currently
* enqueued on).
*
* @field context
* Context in enqueued item.
*
* @field block_invoke
* Function pointer in enqueued item.
*
* @field group
* Group containing enqueued item (may be NULL).
*
* @field waiter
* Thread waiting for completion of enqueued item (NULL if sync == 0).
*
* @field barrier
* Item is a barrier on the queue (all items on serial queues are barriers).
*
* @field sync
* Item was enqueued by a dispatch_sync_f/dispatch_barrier_sync_f.
*
* @field apply
* Item is part of a dispatch_apply_f.
*/
typedef struct dispatch_introspection_queue_function_s {
dispatch_continuation_t continuation;
dispatch_queue_t target_queue;
void *context;
dispatch_function_t function;
dispatch_group_t group;
pthread_t waiter;
unsigned long barrier:1,
sync:1,
apply:1;
} dispatch_introspection_queue_function_s;
typedef dispatch_introspection_queue_function_s
*dispatch_introspection_queue_function_t;
/*!
* @typedef dispatch_introspection_object_s
*
* @abstract
* A structure of introspection information for a generic dispatch object.
*
* @field object
* Pointer to object.
*
* @field target_queue
* Target queue of object (may be different to the queue the object is
* currently enqueued on).
*
* @field type
* Object class pointer.
*
* @field kind
* String describing the object type.
*/
typedef struct dispatch_introspection_object_s {
dispatch_continuation_t object;
dispatch_queue_t target_queue;
void *type;
const char *kind;
} dispatch_introspection_object_s;
typedef dispatch_introspection_object_s *dispatch_introspection_object_t;
/*!
* @typedef dispatch_introspection_queue_s
*
* @abstract
* A structure of introspection information for a dispatch queue.
*
* @field queue
* Pointer to queue object.
*
* @field target_queue
* Target queue of queue (may be different to the queue the queue is currently
* enqueued on). NULL indicates queue is a root queue.
*
* @field label
* Pointer to queue label.
*
* @field serialnum
* Queue serial number (unique per process).
*
* @field width
* Queue width (1: serial queue, UINT_MAX: concurrent queue).
*
* @field suspend_count
* Number of times the queue has been suspended.
*
* @field enqueued
* Queue is enqueued on another queue.
*
* @field barrier
* Queue is executing a barrier item.
*
* @field draining
* Queue is being drained (cannot get queue items).
*
* @field global
* Queue is a global queue.
*
* @field main
* Queue is the main queue.
*/
typedef struct dispatch_introspection_queue_s {
dispatch_queue_t queue;
dispatch_queue_t target_queue;
const char *label;
unsigned long serialnum;
unsigned int width;
unsigned int suspend_count;
unsigned long enqueued:1,
barrier:1,
draining:1,
global:1,
main:1;
} dispatch_introspection_queue_s;
typedef dispatch_introspection_queue_s *dispatch_introspection_queue_t;
/*!
* @typedef dispatch_introspection_source_s
*
* @abstract
* A structure of introspection information for a dispatch source.
*
* @field source
* Pointer to source object.
*
* @field target_queue
* Target queue of source (may be different to the queue the source is currently
* enqueued on).
*
* @field type
* Source type (kevent filter)
*
* @field handle
* Source handle (monitored entity).
*
* @field context
* Context pointer passed to source handler. Pointer to handler block if
* handler_is_block == 1.
*
* @field handler
* Source handler function. Function pointer of handler block if
* handler_is_block == 1.
*
* @field suspend_count
* Number of times the source has been suspended.
*
* @field enqueued
* Source is enqueued on a queue.
*
* @field handler_is_block
* Source handler is a block.
*
* @field timer
* Source is a timer.
*
* @field after
* Source is a dispatch_after timer.
*/
typedef struct dispatch_introspection_source_s {
dispatch_source_t source;
dispatch_queue_t target_queue;
unsigned long type;
unsigned long handle;
void *context;
dispatch_function_t handler;
unsigned int suspend_count;
unsigned long enqueued:1,
handler_is_block:1,
timer:1,
after:1,
is_xpc:1;
} dispatch_introspection_source_s;
typedef dispatch_introspection_source_s *dispatch_introspection_source_t;
/*!
* @typedef dispatch_introspection_queue_thread_s
*
* @abstract
* A structure of introspection information about a thread executing items for
* a dispatch queue.
*
* @field object
* Pointer to thread object.
*
* @field thread
* Thread executing items for a queue.
*
* @field queue
* Queue introspection information. The queue.queue field is NULL if this thread
* is not currently executing items for a queue.
*/
typedef struct dispatch_introspection_queue_thread_s {
dispatch_continuation_t object;
pthread_t thread;
dispatch_introspection_queue_s queue;
} dispatch_introspection_queue_thread_s;
typedef dispatch_introspection_queue_thread_s
*dispatch_introspection_queue_thread_t;
/*!
* @enum dispatch_introspection_queue_item_type
*
* @abstract
* Types of items enqueued on a dispatch queue.
*/
enum dispatch_introspection_queue_item_type {
dispatch_introspection_queue_item_type_none = 0x0,
dispatch_introspection_queue_item_type_block = 0x11,
dispatch_introspection_queue_item_type_function = 0x12,
dispatch_introspection_queue_item_type_object = 0x100,
dispatch_introspection_queue_item_type_queue = 0x101,
dispatch_introspection_queue_item_type_source = 0x42,
};
/*!
* @typedef dispatch_introspection_queue_item_s
*
* @abstract
* A structure of introspection information about an item enqueued on a
* dispatch queue.
*
* @field type
* Indicates which of the union members applies to this item.
*/
typedef struct dispatch_introspection_queue_item_s {
unsigned long type; // dispatch_introspection_queue_item_type
union {
dispatch_introspection_queue_block_s block;
dispatch_introspection_queue_function_s function;
dispatch_introspection_object_s object;
dispatch_introspection_queue_s queue;
dispatch_introspection_source_s source;
};
} dispatch_introspection_queue_item_s;
typedef dispatch_introspection_queue_item_s
*dispatch_introspection_queue_item_t;
/*!
* @typedef dispatch_introspection_hook_queue_create_t
*
* @abstract
* A function pointer called when a dispatch queue is created.
*
* @param queue_info
* Pointer to queue introspection structure.
*/
typedef void (*dispatch_introspection_hook_queue_create_t)(
dispatch_introspection_queue_t queue_info);
/*!
* @typedef dispatch_introspection_hook_queue_dispose_t
*
* @abstract
* A function pointer called when a dispatch queue is destroyed.
*
* @param queue_info
* Pointer to queue introspection structure.
*/
typedef void (*dispatch_introspection_hook_queue_dispose_t)(
dispatch_introspection_queue_t queue_info);
/*!
* @typedef dispatch_introspection_hook_queue_item_enqueue_t
*
* @abstract
* A function pointer called when an item is enqueued onto a dispatch queue.
*
* @param queue
* Pointer to queue.
*
* @param item
* Pointer to item introspection structure.
*/
typedef void (*dispatch_introspection_hook_queue_item_enqueue_t)(
dispatch_queue_t queue, dispatch_introspection_queue_item_t item);
/*!
* @typedef dispatch_introspection_hook_queue_item_dequeue_t
*
* @abstract
* A function pointer called when an item is dequeued from a dispatch queue.
*
* @param queue
* Pointer to queue.
*
* @param item
* Pointer to item introspection structure.
*/
typedef void (*dispatch_introspection_hook_queue_item_dequeue_t)(
dispatch_queue_t queue, dispatch_introspection_queue_item_t item);
/*!
* @typedef dispatch_introspection_hook_queue_item_complete_t
*
* @abstract
* A function pointer called when an item previously dequeued from a dispatch
* queue has completed processing.
*
* @discussion
* The object pointer value passed to this function pointer must be treated as a
* value only. It is intended solely for matching up with an earlier call to a
* dequeue hook function pointer by comparing to the first member of the
* dispatch_introspection_queue_item_t structure. It must NOT be dereferenced
* or e.g. passed to dispatch_introspection_queue_item_get_info(), the memory
* that was backing it may have been reused at the time this hook is called.
*
* @param object
* Opaque dentifier for completed item. Must NOT be dereferenced.
*/
typedef void (*dispatch_introspection_hook_queue_item_complete_t)(
dispatch_continuation_t object);
/*!
* @enum dispatch_introspection_runtime_event
*
* @abstract
* Types for major events the dispatch runtime goes through as sent by
* the runtime_event hook.
*
* @const dispatch_introspection_runtime_event_worker_event_delivery
* A worker thread was unparked to deliver some kernel events.
* There may be an unpark event if the thread will pick up a queue to drain.
* There always is a worker_park event when the thread is returned to the pool.
* `ptr` is the queue for which events are being delivered, or NULL (for generic
* events).
* `value` is the number of events delivered.
*
* @const dispatch_introspection_runtime_event_worker_unpark
* A worker thread junst unparked (sent from the context of the thread).
* `ptr` is the queue for which the thread unparked.
* `value` is 0.
*
* @const dispatch_introspection_runtime_event_worker_request
* `ptr` is set to the queue on behalf of which the thread request is made.
* `value` is the number of threads requested.
*
* @const dispatch_introspection_runtime_event_worker_park
* A worker thread is about to park (sent from the context of the thread).
* `ptr` and `value` are 0.
*
* @const dispatch_introspection_runtime_event_sync_wait
* A caller of dispatch_sync or dispatch_async_and_wait hit contention.
* `ptr` is the queue that caused the initial contention.
* `value` is 0.
*
* @const dispatch_introspection_runtime_event_async_sync_handoff
* @const dispatch_introspection_runtime_event_sync_sync_handoff
* @const dispatch_introspection_runtime_event_sync_async_handoff
*
* A queue is being handed off from a thread to another due to respectively:
* - async/sync contention
* - sync/sync contention
* - sync/async contention
*
* `ptr` is set to dispatch_queue_t which is handed off to the next thread.
* `value` is 0.
*/
#ifndef __DISPATCH_BUILDING_DISPATCH__
enum dispatch_introspection_runtime_event {
dispatch_introspection_runtime_event_worker_event_delivery = 1,
dispatch_introspection_runtime_event_worker_unpark = 2,
dispatch_introspection_runtime_event_worker_request = 3,
dispatch_introspection_runtime_event_worker_park = 4,
dispatch_introspection_runtime_event_sync_wait = 10,
dispatch_introspection_runtime_event_async_sync_handoff = 11,
dispatch_introspection_runtime_event_sync_sync_handoff = 12,
dispatch_introspection_runtime_event_sync_async_handoff = 13,
};
#endif
/*!
* @typedef dispatch_introspection_hook_runtime_event_t
*
* @abstract
* A function pointer called for various runtime events.
*
* @discussion
* The actual payloads are discussed in the documentation of the
* dispatch_introspection_runtime_event enum.
*/
typedef void (*dispatch_introspection_hook_runtime_event_t)(
enum dispatch_introspection_runtime_event event,
void *ptr, unsigned long long value);
/*!
* @typedef dispatch_introspection_hooks_s
*
* @abstract
* A structure of function pointer hooks into libdispatch.
*/
typedef struct dispatch_introspection_hooks_s {
dispatch_introspection_hook_queue_create_t queue_create;
dispatch_introspection_hook_queue_dispose_t queue_dispose;
dispatch_introspection_hook_queue_item_enqueue_t queue_item_enqueue;
dispatch_introspection_hook_queue_item_dequeue_t queue_item_dequeue;
dispatch_introspection_hook_queue_item_complete_t queue_item_complete;
dispatch_introspection_hook_runtime_event_t runtime_event;
void *_reserved[4];
} dispatch_introspection_hooks_s;
typedef dispatch_introspection_hooks_s *dispatch_introspection_hooks_t;
/*!
* @function dispatch_introspection_get_queues
*
* @abstract
* Retrieve introspection information about all dispatch queues in the process,
* in batches of specified size.
*
* @discussion
* Retrieving queue information and iterating through the list of all queues
* must take place from a debugger context (while the rest of the process is
* suspended).
*
* @param start
* Starting point for this batch of queue information, as returned by a previous
* call to _dispatch_introspection_get_queues().
* Pass NULL to retrieve the initial batch.
*
* @param count
* Number of queues to introspect.
*
* @param queues
* Array to fill with queue information. If less than 'count' queues are left
* in this batch, the end of valid entries in the array will be indicated
* by an entry with NULL queue member.
*
* @result
* Queue to pass to another call to _dispatch_introspection_get_queues() to
* retrieve information about the next batch of queues. May be NULL if there
* are no more queues to iterate over.
*/
extern dispatch_queue_t
dispatch_introspection_get_queues(dispatch_queue_t start, size_t count,
dispatch_introspection_queue_t queues);
/*!
* @function dispatch_introspection_get_queue_threads
*
* @abstract
* Retrieve introspection information about all threads in the process executing
* items for dispatch queues, in batches of specified size.
*
* @discussion
* Retrieving thread information and iterating through the list of all queue
* threads must take place from a debugger context (while the rest of the
* process is suspended).
*
* @param start
* Starting point for this batch of thread information, as returned by a
* previous call to _dispatch_introspection_get_queue_threads().
* Pass NULL to retrieve the initial batch.
*
* @param count
* Number of queue threads to introspect.
*
* @param threads
* Array to fill with queue thread information. If less than 'count' threads are
* left in this batch, the end of valid entries in the array will be indicated
* by an entry with NULL object member.
*
* @result
* Object to pass to another call to _dispatch_introspection_get_queues() to
* retrieve information about the next batch of queues. May be NULL if there
* are no more queues to iterate over.
*/
extern dispatch_continuation_t
dispatch_introspection_get_queue_threads(dispatch_continuation_t start,
size_t count, dispatch_introspection_queue_thread_t threads);
/*!
* @function dispatch_introspection_queue_get_items
*
* @abstract
* Retrieve introspection information about all items enqueued on a queue, in
* batches of specified size.
*
* @discussion
* Retrieving queue item information and iterating through a queue must take
* place from a debugger context (while the rest of the process is suspended).
*
* @param queue
* Queue to introspect.
*
* @param start
* Starting point for this batch of queue item information, as returned by a
* previous call to _dispatch_introspection_queue_get_items().
* Pass NULL to retrieve the initial batch.
*
* @param count
* Number of items to introspect.
*
* @param items
* Array to fill with queue item information. If less than 'count' queues are
* left in this batch, the end of valid entries in the array will be indicated
* by an entry with type dispatch_introspection_queue_item_type_none.
*
* @result
* Item to pass to another call to _dispatch_introspection_queue_get_items() to
* retrieve information about the next batch of queue items. May be NULL if
* there are no more items to iterate over.
*/
extern dispatch_continuation_t
dispatch_introspection_queue_get_items(dispatch_queue_t queue,
dispatch_continuation_t start, size_t count,
dispatch_introspection_queue_item_t items);
/*!
* @function dispatch_introspection_queue_get_info
*
* @abstract
* Retrieve introspection information about a specified dispatch queue.
*
* @discussion
* Retrieving queue information must take place from a debugger context (while
* the rest of the process is suspended).
*
* @param queue
* Queue to introspect.
*
* @result
* Queue information struct.
*/
extern dispatch_introspection_queue_s
dispatch_introspection_queue_get_info(dispatch_queue_t queue);
/*!
* @function dispatch_introspection_queue_item_get_info
*
* @abstract
* Retrieve introspection information about a specified dispatch queue item.
*
* @discussion
* Retrieving queue item information must take place from a debugger context
* (while the rest of the process is suspended).
*
* @param queue
* Queue to introspect.
*
* @param item
* Item to introspect.
*
* @result
* Queue item information struct.
*/
extern dispatch_introspection_queue_item_s
dispatch_introspection_queue_item_get_info(dispatch_queue_t queue,
dispatch_continuation_t item);
/*!
* @function dispatch_introspection_hooks_install
*
* @abstract
* Install hook functions into libdispatch.
*
* @discussion
* Installing hook functions must take place from a debugger context (while the
* rest of the process is suspended) or early enough in the process lifecycle
* that the process is still single-threaded.
*
* The caller is responsible for implementing chaining to the hooks that were
* previously installed (if any).
*
* @param hooks
* Pointer to structure of hook function pointers. Any of the structure members
* may be NULL to indicate that the hook in question should not be installed.
* The structure is copied on input and filled with the previously installed
* hooks on output.
*/
API_AVAILABLE(macos(10.9), ios(7.0))
DISPATCH_EXPORT void
dispatch_introspection_hooks_install(dispatch_introspection_hooks_t hooks);
/*!
* @function dispatch_introspection_hook_callouts_enable
*
* @abstract
* Enable hook callout functions in libdispatch that a debugger can break on
* and get introspection arguments even if there are no hook functions
* installed via dispatch_introspection_hooks_install().
*
* @discussion
* Enabling hook callout functions must take place from a debugger context
* (while the rest of the process is suspended).
*
* @param enable
* Pointer to dispatch_introspection_hooks_s structure. For every structure
* member with (any) non-NULL value, the corresponding hook callout will be
* enabled; for every NULL member the hook callout will be disabled (if there
* is no hook function installed).
* As a convenience, the 'enable' pointer may itself be NULL to indicate that
* all hook callouts should be enabled.
*/
extern void
dispatch_introspection_hook_callouts_enable(
dispatch_introspection_hooks_t enable);
/*!
* @function dispatch_introspection_hook_callout_queue_create
*
* @abstract
* Callout to queue creation hook that a debugger can break on.
*/
extern void
dispatch_introspection_hook_callout_queue_create(
dispatch_introspection_queue_t queue_info);
/*!
* @function dispatch_introspection_hook_callout_queue_dispose
*
* @abstract
* Callout to queue destruction hook that a debugger can break on.
*/
extern void
dispatch_introspection_hook_callout_queue_dispose(
dispatch_introspection_queue_t queue_info);
/*!
* @function dispatch_introspection_hook_callout_queue_item_enqueue
*
* @abstract
* Callout to queue enqueue hook that a debugger can break on.
*/
extern void
dispatch_introspection_hook_callout_queue_item_enqueue(
dispatch_queue_t queue, dispatch_introspection_queue_item_t item);
/*!
* @function dispatch_introspection_hook_callout_queue_item_dequeue
*
* @abstract
* Callout to queue dequeue hook that a debugger can break on.
*/
extern void
dispatch_introspection_hook_callout_queue_item_dequeue(
dispatch_queue_t queue, dispatch_introspection_queue_item_t item);
/*!
* @function dispatch_introspection_hook_callout_queue_item_complete
*
* @abstract
* Callout to queue item complete hook that a debugger can break on.
*/
extern void
dispatch_introspection_hook_callout_queue_item_complete(
dispatch_continuation_t object);
__END_DECLS
#endif

View File

@@ -0,0 +1,416 @@
/*
* Copyright (c) 2009-2013 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_IO_PRIVATE__
#define __DISPATCH_IO_PRIVATE__
#ifndef __DISPATCH_INDIRECT__
#error "Please #include <dispatch/dispatch.h> instead of this file directly."
#include <dispatch/base.h> // for HeaderDoc
#endif
DISPATCH_ASSUME_NONNULL_BEGIN
__BEGIN_DECLS
/*!
* @function dispatch_read_f
* Schedule a read operation for asynchronous execution on the specified file
* descriptor. The specified handler is enqueued with the data read from the
* file descriptor when the operation has completed or an error occurs.
*
* The data object passed to the handler will be automatically released by the
* system when the handler returns. It is the responsibility of the application
* to retain, concatenate or copy the data object if it is needed after the
* handler returns.
*
* The data object passed to the handler will only contain as much data as is
* currently available from the file descriptor (up to the specified length).
*
* If an unrecoverable error occurs on the file descriptor, the handler will be
* enqueued with the appropriate error code along with a data object of any data
* that could be read successfully.
*
* An invocation of the handler with an error code of zero and an empty data
* object indicates that EOF was reached.
*
* The system takes control of the file descriptor until the handler is
* enqueued, and during this time file descriptor flags such as O_NONBLOCK will
* be modified by the system on behalf of the application. It is an error for
* the application to modify a file descriptor directly while it is under the
* control of the system, but it may create additional dispatch I/O convenience
* operations or dispatch I/O channels associated with that file descriptor.
*
* @param fd The file descriptor from which to read the data.
* @param length The length of data to read from the file descriptor,
* or SIZE_MAX to indicate that all of the data currently
* available from the file descriptor should be read.
* @param queue The dispatch queue to which the handler should be
* submitted.
* @param context The application-defined context parameter to pass to
* the handler function.
* @param handler The handler to enqueue when data is ready to be
* delivered.
* param context Application-defined context parameter.
* param data The data read from the file descriptor.
* param error An errno condition for the read operation or
* zero if the read was successful.
*/
API_AVAILABLE(macos(10.9), ios(7.0))
DISPATCH_EXPORT DISPATCH_NONNULL3 DISPATCH_NONNULL5 DISPATCH_NOTHROW
void
dispatch_read_f(dispatch_fd_t fd,
size_t length,
dispatch_queue_t queue,
void *_Nullable context,
void (*handler)(void *_Nullable context, dispatch_data_t data, int error));
/*!
* @function dispatch_write_f
* Schedule a write operation for asynchronous execution on the specified file
* descriptor. The specified handler is enqueued when the operation has
* completed or an error occurs.
*
* If an unrecoverable error occurs on the file descriptor, the handler will be
* enqueued with the appropriate error code along with the data that could not
* be successfully written.
*
* An invocation of the handler with an error code of zero indicates that the
* data was fully written to the channel.
*
* The system takes control of the file descriptor until the handler is
* enqueued, and during this time file descriptor flags such as O_NONBLOCK will
* be modified by the system on behalf of the application. It is an error for
* the application to modify a file descriptor directly while it is under the
* control of the system, but it may create additional dispatch I/O convenience
* operations or dispatch I/O channels associated with that file descriptor.
*
* @param fd The file descriptor to which to write the data.
* @param data The data object to write to the file descriptor.
* @param queue The dispatch queue to which the handler should be
* submitted.
* @param context The application-defined context parameter to pass to
* the handler function.
* @param handler The handler to enqueue when the data has been written.
* param context Application-defined context parameter.
* param data The data that could not be written to the I/O
* channel, or NULL.
* param error An errno condition for the write operation or
* zero if the write was successful.
*/
API_AVAILABLE(macos(10.9), ios(7.0))
DISPATCH_EXPORT DISPATCH_NONNULL2 DISPATCH_NONNULL3 DISPATCH_NONNULL5
DISPATCH_NOTHROW
void
dispatch_write_f(dispatch_fd_t fd,
dispatch_data_t data,
dispatch_queue_t queue,
void *_Nullable context,
void (*handler)(void *_Nullable context, dispatch_data_t _Nullable data,
int error));
/*!
* @function dispatch_io_create_f
* Create a dispatch I/O channel associated with a file descriptor. The system
* takes control of the file descriptor until the channel is closed, an error
* occurs on the file descriptor or all references to the channel are released.
* At that time the specified cleanup handler will be enqueued and control over
* the file descriptor relinquished.
*
* While a file descriptor is under the control of a dispatch I/O channel, file
* descriptor flags such as O_NONBLOCK will be modified by the system on behalf
* of the application. It is an error for the application to modify a file
* descriptor directly while it is under the control of a dispatch I/O channel,
* but it may create additional channels associated with that file descriptor.
*
* @param type The desired type of I/O channel (DISPATCH_IO_STREAM
* or DISPATCH_IO_RANDOM).
* @param fd The file descriptor to associate with the I/O channel.
* @param queue The dispatch queue to which the handler should be submitted.
* @param context The application-defined context parameter to pass to
* the cleanup handler function.
* @param cleanup_handler The handler to enqueue when the system
* relinquishes control over the file descriptor.
* param context Application-defined context parameter.
* param error An errno condition if control is relinquished
* because channel creation failed, zero otherwise.
* @result The newly created dispatch I/O channel or NULL if an error
* occurred (invalid type specified).
*/
API_AVAILABLE(macos(10.9), ios(7.0))
DISPATCH_EXPORT DISPATCH_MALLOC DISPATCH_RETURNS_RETAINED DISPATCH_WARN_RESULT
DISPATCH_NOTHROW
dispatch_io_t
dispatch_io_create_f(dispatch_io_type_t type,
dispatch_fd_t fd,
dispatch_queue_t queue,
void *_Nullable context,
void (*cleanup_handler)(void *_Nullable context, int error));
/*!
* @function dispatch_io_create_with_path_f
* Create a dispatch I/O channel associated with a path name. The specified
* path, oflag and mode parameters will be passed to open(2) when the first I/O
* operation on the channel is ready to execute and the resulting file
* descriptor will remain open and under the control of the system until the
* channel is closed, an error occurs on the file descriptor or all references
* to the channel are released. At that time the file descriptor will be closed
* and the specified cleanup handler will be enqueued.
*
* @param type The desired type of I/O channel (DISPATCH_IO_STREAM
* or DISPATCH_IO_RANDOM).
* @param path The absolute path to associate with the I/O channel.
* @param oflag The flags to pass to open(2) when opening the file at
* path.
* @param mode The mode to pass to open(2) when creating the file at
* path (i.e. with flag O_CREAT), zero otherwise.
* @param queue The dispatch queue to which the handler should be
* submitted.
* @param context The application-defined context parameter to pass to
* the cleanup handler function.
* @param cleanup_handler The handler to enqueue when the system
* has closed the file at path.
* param context Application-defined context parameter.
* param error An errno condition if control is relinquished
* because channel creation or opening of the
* specified file failed, zero otherwise.
* @result The newly created dispatch I/O channel or NULL if an error
* occurred (invalid type or non-absolute path specified).
*/
API_AVAILABLE(macos(10.9), ios(7.0))
DISPATCH_EXPORT DISPATCH_NONNULL2 DISPATCH_MALLOC DISPATCH_RETURNS_RETAINED
DISPATCH_WARN_RESULT DISPATCH_NOTHROW
dispatch_io_t
dispatch_io_create_with_path_f(dispatch_io_type_t type,
const char *path, int oflag, mode_t mode,
dispatch_queue_t queue,
void *_Nullable context,
void (*cleanup_handler)(void *_Nullable context, int error));
/*!
* @function dispatch_io_create_with_io_f
* Create a new dispatch I/O channel from an existing dispatch I/O channel.
* The new channel inherits the file descriptor or path name associated with
* the existing channel, but not its channel type or policies.
*
* If the existing channel is associated with a file descriptor, control by the
* system over that file descriptor is extended until the new channel is also
* closed, an error occurs on the file descriptor, or all references to both
* channels are released. At that time the specified cleanup handler will be
* enqueued and control over the file descriptor relinquished.
*
* While a file descriptor is under the control of a dispatch I/O channel, file
* descriptor flags such as O_NONBLOCK will be modified by the system on behalf
* of the application. It is an error for the application to modify a file
* descriptor directly while it is under the control of a dispatch I/O channel,
* but it may create additional channels associated with that file descriptor.
*
* @param type The desired type of I/O channel (DISPATCH_IO_STREAM
* or DISPATCH_IO_RANDOM).
* @param io The existing channel to create the new I/O channel from.
* @param queue The dispatch queue to which the handler should be submitted.
* @param context The application-defined context parameter to pass to
* the cleanup handler function.
* @param cleanup_handler The handler to enqueue when the system
* relinquishes control over the file descriptor
* (resp. closes the file at path) associated with
* the existing channel.
* param context Application-defined context parameter.
* param error An errno condition if control is relinquished
* because channel creation failed, zero otherwise.
* @result The newly created dispatch I/O channel or NULL if an error
* occurred (invalid type specified).
*/
API_AVAILABLE(macos(10.9), ios(7.0))
DISPATCH_EXPORT DISPATCH_NONNULL2 DISPATCH_MALLOC DISPATCH_RETURNS_RETAINED
DISPATCH_WARN_RESULT DISPATCH_NOTHROW
dispatch_io_t
dispatch_io_create_with_io_f(dispatch_io_type_t type,
dispatch_io_t io,
dispatch_queue_t queue,
void *_Nullable context,
void (*cleanup_handler)(void *_Nullable context, int error));
/*!
* @typedef dispatch_io_handler_function_t
* The prototype of I/O handler functions for dispatch I/O operations.
*
* @param context Application-defined context parameter.
* @param done A flag indicating whether the operation is complete.
* @param data The data object to be handled.
* @param error An errno condition for the operation.
*/
typedef void (*dispatch_io_handler_function_t)(void *_Nullable context,
bool done, dispatch_data_t _Nullable data, int error);
/*!
* @function dispatch_io_read_f
* Schedule a read operation for asynchronous execution on the specified I/O
* channel. The I/O handler is enqueued one or more times depending on the
* general load of the system and the policy specified on the I/O channel.
*
* Any data read from the channel is described by the dispatch data object
* passed to the I/O handler. This object will be automatically released by the
* system when the I/O handler returns. It is the responsibility of the
* application to retain, concatenate or copy the data object if it is needed
* after the I/O handler returns.
*
* Dispatch I/O handlers are not reentrant. The system will ensure that no new
* I/O handler instance is invoked until the previously enqueued handler
* function has returned.
*
* An invocation of the I/O handler with the done flag set indicates that the
* read operation is complete and that the handler will not be enqueued again.
*
* If an unrecoverable error occurs on the I/O channel's underlying file
* descriptor, the I/O handler will be enqueued with the done flag set, the
* appropriate error code and a NULL data object.
*
* An invocation of the I/O handler with the done flag set, an error code of
* zero and an empty data object indicates that EOF was reached.
*
* @param channel The dispatch I/O channel from which to read the data.
* @param offset The offset relative to the channel position from which
* to start reading (only for DISPATCH_IO_RANDOM).
* @param length The length of data to read from the I/O channel, or
* SIZE_MAX to indicate that data should be read until EOF
* is reached.
* @param queue The dispatch queue to which the I/O handler should be
* submitted.
* @param context The application-defined context parameter to pass to
* the handler function.
* @param io_handler The I/O handler to enqueue when data is ready to be
* delivered.
* param context Application-defined context parameter.
* param done A flag indicating whether the operation is complete.
* param data An object with the data most recently read from the
* I/O channel as part of this read operation, or NULL.
* param error An errno condition for the read operation or zero if
* the read was successful.
*/
API_AVAILABLE(macos(10.9), ios(7.0))
DISPATCH_EXPORT DISPATCH_NONNULL1 DISPATCH_NONNULL4 DISPATCH_NONNULL6
DISPATCH_NOTHROW
void
dispatch_io_read_f(dispatch_io_t channel,
off_t offset,
size_t length,
dispatch_queue_t queue,
void *_Nullable context,
dispatch_io_handler_function_t io_handler);
/*!
* @function dispatch_io_write_f
* Schedule a write operation for asynchronous execution on the specified I/O
* channel. The I/O handler is enqueued one or more times depending on the
* general load of the system and the policy specified on the I/O channel.
*
* Any data remaining to be written to the I/O channel is described by the
* dispatch data object passed to the I/O handler. This object will be
* automatically released by the system when the I/O handler returns. It is the
* responsibility of the application to retain, concatenate or copy the data
* object if it is needed after the I/O handler returns.
*
* Dispatch I/O handlers are not reentrant. The system will ensure that no new
* I/O handler instance is invoked until the previously enqueued handler
* function has returned.
*
* An invocation of the I/O handler with the done flag set indicates that the
* write operation is complete and that the handler will not be enqueued again.
*
* If an unrecoverable error occurs on the I/O channel's underlying file
* descriptor, the I/O handler will be enqueued with the done flag set, the
* appropriate error code and an object containing the data that could not be
* written.
*
* An invocation of the I/O handler with the done flag set and an error code of
* zero indicates that the data was fully written to the channel.
*
* @param channel The dispatch I/O channel on which to write the data.
* @param offset The offset relative to the channel position from which
* to start writing (only for DISPATCH_IO_RANDOM).
* @param data The data to write to the I/O channel. The data object
* will be retained by the system until the write operation
* is complete.
* @param queue The dispatch queue to which the I/O handler should be
* submitted.
* @param context The application-defined context parameter to pass to
* the handler function.
* @param io_handler The I/O handler to enqueue when data has been delivered.
* param context Application-defined context parameter.
* param done A flag indicating whether the operation is complete.
* param data An object of the data remaining to be
* written to the I/O channel as part of this write
* operation, or NULL.
* param error An errno condition for the write operation or zero
* if the write was successful.
*/
API_AVAILABLE(macos(10.9), ios(7.0))
DISPATCH_EXPORT DISPATCH_NONNULL1 DISPATCH_NONNULL3 DISPATCH_NONNULL4
DISPATCH_NONNULL6 DISPATCH_NOTHROW
void
dispatch_io_write_f(dispatch_io_t channel,
off_t offset,
dispatch_data_t data,
dispatch_queue_t queue,
void *_Nullable context,
dispatch_io_handler_function_t io_handler);
/*!
* @function dispatch_io_barrier_f
* Schedule a barrier operation on the specified I/O channel; all previously
* scheduled operations on the channel will complete before the provided
* barrier function is enqueued onto the global queue determined by the
* channel's target queue, and no subsequently scheduled operations will start
* until the barrier function has returned.
*
* If multiple channels are associated with the same file descriptor, a barrier
* operation scheduled on any of these channels will act as a barrier across all
* channels in question, i.e. all previously scheduled operations on any of the
* channels will complete before the barrier function is enqueued, and no
* operations subsequently scheduled on any of the channels will start until the
* barrier function has returned.
*
* While the barrier function is running, it may safely operate on the channel's
* underlying file descriptor with fsync(2), lseek(2) etc. (but not close(2)).
*
* @param channel The dispatch I/O channel to schedule the barrier on.
* @param context The application-defined context parameter to pass to
* the barrier function.
* @param barrier The barrier function.
*/
API_AVAILABLE(macos(10.9), ios(7.0))
DISPATCH_EXPORT DISPATCH_NONNULL1 DISPATCH_NONNULL3 DISPATCH_NOTHROW
void
dispatch_io_barrier_f(dispatch_io_t channel,
void *_Nullable context,
dispatch_function_t barrier);
__END_DECLS
DISPATCH_ASSUME_NONNULL_END
#endif /* __DISPATCH_IO_PRIVATE__ */

View File

@@ -0,0 +1,101 @@
/*
* Copyright (c) 2014 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_LAYOUT_PRIVATE__
#define __DISPATCH_LAYOUT_PRIVATE__
#ifndef __DISPATCH_INDIRECT__
#error "Please #include <dispatch/private.h> instead of this file directly."
#include <dispatch/base.h> // for HeaderDoc
#endif
__BEGIN_DECLS
API_AVAILABLE(macos(10.6), ios(4.0))
DISPATCH_EXPORT 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;
// fields added in dqo_version 5:
const uint16_t dqo_suspend_cnt;
const uint16_t dqo_suspend_cnt_size;
const uint16_t dqo_target_queue;
const uint16_t dqo_target_queue_size;
const uint16_t dqo_priority;
const uint16_t dqo_priority_size;
} dispatch_queue_offsets;
#if DISPATCH_LAYOUT_SPI
/*!
* @group Data Structure Layout SPI
* SPI intended for CoreSymbolication only
*/
API_AVAILABLE(macos(10.10), ios(8.0))
DISPATCH_EXPORT const struct dispatch_tsd_indexes_s {
// always add new fields at the end
const uint16_t dti_version;
const uint16_t dti_queue_index;
const uint16_t dti_voucher_index;
const uint16_t dti_qos_class_index;
/* version 3 */
const uint16_t dti_continuation_cache_index;
} dispatch_tsd_indexes;
#if TARGET_OS_MAC
#include <malloc/malloc.h>
API_AVAILABLE(macos(10.14), ios(12.0), tvos(12.0), watchos(5.0))
DISPATCH_EXPORT const struct dispatch_allocator_layout_s {
const uint16_t dal_version;
/* version 1 */
/* Pointer to the allocator metadata address, points to NULL if unused */
void **const dal_allocator_zone;
/* Magical "isa" for allocations that are on freelists */
void *const *const dal_deferred_free_isa;
/* Size of allocations made in the magazine */
const uint16_t dal_allocation_size;
/* fields used by the enumerator */
const uint16_t dal_magazine_size;
const uint16_t dal_first_allocation_offset;
const uint16_t dal_allocation_isa_offset;
/* Enumerates allocated continuations */
kern_return_t (*dal_enumerator)(task_t remote_task,
const struct dispatch_allocator_layout_s *remote_allocator_layout,
vm_address_t zone_address, memory_reader_t reader,
void (^recorder)(vm_address_t dc_address, void *dc_mem,
size_t size, bool *stop));
} dispatch_allocator_layout;
#endif // TARGET_OS_MAC
#endif // DISPATCH_LAYOUT_SPI
__END_DECLS
#endif // __DISPATCH_LAYOUT_PRIVATE__

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,269 @@
/*
* Copyright (c) 2008-2013 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__
#ifdef __APPLE__
#include <Availability.h>
#include <os/availability.h>
#include <TargetConditionals.h>
#include <os/base.h>
#elif defined(_WIN32)
#include <os/generic_win_base.h>
#elif defined(__unix__)
#include <os/generic_unix_base.h>
#endif
#if TARGET_OS_MAC
#include <mach/boolean.h>
#include <mach/mach.h>
#include <mach/message.h>
#endif
#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__))
#include <unistd.h>
#endif
#if !defined(_WIN32)
#include <pthread.h>
#endif
#if TARGET_OS_MAC
#include <pthread/qos.h>
#endif
#ifndef __DISPATCH_BUILDING_DISPATCH__
#include <dispatch/dispatch.h>
#ifndef __DISPATCH_INDIRECT__
#define __DISPATCH_INDIRECT__
#endif
#include <dispatch/benchmark.h>
#include <dispatch/queue_private.h>
#include <dispatch/workloop_private.h>
#include <dispatch/source_private.h>
#if DISPATCH_MACH_SPI
#include <dispatch/mach_private.h>
#endif // DISPATCH_MACH_SPI
#include <dispatch/data_private.h>
#include <dispatch/io_private.h>
#include <dispatch/layout_private.h>
#include <dispatch/time_private.h>
#undef __DISPATCH_INDIRECT__
#endif /* !__DISPATCH_BUILDING_DISPATCH__ */
// <rdar://problem/9627726> Check that public and private dispatch headers match
#if DISPATCH_API_VERSION != 20180109 // Keep in sync with <dispatch/dispatch.h>
#error "Dispatch header mismatch between /usr/include and /usr/local/include"
#endif
DISPATCH_ASSUME_NONNULL_BEGIN
__BEGIN_DECLS
/*!
* @function _dispatch_is_multithreaded
*
* @abstract
* Returns true if the current process has become multithreaded by the use
* of libdispatch functionality.
*
* @discussion
* This SPI is intended for use by low-level system components that need to
* ensure that they do not make a single-threaded process multithreaded, to
* avoid negatively affecting child processes of a fork (without exec).
*
* Such components must not use any libdispatch functionality if this function
* returns false.
*
* @result
* Boolean indicating whether the process has used libdispatch and become
* multithreaded.
*/
API_AVAILABLE(macos(10.8), ios(6.0))
DISPATCH_EXPORT DISPATCH_NOTHROW
bool _dispatch_is_multithreaded(void);
/*!
* @function _dispatch_is_fork_of_multithreaded_parent
*
* @abstract
* Returns true if the current process is a child of a parent process that had
* become multithreaded by the use of libdispatch functionality at the time of
* fork (without exec).
*
* @discussion
* This SPI is intended for use by (rare) low-level system components that need
* to continue working on the child side of a fork (without exec) of a
* multithreaded process.
*
* Such components must not use any libdispatch functionality if this function
* returns true.
*
* @result
* Boolean indicating whether the parent process had used libdispatch and
* become multithreaded at the time of fork.
*/
API_AVAILABLE(macos(10.9), ios(7.0))
DISPATCH_EXPORT DISPATCH_NOTHROW
bool _dispatch_is_fork_of_multithreaded_parent(void);
/*!
* @function _dispatch_prohibit_transition_to_multithreaded
*
* @abstract
* Sets a mode that aborts if a program tries to use dispatch.
*
* @discussion
* This SPI is intended for use by programs that know they will use fork() and
* want their children to be able to use dispatch before exec(). Such programs
* should call _dispatch_prohibit_transition_to_multithreaded(true) as early as
* possible, which will cause any use of dispatch API that would make the
* process multithreaded to abort immediately.
*
* Once the program no longer intends to call fork() it can call
* _dispatch_prohibit_transition_to_multithreaded(false).
*
* This status is not inherited by the child process, so if the behavior
* is required after fork, _dispatch_prohibit_transition_to_multithreaded(true)
* should be called manually in the child after fork.
*
* If the program already used dispatch before the guard is enabled, then
* this function will abort immediately.
*/
API_AVAILABLE(macos(10.12), ios(10.0), tvos(10.0), watchos(3.0))
DISPATCH_EXPORT DISPATCH_NOTHROW
void _dispatch_prohibit_transition_to_multithreaded(bool prohibit);
/*
* dispatch_time convenience macros
*/
#define _dispatch_time_after_nsec(t) \
dispatch_time(DISPATCH_TIME_NOW, (t))
#define _dispatch_time_after_usec(t) \
dispatch_time(DISPATCH_TIME_NOW, (t) * NSEC_PER_USEC)
#define _dispatch_time_after_msec(t) \
dispatch_time(DISPATCH_TIME_NOW, (t) * NSEC_PER_MSEC)
#define _dispatch_time_after_sec(t) \
dispatch_time(DISPATCH_TIME_NOW, (t) * NSEC_PER_SEC)
/*
* SPI for CoreFoundation/Foundation ONLY
*/
#if TARGET_OS_MAC
#define DISPATCH_COCOA_COMPAT 1
#elif defined(__linux__) || defined(__FreeBSD__) || defined(_WIN32)
#define DISPATCH_COCOA_COMPAT 1
#else
#define DISPATCH_COCOA_COMPAT 0
#endif
#if DISPATCH_COCOA_COMPAT
#define DISPATCH_CF_SPI_VERSION 20160712
#if TARGET_OS_MAC
typedef mach_port_t dispatch_runloop_handle_t;
#elif defined(__linux__) || defined(__FreeBSD__)
typedef int dispatch_runloop_handle_t;
#elif defined(_WIN32)
typedef void *dispatch_runloop_handle_t;
#else
#error "runloop support not implemented on this platform"
#endif
API_AVAILABLE(macos(10.6), ios(4.0))
DISPATCH_EXPORT DISPATCH_CONST DISPATCH_WARN_RESULT DISPATCH_NOTHROW
dispatch_runloop_handle_t
_dispatch_get_main_queue_port_4CF(void);
API_AVAILABLE(macos(10.12), ios(10.0), tvos(10.0), watchos(3.0))
DISPATCH_EXPORT DISPATCH_NOTHROW
dispatch_runloop_handle_t
_dispatch_get_main_queue_handle_4CF(void);
API_AVAILABLE(macos(10.6), ios(4.0))
DISPATCH_EXPORT DISPATCH_NOTHROW
void
_dispatch_main_queue_callback_4CF(void *_Null_unspecified msg);
API_AVAILABLE(macos(10.9), ios(7.0))
DISPATCH_EXPORT DISPATCH_MALLOC DISPATCH_RETURNS_RETAINED DISPATCH_WARN_RESULT
DISPATCH_NOTHROW
dispatch_queue_serial_t
_dispatch_runloop_root_queue_create_4CF(const char *_Nullable label,
unsigned long flags);
API_AVAILABLE(macos(10.9), ios(7.0))
DISPATCH_EXPORT DISPATCH_WARN_RESULT DISPATCH_NOTHROW
dispatch_runloop_handle_t
_dispatch_runloop_root_queue_get_port_4CF(dispatch_queue_t queue);
#if TARGET_OS_MAC
API_AVAILABLE(macos(10.13.2), ios(11.2), tvos(11.2), watchos(4.2))
DISPATCH_EXPORT DISPATCH_WARN_RESULT DISPATCH_NOTHROW
bool
_dispatch_source_will_reenable_kevent_4NW(dispatch_source_t source);
#endif
API_AVAILABLE(macos(10.9), ios(7.0))
DISPATCH_EXPORT DISPATCH_NOTHROW
void
_dispatch_runloop_root_queue_wakeup_4CF(dispatch_queue_t queue);
API_AVAILABLE(macos(10.9), ios(7.0))
DISPATCH_EXPORT DISPATCH_WARN_RESULT DISPATCH_NOTHROW
bool
_dispatch_runloop_root_queue_perform_4CF(dispatch_queue_t queue);
API_AVAILABLE(macos(10.9), ios(7.0))
DISPATCH_EXPORT DISPATCH_NONNULL_ALL DISPATCH_NOTHROW
void
_dispatch_source_set_runloop_timer_4CF(dispatch_source_t source,
dispatch_time_t start, uint64_t interval, uint64_t leeway);
API_AVAILABLE(macos(10.6), ios(4.0))
DISPATCH_EXPORT
void *_Nonnull (*_Nullable _dispatch_begin_NSAutoReleasePool)(void);
API_AVAILABLE(macos(10.6), ios(4.0))
DISPATCH_EXPORT
void (*_Nullable _dispatch_end_NSAutoReleasePool)(void *);
#endif /* DISPATCH_COCOA_COMPAT */
API_AVAILABLE(macos(10.13), ios(11.0), tvos(11.0), watchos(4.0))
DISPATCH_EXPORT DISPATCH_NOTHROW
void
_dispatch_poll_for_events_4launchd(void);
__END_DECLS
DISPATCH_ASSUME_NONNULL_END
#endif // __DISPATCH_PRIVATE__

View File

@@ -0,0 +1,503 @@
/*
* Copyright (c) 2008-2013 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/private.h> instead of this file directly."
#include <dispatch/base.h> // for HeaderDoc
#endif
DISPATCH_ASSUME_NONNULL_BEGIN
__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,
};
/*!
* @function dispatch_set_qos_class
*
* @abstract
* Sets the QOS class on a dispatch queue, source or mach channel.
*
* @discussion
* This is equivalent to using dispatch_queue_make_attr_with_qos_class()
* when creating a dispatch queue, but is availabile on additional dispatch
* object types.
*
* When configured in this manner, the specified QOS class will be used over
* the assigned QOS of workitems submitted asynchronously to this object,
* unless the workitem has been created with ENFORCE semantics
* (see DISPATCH_BLOCK_ENFORCE_QOS_CLASS).
*
* Calling this function will supersede any prior calls to
* dispatch_set_qos_class() or dispatch_set_qos_class_floor().
*
* @param object
* A dispatch queue, source or mach channel to configure.
* The object must be inactive, and can't be a workloop.
*
* Passing another object type or an object that has been activated is undefined
* and will cause the process to be terminated.
*
* @param qos_class
* A QOS class value:
* - QOS_CLASS_USER_INTERACTIVE
* - QOS_CLASS_USER_INITIATED
* - QOS_CLASS_DEFAULT
* - QOS_CLASS_UTILITY
* - QOS_CLASS_BACKGROUND
* Passing any other value is undefined.
*
* @param relative_priority
* A relative priority within the QOS class. This value is a negative
* offset from the maximum supported scheduler priority for the given class.
* Passing a value greater than zero or less than QOS_MIN_RELATIVE_PRIORITY
* is undefined.
*/
API_AVAILABLE(macos(10.14), ios(12.0), tvos(12.0), watchos(5.0))
DISPATCH_EXPORT DISPATCH_NOTHROW
void
dispatch_set_qos_class(dispatch_object_t object,
dispatch_qos_class_t qos_class, int relative_priority);
/*!
* @function dispatch_set_qos_class_floor
*
* @abstract
* Sets the QOS class floor on a dispatch queue, source, workloop or mach
* channel.
*
* @discussion
* The QOS class of workitems submitted to this object asynchronously will be
* elevated to at least the specified QOS class floor.
* Unlike dispatch_set_qos_class(), the QOS of the workitem will be used if
* higher than the floor even when the workitem has been created without
* "ENFORCE" semantics.
*
* Setting the QOS class floor is equivalent to the QOS effects of configuring
* a target queue whose QOS class has been set with dispatch_set_qos_class().
*
* Calling this function will supersede any prior calls to
* dispatch_set_qos_class() or dispatch_set_qos_class_floor().
*
* @param object
* A dispatch queue, workloop, source or mach channel to configure.
* The object must be inactive.
*
* Passing another object type or an object that has been activated is undefined
* and will cause the process to be terminated.
*
* @param qos_class
* A QOS class value:
* - QOS_CLASS_USER_INTERACTIVE
* - QOS_CLASS_USER_INITIATED
* - QOS_CLASS_DEFAULT
* - QOS_CLASS_UTILITY
* - QOS_CLASS_BACKGROUND
* Passing any other value is undefined.
*
* @param relative_priority
* A relative priority within the QOS class. This value is a negative
* offset from the maximum supported scheduler priority for the given class.
* Passing a value greater than zero or less than QOS_MIN_RELATIVE_PRIORITY
* is undefined.
*/
API_AVAILABLE(macos(10.14), ios(12.0), tvos(12.0), watchos(5.0))
DISPATCH_EXPORT DISPATCH_NOTHROW
void
dispatch_set_qos_class_floor(dispatch_object_t object,
dispatch_qos_class_t qos_class, int relative_priority);
/*!
* @function dispatch_set_qos_class_fallback
*
* @abstract
* Sets the fallback QOS class on a dispatch queue, source, workloop or mach
* channel.
*
* @discussion
* Workitems submitted asynchronously to this object that don't have an assigned
* QOS class will use the specified QOS class as a fallback. This interface
* doesn't support relative priority.
*
* Workitems without an assigned QOS are:
* - workitems submitted from the context of a thread opted-out of QOS,
* - workitems created with the DISPATCH_BLOCK_DETACHED or
* DISPATCH_BLOCK_NO_QOS_CLASS flags,
* - XPC messages sent with xpc_connection_send_notification(),
* - XPC connection and dispatch source handlers.
*
* Calling both dispatch_set_qos_class_fallback() and dispatch_set_qos_class()
* on an object will only apply the effect of dispatch_set_qos_class().
*
* A QOS class fallback must always be at least as high as the current QOS
* floor for the dispatch queue hierarchy, else it is ignored.
*
* When no QOS fallback has been explicitly specified:
* - queues on hierarchies without a QOS class or QOS class floor have
* a fallback of QOS_CLASS_DEFAULT,
* - queues on hierarchies with a QOS class or QOS class floor configured will
* also use that QOS class as a fallback.
*
* @param object
* A dispatch queue, workloop, source or mach channel to configure.
* The object must be inactive.
*
* Passing another object type or an object that has been activated is undefined
* and will cause the process to be terminated.
*
* @param qos_class
* A QOS class value:
* - QOS_CLASS_USER_INTERACTIVE
* - QOS_CLASS_USER_INITIATED
* - QOS_CLASS_DEFAULT
* - QOS_CLASS_UTILITY
* - QOS_CLASS_BACKGROUND
* Passing any other value is undefined.
*/
API_AVAILABLE(macos(10.14), ios(12.0), tvos(12.0), watchos(5.0))
DISPATCH_EXPORT DISPATCH_NOTHROW
void
dispatch_set_qos_class_fallback(dispatch_object_t object,
dispatch_qos_class_t qos_class);
#define DISPATCH_QUEUE_FLAGS_MASK (DISPATCH_QUEUE_OVERCOMMIT)
// On FreeBSD pthread_attr_t is a typedef to a pointer type
#if defined(__FreeBSD__)
# define DISPATCH_QUEUE_NULLABLE_PTHREAD_ATTR_PTR _Nullable
#else
# define DISPATCH_QUEUE_NULLABLE_PTHREAD_ATTR_PTR
#endif
/*!
* @function dispatch_queue_attr_make_with_overcommit
*
* @discussion
* Returns a dispatch queue attribute value with the overcommit flag set to the
* specified value.
*
* This attribute only makes sense when the specified queue is targeted at
* a root queue. Passing this attribute to dispatch_queue_create_with_target()
* with a target queue that is not a root queue will result in an assertion and
* the process being terminated.
*
* It is recommended to not specify a target queue at all when using this
* attribute and to use dispatch_queue_attr_make_with_qos_class() to select the
* appropriate QOS class instead.
*
* Queues created with this attribute cannot change target after having been
* activated. See dispatch_set_target_queue() and dispatch_activate().
*
* @param attr
* A queue attribute value to be combined with the overcommit flag, or NULL.
*
* @param overcommit
* Boolean overcommit flag.
*
* @return
* Returns an attribute value which may be provided to dispatch_queue_create().
* This new value combines the attributes specified by the 'attr' parameter and
* the overcommit flag.
*/
API_AVAILABLE(macos(10.10), ios(8.0))
DISPATCH_EXPORT DISPATCH_WARN_RESULT DISPATCH_PURE DISPATCH_NOTHROW
dispatch_queue_attr_t
dispatch_queue_attr_make_with_overcommit(dispatch_queue_attr_t _Nullable attr,
bool overcommit);
/*!
* @typedef dispatch_queue_priority_t
*
* @constant DISPATCH_QUEUE_PRIORITY_NON_INTERACTIVE
* Items dispatched to the queue will run at non-interactive priority.
* This priority level is intended for user-initiated application activity that
* is long-running and CPU or IO intensive and that the user is actively waiting
* on, but that should not interfere with interactive use of the application.
*
* This global queue priority level is mapped to QOS_CLASS_UTILITY.
*/
#define DISPATCH_QUEUE_PRIORITY_NON_INTERACTIVE INT8_MIN
/*!
* @function dispatch_queue_set_label_nocopy
*
* @abstract
* Set the label for a given queue, without copying the input string.
*
* @discussion
* The queue must have been initially created with a NULL label, else using
* this function to set the queue label is undefined.
*
* The caller of this function must make sure the label pointer remains valid
* while it is used as the queue label and while any callers to
* dispatch_queue_get_label() may have obtained it. Since the queue lifetime
* may extend past the last release, it is advised to call this function with
* a constant string or NULL before the queue is released, or to destroy the
* label from a finalizer for that queue.
*
* This function should be called before any work item could call
* dispatch_queue_get_label(DISPATCH_CURRENT_QUEUE_LABEL) or from the context of
* the queue itself.
*
* @param queue
* The queue to adjust. Attempts to set the label of the main queue or a global
* concurrent queue will be ignored.
*
* @param label
* The new label for the queue.
*/
API_AVAILABLE(macos(10.13), ios(11.0), tvos(11.0), watchos(4.0))
DISPATCH_EXPORT DISPATCH_NONNULL1 DISPATCH_NOTHROW
void
dispatch_queue_set_label_nocopy(dispatch_queue_t queue,
const char * _Nullable label);
/*!
* @function dispatch_queue_set_width
*
* @abstract
* Set the width of concurrency for a given queue. The width of a serial queue
* is one.
*
* @discussion
* This SPI is DEPRECATED and will be removed in a future release.
* Uses of this SPI to make a queue concurrent by setting its width to LONG_MAX
* should be replaced by passing DISPATCH_QUEUE_CONCURRENT to
* dispatch_queue_create().
* Uses of this SPI to limit queue concurrency are not recommended and should
* be replaced by alternative mechanisms such as a dispatch semaphore created
* with the desired concurrency width.
*
* @param queue
* The queue to adjust. Attempts to set the width of the main queue or a global
* concurrent 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
API_DEPRECATED("Use dispatch_queue_create(name, DISPATCH_QUEUE_CONCURRENT)",
macos(10.6,10.10), ios(4.0,8.0))
DISPATCH_EXPORT DISPATCH_NONNULL_ALL DISPATCH_NOTHROW
void
dispatch_queue_set_width(dispatch_queue_t dq, long width);
#if defined(__BLOCKS__) && defined(__APPLE__)
/*!
* @function dispatch_pthread_root_queue_create
*
* @abstract
* Creates a new concurrent dispatch root queue with a pthread-based pool of
* worker threads owned by the application.
*
* @discussion
* Dispatch pthread root queues are similar to the global concurrent dispatch
* queues in that they invoke blocks concurrently, however the blocks are not
* executed on ordinary worker threads but use a dedicated pool of pthreads not
* shared with the global queues or any other pthread root queues.
*
* NOTE: this is a special-purpose facility that should only be used in very
* limited circumstances, in almost all cases the global concurrent queues
* should be preferred. While this facility allows for more flexibility in
* configuring worker threads for special needs it comes at the cost of
* increased overall memory usage due to reduced thread sharing and higher
* latency in worker thread bringup.
*
* Dispatch pthread root queues do not support suspension, application context
* and change of width or of target queue. They can however be used as the
* target queue for serial or concurrent queues obtained via
* dispatch_queue_create() or dispatch_queue_create_with_target(), which
* enables the blocks submitted to those queues to be processed on the root
* queue's pthread pool.
*
* When a dispatch pthread root queue is no longer needed, it should be
* released with dispatch_release(). Existing worker pthreads and pending blocks
* submitted to the root queue will hold a reference to the queue so it will not
* be deallocated until all blocks have finished and worker threads exited.
*
* @param label
* A string label to attach to the queue.
* This parameter is optional and may be NULL.
*
* @param flags
* Pass flags value returned by dispatch_pthread_root_queue_flags_pool_size()
* or 0 if unused.
*
* @param attr
* Attributes passed to pthread_create(3) when creating worker pthreads. This
* parameter is copied and can be destroyed after this call returns.
* This parameter is optional and may be NULL.
*
* @param configure
* Configuration block called on newly created worker pthreads before any blocks
* for the root queue are executed. The block may configure the current thread
* as needed.
* This parameter is optional and may be NULL.
*
* @result
* The newly created dispatch pthread root queue.
*/
API_AVAILABLE(macos(10.9), ios(6.0)) DISPATCH_LINUX_UNAVAILABLE()
DISPATCH_EXPORT DISPATCH_MALLOC DISPATCH_RETURNS_RETAINED DISPATCH_WARN_RESULT
DISPATCH_NOTHROW
dispatch_queue_global_t
dispatch_pthread_root_queue_create(const char *_Nullable label,
unsigned long flags, const pthread_attr_t DISPATCH_QUEUE_NULLABLE_PTHREAD_ATTR_PTR *_Nullable attr,
dispatch_block_t _Nullable configure);
/*!
* @function dispatch_pthread_root_queue_flags_pool_size
*
* @abstract
* Returns flags argument to pass to dispatch_pthread_root_queue_create() to
* specify the maximum size of the pthread pool to use for a pthread root queue.
*
* @param pool_size
* Maximum size of the pthread pool to use for the root queue. The number of
* pthreads created for this root queue will never exceed this number but there
* is no guarantee that the specified number will be reached.
* Pass 0 to specify that a default pool size determined by the system should
* be used.
* NOTE: passing pool_size == 1 does NOT make the pthread root queue equivalent
* to a serial queue.
*
* @result
* The flags argument to pass to dispatch_pthread_root_queue_create().
*/
DISPATCH_INLINE DISPATCH_ALWAYS_INLINE
unsigned long
dispatch_pthread_root_queue_flags_pool_size(uint8_t pool_size)
{
#define _DISPATCH_PTHREAD_ROOT_QUEUE_FLAG_POOL_SIZE (0x80000000ul)
return (_DISPATCH_PTHREAD_ROOT_QUEUE_FLAG_POOL_SIZE |
(unsigned long)pool_size);
}
/*!
* @function dispatch_pthread_root_queue_copy_current
*
* @abstract
* Returns a reference to the pthread root queue object that has created the
* currently executing thread, or NULL if the current thread is not associated
* to a pthread root queue.
*
* @result
* A new reference to a pthread root queue object or NULL.
*/
API_AVAILABLE(macos(10.12), ios(10.0), tvos(10.0), watchos(3.0))
DISPATCH_LINUX_UNAVAILABLE()
DISPATCH_EXPORT DISPATCH_RETURNS_RETAINED DISPATCH_WARN_RESULT DISPATCH_NOTHROW
dispatch_queue_global_t _Nullable
dispatch_pthread_root_queue_copy_current(void);
/*!
* @constant DISPATCH_APPLY_CURRENT_ROOT_QUEUE
*
* @discussion
* This constant is deprecated, please use DISPATCH_APPLY_AUTO.
*
* DISPATCH_APPLY_AUTO also selects the current pthread root queue if
* applicable.
*/
#define DISPATCH_APPLY_CURRENT_ROOT_QUEUE ((dispatch_queue_t _Nonnull)0)
#endif /* defined(__BLOCKS__) && defined(__APPLE__) */
/*!
* @function dispatch_async_enforce_qos_class_f
*
* @abstract
* Submits a function for asynchronous execution on a dispatch queue.
*
* @discussion
* See dispatch_async() for details. The QOS will be enforced as if
* this was called:
* <code>
* dispatch_async(queue, dispatch_block_create(DISPATCH_BLOCK_ENFORCE_QOS_CLASS, ^{
* work(context);
* });
* </code>
*
* @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.
*/
API_AVAILABLE(macos(10.11), ios(9.0))
DISPATCH_EXPORT DISPATCH_NONNULL1 DISPATCH_NONNULL3 DISPATCH_NOTHROW
void
dispatch_async_enforce_qos_class_f(dispatch_queue_t queue,
void *_Nullable context, dispatch_function_t work);
#ifdef __ANDROID__
/*!
* @function _dispatch_install_thread_detach_callback
*
* @param cb
* Function to be called before each worker thread exits to detach JVM.
*
* Hook to be able to detach threads from the Java JVM before they exit.
* If JNI has been used on a thread on Android it needs to have been
* "detached" before the thread exits or the application will crash.
*/
DISPATCH_EXPORT
void _dispatch_install_thread_detach_callback(void (*cb)(void));
#endif
__END_DECLS
DISPATCH_ASSUME_NONNULL_END
#endif

View File

@@ -0,0 +1,649 @@
/*
* Copyright (c) 2008-2013 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/private.h> instead of this file directly."
#include <dispatch/base.h> // for HeaderDoc
#endif
DISPATCH_ASSUME_NONNULL_BEGIN
__BEGIN_DECLS
/*!
* @const DISPATCH_SOURCE_TYPE_INTERVAL
* @discussion A dispatch source that submits the event handler block at a
* specified time interval, phase-aligned with all other interval sources on
* the system that have the same interval value.
*
* The initial submission of the event handler will occur at some point during
* the first time interval after the source is created (assuming the source is
* resumed at that time).
*
* By default, the unit for the interval value is milliseconds and the leeway
* (maximum amount of time any individual handler submission may be deferred to
* align with other system activity) for the source is fixed at interval/2.
*
* If the DISPATCH_INTERVAL_UI_ANIMATION flag is specified, the unit for the
* interval value is animation frames (1/60th of a second) and the leeway is
* fixed at one frame.
*
* The handle is the interval value in milliseconds or frames.
* The mask specifies which flags from dispatch_source_timer_flags_t to apply.
*
* Starting with macOS 10.14, iOS 12, dispatch_source_set_timer()
* can be used on such sources, and its arguments are used as follow:
* - start:
* must be DISPATCH_TIME_NOW or DISPATCH_TIME_FOREVER.
* DISPATCH_TIME_NOW will enable the timer, and align its phase, and
* DISPATCH_TIME_FOREVER will disable the timer as usual.*
* - interval:
* its unit is in milliseconds by default, or frames if the source
* was created with the DISPATCH_INTERVAL_UI_ANIMATION flag.
* - leeway:
* per-thousands of the interval (valid values range from 0 to 1000).
* If ~0ull is passed, the default leeway for the interval is used instead.
*/
#define DISPATCH_SOURCE_TYPE_INTERVAL (&_dispatch_source_type_interval)
API_AVAILABLE(macos(10.9), ios(7.0))
DISPATCH_SOURCE_TYPE_DECL(interval);
/*!
* @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)
API_AVAILABLE(macos(10.6), ios(4.0)) DISPATCH_LINUX_UNAVAILABLE()
DISPATCH_SOURCE_TYPE_DECL(vfs);
/*!
* @const DISPATCH_SOURCE_TYPE_VM
* @discussion A dispatch source that monitors virtual memory
* The mask is a mask of desired events from dispatch_source_vm_flags_t.
* This type is deprecated, use DISPATCH_SOURCE_TYPE_MEMORYPRESSURE instead.
*/
#define DISPATCH_SOURCE_TYPE_VM (&_dispatch_source_type_vm)
API_DEPRECATED_WITH_REPLACEMENT("DISPATCH_SOURCE_TYPE_MEMORYPRESSURE",
macos(10.7,10.10), ios(4.3,8.0)) DISPATCH_LINUX_UNAVAILABLE()
DISPATCH_SOURCE_TYPE_DECL(vm);
/*!
* @const DISPATCH_SOURCE_TYPE_MEMORYSTATUS
* @discussion A dispatch source that monitors memory status
* The mask is a mask of desired events from
* dispatch_source_memorystatus_flags_t.
*/
#define DISPATCH_SOURCE_TYPE_MEMORYSTATUS (&_dispatch_source_type_memorystatus)
API_DEPRECATED_WITH_REPLACEMENT("DISPATCH_SOURCE_TYPE_MEMORYPRESSURE",
macos(10.9, 10.12), ios(6.0, 10.0), tvos(6.0, 10.0), watchos(1.0, 3.0))
DISPATCH_LINUX_UNAVAILABLE()
DISPATCH_SOURCE_TYPE_DECL(memorystatus);
/*!
* @const DISPATCH_SOURCE_TYPE_SOCK
* @discussion A dispatch source that monitors events on socket state changes.
*/
#define DISPATCH_SOURCE_TYPE_SOCK (&_dispatch_source_type_sock)
API_AVAILABLE(macos(10.8), ios(6.0)) DISPATCH_LINUX_UNAVAILABLE()
DISPATCH_SOURCE_TYPE_DECL(sock);
/*!
* @const DISPATCH_SOURCE_TYPE_NW_CHANNEL
* @discussion A dispatch source that monitors events on a network channel.
*/
#define DISPATCH_SOURCE_TYPE_NW_CHANNEL (&_dispatch_source_type_nw_channel)
API_AVAILABLE(macos(10.13), ios(11.0), tvos(11.0), watchos(4.0)) DISPATCH_LINUX_UNAVAILABLE()
DISPATCH_SOURCE_TYPE_DECL(nw_channel);
__END_DECLS
/*!
* @enum dispatch_source_sock_flags_t
*
* @constant DISPATCH_SOCK_CONNRESET
* Received RST
*
* @constant DISPATCH_SOCK_READCLOSED
* Read side is shutdown
*
* @constant DISPATCH_SOCK_WRITECLOSED
* Write side is shutdown
*
* @constant DISPATCH_SOCK_TIMEOUT
* Timeout: rexmt, keep-alive or persist
*
* @constant DISPATCH_SOCK_NOSRCADDR
* Source address not available
*
* @constant DISPATCH_SOCK_IFDENIED
* Interface denied connection
*
* @constant DISPATCH_SOCK_SUSPEND
* Output queue suspended
*
* @constant DISPATCH_SOCK_RESUME
* Output queue resumed
*
* @constant DISPATCH_SOCK_KEEPALIVE
* TCP Keepalive received
*
* @constant DISPATCH_SOCK_CONNECTED
* Socket is connected
*
* @constant DISPATCH_SOCK_DISCONNECTED
* Socket is disconnected
*
* @constant DISPATCH_SOCK_CONNINFO_UPDATED
* Connection info was updated
*
* @constant DISPATCH_SOCK_NOTIFY_ACK
* Notify acknowledgement
*/
enum {
DISPATCH_SOCK_CONNRESET = 0x00000001,
DISPATCH_SOCK_READCLOSED = 0x00000002,
DISPATCH_SOCK_WRITECLOSED = 0x00000004,
DISPATCH_SOCK_TIMEOUT = 0x00000008,
DISPATCH_SOCK_NOSRCADDR = 0x00000010,
DISPATCH_SOCK_IFDENIED = 0x00000020,
DISPATCH_SOCK_SUSPEND = 0x00000040,
DISPATCH_SOCK_RESUME = 0x00000080,
DISPATCH_SOCK_KEEPALIVE = 0x00000100,
DISPATCH_SOCK_ADAPTIVE_WTIMO = 0x00000200,
DISPATCH_SOCK_ADAPTIVE_RTIMO = 0x00000400,
DISPATCH_SOCK_CONNECTED = 0x00000800,
DISPATCH_SOCK_DISCONNECTED = 0x00001000,
DISPATCH_SOCK_CONNINFO_UPDATED = 0x00002000,
DISPATCH_SOCK_NOTIFY_ACK = 0x00004000,
};
/*!
* @enum dispatch_source_nw_channel_flags_t
*
* @constant DISPATCH_NW_CHANNEL_FLOW_ADV_UPDATE
* Received network channel flow advisory.
*/
enum {
DISPATCH_NW_CHANNEL_FLOW_ADV_UPDATE = 0x00000001,
};
/*!
* @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.
*
* @constant DISPATCH_VFS_QUOTA
* We hit a user quota (quotactl) for this filesystem.
*
* @constant DISPATCH_VFS_NEARLOWDISK
* Filesystem is nearly full (below NEARLOWDISK level).
*
* @constant DISPATCH_VFS_DESIREDDISK
* Filesystem has exceeded the DESIREDDISK level
*
* @constant DISPATCH_VFS_FREE_SPACE_CHANGE
* Filesystem free space changed.
*/
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,
DISPATCH_VFS_QUOTA = 0x1000,
DISPATCH_VFS_NEARLOWDISK = 0x2000,
DISPATCH_VFS_DESIREDDISK = 0x4000,
DISPATCH_VFS_FREE_SPACE_CHANGE = 0x8000,
};
/*!
* @enum dispatch_clockid_t
*
* @discussion
* These values can be used with DISPATCH_SOURCE_TYPE_TIMER as a "handle"
* to anchor the timer to a given clock which allows for various optimizations.
*
* Note that using an explicit clock will make the dispatch source "strict"
* like dispatch_source_set_mandatory_cancel_handler() does.
*
* @constant DISPATCH_CLOCKID_UPTIME
* A monotonic clock that doesn't tick while the machine is asleep.
* Equivalent to the CLOCK_UPTIME clock ID on BSD systems.
*
* @constant DISPATCH_CLOCKID_MONOTONIC
* A monotonic clock that ticks while the machine sleeps.
* Equivalent to POSIX CLOCK_MONOTONIC.
* (Note that on Linux, CLOCK_MONOTONIC isn't conformant and doesn't tick while
* sleeping, hence on Linux this is the same clock as CLOCK_BOOTTIME).
*
* @constant DISPATCH_CLOCKID_WALLTIME
* A clock equivalent to the wall clock time, as returned by gettimeofday().
* Equivalent to POSIX CLOCK_REALTIME.
*
* @constant DISPATCH_CLOCKID_REALTIME
* An alias for DISPATCH_CLOCKID_WALLTIME to match the POSIX clock of the
* same name.
*/
DISPATCH_ENUM(dispatch_clockid, uintptr_t,
DISPATCH_CLOCKID_UPTIME DISPATCH_ENUM_API_AVAILABLE(macos(10.14), ios(12.0), tvos(12.0), watchos(5.0)) = 1,
DISPATCH_CLOCKID_MONOTONIC DISPATCH_ENUM_API_AVAILABLE(macos(10.14), ios(12.0), tvos(12.0), watchos(5.0)) = 2,
DISPATCH_CLOCKID_WALLTIME DISPATCH_ENUM_API_AVAILABLE(macos(10.14), ios(12.0), tvos(12.0), watchos(5.0)) = 3,
DISPATCH_CLOCKID_REALTIME DISPATCH_ENUM_API_AVAILABLE(macos(10.14), ios(12.0), tvos(12.0), watchos(5.0)) = 3,
);
/*!
* @enum dispatch_source_timer_flags_t
*
* @constant DISPATCH_TIMER_BACKGROUND
* Specifies that the timer is used to trigger low priority maintenance-level
* activity and that the system may apply larger minimum leeway values to the
* timer in order to align it with other system activity.
*
* @constant DISPATCH_INTERVAL_UI_ANIMATION
* Specifies that the interval source is used for UI animation. The unit for
* the interval value of such sources is frames (1/60th of a second) and the
* leeway is fixed at one frame.
*/
enum {
DISPATCH_TIMER_BACKGROUND = 0x2,
DISPATCH_INTERVAL_UI_ANIMATION = 0x20,
};
/*!
* @enum dispatch_source_mach_send_flags_t
*
* @constant DISPATCH_MACH_SEND_POSSIBLE
* The mach port corresponding to the given send right has space available
* for messages. Delivered only once a mach_msg() to that send right with
* options MACH_SEND_MSG|MACH_SEND_TIMEOUT|MACH_SEND_NOTIFY has returned
* MACH_SEND_TIMED_OUT (and not again until the next such mach_msg() timeout).
* NOTE: The source must have registered the send right for monitoring with the
* system for such a mach_msg() to arm the send-possible notifcation, so
* the initial send attempt must occur from a source registration handler.
*/
enum {
DISPATCH_MACH_SEND_POSSIBLE = 0x8,
};
/*!
* @enum dispatch_source_proc_flags_t
*
* @constant DISPATCH_PROC_REAP
* The process has been reaped by the parent process via wait*().
* This flag is deprecated and will be removed in a future release.
*
* @constant DISPATCH_PROC_EXIT_STATUS
* The process has exited. Specifying this flag allows the process exit status
* to be retrieved from the source's status value, as returned by the
* dispatch_source_get_extended_data() function. The macros
* DISPATCH_PROC_EXIT_STATUS_EXITED(), DISPATCH_PROC_EXIT_STATUS_CODE(),
* DISPATCH_PROC_EXIT_STATUS_SIGNALED(), DISPATCH_PROC_EXIT_STATUS_TERMSIG() and
* DISPATCH_PROC_EXIT_STATUS_CORE_DUMPED() can be used to examine the status
* value.
*/
enum {
DISPATCH_PROC_REAP DISPATCH_ENUM_API_DEPRECATED("unsupported flag",
macos(10.6,10.9), ios(4.0,7.0)) = 0x10000000,
DISPATCH_PROC_EXIT_STATUS DISPATCH_ENUM_API_AVAILABLE(macos(10.13), ios(11.0), tvos(11.0), watchos(2.0)) = 0x04000000,
};
/*!
* @enum dispatch_source_vm_flags_t
*
* @constant DISPATCH_VM_PRESSURE
* The VM has experienced memory pressure.
*/
enum {
DISPATCH_VM_PRESSURE DISPATCH_ENUM_API_DEPRECATED_WITH_REPLACEMENT("DISPATCH_MEMORYPRESSURE_WARN", macos(10.7, 10.10), ios(4.3, 8.0))
= 0x80000000,
};
/*!
* @typedef dispatch_source_memorypressure_flags_t
* Type of dispatch_source_memorypressure flags
*
* @constant DISPATCH_MEMORYPRESSURE_LOW_SWAP
* The system's memory pressure state has entered the "low swap" condition.
* Restricted to the root user.
*/
enum {
DISPATCH_MEMORYPRESSURE_LOW_SWAP DISPATCH_ENUM_API_AVAILABLE(macos(10.10), ios(8.0)) = 0x08,
};
/*!
* @enum dispatch_source_memorystatus_flags_t
* @warning Deprecated, see DISPATCH_MEMORYPRESSURE_*
*/
enum {
DISPATCH_MEMORYSTATUS_PRESSURE_NORMAL
DISPATCH_ENUM_API_DEPRECATED_WITH_REPLACEMENT("DISPATCH_MEMORYPRESSURE_NORMAL", macos(10.9, 10.12),
ios(6.0, 10.0), tvos(6.0, 10.0), watchos(1.0, 3.0)) = 0x01,
DISPATCH_MEMORYSTATUS_PRESSURE_WARN
DISPATCH_ENUM_API_DEPRECATED_WITH_REPLACEMENT("DISPATCH_MEMORYPRESSURE_WARN", macos(10.9, 10.12),
ios(6.0, 10.0), tvos(6.0, 10.0), watchos(1.0, 3.0)) = 0x02,
DISPATCH_MEMORYSTATUS_PRESSURE_CRITICAL
DISPATCH_ENUM_API_DEPRECATED_WITH_REPLACEMENT("DISPATCH_MEMORYPRESSURE_CRITICAL", macos(10.9, 10.12),
ios(6.0, 10.0), tvos(6.0, 10.0), watchos(1.0, 3.0)) = 0x04,
DISPATCH_MEMORYSTATUS_LOW_SWAP
DISPATCH_ENUM_API_DEPRECATED_WITH_REPLACEMENT("DISPATCH_MEMORYPRESSURE_LOW_SWAP", macos(10.9, 10.12),
ios(6.0, 10.0), tvos(6.0, 10.0), watchos(1.0, 3.0)) = 0x08,
};
/*!
* @typedef dispatch_source_memorypressure_flags_t
* Type of dispatch_source_memorypressure flags
*
* @constant DISPATCH_MEMORYPRESSURE_PROC_LIMIT_WARN
* The memory of the process has crossed 80% of its high watermark limit.
*
* @constant DISPATCH_MEMORYPRESSURE_PROC_LIMIT_CRITICAL
* The memory of the process has reached 100% of its high watermark limit.
*
* @constant DISPATCH_MEMORYPRESSURE_MSL_STATUS
* Mask for enabling/disabling malloc stack logging.
*/
enum {
DISPATCH_MEMORYPRESSURE_PROC_LIMIT_WARN DISPATCH_ENUM_API_AVAILABLE(macos(10.12), ios(10.0), tvos(10.0), watchos(3.0)) = 0x10,
DISPATCH_MEMORYPRESSURE_PROC_LIMIT_CRITICAL DISPATCH_ENUM_API_AVAILABLE(macos(10.12), ios(10.0), tvos(10.0), watchos(3.0)) = 0x20,
DISPATCH_MEMORYPRESSURE_MSL_STATUS DISPATCH_ENUM_API_AVAILABLE(macos(10.13), ios(11.0), tvos(11.0), watchos(4.0)) = 0xf0000000,
};
/*!
* Macros to check the exit status obtained from the status field of the
* structure returned by the dispatch_source_get_extended_data() function for a
* source of type DISPATCH_SOURCE_TYPE_PROC when DISPATCH_PROC_EXIT_STATUS has
* been requested.
*
* DISPATCH_PROC_EXIT_STATUS_EXITED returns whether the process exited. If this
* is true, the exit status can be obtained from DISPATCH_PROC_EXIT_STATUS_CODE.
*
* DISPATCH_PROC_EXIT_STATUS_SIGNALED returns whether the process was terminated
* by a signal.
*
* DISPATCH_PROC_EXIT_STATUS_TERMSIG returns the signal that caused the process
* to terminate, or 0 if the process was not terminated by a signal.
*
* DISPATCH_PROC_EXIT_STATUS_CORE_DUMPED returns whether a core dump of the
* process was created.
*/
#define DISPATCH_PROC_EXIT_STATUS_EXITED(status) ((bool)WIFEXITED(status))
#define DISPATCH_PROC_EXIT_STATUS_CODE(status) ((int)WEXITSTATUS(status))
#define DISPATCH_PROC_EXIT_STATUS_SIGNALED(status) ((bool)WIFSIGNALED(status))
#define DISPATCH_PROC_EXIT_STATUS_TERMSIG(status) ((int)WTERMSIG(status))
#define DISPATCH_PROC_EXIT_STATUS_CORE_DUMPED(status) ((bool)WCOREDUMP(status))
__BEGIN_DECLS
/*!
* @function dispatch_source_set_mandatory_cancel_handler
*
* @abstract
* Sets the event handler block for the given dispatch source, and indicates
* that calling dispatch_source_cancel() is mandatory for this source object.
*
* @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.
*
* When this function has been used used to set a cancellation handler, then
* the following result in an assertion and the process being terminated:
* - releasing the last reference on the dispatch source without having
* cancelled it by calling dispatch_source_cancel();
* - changing any handler after the source has been activated;
* - changing the target queue of the source after it has been activated.
*
* IMPORTANT:
* Source cancellation and a cancellation handler are required for file
* descriptor and mach port based sources in order to safely close the
* descriptor or destroy the port. Making the cancellation handler of such
* sources mandatory is strongly recommended.
* Closing the descriptor or port before the cancellation handler is invoked 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.
* The result of passing NULL in this parameter is undefined.
*/
#ifdef __BLOCKS__
API_AVAILABLE(macos(10.13), ios(11.0), tvos(11.0), watchos(4.0))
DISPATCH_EXPORT DISPATCH_NONNULL_ALL DISPATCH_NOTHROW
void
dispatch_source_set_mandatory_cancel_handler(dispatch_source_t source,
dispatch_block_t handler);
#endif /* __BLOCKS__ */
/*!
* @function dispatch_source_set_mandatory_cancel_handler_f
*
* @abstract
* Sets the event handler function for the given dispatch source, and causes an
* assertion if this source is released before having been explicitly canceled.
*
* @discussion
* See dispatch_source_set_mandatory_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.
* The result of passing NULL in this parameter is undefined.
*/
API_AVAILABLE(macos(10.13), ios(11.0), tvos(11.0), watchos(4.0))
DISPATCH_EXPORT DISPATCH_NONNULL_ALL DISPATCH_NOTHROW
void
dispatch_source_set_mandatory_cancel_handler_f(dispatch_source_t source,
dispatch_function_t handler);
/*!
* @function dispatch_source_cancel_and_wait
*
* @abstract
* Synchronously cancel the dispatch source, preventing any further invocation
* of its event handler block.
*
* @discussion
* Cancellation prevents any further invocation of handler blocks for the
* specified dispatch source, but does not interrupt a handler block that is
* already in progress.
*
* When this function returns, any handler block that may have been in progress
* has returned, the specified source has been unregistered and it is safe to
* reclaim any system resource (such as file descriptors or mach ports) that
* the specified source was monitoring.
*
* If the specified dispatch source is inactive, it will be activated as a side
* effect of calling this function.
*
* It is possible to call this function from several threads concurrently,
* and it is the responsibility of the callers to synchronize reclaiming the
* associated system resources.
*
* This function is not subject to priority inversion when it is waiting on
* a handler block still in progress, unlike patterns based on waiting on
* a dispatch semaphore or a dispatch group signaled (or left) from the source
* cancel handler.
*
* This function must not be called if the specified source has a cancel
* handler set, or from the context of its handler blocks.
*
* This function must not be called from the context of the target queue of
* the specified source or from any queue that synchronizes with it. Note that
* calling dispatch_source_cancel() from such a context already guarantees
* that no handler is in progress, and that no new event will be delivered.
*
* This function must not be called on sources suspended with an explicit
* call to dispatch_suspend(), or being concurrently activated on another
* thread.
*
* @param source
* The dispatch source to be canceled.
* The result of passing NULL in this parameter is undefined.
*/
API_AVAILABLE(macos(10.12), ios(10.0), tvos(10.0), watchos(3.0))
DISPATCH_EXPORT DISPATCH_NOTHROW
void
dispatch_source_cancel_and_wait(dispatch_source_t source);
#if __has_include(<mach/mach.h>)
/*!
* @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);
API_AVAILABLE(macos(10.6), ios(4.0)) DISPATCH_LINUX_UNAVAILABLE()
DISPATCH_EXPORT DISPATCH_NONNULL_ALL DISPATCH_NOTHROW
mach_msg_return_t
dispatch_mig_server(dispatch_source_t ds, size_t maxmsgsz,
dispatch_mig_callback_t callback);
/*!
* @function dispatch_mach_msg_get_context
*
* @abstract
* Extract the context pointer from a mach message trailer.
*/
API_AVAILABLE(macos(10.6), ios(4.0)) DISPATCH_LINUX_UNAVAILABLE()
DISPATCH_EXPORT DISPATCH_PURE DISPATCH_WARN_RESULT DISPATCH_NONNULL_ALL
DISPATCH_NOTHROW
void *_Nullable
dispatch_mach_msg_get_context(mach_msg_header_t *msg);
#endif
/*!
* @typedef dispatch_source_extended_data_t
*
* @abstract
* Type used by dispatch_source_get_extended_data() to return a consistent
* snapshot of the data and status of a dispatch source.
*/
typedef struct dispatch_source_extended_data_s {
unsigned long data;
unsigned long status;
} *dispatch_source_extended_data_t;
/*!
* @function dispatch_source_get_extended_data
*
* @abstract
* Returns the current data and status values for a 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.
*
* @param data
* A pointer to a dispatch_source_extended_data_s in which the data and status
* will be returned. The data field is populated with the value that would be
* returned by dispatch_source_get_data(). The value of the status field should
* be interpreted according to the type of the dispatch source:
*
* DISPATCH_SOURCE_TYPE_PROC: dispatch_source_proc_exit_flags_t
*
* If called from the event handler of a data source type not listed above, the
* status value is undefined.
*
* @param size
* The size of the specified structure. Should be set to
* sizeof(dispatch_source_extended_data_s).
*
* @result
* The size of the structure returned in *data, which will never be greater than
* the value of the size argument. If this is less than the value of the size
* argument, the remaining space in data will have been populated with zeroes.
*/
API_AVAILABLE(macos(10.13), ios(11.0), tvos(11.0), watchos(4.0))
DISPATCH_EXPORT DISPATCH_NONNULL_ALL DISPATCH_WARN_RESULT DISPATCH_PURE
DISPATCH_NOTHROW
size_t
dispatch_source_get_extended_data(dispatch_source_t source,
dispatch_source_extended_data_t data, size_t size);
__END_DECLS
DISPATCH_ASSUME_NONNULL_END
#endif

View File

@@ -0,0 +1,87 @@
/*
* Copyright (c) 20017 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. Any applications relying on
* these interfaces WILL break.
*/
#ifndef __DISPATCH_TIME_PRIVATE__
#define __DISPATCH_TIME_PRIVATE__
#ifndef __DISPATCH_INDIRECT__
#error "Please #include <dispatch/private.h> instead of this file directly."
#include <dispatch/base.h> // for HeaderDoc
#endif
/*
* @constant DISPATCH_MONOTONICTIME_NOW
* A dispatch_time_t value that corresponds to the current value of the
* platform's monotonic clock. On Apple platforms, this clock is based on
* mach_continuous_time(). Use this value with the dispatch_time() function to
* derive a time value for a timer in monotonic time (i.e. a timer that
* continues to tick while the system is asleep). For example:
*
* dispatch_time_t t = dispatch_time(DISPATCH_MONOTONICTIME_NOW,5*NSEC_PER_SEC);
* dispatch_source_t ds = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER,
* 0, 0, q);
* dispatch_source_set_event_handler(ds, ^{ ... });
* dispatch_source_set_timer(ds, t, 10 * NSEC_PER_SEC, 0);
* dispatch_activate(ds);
*/
enum {
DISPATCH_MONOTONICTIME_NOW DISPATCH_ENUM_API_AVAILABLE(macos(10.14), ios(12.0), tvos(12.0), watchos(5.0)) = (1ull << 63)
};
#ifdef __APPLE__
// Helper macros for up time, montonic time and wall time.
#define _dispatch_uptime_after_nsec(t) \
dispatch_time(DISPATCH_TIME_NOW, (t))
#define _dispatch_uptime_after_usec(t) \
dispatch_time(DISPATCH_TIME_NOW, (t) * NSEC_PER_USEC)
#define _dispatch_uptime_after_msec(t) \
dispatch_time(DISPATCH_TIME_NOW, (t) * NSEC_PER_MSEC)
#define _dispatch_uptime_after_sec(t) \
dispatch_time(DISPATCH_TIME_NOW, (t) * NSEC_PER_SEC)
#define _dispatch_monotonictime_after_nsec(t) \
dispatch_time(DISPATCH_MONOTONICTIME_NOW, (t))
#define _dispatch_monotonictime_after_usec(t) \
dispatch_time(DISPATCH_MONOTONICTIME_NOW, (t) * NSEC_PER_USEC)
#define _dispatch_monotonictime_after_msec(t) \
dispatch_time(DISPATCH_MONOTONICTIME_NOW, (t) * NSEC_PER_MSEC)
#define _dispatch_monotonictime_after_sec(t) \
dispatch_time(DISPATCH_MONOTONICTIME_NOW, (t) * NSEC_PER_SEC)
#define _dispatch_walltime_after_nsec(t) \
dispatch_time(DISPATCH_WALLTIME_NOW, (t))
#define _dispatch_walltime_after_usec(t) \
dispatch_time(DISPATCH_WALLTIME_NOW, (t) * NSEC_PER_USEC)
#define _dispatch_walltime_after_msec(t) \
dispatch_time(DISPATCH_WALLTIME_NOW, (t) * NSEC_PER_MSEC)
#define _dispatch_walltime_after_sec(t) \
dispatch_time(DISPATCH_WALLTIME_NOW, (t) * NSEC_PER_SEC)
#endif // __APPLE__
#endif

View File

@@ -0,0 +1,440 @@
/*
* Copyright (c) 2017-2018 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_WORKLOOP_PRIVATE__
#define __DISPATCH_WORKLOOP_PRIVATE__
#ifndef __DISPATCH_INDIRECT__
#error "Please #include <dispatch/private.h> instead of this file directly."
#include <dispatch/base.h> // for HeaderDoc
#endif
/******************************************************************************\
*
* THIS FILE IS AN IN-PROGRESS INTERFACE THAT IS SUBJECT TO CHANGE
*
\******************************************************************************/
DISPATCH_ASSUME_NONNULL_BEGIN
__BEGIN_DECLS
/*!
* @typedef dispatch_workloop_t
*
* @abstract
* Dispatch workloops invoke workitems submitted to them in priority order.
*
* @discussion
* A dispatch workloop is a flavor of dispatch_queue_t that is a priority
* ordered queue (using the QOS class of the submitted workitems as the
* ordering).
*
* Between each workitem invocation, the workloop will evaluate whether higher
* priority workitems have since been submitted and execute these first.
*
* Serial queues targeting a workloop maintain FIFO execution of their
* workitems. However, the workloop may reorder workitems submitted to
* independent serial queues targeting it with respect to each other,
* based on their priorities.
*
* A dispatch workloop is a "subclass" of dispatch_queue_t which can be passed
* to all APIs accepting a dispatch queue, except for functions from the
* dispatch_sync() family. dispatch_async_and_wait() must be used for workloop
* objects. Functions from the dispatch_sync() family on queues targeting
* a workloop are still permitted but discouraged for performance reasons.
*/
#if defined(__DISPATCH_BUILDING_DISPATCH__) && !defined(__OBJC__)
typedef struct dispatch_workloop_s *dispatch_workloop_t;
#else
DISPATCH_DECL_SUBCLASS(dispatch_workloop, dispatch_queue);
#endif
/*!
* @function dispatch_workloop_create
*
* @abstract
* Creates a new dispatch workloop to which workitems may be submitted.
*
* @param label
* A string label to attach to the workloop.
*
* @result
* The newly created dispatch workloop.
*/
API_AVAILABLE(macos(10.14), ios(12.0), tvos(12.0), watchos(5.0))
DISPATCH_EXPORT DISPATCH_MALLOC DISPATCH_RETURNS_RETAINED DISPATCH_WARN_RESULT
DISPATCH_NOTHROW
dispatch_workloop_t
dispatch_workloop_create(const char *_Nullable label);
/*!
* @function dispatch_workloop_create_inactive
*
* @abstract
* Creates a new inactive dispatch workloop that can be setup and then
* activated.
*
* @discussion
* Creating an inactive workloop allows for it to receive further configuration
* before it is activated, and workitems can be submitted to it.
*
* Submitting workitems to an inactive workloop is undefined and will cause the
* process to be terminated.
*
* @param label
* A string label to attach to the workloop.
*
* @result
* The newly created dispatch workloop.
*/
API_AVAILABLE(macos(10.14), ios(12.0), tvos(12.0), watchos(5.0))
DISPATCH_EXPORT DISPATCH_MALLOC DISPATCH_RETURNS_RETAINED DISPATCH_WARN_RESULT
DISPATCH_NOTHROW
dispatch_workloop_t
dispatch_workloop_create_inactive(const char *_Nullable label);
/*!
* @function dispatch_workloop_set_autorelease_frequency
*
* @abstract
* Sets the autorelease frequency of the workloop.
*
* @discussion
* See dispatch_queue_attr_make_with_autorelease_frequency().
* The default policy for a workloop is
* DISPATCH_AUTORELEASE_FREQUENCY_WORK_ITEM.
*
* @param workloop
* The dispatch workloop to modify.
*
* This workloop must be inactive, passing an activated object is undefined
* and will cause the process to be terminated.
*
* @param frequency
* The requested autorelease frequency.
*/
API_AVAILABLE(macos(10.14), ios(12.0), tvos(12.0), watchos(5.0))
DISPATCH_EXPORT DISPATCH_NONNULL_ALL DISPATCH_NOTHROW
void
dispatch_workloop_set_autorelease_frequency(dispatch_workloop_t workloop,
dispatch_autorelease_frequency_t frequency);
DISPATCH_ENUM(dispatch_workloop_param_flags, uint64_t,
DISPATCH_WORKLOOP_NONE DISPATCH_ENUM_API_AVAILABLE(macos(10.14), ios(12.0), tvos(12.0), watchos(5.0)) = 0x0,
DISPATCH_WORKLOOP_FIXED_PRIORITY DISPATCH_ENUM_API_AVAILABLE(macos(10.14), ios(12.0), tvos(12.0), watchos(5.0)) = 0x1,
);
/*!
* @function dispatch_workloop_set_qos_class_floor
*
* @abstract
* Sets the QOS class floor of a workloop.
*
* @discussion
* See dispatch_set_qos_class_floor().
*
* This function is strictly equivalent to dispatch_set_qos_class_floor() but
* allows to pass extra flags.
*
* Using both dispatch_workloop_set_scheduler_priority() and
* dispatch_set_qos_class_floor() or dispatch_workloop_set_qos_class_floor()
* is undefined and will cause the process to be terminated.
*
* @param workloop
* The dispatch workloop to modify.
*
* This workloop must be inactive, passing an activated object is undefined
* and will cause the process to be terminated.
*/
API_AVAILABLE(macos(10.14), ios(12.0), tvos(12.0), watchos(5.0))
DISPATCH_EXPORT DISPATCH_NONNULL_ALL DISPATCH_NOTHROW
void
dispatch_workloop_set_qos_class_floor(dispatch_workloop_t workloop,
dispatch_qos_class_t qos, int relpri, dispatch_workloop_param_flags_t flags);
/*!
* @function dispatch_workloop_set_scheduler_priority
*
* @abstract
* Sets the scheduler priority for a dispatch workloop.
*
* @discussion
* This sets the scheduler priority of the threads that the runtime will bring
* up to service this workloop.
*
* QOS propagation still functions on these workloops, but its effect on the
* priority of the thread brought up to service this workloop is ignored.
*
* Using both dispatch_workloop_set_scheduler_priority() and
* dispatch_set_qos_class_floor() or dispatch_workloop_set_qos_class_floor()
* is undefined and will cause the process to be terminated.
*
* @param workloop
* The dispatch workloop to modify.
*
* This workloop must be inactive, passing an activated object is undefined
* and will cause the process to be terminated.
*/
API_AVAILABLE(macos(10.14), ios(12.0), tvos(12.0), watchos(5.0))
DISPATCH_EXPORT DISPATCH_NONNULL_ALL DISPATCH_NOTHROW
void
dispatch_workloop_set_scheduler_priority(dispatch_workloop_t workloop,
int priority, dispatch_workloop_param_flags_t flags);
/*!
* @function dispatch_workloop_set_cpupercent
*
* @abstract
* Sets the cpu percent and refill attributes for a dispatch workloop.
*
* @discussion
* This should only used if the workloop was also setup with the
* DISPATCH_WORKLOOP_FIXED_PRIORITY flag as a safe guard against
* busy loops that could starve the rest of the system forever.
*
* If DISPATCH_WORKLOOP_FIXED_PRIORITY wasn't passed, using this function is
* undefined and will cause the process to be terminated.
*
* @param workloop
* The dispatch workloop to modify.
*
* This workloop must be inactive, passing an activated object is undefined
* and will cause the process to be terminated.
*/
API_AVAILABLE(macos(10.14), ios(12.0), tvos(12.0), watchos(5.0))
DISPATCH_EXPORT DISPATCH_NONNULL_ALL DISPATCH_NOTHROW
void
dispatch_workloop_set_cpupercent(dispatch_workloop_t workloop, uint8_t percent,
uint32_t refillms);
/*!
* @function dispatch_workloop_is_current()
*
* @abstract
* Returns whether the current thread has been made by the runtime to service
* this workloop.
*
* @discussion
* Note that when using <code>dispatch_async_and_wait(workloop, ^{ ... })</code>
* then <code>workloop</code> will be seen as the "current" one by the submitted
* workitem, but that is not the case when using dispatch_sync() on a queue
* targeting the workloop.
*/
API_AVAILABLE(macos(10.14), ios(12.0), tvos(12.0), watchos(5.0))
DISPATCH_EXPORT DISPATCH_NONNULL_ALL DISPATCH_NOTHROW
bool
dispatch_workloop_is_current(dispatch_workloop_t workloop);
/*!
* @function dispatch_workloop_copy_current()
*
* @abstract
* Returns a copy of the workoop that is being serviced on the calling thread
* if any.
*
* @discussion
* If the thread is not a workqueue thread, or is not servicing a dispatch
* workloop, then NULL is returned.
*
* This returns a retained object that must be released with dispatch_release().
*/
API_AVAILABLE(macos(10.14), ios(12.0), tvos(12.0), watchos(5.0))
DISPATCH_EXPORT DISPATCH_RETURNS_RETAINED DISPATCH_NOTHROW
dispatch_workloop_t _Nullable
dispatch_workloop_copy_current(void);
// Equivalent to dispatch_workloop_set_qos_class_floor(workoop, qos, 0, flags)
API_DEPRECATED_WITH_REPLACEMENT("dispatch_workloop_set_qos_class_floor",
macos(10.14,10.14), ios(12.0,12.0), tvos(12.0,12.0), watchos(5.0,5.0))
DISPATCH_EXPORT DISPATCH_NONNULL_ALL DISPATCH_NOTHROW
void
dispatch_workloop_set_qos_class(dispatch_workloop_t workloop,
dispatch_qos_class_t qos, dispatch_workloop_param_flags_t flags);
API_AVAILABLE(macos(10.14), ios(12.0), tvos(12.0), watchos(5.0))
DISPATCH_EXPORT DISPATCH_NOTHROW
bool
_dispatch_workloop_should_yield_4NW(void);
/*!
* @function dispatch_async_and_wait
*
* @abstract
* Submits a block for synchronous execution on a dispatch queue.
*
* @discussion
* Submits a workitem to a dispatch queue like dispatch_async(), however
* dispatch_async_and_wait() will not return until the workitem has finished.
*
* Like functions of the dispatch_sync family, dispatch_async_and_wait() is
* subject to dead-lock (See dispatch_sync() for details).
*
* However, dispatch_async_and_wait() differs from functions of the
* dispatch_sync family in two fundamental ways: how it respects queue
* attributes and how it chooses the execution context invoking the workitem.
*
* <b>Differences with dispatch_sync()</b>
*
* Work items submitted to a queue with dispatch_async_and_wait() observe all
* queue attributes of that queue when invoked (inluding autorelease frequency
* or QOS class).
*
* When the runtime has brought up a thread to invoke the asynchronous workitems
* already submitted to the specified queue, that servicing thread will also be
* used to execute synchronous work submitted to the queue with
* dispatch_async_and_wait().
*
* However, if the runtime has not brought up a thread to service the specified
* queue (because it has no workitems enqueued, or only synchronous workitems),
* then dispatch_async_and_wait() will invoke the workitem on the calling thread,
* similar to the behaviour of functions in the dispatch_sync family.
*
* As an exception, if the queue the work is submitted to doesn't target
* a global concurrent queue (for example because it targets the main queue),
* then the workitem will never be invoked by the thread calling
* dispatch_async_and_wait().
*
* In other words, dispatch_async_and_wait() is similar to submitting
* a dispatch_block_create()d workitem to a queue and then waiting on it, as
* shown in the code example below. However, dispatch_async_and_wait() is
* significantly more efficient when a new thread is not required to execute
* the workitem (as it will use the stack of the submitting thread instead of
* requiring heap allocations).
*
* <code>
* dispatch_block_t b = dispatch_block_create(0, block);
* dispatch_async(queue, b);
* dispatch_block_wait(b, DISPATCH_TIME_FOREVER);
* Block_release(b);
* </code>
*
* @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__
API_AVAILABLE(macos(10.14), ios(12.0), tvos(12.0), watchos(5.0))
DISPATCH_EXPORT DISPATCH_NONNULL_ALL DISPATCH_NOTHROW
void
dispatch_async_and_wait(dispatch_queue_t queue,
DISPATCH_NOESCAPE dispatch_block_t block);
#endif
/*!
* @function dispatch_async_and_wait_f
*
* @abstract
* Submits a function for synchronous execution on a dispatch queue.
*
* @discussion
* See dispatch_async_and_wait() 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_async_and_wait_f().
* The result of passing NULL in this parameter is undefined.
*/
API_AVAILABLE(macos(10.14), ios(12.0), tvos(12.0), watchos(5.0))
DISPATCH_EXPORT DISPATCH_NONNULL1 DISPATCH_NONNULL3 DISPATCH_NOTHROW
void
dispatch_async_and_wait_f(dispatch_queue_t queue,
void *_Nullable context, dispatch_function_t work);
/*!
* @function dispatch_barrier_async_and_wait
*
* @abstract
* Submits a block for synchronous execution on a dispatch queue.
*
* @discussion
* Submits a block to a dispatch queue like dispatch_async_and_wait(), but marks
* that block as a barrier (relevant only on DISPATCH_QUEUE_CONCURRENT
* queues).
*
* @param queue
* The target dispatch queue to which the block is submitted.
* The result of passing NULL in this parameter is undefined.
*
* @param work
* The application-defined block to invoke on the target queue.
* The result of passing NULL in this parameter is undefined.
*/
#ifdef __BLOCKS__
API_AVAILABLE(macos(10.14), ios(12.0), tvos(12.0), watchos(5.0))
DISPATCH_EXPORT DISPATCH_NONNULL_ALL DISPATCH_NOTHROW
void
dispatch_barrier_async_and_wait(dispatch_queue_t queue,
DISPATCH_NOESCAPE dispatch_block_t block);
#endif
/*!
* @function dispatch_barrier_async_and_wait_f
*
* @abstract
* Submits a function for synchronous execution on a dispatch queue.
*
* @discussion
* Submits a function to a dispatch queue like dispatch_async_and_wait_f(), but
* marks that function as a barrier (relevant only on DISPATCH_QUEUE_CONCURRENT
* queues).
*
* @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_barrier_async_and_wait_f().
* The result of passing NULL in this parameter is undefined.
*/
API_AVAILABLE(macos(10.14), ios(12.0), tvos(12.0), watchos(5.0))
DISPATCH_EXPORT DISPATCH_NONNULL1 DISPATCH_NONNULL3 DISPATCH_NOTHROW
void
dispatch_barrier_async_and_wait_f(dispatch_queue_t queue,
void *_Nullable context, dispatch_function_t work);
__END_DECLS
DISPATCH_ASSUME_NONNULL_END
#endif

View File

@@ -0,0 +1,26 @@
/*
* Copyright (c) 2010-2013 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.
*/

View File

@@ -0,0 +1,20 @@
/*
* Copyright (c) 2010-2013 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@
*/

View File

@@ -0,0 +1,31 @@
/*
* Copyright (c) 2010 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_RESOLVERS__
#define __DISPATCH_RESOLVERS__
#endif

View File

@@ -0,0 +1,9 @@
provider.h
module.map
module.build.map
.libs
*.lo
*.la
*.o
*.swiftmodule
*.swiftdoc

View File

@@ -0,0 +1,73 @@
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
#ifndef _Block_H_
#define _Block_H_
#if defined(_WIN32)
# if defined(BlocksRuntime_STATIC)
# define BLOCK_ABI
# else
# if defined(BlocksRuntime_EXPORTS)
# define BLOCK_ABI __declspec(dllexport)
# else
# define BLOCK_ABI __declspec(dllimport)
# endif
# endif
#else
# define BLOCK_ABI __attribute__((__visibility__("default")))
#endif
#if !defined(BLOCK_EXPORT)
# if defined(__cplusplus)
# define BLOCK_EXPORT extern "C" BLOCK_ABI
# else
# define BLOCK_EXPORT extern BLOCK_ABI
# endif
#endif
#if __cplusplus
extern "C" {
#endif
// Create a heap based copy of a Block or simply add a reference to an existing one.
// This must be paired with Block_release to recover memory, even when running
// under Objective-C Garbage Collection.
BLOCK_EXPORT void *_Block_copy(const void *aBlock);
// Lose the reference, and if heap based and last reference, recover the memory
BLOCK_EXPORT void _Block_release(const void *aBlock);
// Used by the compiler. Do not call this function yourself.
BLOCK_EXPORT void _Block_object_assign(void *, const void *, const int);
// Used by the compiler. Do not call this function yourself.
BLOCK_EXPORT void _Block_object_dispose(const void *, const int);
// Used by the compiler. Do not use these variables yourself.
#if defined(_WIN32)
extern void * _NSConcreteGlobalBlock[32];
extern void * _NSConcreteStackBlock[32];
#else
BLOCK_EXPORT void * _NSConcreteGlobalBlock[32];
BLOCK_EXPORT void * _NSConcreteStackBlock[32];
#endif
#if __cplusplus
}
#endif
// Type correct macros
#define Block_copy(...) ((__typeof(__VA_ARGS__))_Block_copy((const void *)(__VA_ARGS__)))
#define Block_release(...) _Block_release((const void *)(__VA_ARGS__))
#endif

View File

@@ -0,0 +1,264 @@
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
#ifndef _BLOCK_PRIVATE_H_
#define _BLOCK_PRIVATE_H_
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include "Block.h"
#if __cplusplus
extern "C" {
#endif
// Values for Block_layout->flags to describe block objects
enum {
BLOCK_DEALLOCATING = (0x0001), // runtime
BLOCK_REFCOUNT_MASK = (0xfffe), // runtime
BLOCK_NEEDS_FREE = (1 << 24), // runtime
BLOCK_HAS_COPY_DISPOSE = (1 << 25), // compiler
BLOCK_HAS_CTOR = (1 << 26), // compiler: helpers have C++ code
BLOCK_IS_GC = (1 << 27), // runtime
BLOCK_IS_GLOBAL = (1 << 28), // compiler
BLOCK_USE_STRET = (1 << 29), // compiler: undefined if !BLOCK_HAS_SIGNATURE
BLOCK_HAS_SIGNATURE = (1 << 30), // compiler
BLOCK_HAS_EXTENDED_LAYOUT=(1 << 31) // compiler
};
#define BLOCK_DESCRIPTOR_1 1
struct Block_descriptor_1 {
unsigned long int reserved;
unsigned long int size;
};
#define BLOCK_DESCRIPTOR_2 1
struct Block_descriptor_2 {
// requires BLOCK_HAS_COPY_DISPOSE
void (*copy)(void *dst, const void *src);
void (*dispose)(const void *);
};
#define BLOCK_DESCRIPTOR_3 1
struct Block_descriptor_3 {
// requires BLOCK_HAS_SIGNATURE
const char *signature;
const char *layout; // contents depend on BLOCK_HAS_EXTENDED_LAYOUT
};
struct Block_layout {
void *isa;
volatile int32_t flags; // contains ref count
int32_t reserved;
void (*invoke)(void *, ...);
struct Block_descriptor_1 *descriptor;
// imported variables
};
// Values for Block_byref->flags to describe __block variables
enum {
// Byref refcount must use the same bits as Block_layout's refcount.
// BLOCK_DEALLOCATING = (0x0001), // runtime
// BLOCK_REFCOUNT_MASK = (0xfffe), // runtime
BLOCK_BYREF_LAYOUT_MASK = (0xf << 28), // compiler
BLOCK_BYREF_LAYOUT_EXTENDED = ( 1 << 28), // compiler
BLOCK_BYREF_LAYOUT_NON_OBJECT = ( 2 << 28), // compiler
BLOCK_BYREF_LAYOUT_STRONG = ( 3 << 28), // compiler
BLOCK_BYREF_LAYOUT_WEAK = ( 4 << 28), // compiler
BLOCK_BYREF_LAYOUT_UNRETAINED = ( 5 << 28), // compiler
BLOCK_BYREF_IS_GC = ( 1 << 27), // runtime
BLOCK_BYREF_HAS_COPY_DISPOSE = ( 1 << 25), // compiler
BLOCK_BYREF_NEEDS_FREE = ( 1 << 24), // runtime
};
struct Block_byref {
void *isa;
struct Block_byref *forwarding;
volatile int32_t flags; // contains ref count
uint32_t size;
};
struct Block_byref_2 {
// requires BLOCK_BYREF_HAS_COPY_DISPOSE
void (*byref_keep)(struct Block_byref *dst, struct Block_byref *src);
void (*byref_destroy)(struct Block_byref *);
};
struct Block_byref_3 {
// requires BLOCK_BYREF_LAYOUT_EXTENDED
const char *layout;
};
// Extended layout encoding.
// Values for Block_descriptor_3->layout with BLOCK_HAS_EXTENDED_LAYOUT
// and for Block_byref_3->layout with BLOCK_BYREF_LAYOUT_EXTENDED
// If the layout field is less than 0x1000, then it is a compact encoding
// of the form 0xXYZ: X strong pointers, then Y byref pointers,
// then Z weak pointers.
// If the layout field is 0x1000 or greater, it points to a
// string of layout bytes. Each byte is of the form 0xPN.
// Operator P is from the list below. Value N is a parameter for the operator.
// Byte 0x00 terminates the layout; remaining block data is non-pointer bytes.
enum {
BLOCK_LAYOUT_ESCAPE = 0, // N=0 halt, rest is non-pointer. N!=0 reserved.
BLOCK_LAYOUT_NON_OBJECT_BYTES = 1, // N bytes non-objects
BLOCK_LAYOUT_NON_OBJECT_WORDS = 2, // N words non-objects
BLOCK_LAYOUT_STRONG = 3, // N words strong pointers
BLOCK_LAYOUT_BYREF = 4, // N words byref pointers
BLOCK_LAYOUT_WEAK = 5, // N words weak pointers
BLOCK_LAYOUT_UNRETAINED = 6, // N words unretained pointers
BLOCK_LAYOUT_UNKNOWN_WORDS_7 = 7, // N words, reserved
BLOCK_LAYOUT_UNKNOWN_WORDS_8 = 8, // N words, reserved
BLOCK_LAYOUT_UNKNOWN_WORDS_9 = 9, // N words, reserved
BLOCK_LAYOUT_UNKNOWN_WORDS_A = 0xA, // N words, reserved
BLOCK_LAYOUT_UNUSED_B = 0xB, // unspecified, reserved
BLOCK_LAYOUT_UNUSED_C = 0xC, // unspecified, reserved
BLOCK_LAYOUT_UNUSED_D = 0xD, // unspecified, reserved
BLOCK_LAYOUT_UNUSED_E = 0xE, // unspecified, reserved
BLOCK_LAYOUT_UNUSED_F = 0xF, // unspecified, reserved
};
// Runtime support functions used by compiler when generating copy/dispose helpers
// Values for _Block_object_assign() and _Block_object_dispose() parameters
enum {
// see function implementation for a more complete description of these fields and combinations
BLOCK_FIELD_IS_OBJECT = 3, // id, NSObject, __attribute__((NSObject)), block, ...
BLOCK_FIELD_IS_BLOCK = 7, // a block variable
BLOCK_FIELD_IS_BYREF = 8, // the on stack structure holding the __block variable
BLOCK_FIELD_IS_WEAK = 16, // declared __weak, only used in byref copy helpers
BLOCK_BYREF_CALLER = 128, // called from __block (byref) copy/dispose support routines.
};
enum {
BLOCK_ALL_COPY_DISPOSE_FLAGS =
BLOCK_FIELD_IS_OBJECT | BLOCK_FIELD_IS_BLOCK | BLOCK_FIELD_IS_BYREF |
BLOCK_FIELD_IS_WEAK | BLOCK_BYREF_CALLER
};
// Runtime entry point called by compiler when assigning objects inside copy helper routines
BLOCK_EXPORT void _Block_object_assign(void *destAddr, const void *object, const int flags);
// BLOCK_FIELD_IS_BYREF is only used from within block copy helpers
// runtime entry point called by the compiler when disposing of objects inside dispose helper routine
BLOCK_EXPORT void _Block_object_dispose(const void *object, const int flags);
// Other support functions
// runtime entry to get total size of a closure
BLOCK_EXPORT size_t Block_size(void *aBlock);
// indicates whether block was compiled with compiler that sets the ABI related metadata bits
BLOCK_EXPORT bool _Block_has_signature(void *aBlock);
// returns TRUE if return value of block is on the stack, FALSE otherwise
BLOCK_EXPORT bool _Block_use_stret(void *aBlock);
// Returns a string describing the block's parameter and return types.
// The encoding scheme is the same as Objective-C @encode.
// Returns NULL for blocks compiled with some compilers.
BLOCK_EXPORT const char * _Block_signature(void *aBlock);
// Returns a string describing the block's GC layout.
// This uses the GC skip/scan encoding.
// May return NULL.
BLOCK_EXPORT const char * _Block_layout(void *aBlock);
// Returns a string describing the block's layout.
// This uses the "extended layout" form described above.
// May return NULL.
BLOCK_EXPORT const char * _Block_extended_layout(void *aBlock);
// Callable only from the ARR weak subsystem while in exclusion zone
BLOCK_EXPORT bool _Block_tryRetain(const void *aBlock);
// Callable only from the ARR weak subsystem while in exclusion zone
BLOCK_EXPORT bool _Block_isDeallocating(const void *aBlock);
// the raw data space for runtime classes for blocks
// class+meta used for stack, malloc, and collectable based blocks
BLOCK_EXPORT void * _NSConcreteMallocBlock[32];
BLOCK_EXPORT void * _NSConcreteAutoBlock[32];
BLOCK_EXPORT void * _NSConcreteFinalizingBlock[32];
BLOCK_EXPORT void * _NSConcreteWeakBlockVariable[32];
// declared in Block.h
// BLOCK_EXPORT void * _NSConcreteGlobalBlock[32];
// BLOCK_EXPORT void * _NSConcreteStackBlock[32];
// the intercept routines that must be used under GC
BLOCK_EXPORT void _Block_use_GC( void *(*alloc)(const unsigned long, const bool isOne, const bool isObject),
void (*setHasRefcount)(const void *, const bool),
void (*gc_assign_strong)(void *, void **),
void (*gc_assign_weak)(const void *, void *),
void (*gc_memmove)(void *, void *, unsigned long));
// earlier version, now simply transitional
BLOCK_EXPORT void _Block_use_GC5( void *(*alloc)(const unsigned long, const bool isOne, const bool isObject),
void (*setHasRefcount)(const void *, const bool),
void (*gc_assign_strong)(void *, void **),
void (*gc_assign_weak)(const void *, void *));
BLOCK_EXPORT void _Block_use_RR( void (*retain)(const void *),
void (*release)(const void *));
struct Block_callbacks_RR {
size_t size; // size == sizeof(struct Block_callbacks_RR)
void (*retain)(const void *);
void (*release)(const void *);
void (*destructInstance)(const void *);
};
typedef struct Block_callbacks_RR Block_callbacks_RR;
BLOCK_EXPORT void _Block_use_RR2(const Block_callbacks_RR *callbacks);
// make a collectable GC heap based Block. Not useful under non-GC.
BLOCK_EXPORT void *_Block_copy_collectable(const void *aBlock);
// thread-unsafe diagnostic
BLOCK_EXPORT const char *_Block_dump(const void *block);
// Obsolete
// first layout
struct Block_basic {
void *isa;
int Block_flags; // int32_t
int Block_size; // XXX should be packed into Block_flags
void (*Block_invoke)(void *);
void (*Block_copy)(void *dst, void *src); // iff BLOCK_HAS_COPY_DISPOSE
void (*Block_dispose)(void *); // iff BLOCK_HAS_COPY_DISPOSE
//long params[0]; // where const imports, __block storage references, etc. get laid down
} __attribute__((deprecated));
#if __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,4 @@
LIBRARY BlocksRuntime
EXPORTS
_NSConcreteGlobalBlock CONSTANT
_NSConcreteStackBlock CONSTANT

View File

@@ -0,0 +1,42 @@
add_library(BlocksRuntime
data.c
runtime.c)
if(CMAKE_SYSTEM_NAME STREQUAL Windows)
target_sources(BlocksRuntime PRIVATE
BlocksRuntime.def)
if(NOT BUILD_SHARED_LIBS)
target_compile_definitions(BlocksRuntime PRIVATE
BlocksRuntime_STATIC)
endif()
endif()
target_include_directories(BlocksRuntime PUBLIC
${CMAKE_CURRENT_SOURCE_DIR})
if(HAVE_OBJC AND CMAKE_DL_LIBS)
target_link_libraries(BlocksRuntime PUBLIC
${CMAKE_DL_LIBS})
endif()
set_target_properties(BlocksRuntime PROPERTIES
POSITION_INDEPENDENT_CODE TRUE)
if(LINKER_SUPPORTS_BUILD_ID)
target_link_options(BlocksRuntime PRIVATE "LINKER:--build-id=sha1")
endif()
add_library(BlocksRuntime::BlocksRuntime ALIAS BlocksRuntime)
install(FILES Block.h
DESTINATION ${INSTALL_BLOCK_HEADERS_DIR})
if(INSTALL_PRIVATE_HEADERS)
install(FILES Block_private.h
DESTINATION ${INSTALL_BLOCK_HEADERS_DIR})
endif()
set_property(GLOBAL APPEND PROPERTY DISPATCH_EXPORTS BlocksRuntime)
install(TARGETS BlocksRuntime
EXPORT dispatchExports
ARCHIVE DESTINATION ${INSTALL_TARGET_DIR}
LIBRARY DESTINATION ${INSTALL_TARGET_DIR}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})

View File

@@ -0,0 +1,30 @@
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
/********************
NSBlock support
We allocate space and export a symbol to be used as the Class for the on-stack and malloc'ed copies until ObjC arrives on the scene. These data areas are set up by Foundation to link in as real classes post facto.
We keep these in a separate file so that we can include the runtime code in test subprojects but not include the data so that compiled code that sees the data in libSystem doesn't get confused by a second copy. Somehow these don't get unified in a common block.
**********************/
#include "Block.h"
#if defined(_WIN32)
void * _NSConcreteStackBlock[32] = { 0 };
void * _NSConcreteGlobalBlock[32] = { 0 };
#else
BLOCK_ABI void * _NSConcreteStackBlock[32] = { 0 };
BLOCK_ABI void * _NSConcreteGlobalBlock[32] = { 0 };
#endif
BLOCK_ABI void * _NSConcreteMallocBlock[32] = { 0 };
BLOCK_ABI void * _NSConcreteAutoBlock[32] = { 0 };
BLOCK_ABI void * _NSConcreteFinalizingBlock[32] = { 0 };
BLOCK_ABI void * _NSConcreteWeakBlockVariable[32] = { 0 };

View File

@@ -0,0 +1,760 @@
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2015 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
#include "Block_private.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#if HAVE_OBJC
#define __USE_GNU
#include <dlfcn.h>
#endif
#if __has_include(<os/assumes.h>)
#include <os/assumes.h>
#else
#include <assert.h>
#endif
#ifndef os_assumes
#define os_assumes(_x) _x
#endif
#ifndef os_assert
#define os_assert(_x) assert(_x)
#endif
#if !defined(__has_builtin)
#define __has_builtin(builtin) 0
#endif
#if __has_builtin(__sync_bool_compare_and_swap)
#define OSAtomicCompareAndSwapInt(_Old, _New, _Ptr) \
__sync_bool_compare_and_swap(_Ptr, _Old, _New)
#else
#define _CRT_SECURE_NO_WARNINGS 1
#include <Windows.h>
static __inline bool OSAtomicCompareAndSwapInt(int oldi, int newi,
int volatile *dst) {
// fixme barrier is overkill -- see objc-os.h
int original = InterlockedCompareExchange((LONG volatile *)dst, newi, oldi);
return (original == oldi);
}
#endif
/***********************
Globals
************************/
#if HAVE_OBJC
static void *_Block_copy_class = _NSConcreteMallocBlock;
static void *_Block_copy_finalizing_class = _NSConcreteMallocBlock;
static int _Block_copy_flag = BLOCK_NEEDS_FREE;
#endif
static int _Byref_flag_initial_value = BLOCK_BYREF_NEEDS_FREE | 4; // logical 2
static bool isGC = false;
/*******************************************************************************
Internal Utilities
********************************************************************************/
static int32_t latching_incr_int(volatile int32_t *where) {
while (1) {
int32_t old_value = *where;
if ((old_value & BLOCK_REFCOUNT_MASK) == BLOCK_REFCOUNT_MASK) {
return BLOCK_REFCOUNT_MASK;
}
if (OSAtomicCompareAndSwapInt(old_value, old_value+2, where)) {
return old_value+2;
}
}
}
static bool latching_incr_int_not_deallocating(volatile int32_t *where) {
while (1) {
int32_t old_value = *where;
if (old_value & BLOCK_DEALLOCATING) {
// if deallocating we can't do this
return false;
}
if ((old_value & BLOCK_REFCOUNT_MASK) == BLOCK_REFCOUNT_MASK) {
// if latched, we're leaking this block, and we succeed
return true;
}
if (OSAtomicCompareAndSwapInt(old_value, old_value+2, where)) {
// otherwise, we must store a new retained value without the deallocating bit set
return true;
}
}
}
// return should_deallocate?
static bool latching_decr_int_should_deallocate(volatile int32_t *where) {
while (1) {
int32_t old_value = *where;
if ((old_value & BLOCK_REFCOUNT_MASK) == BLOCK_REFCOUNT_MASK) {
return false; // latched high
}
if ((old_value & BLOCK_REFCOUNT_MASK) == 0) {
return false; // underflow, latch low
}
int32_t new_value = old_value - 2;
bool result = false;
if ((old_value & (BLOCK_REFCOUNT_MASK|BLOCK_DEALLOCATING)) == 2) {
new_value = old_value - 1;
result = true;
}
if (OSAtomicCompareAndSwapInt(old_value, new_value, where)) {
return result;
}
}
}
// hit zero?
static bool latching_decr_int_now_zero(volatile int32_t *where) {
while (1) {
int32_t old_value = *where;
if ((old_value & BLOCK_REFCOUNT_MASK) == BLOCK_REFCOUNT_MASK) {
return false; // latched high
}
if ((old_value & BLOCK_REFCOUNT_MASK) == 0) {
return false; // underflow, latch low
}
int32_t new_value = old_value - 2;
if (OSAtomicCompareAndSwapInt(old_value, new_value, where)) {
return (new_value & BLOCK_REFCOUNT_MASK) == 0;
}
}
}
/***********************
GC support stub routines
************************/
#if !defined(_MSC_VER) || defined(__clang__)
#pragma mark GC Support Routines
#endif
static void *_Block_alloc_default(size_t size, const bool initialCountIsOne, const bool isObject) {
(void)initialCountIsOne;
(void)isObject;
return malloc(size);
}
static void _Block_assign_default(void *value, void **destptr) {
*destptr = value;
}
static void _Block_setHasRefcount_default(const void *ptr, const bool hasRefcount) {
(void)ptr;
(void)hasRefcount;
}
#if HAVE_OBJC
static void _Block_do_nothing(const void *aBlock) { }
#endif
static void _Block_retain_object_default(const void *ptr) {
(void)ptr;
}
static void _Block_release_object_default(const void *ptr) {
(void)ptr;
}
static void _Block_assign_weak_default(const void *ptr, void *dest) {
#if !defined(_WIN32)
*(long *)dest = (long)ptr;
#else
*(void **)dest = (void *)ptr;
#endif
}
static void _Block_memmove_default(void *dst, void *src, unsigned long size) {
memmove(dst, src, (size_t)size);
}
#if HAVE_OBJC
static void _Block_memmove_gc_broken(void *dest, void *src, unsigned long size) {
void **destp = (void **)dest;
void **srcp = (void **)src;
while (size) {
_Block_assign_default(*srcp, destp);
destp++;
srcp++;
size -= sizeof(void *);
}
}
#endif
static void _Block_destructInstance_default(const void *aBlock) {
(void)aBlock;
}
/**************************************************************************
GC support callout functions - initially set to stub routines
***************************************************************************/
static void *(*_Block_allocator)(size_t, const bool isOne, const bool isObject) = _Block_alloc_default;
static void (*_Block_deallocator)(const void *) = (void (*)(const void *))free;
static void (*_Block_assign)(void *value, void **destptr) = _Block_assign_default;
static void (*_Block_setHasRefcount)(const void *ptr, const bool hasRefcount) = _Block_setHasRefcount_default;
static void (*_Block_retain_object)(const void *ptr) = _Block_retain_object_default;
static void (*_Block_release_object)(const void *ptr) = _Block_release_object_default;
static void (*_Block_assign_weak)(const void *dest, void *ptr) = _Block_assign_weak_default;
static void (*_Block_memmove)(void *dest, void *src, unsigned long size) = _Block_memmove_default;
static void (*_Block_destructInstance) (const void *aBlock) = _Block_destructInstance_default;
#if HAVE_OBJC
/**************************************************************************
GC support SPI functions - called from ObjC runtime and CoreFoundation
***************************************************************************/
// Public SPI
// Called from objc-auto to turn on GC.
// version 3, 4 arg, but changed 1st arg
void _Block_use_GC( void *(*alloc)(size_t, const bool isOne, const bool isObject),
void (*setHasRefcount)(const void *, const bool),
void (*gc_assign)(void *, void **),
void (*gc_assign_weak)(const void *, void *),
void (*gc_memmove)(void *, void *, unsigned long)) {
isGC = true;
_Block_allocator = alloc;
_Block_deallocator = _Block_do_nothing;
_Block_assign = gc_assign;
_Block_copy_flag = BLOCK_IS_GC;
_Block_copy_class = _NSConcreteAutoBlock;
// blocks with ctors & dtors need to have the dtor run from a class with a finalizer
_Block_copy_finalizing_class = _NSConcreteFinalizingBlock;
_Block_setHasRefcount = setHasRefcount;
_Byref_flag_initial_value = BLOCK_BYREF_IS_GC; // no refcount
_Block_retain_object = _Block_do_nothing;
_Block_release_object = _Block_do_nothing;
_Block_assign_weak = gc_assign_weak;
_Block_memmove = gc_memmove;
}
// transitional
void _Block_use_GC5( void *(*alloc)(size_t, const bool isOne, const bool isObject),
void (*setHasRefcount)(const void *, const bool),
void (*gc_assign)(void *, void **),
void (*gc_assign_weak)(const void *, void *)) {
// until objc calls _Block_use_GC it will call us; supply a broken internal memmove implementation until then
_Block_use_GC(alloc, setHasRefcount, gc_assign, gc_assign_weak, _Block_memmove_gc_broken);
}
// Called from objc-auto to alternatively turn on retain/release.
// Prior to this the only "object" support we can provide is for those
// super special objects that live in libSystem, namely dispatch queues.
// Blocks and Block_byrefs have their own special entry points.
BLOCK_EXPORT
void _Block_use_RR( void (*retain)(const void *),
void (*release)(const void *)) {
_Block_retain_object = retain;
_Block_release_object = release;
_Block_destructInstance = dlsym(RTLD_DEFAULT, "objc_destructInstance");
}
#endif // HAVE_OBJC
// Called from CF to indicate MRR. Newer version uses a versioned structure, so we can add more functions
// without defining a new entry point.
BLOCK_EXPORT
void _Block_use_RR2(const Block_callbacks_RR *callbacks) {
_Block_retain_object = callbacks->retain;
_Block_release_object = callbacks->release;
_Block_destructInstance = callbacks->destructInstance;
}
/****************************************************************************
Accessors for block descriptor fields
*****************************************************************************/
#if 0
static struct Block_descriptor_1 * _Block_descriptor_1(struct Block_layout *aBlock)
{
return aBlock->descriptor;
}
#endif
static struct Block_descriptor_2 * _Block_descriptor_2(struct Block_layout *aBlock)
{
if (! (aBlock->flags & BLOCK_HAS_COPY_DISPOSE)) return NULL;
uint8_t *desc = (uint8_t *)aBlock->descriptor;
desc += sizeof(struct Block_descriptor_1);
return (struct Block_descriptor_2 *)desc;
}
static struct Block_descriptor_3 * _Block_descriptor_3(struct Block_layout *aBlock)
{
if (! (aBlock->flags & BLOCK_HAS_SIGNATURE)) return NULL;
uint8_t *desc = (uint8_t *)aBlock->descriptor;
desc += sizeof(struct Block_descriptor_1);
if (aBlock->flags & BLOCK_HAS_COPY_DISPOSE) {
desc += sizeof(struct Block_descriptor_2);
}
return (struct Block_descriptor_3 *)desc;
}
static __inline bool _Block_has_layout(struct Block_layout *aBlock) {
if (! (aBlock->flags & BLOCK_HAS_SIGNATURE)) return false;
uint8_t *desc = (uint8_t *)aBlock->descriptor;
desc += sizeof(struct Block_descriptor_1);
if (aBlock->flags & BLOCK_HAS_COPY_DISPOSE) {
desc += sizeof(struct Block_descriptor_2);
}
return ((struct Block_descriptor_3 *)desc)->layout != NULL;
}
static void _Block_call_copy_helper(void *result, struct Block_layout *aBlock)
{
struct Block_descriptor_2 *desc = _Block_descriptor_2(aBlock);
if (!desc) return;
(*desc->copy)(result, aBlock); // do fixup
}
static void _Block_call_dispose_helper(struct Block_layout *aBlock)
{
struct Block_descriptor_2 *desc = _Block_descriptor_2(aBlock);
if (!desc) return;
(*desc->dispose)(aBlock);
}
/*******************************************************************************
Internal Support routines for copying
********************************************************************************/
#if !defined(_MSC_VER) || defined(__clang__)
#pragma mark Copy/Release support
#endif
// Copy, or bump refcount, of a block. If really copying, call the copy helper if present.
static void *_Block_copy_internal(const void *arg, const bool wantsOne) {
struct Block_layout *aBlock;
if (!arg) return NULL;
// The following would be better done as a switch statement
aBlock = (struct Block_layout *)arg;
if (aBlock->flags & BLOCK_NEEDS_FREE) {
// latches on high
latching_incr_int(&aBlock->flags);
return aBlock;
}
else if (aBlock->flags & BLOCK_IS_GC) {
// GC refcounting is expensive so do most refcounting here.
if (wantsOne && ((latching_incr_int(&aBlock->flags) & BLOCK_REFCOUNT_MASK) == 2)) {
// Tell collector to hang on this - it will bump the GC refcount version
_Block_setHasRefcount(aBlock, true);
}
return aBlock;
}
else if (aBlock->flags & BLOCK_IS_GLOBAL) {
return aBlock;
}
// Its a stack block. Make a copy.
if (!isGC) {
struct Block_layout *result = malloc(aBlock->descriptor->size);
if (!result) return NULL;
memmove(result, aBlock, aBlock->descriptor->size); // bitcopy first
// reset refcount
result->flags &= ~(BLOCK_REFCOUNT_MASK|BLOCK_DEALLOCATING); // XXX not needed
result->flags |= BLOCK_NEEDS_FREE | 2; // logical refcount 1
result->isa = _NSConcreteMallocBlock;
_Block_call_copy_helper(result, aBlock);
return result;
}
else {
// Under GC want allocation with refcount 1 so we ask for "true" if wantsOne
// This allows the copy helper routines to make non-refcounted block copies under GC
int32_t flags = aBlock->flags;
bool hasCTOR = (flags & BLOCK_HAS_CTOR) != 0;
struct Block_layout *result = _Block_allocator(aBlock->descriptor->size, wantsOne, hasCTOR || _Block_has_layout(aBlock));
if (!result) return NULL;
memmove(result, aBlock, aBlock->descriptor->size); // bitcopy first
// reset refcount
// if we copy a malloc block to a GC block then we need to clear NEEDS_FREE.
flags &= ~(BLOCK_NEEDS_FREE|BLOCK_REFCOUNT_MASK|BLOCK_DEALLOCATING); // XXX not needed
if (wantsOne)
flags |= BLOCK_IS_GC | 2;
else
flags |= BLOCK_IS_GC;
result->flags = flags;
_Block_call_copy_helper(result, aBlock);
if (hasCTOR) {
result->isa = _NSConcreteFinalizingBlock;
}
else {
result->isa = _NSConcreteAutoBlock;
}
return result;
}
}
// Runtime entry points for maintaining the sharing knowledge of byref data blocks.
// A closure has been copied and its fixup routine is asking us to fix up the reference to the shared byref data
// Closures that aren't copied must still work, so everyone always accesses variables after dereferencing the forwarding ptr.
// We ask if the byref pointer that we know about has already been copied to the heap, and if so, increment it.
// Otherwise we need to copy it and update the stack forwarding pointer
static void _Block_byref_assign_copy(void *dest, const void *arg, const int flags) {
struct Block_byref **destp = (struct Block_byref **)dest;
struct Block_byref *src = (struct Block_byref *)arg;
if (src->forwarding->flags & BLOCK_BYREF_IS_GC) {
; // don't need to do any more work
}
else if ((src->forwarding->flags & BLOCK_REFCOUNT_MASK) == 0) {
// src points to stack
bool isWeak = ((flags & (BLOCK_FIELD_IS_BYREF|BLOCK_FIELD_IS_WEAK)) == (BLOCK_FIELD_IS_BYREF|BLOCK_FIELD_IS_WEAK));
// if its weak ask for an object (only matters under GC)
struct Block_byref *copy = (struct Block_byref *)_Block_allocator(src->size, false, isWeak);
copy->flags = src->flags | _Byref_flag_initial_value; // non-GC one for caller, one for stack
copy->forwarding = copy; // patch heap copy to point to itself (skip write-barrier)
src->forwarding = copy; // patch stack to point to heap copy
copy->size = src->size;
if (isWeak) {
copy->isa = &_NSConcreteWeakBlockVariable; // mark isa field so it gets weak scanning
}
if (src->flags & BLOCK_BYREF_HAS_COPY_DISPOSE) {
// Trust copy helper to copy everything of interest
// If more than one field shows up in a byref block this is wrong XXX
struct Block_byref_2 *src2 = (struct Block_byref_2 *)(src+1);
struct Block_byref_2 *copy2 = (struct Block_byref_2 *)(copy+1);
copy2->byref_keep = src2->byref_keep;
copy2->byref_destroy = src2->byref_destroy;
if (src->flags & BLOCK_BYREF_LAYOUT_EXTENDED) {
struct Block_byref_3 *src3 = (struct Block_byref_3 *)(src2+1);
struct Block_byref_3 *copy3 = (struct Block_byref_3*)(copy2+1);
copy3->layout = src3->layout;
}
(*src2->byref_keep)(copy, src);
}
else {
// just bits. Blast 'em using _Block_memmove in case they're __strong
// This copy includes Block_byref_3, if any.
_Block_memmove(copy+1, src+1,
src->size - sizeof(struct Block_byref));
}
}
// already copied to heap
else if ((src->forwarding->flags & BLOCK_BYREF_NEEDS_FREE) == BLOCK_BYREF_NEEDS_FREE) {
latching_incr_int(&src->forwarding->flags);
}
// assign byref data block pointer into new Block
_Block_assign(src->forwarding, (void **)destp);
}
// Old compiler SPI
static void _Block_byref_release(const void *arg) {
struct Block_byref *byref = (struct Block_byref *)arg;
// dereference the forwarding pointer since the compiler isn't doing this anymore (ever?)
byref = byref->forwarding;
// To support C++ destructors under GC we arrange for there to be a finalizer for this
// by using an isa that directs the code to a finalizer that calls the byref_destroy method.
if ((byref->flags & BLOCK_BYREF_NEEDS_FREE) == 0) {
return; // stack or GC or global
}
os_assert(byref->flags & BLOCK_REFCOUNT_MASK);
if (latching_decr_int_should_deallocate(&byref->flags)) {
if (byref->flags & BLOCK_BYREF_HAS_COPY_DISPOSE) {
struct Block_byref_2 *byref2 = (struct Block_byref_2 *)(byref+1);
(*byref2->byref_destroy)(byref);
}
_Block_deallocator((struct Block_layout *)byref);
}
}
/************************************************************
*
* API supporting SPI
* _Block_copy, _Block_release, and (old) _Block_destroy
*
***********************************************************/
#if !defined(_MSC_VER) || defined(__clang__)
#pragma mark SPI/API
#endif
BLOCK_EXPORT
void *_Block_copy(const void *arg) {
return _Block_copy_internal(arg, true);
}
// API entry point to release a copied Block
BLOCK_EXPORT
void _Block_release(const void *arg) {
struct Block_layout *aBlock = (struct Block_layout *)arg;
if (!aBlock
|| (aBlock->flags & BLOCK_IS_GLOBAL)
|| ((aBlock->flags & (BLOCK_IS_GC|BLOCK_NEEDS_FREE)) == 0)
) return;
if (aBlock->flags & BLOCK_IS_GC) {
if (latching_decr_int_now_zero(&aBlock->flags)) {
// Tell GC we no longer have our own refcounts. GC will decr its refcount
// and unless someone has done a CFRetain or marked it uncollectable it will
// now be subject to GC reclamation.
_Block_setHasRefcount(aBlock, false);
}
}
else if (aBlock->flags & BLOCK_NEEDS_FREE) {
if (latching_decr_int_should_deallocate(&aBlock->flags)) {
_Block_call_dispose_helper(aBlock);
_Block_destructInstance(aBlock);
_Block_deallocator(aBlock);
}
}
}
BLOCK_EXPORT
bool _Block_tryRetain(const void *arg) {
struct Block_layout *aBlock = (struct Block_layout *)arg;
return latching_incr_int_not_deallocating(&aBlock->flags);
}
BLOCK_EXPORT
bool _Block_isDeallocating(const void *arg) {
struct Block_layout *aBlock = (struct Block_layout *)arg;
return (aBlock->flags & BLOCK_DEALLOCATING) != 0;
}
// Old Compiler SPI point to release a copied Block used by the compiler in dispose helpers
static void _Block_destroy(const void *arg) {
struct Block_layout *aBlock;
if (!arg) return;
aBlock = (struct Block_layout *)arg;
if (aBlock->flags & BLOCK_IS_GC) {
// assert(aBlock->Block_flags & BLOCK_HAS_CTOR);
return; // ignore, we are being called because of a DTOR
}
_Block_release(aBlock);
}
/************************************************************
*
* SPI used by other layers
*
***********************************************************/
// SPI, also internal. Called from NSAutoBlock only under GC
BLOCK_EXPORT
void *_Block_copy_collectable(const void *aBlock) {
return _Block_copy_internal(aBlock, false);
}
// SPI
BLOCK_EXPORT
size_t Block_size(void *aBlock) {
return ((struct Block_layout *)aBlock)->descriptor->size;
}
BLOCK_EXPORT
bool _Block_use_stret(void *aBlock) {
struct Block_layout *layout = (struct Block_layout *)aBlock;
int requiredFlags = BLOCK_HAS_SIGNATURE | BLOCK_USE_STRET;
return (layout->flags & requiredFlags) == requiredFlags;
}
// Checks for a valid signature, not merely the BLOCK_HAS_SIGNATURE bit.
BLOCK_EXPORT
bool _Block_has_signature(void *aBlock) {
return _Block_signature(aBlock) ? true : false;
}
BLOCK_EXPORT
const char * _Block_signature(void *aBlock)
{
struct Block_descriptor_3 *desc3 = _Block_descriptor_3(aBlock);
if (!desc3) return NULL;
return desc3->signature;
}
BLOCK_EXPORT
const char * _Block_layout(void *aBlock)
{
// Don't return extended layout to callers expecting GC layout
struct Block_layout *layout = (struct Block_layout *)aBlock;
if (layout->flags & BLOCK_HAS_EXTENDED_LAYOUT) return NULL;
struct Block_descriptor_3 *desc3 = _Block_descriptor_3(aBlock);
if (!desc3) return NULL;
return desc3->layout;
}
BLOCK_EXPORT
const char * _Block_extended_layout(void *aBlock)
{
// Don't return GC layout to callers expecting extended layout
struct Block_layout *layout = (struct Block_layout *)aBlock;
if (! (layout->flags & BLOCK_HAS_EXTENDED_LAYOUT)) return NULL;
struct Block_descriptor_3 *desc3 = _Block_descriptor_3(aBlock);
if (!desc3) return NULL;
// Return empty string (all non-object bytes) instead of NULL
// so callers can distinguish "empty layout" from "no layout".
if (!desc3->layout) return "";
else return desc3->layout;
}
#if !defined(_MSC_VER) || defined(__clang__)
#pragma mark Compiler SPI entry points
#endif
/*******************************************************
Entry points used by the compiler - the real API!
A Block can reference four different kinds of things that require help when the Block is copied to the heap.
1) C++ stack based objects
2) References to Objective-C objects
3) Other Blocks
4) __block variables
In these cases helper functions are synthesized by the compiler for use in Block_copy and Block_release, called the copy and dispose helpers. The copy helper emits a call to the C++ const copy constructor for C++ stack based objects and for the rest calls into the runtime support function _Block_object_assign. The dispose helper has a call to the C++ destructor for case 1 and a call into _Block_object_dispose for the rest.
The flags parameter of _Block_object_assign and _Block_object_dispose is set to
* BLOCK_FIELD_IS_OBJECT (3), for the case of an Objective-C Object,
* BLOCK_FIELD_IS_BLOCK (7), for the case of another Block, and
* BLOCK_FIELD_IS_BYREF (8), for the case of a __block variable.
If the __block variable is marked weak the compiler also or's in BLOCK_FIELD_IS_WEAK (16)
So the Block copy/dispose helpers should only ever generate the four flag values of 3, 7, 8, and 24.
When a __block variable is either a C++ object, an Objective-C object, or another Block then the compiler also generates copy/dispose helper functions. Similarly to the Block copy helper, the "__block" copy helper (formerly and still a.k.a. "byref" copy helper) will do a C++ copy constructor (not a const one though!) and the dispose helper will do the destructor. And similarly the helpers will call into the same two support functions with the same values for objects and Blocks with the additional BLOCK_BYREF_CALLER (128) bit of information supplied.
So the __block copy/dispose helpers will generate flag values of 3 or 7 for objects and Blocks respectively, with BLOCK_FIELD_IS_WEAK (16) or'ed as appropriate and always 128 or'd in, for the following set of possibilities:
__block id 128+3 (0x83)
__block (^Block) 128+7 (0x87)
__weak __block id 128+3+16 (0x93)
__weak __block (^Block) 128+7+16 (0x97)
********************************************************/
//
// When Blocks or Block_byrefs hold objects then their copy routine helpers use this entry point
// to do the assignment.
//
BLOCK_EXPORT
void _Block_object_assign(void *destAddr, const void *object, const int flags) {
switch (os_assumes(flags & BLOCK_ALL_COPY_DISPOSE_FLAGS)) {
case BLOCK_FIELD_IS_OBJECT:
/*******
id object = ...;
[^{ object; } copy];
********/
_Block_retain_object(object);
_Block_assign((void *)object, destAddr);
break;
case BLOCK_FIELD_IS_BLOCK:
/*******
void (^object)(void) = ...;
[^{ object; } copy];
********/
_Block_assign(_Block_copy_internal(object, false), destAddr);
break;
case BLOCK_FIELD_IS_BYREF | BLOCK_FIELD_IS_WEAK:
case BLOCK_FIELD_IS_BYREF:
/*******
// copy the onstack __block container to the heap
__block ... x;
__weak __block ... x;
[^{ x; } copy];
********/
_Block_byref_assign_copy(destAddr, object, flags);
break;
case BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_OBJECT:
case BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_BLOCK:
/*******
// copy the actual field held in the __block container
__block id object;
__block void (^object)(void);
[^{ object; } copy];
********/
// under manual retain release __block object/block variables are dangling
_Block_assign((void *)object, destAddr);
break;
case BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_OBJECT | BLOCK_FIELD_IS_WEAK:
case BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_BLOCK | BLOCK_FIELD_IS_WEAK:
/*******
// copy the actual field held in the __block container
__weak __block id object;
__weak __block void (^object)(void);
[^{ object; } copy];
********/
_Block_assign_weak(object, destAddr);
break;
default:
break;
}
}
// When Blocks or Block_byrefs hold objects their destroy helper routines call this entry point
// to help dispose of the contents
// Used initially only for __attribute__((NSObject)) marked pointers.
BLOCK_EXPORT
void _Block_object_dispose(const void *object, const int flags) {
switch (os_assumes(flags & BLOCK_ALL_COPY_DISPOSE_FLAGS)) {
case BLOCK_FIELD_IS_BYREF | BLOCK_FIELD_IS_WEAK:
case BLOCK_FIELD_IS_BYREF:
// get rid of the __block data structure held in a Block
_Block_byref_release(object);
break;
case BLOCK_FIELD_IS_BLOCK:
_Block_destroy(object);
break;
case BLOCK_FIELD_IS_OBJECT:
_Block_release_object(object);
break;
case BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_OBJECT:
case BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_BLOCK:
case BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_OBJECT | BLOCK_FIELD_IS_WEAK:
case BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_BLOCK | BLOCK_FIELD_IS_WEAK:
break;
default:
break;
}
}

View File

@@ -0,0 +1,194 @@
if(NOT CMAKE_SYSTEM_NAME STREQUAL Darwin)
add_subdirectory(BlocksRuntime)
endif()
add_library(dispatch
allocator.c
apply.c
benchmark.c
data.c
init.c
introspection.c
io.c
mach.c
object.c
once.c
queue.c
semaphore.c
source.c
time.c
transform.c
voucher.c
shims.c
protocol.defs
provider.d
allocator_internal.h
data_internal.h
inline_internal.h
internal.h
introspection_internal.h
io_internal.h
mach_internal.h
object_internal.h
queue_internal.h
semaphore_internal.h
shims.h
source_internal.h
trace.h
voucher_internal.h
event/event.c
event/event_config.h
event/event_epoll.c
event/event_internal.h
event/event_kevent.c
event/event_windows.c
firehose/firehose_internal.h
shims/android_stubs.h
shims/atomic.h
shims/atomic_sfb.h
shims/getprogname.h
shims/hw_config.h
shims/lock.c
shims/lock.h
shims/perfmon.h
shims/time.h
shims/tsd.h
shims/yield.c
shims/yield.h)
if(CMAKE_SYSTEM_NAME STREQUAL Windows)
target_sources(dispatch PRIVATE
shims/generic_sys_queue.h
shims/generic_win_stubs.c
shims/generic_win_stubs.h
shims/getprogname.c)
endif()
if(DISPATCH_USE_INTERNAL_WORKQUEUE)
target_sources(dispatch PRIVATE
event/workqueue.c
event/workqueue_internal.h)
endif()
target_sources(dispatch PRIVATE
block.cpp)
if(ENABLE_DTRACE)
dtrace_usdt_probe(${CMAKE_CURRENT_SOURCE_DIR}/provider.d OUTPUT_SOURCES
dispatch_dtrace_provider_headers)
target_sources(dispatch PRIVATE
${dispatch_dtrace_provider_headers})
endif()
if(HAVE_OBJC)
# TODO(compnerd) split DispatchStubs.cc into a separate component for the ObjC
# registration and a separate component for the swift compiler's emission of a
# call to the ObjC autorelease elision entry point.
target_sources(dispatch PRIVATE
data.m
object.m
swift/DispatchStubs.cc)
endif()
set_target_properties(dispatch PROPERTIES
POSITION_INDEPENDENT_CODE YES)
target_include_directories(dispatch PUBLIC
${PROJECT_BINARY_DIR}
${PROJECT_SOURCE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_BINARY_DIR})
target_include_directories(dispatch PRIVATE
${PROJECT_SOURCE_DIR}/private)
if(CMAKE_SYSTEM_NAME STREQUAL Windows)
target_compile_definitions(dispatch PRIVATE
_CRT_NONSTDC_NO_WARNINGS
_CRT_SECURE_NO_WARNINGS)
elseif(CMAKE_SYSTEM_NAME STREQUAL Android)
target_compile_options(dispatch PRIVATE
-U_GNU_SOURCE)
endif()
if(DISPATCH_ENABLE_ASSERTS)
target_compile_definitions(dispatch PRIVATE
DISPATCH_DEBUG=1)
endif()
if("${CMAKE_C_SIMULATE_ID}" STREQUAL "MSVC")
target_compile_options(dispatch PRIVATE /EHs-c-)
target_compile_options(dispatch PRIVATE /W3)
else()
target_compile_options(dispatch PRIVATE -fno-exceptions)
target_compile_options(dispatch PRIVATE -Wall)
endif()
# Work around a release-mode miscompile on windows arm64
# Disable /Os and /Ot in /O1 and /O2 on queue.c
if(("${CMAKE_C_SIMULATE_ID}" STREQUAL "MSVC") AND
(("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "ARM64") OR
("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "aarch64")))
string(TOUPPER "${CMAKE_BUILD_TYPE}" uppercase_CMAKE_BUILD_TYPE)
set(FLAGS_BUILD_TYPE "${CMAKE_C_FLAGS_${uppercase_CMAKE_BUILD_TYPE}}")
string(REGEX MATCHALL "/[Oo][12]" FLAGS "${CMAKE_C_FLAGS} ${FLAGS_BUILD_TYPE}")
if (FLAGS)
if (FLAGS MATCHES "1$")
set(FLAGS "/Od;/Og;/Oy;/Ob2;/GF;/Gy")
elseif (FLAGS MATCHES "2$")
set(FLAGS "/Od;/Og;/Oi;/Oy;/Ob2;/GF;/Gy")
endif()
set_source_files_properties(queue.c PROPERTIES COMPILE_OPTIONS "${FLAGS}")
endif()
endif()
# FIXME(compnerd) add check for -fblocks?
target_compile_options(dispatch PRIVATE -fblocks)
check_c_compiler_flag("-momit-leaf-frame-pointer -Werror -Wall -O3" C_SUPPORTS_OMIT_LEAF_FRAME_POINTER)
if (C_SUPPORTS_OMIT_LEAF_FRAME_POINTER)
target_compile_options(dispatch PRIVATE -momit-leaf-frame-pointer)
endif()
if(LibRT_FOUND)
target_link_libraries(dispatch PRIVATE RT::rt)
endif()
target_link_libraries(dispatch PRIVATE
Threads::Threads)
target_link_libraries(dispatch PUBLIC
BlocksRuntime::BlocksRuntime)
if(CMAKE_SYSTEM_NAME STREQUAL Windows)
target_link_libraries(dispatch PRIVATE
AdvAPI32
ShLwApi
WS2_32
WinMM
synchronization)
endif()
if(CMAKE_SYSTEM_NAME STREQUAL Darwin)
set_property(TARGET dispatch APPEND_STRING PROPERTY LINK_FLAGS
"-Xlinker -compatibility_version -Xlinker 1"
"-Xlinker -current_version -Xlinker ${VERSION}"
"-Xlinker -dead_strip"
"-Xlinker -alias_list -Xlinker ${PROJECT_SOURCE_DIR}/xcodeconfig/libdispatch.aliases")
endif()
if(NOT CMAKE_SYSTEM_NAME MATCHES "Darwin|Windows")
set_target_properties(dispatch PROPERTIES INSTALL_RPATH "$ORIGIN")
endif()
if(LINKER_SUPPORTS_BUILD_ID)
target_link_options(dispatch PRIVATE "LINKER:--build-id=sha1")
endif()
if(ENABLE_SWIFT)
add_subdirectory(swift)
endif()
set_property(GLOBAL APPEND PROPERTY DISPATCH_EXPORTS dispatch)
install(TARGETS dispatch
EXPORT dispatchExports
ARCHIVE DESTINATION ${INSTALL_TARGET_DIR}
LIBRARY DESTINATION ${INSTALL_TARGET_DIR}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})

View File

@@ -0,0 +1,797 @@
/*
* Copyright (c) 2012-2013 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 "allocator_internal.h"
#if DISPATCH_ALLOCATOR
#ifndef VM_MEMORY_LIBDISPATCH
#define VM_MEMORY_LIBDISPATCH 74
#endif
// _dispatch_main_heap is is the first heap in the linked list, where searches
// always begin.
//
// _dispatch_main_heap, and dh_next, are read normally but only written (in
// try_create_heap) by cmpxchg. They start life at 0, and are only written
// once to non-zero. They are not marked volatile. There is a small risk that
// some thread may see a stale 0 value and enter try_create_heap. It will
// waste some time in an allocate syscall, but eventually it will try to
// cmpxchg, expecting to overwrite 0 with an address. This will fail
// (because another thread already did this), the thread will deallocate the
// unused allocated memory, and continue with the new value.
//
// If something goes wrong here, the symptom would be a NULL dereference
// in alloc_continuation_from_heap or _magazine when derefing the magazine ptr.
DISPATCH_GLOBAL(dispatch_heap_t _dispatch_main_heap);
DISPATCH_ALWAYS_INLINE
static void
set_last_found_page(bitmap_t *val)
{
dispatch_assert(_dispatch_main_heap);
unsigned int cpu = _dispatch_cpu_number();
_dispatch_main_heap[cpu].header.last_found_page = val;
}
DISPATCH_ALWAYS_INLINE
static bitmap_t *
last_found_page(void)
{
dispatch_assert(_dispatch_main_heap);
unsigned int cpu = _dispatch_cpu_number();
return _dispatch_main_heap[cpu].header.last_found_page;
}
#pragma mark -
#pragma mark dispatch_alloc_bitmaps
DISPATCH_ALWAYS_INLINE_NDEBUG DISPATCH_CONST
static bitmap_t *
supermap_address(struct dispatch_magazine_s *magazine, unsigned int supermap)
{
return &magazine->supermaps[supermap];
}
DISPATCH_ALWAYS_INLINE_NDEBUG DISPATCH_CONST
static bitmap_t *
bitmap_address(struct dispatch_magazine_s *magazine, unsigned int supermap,
unsigned int map)
{
return &magazine->maps[supermap][map];
}
DISPATCH_ALWAYS_INLINE_NDEBUG DISPATCH_CONST
static dispatch_continuation_t
continuation_address(struct dispatch_magazine_s *magazine,
unsigned int supermap, unsigned int map, unsigned int index)
{
#if DISPATCH_DEBUG
dispatch_assert(supermap < SUPERMAPS_PER_MAGAZINE);
dispatch_assert(map < BITMAPS_PER_SUPERMAP);
dispatch_assert(index < CONTINUATIONS_PER_BITMAP);
#endif
return (dispatch_continuation_t)&magazine->conts[supermap][map][index];
}
DISPATCH_ALWAYS_INLINE_NDEBUG DISPATCH_CONST
static struct dispatch_magazine_s *
magazine_for_continuation(dispatch_continuation_t c)
{
return (struct dispatch_magazine_s *)((uintptr_t)c & MAGAZINE_MASK);
}
DISPATCH_ALWAYS_INLINE_NDEBUG
static void
get_cont_and_indices_for_bitmap_and_index(bitmap_t *bitmap,
unsigned int index, dispatch_continuation_t *continuation_out,
bitmap_t **supermap_out, unsigned int *bitmap_index_out)
{
// m_for_c wants a continuation not a bitmap, but it works because it
// just masks off the bottom bits of the address.
struct dispatch_magazine_s *m = magazine_for_continuation((void *)bitmap);
unsigned int mindex = (unsigned int)(bitmap - m->maps[0]);
unsigned int bindex = mindex % BITMAPS_PER_SUPERMAP;
unsigned int sindex = mindex / BITMAPS_PER_SUPERMAP;
dispatch_assert(&m->maps[sindex][bindex] == bitmap);
if (likely(continuation_out)) {
*continuation_out = continuation_address(m, sindex, bindex, index);
}
if (likely(supermap_out)) *supermap_out = supermap_address(m, sindex);
if (likely(bitmap_index_out)) *bitmap_index_out = bindex;
}
DISPATCH_ALWAYS_INLINE_NDEBUG DISPATCH_CONST
static bool
continuation_is_in_first_page(dispatch_continuation_t c)
{
#if PACK_FIRST_PAGE_WITH_CONTINUATIONS
// (the base of c's magazine == the base of c's page)
// => c is in first page of magazine
return (((uintptr_t)c & MAGAZINE_MASK) ==
((uintptr_t)c & ~(uintptr_t)DISPATCH_ALLOCATOR_PAGE_MASK));
#else
(void)c;
return false;
#endif
}
DISPATCH_ALWAYS_INLINE_NDEBUG
static void
get_maps_and_indices_for_continuation(dispatch_continuation_t c,
bitmap_t **supermap_out, unsigned int *bitmap_index_out,
bitmap_t **bitmap_out, unsigned int *index_out)
{
unsigned int cindex, sindex, index, mindex;
padded_continuation *p = (padded_continuation *)c;
struct dispatch_magazine_s *m = magazine_for_continuation(c);
#if PACK_FIRST_PAGE_WITH_CONTINUATIONS
if (likely(continuation_is_in_first_page(c))) {
cindex = (unsigned int)(p - m->fp_conts);
index = cindex % CONTINUATIONS_PER_BITMAP;
mindex = cindex / CONTINUATIONS_PER_BITMAP;
if (likely(supermap_out)) *supermap_out = NULL;
if (likely(bitmap_index_out)) *bitmap_index_out = mindex;
if (likely(bitmap_out)) *bitmap_out = &m->fp_maps[mindex];
if (likely(index_out)) *index_out = index;
return;
}
#endif // PACK_FIRST_PAGE_WITH_CONTINUATIONS
cindex = (unsigned int)(p - (padded_continuation *)m->conts);
sindex = cindex / (BITMAPS_PER_SUPERMAP * CONTINUATIONS_PER_BITMAP);
mindex = (cindex / CONTINUATIONS_PER_BITMAP) % BITMAPS_PER_SUPERMAP;
index = cindex % CONTINUATIONS_PER_BITMAP;
if (likely(supermap_out)) *supermap_out = &m->supermaps[sindex];
if (likely(bitmap_index_out)) *bitmap_index_out = mindex;
if (likely(bitmap_out)) *bitmap_out = &m->maps[sindex][mindex];
if (likely(index_out)) *index_out = index;
}
// Base address of page, or NULL if this page shouldn't be madvise()d
DISPATCH_ALWAYS_INLINE_NDEBUG DISPATCH_CONST
static void *
madvisable_page_base_for_continuation(dispatch_continuation_t c)
{
if (likely(continuation_is_in_first_page(c))) {
return NULL;
}
void *page_base = (void *)((uintptr_t)c &
~(uintptr_t)DISPATCH_ALLOCATOR_PAGE_MASK);
#if DISPATCH_DEBUG
struct dispatch_magazine_s *m = magazine_for_continuation(c);
if (unlikely(page_base < (void *)&m->conts)) {
DISPATCH_INTERNAL_CRASH(page_base, "madvisable continuation too low");
}
if (unlikely(page_base > (void *)&m->conts[SUPERMAPS_PER_MAGAZINE-1]
[BITMAPS_PER_SUPERMAP-1][CONTINUATIONS_PER_BITMAP-1])) {
DISPATCH_INTERNAL_CRASH(page_base, "madvisable continuation too high");
}
#endif
return page_base;
}
// Bitmap that controls the first few continuations in the same page as
// the continuations controlled by the passed bitmap. Undefined results if the
// passed bitmap controls continuations in the first page.
DISPATCH_ALWAYS_INLINE_NDEBUG DISPATCH_CONST
static bitmap_t *
first_bitmap_in_same_page(bitmap_t *b)
{
#if DISPATCH_DEBUG
struct dispatch_magazine_s *m;
m = magazine_for_continuation((void*)b);
dispatch_assert(b >= &m->maps[0][0]);
dispatch_assert(b < &m->maps[SUPERMAPS_PER_MAGAZINE]
[BITMAPS_PER_SUPERMAP]);
#endif
const uintptr_t PAGE_BITMAP_MASK = (BITMAPS_PER_PAGE *
BYTES_PER_BITMAP) - 1;
return (bitmap_t *)((uintptr_t)b & ~PAGE_BITMAP_MASK);
}
DISPATCH_ALWAYS_INLINE_NDEBUG DISPATCH_CONST
static bool
bitmap_is_full(bitmap_t bits)
{
return (bits == BITMAP_ALL_ONES);
}
#define NO_BITS_WERE_UNSET (UINT_MAX)
// max_index is the 0-based position of the most significant bit that is
// allowed to be set.
DISPATCH_ALWAYS_INLINE_NDEBUG
static unsigned int
bitmap_set_first_unset_bit_upto_index(volatile bitmap_t *bitmap,
unsigned int max_index)
{
// No barriers needed in acquire path: the just-allocated
// continuation is "uninitialized", so the caller shouldn't
// load from it before storing, so we don't need to guard
// against reordering those loads.
dispatch_assert(sizeof(*bitmap) == sizeof(unsigned long));
return os_atomic_set_first_bit(bitmap, max_index);
}
DISPATCH_ALWAYS_INLINE
static unsigned int
bitmap_set_first_unset_bit(volatile bitmap_t *bitmap)
{
return bitmap_set_first_unset_bit_upto_index(bitmap, UINT_MAX);
}
#define CLEAR_EXCLUSIVELY true
#define CLEAR_NONEXCLUSIVELY false
// Return true if this bit was the last in the bitmap, and it is now all zeroes
DISPATCH_ALWAYS_INLINE_NDEBUG
static bool
bitmap_clear_bit(volatile bitmap_t *bitmap, unsigned int index,
bool exclusively)
{
#if DISPATCH_DEBUG
dispatch_assert(index < CONTINUATIONS_PER_BITMAP);
#endif
const bitmap_t mask = BITMAP_C(1) << index;
bitmap_t b;
if (exclusively == CLEAR_EXCLUSIVELY) {
if (unlikely((*bitmap & mask) == 0)) {
DISPATCH_CLIENT_CRASH(*bitmap,
"Corruption: failed to clear bit exclusively");
}
}
// and-and-fetch
b = os_atomic_and(bitmap, ~mask, release);
return b == 0;
}
DISPATCH_ALWAYS_INLINE_NDEBUG
static void
mark_bitmap_as_full_if_still_full(volatile bitmap_t *supermap,
unsigned int bitmap_index, volatile bitmap_t *bitmap)
{
#if DISPATCH_DEBUG
dispatch_assert(bitmap_index < BITMAPS_PER_SUPERMAP);
#endif
const bitmap_t mask = BITMAP_C(1) << bitmap_index;
bitmap_t s, s_new;
// No barriers because supermaps are only advisory, they
// don't protect access to other memory.
os_atomic_rmw_loop(supermap, s, s_new, relaxed, {
if (!bitmap_is_full(*bitmap)) {
os_atomic_rmw_loop_give_up(return);
}
s_new = s | mask;
});
}
#pragma mark -
#pragma mark dispatch_alloc_continuation_alloc
#if PACK_FIRST_PAGE_WITH_CONTINUATIONS
DISPATCH_ALWAYS_INLINE_NDEBUG
static dispatch_continuation_t
alloc_continuation_from_first_page(struct dispatch_magazine_s *magazine)
{
unsigned int i, index, continuation_index;
// TODO: unroll if this is hot?
for (i = 0; i < FULL_BITMAPS_IN_FIRST_PAGE; i++) {
index = bitmap_set_first_unset_bit(&magazine->fp_maps[i]);
if (likely(index != NO_BITS_WERE_UNSET)) goto found;
}
if (REMAINDERED_CONTINUATIONS_IN_FIRST_PAGE) {
index = bitmap_set_first_unset_bit_upto_index(&magazine->fp_maps[i],
REMAINDERED_CONTINUATIONS_IN_FIRST_PAGE - 1);
if (likely(index != NO_BITS_WERE_UNSET)) goto found;
}
return NULL;
found:
continuation_index = (i * CONTINUATIONS_PER_BITMAP) + index;
return (dispatch_continuation_t)&magazine->fp_conts[continuation_index];
}
#endif // PACK_FIRST_PAGE_WITH_CONTINUATIONS
DISPATCH_ALWAYS_INLINE_NDEBUG
static dispatch_continuation_t
alloc_continuation_from_magazine(struct dispatch_magazine_s *magazine)
{
unsigned int s, b, index;
for (s = 0; s < SUPERMAPS_PER_MAGAZINE; s++) {
volatile bitmap_t *supermap = supermap_address(magazine, s);
if (bitmap_is_full(*supermap)) {
continue;
}
for (b = 0; b < BITMAPS_PER_SUPERMAP; b++) {
volatile bitmap_t *bitmap = bitmap_address(magazine, s, b);
index = bitmap_set_first_unset_bit(bitmap);
if (index != NO_BITS_WERE_UNSET) {
set_last_found_page(
first_bitmap_in_same_page((bitmap_t *)bitmap));
mark_bitmap_as_full_if_still_full(supermap, b, bitmap);
return continuation_address(magazine, s, b, index);
}
}
}
return NULL;
}
DISPATCH_NOINLINE
static void
_dispatch_alloc_try_create_heap(dispatch_heap_t *heap_ptr)
{
#if HAVE_MACH
kern_return_t kr;
mach_vm_size_t vm_size = MAGAZINES_PER_HEAP * BYTES_PER_MAGAZINE;
mach_vm_offset_t vm_mask = ~MAGAZINE_MASK;
mach_vm_address_t vm_addr = vm_page_size;
while (unlikely(kr = mach_vm_map(mach_task_self(), &vm_addr, vm_size,
vm_mask, VM_FLAGS_ANYWHERE | VM_MAKE_TAG(VM_MEMORY_LIBDISPATCH),
MEMORY_OBJECT_NULL, 0, FALSE, VM_PROT_DEFAULT, VM_PROT_ALL,
VM_INHERIT_DEFAULT))) {
if (kr != KERN_NO_SPACE) {
DISPATCH_CLIENT_CRASH(kr, "Could not allocate heap");
}
_dispatch_temporary_resource_shortage();
vm_addr = vm_page_size;
}
uintptr_t aligned_region = (uintptr_t)vm_addr;
#else // HAVE_MACH
const size_t region_sz = (1 + MAGAZINES_PER_HEAP) * BYTES_PER_MAGAZINE;
void *region_p;
while (!dispatch_assume((region_p = mmap(NULL, region_sz,
PROT_READ|PROT_WRITE, MAP_ANON | MAP_PRIVATE,
VM_MAKE_TAG(VM_MEMORY_LIBDISPATCH), 0)) != MAP_FAILED)) {
_dispatch_temporary_resource_shortage();
}
uintptr_t region = (uintptr_t)region_p;
uintptr_t region_end = region + region_sz;
uintptr_t aligned_region, aligned_region_end;
uintptr_t bottom_slop_len, top_slop_len;
// Realign if needed; find the slop at top/bottom to unmap
if ((region & ~(MAGAZINE_MASK)) == 0) {
bottom_slop_len = 0;
aligned_region = region;
aligned_region_end = region_end - BYTES_PER_MAGAZINE;
top_slop_len = BYTES_PER_MAGAZINE;
} else {
aligned_region = (region & MAGAZINE_MASK) + BYTES_PER_MAGAZINE;
aligned_region_end = aligned_region +
(MAGAZINES_PER_HEAP * BYTES_PER_MAGAZINE);
bottom_slop_len = aligned_region - region;
top_slop_len = BYTES_PER_MAGAZINE - bottom_slop_len;
}
#if DISPATCH_DEBUG
// Double-check our math.
dispatch_assert(aligned_region % DISPATCH_ALLOCATOR_PAGE_SIZE == 0);
dispatch_assert(aligned_region % vm_kernel_page_size == 0);
dispatch_assert(aligned_region_end % DISPATCH_ALLOCATOR_PAGE_SIZE == 0);
dispatch_assert(aligned_region_end % vm_kernel_page_size == 0);
dispatch_assert(aligned_region_end > aligned_region);
dispatch_assert(top_slop_len % DISPATCH_ALLOCATOR_PAGE_SIZE == 0);
dispatch_assert(bottom_slop_len % DISPATCH_ALLOCATOR_PAGE_SIZE == 0);
dispatch_assert(aligned_region_end + top_slop_len == region_end);
dispatch_assert(region + bottom_slop_len == aligned_region);
dispatch_assert(region_sz == bottom_slop_len + top_slop_len +
MAGAZINES_PER_HEAP * BYTES_PER_MAGAZINE);
if (bottom_slop_len) {
(void)dispatch_assume_zero(mprotect((void *)region, bottom_slop_len,
PROT_NONE));
}
if (top_slop_len) {
(void)dispatch_assume_zero(mprotect((void *)aligned_region_end,
top_slop_len, PROT_NONE));
}
#else
if (bottom_slop_len) {
(void)dispatch_assume_zero(munmap((void *)region, bottom_slop_len));
}
if (top_slop_len) {
(void)dispatch_assume_zero(munmap((void *)aligned_region_end,
top_slop_len));
}
#endif // DISPATCH_DEBUG
#endif // HAVE_MACH
if (!os_atomic_cmpxchg(heap_ptr, NULL, (void *)aligned_region,
relaxed)) {
// If we lost the race to link in the new region, unmap the whole thing.
#if DISPATCH_DEBUG
(void)dispatch_assume_zero(mprotect((void *)aligned_region,
MAGAZINES_PER_HEAP * BYTES_PER_MAGAZINE, PROT_NONE));
#else
(void)dispatch_assume_zero(munmap((void *)aligned_region,
MAGAZINES_PER_HEAP * BYTES_PER_MAGAZINE));
#endif
}
}
DISPATCH_NOINLINE
static dispatch_continuation_t
_dispatch_alloc_continuation_from_heap(dispatch_heap_t heap)
{
dispatch_continuation_t cont;
unsigned int cpu_number = _dispatch_cpu_number();
#ifdef DISPATCH_DEBUG
dispatch_assert(cpu_number < NUM_CPU);
#endif
#if PACK_FIRST_PAGE_WITH_CONTINUATIONS
// First try the continuations in the first page for this CPU
cont = alloc_continuation_from_first_page(&(heap[cpu_number]));
if (likely(cont)) {
return cont;
}
#endif
// Next, try the rest of the magazine for this CPU
cont = alloc_continuation_from_magazine(&(heap[cpu_number]));
return cont;
}
DISPATCH_NOINLINE
static dispatch_continuation_t
_dispatch_alloc_continuation_from_heap_slow(void)
{
dispatch_heap_t *heap = &_dispatch_main_heap;
dispatch_continuation_t cont;
for (;;) {
if (unlikely(!*heap)) {
_dispatch_alloc_try_create_heap(heap);
}
cont = _dispatch_alloc_continuation_from_heap(*heap);
if (likely(cont)) {
return cont;
}
// If we have tuned our parameters right, 99.999% of apps should
// never reach this point! The ones that do have gone off the rails...
//
// Magazine is full? Onto the next heap!
// We tried 'stealing' from other CPUs' magazines. The net effect
// was worse performance from more wasted search time and more
// cache contention.
// rdar://11378331
// Future optimization: start at the page we last used, start
// in the *zone* we last used. But this would only improve deeply
// pathological cases like dispatch_starfish
heap = &(*heap)->header.dh_next;
}
}
DISPATCH_ALLOC_NOINLINE
static dispatch_continuation_t
_dispatch_alloc_continuation_alloc(void)
{
dispatch_continuation_t cont;
if (likely(_dispatch_main_heap)) {
// Start looking in the same page where we found a continuation
// last time.
bitmap_t *last = last_found_page();
if (likely(last)) {
unsigned int i;
for (i = 0; i < BITMAPS_PER_PAGE; i++) {
bitmap_t *cur = last + i;
unsigned int index = bitmap_set_first_unset_bit(cur);
if (likely(index != NO_BITS_WERE_UNSET)) {
bitmap_t *supermap;
unsigned int bindex;
get_cont_and_indices_for_bitmap_and_index(cur,
index, &cont, &supermap, &bindex);
mark_bitmap_as_full_if_still_full(supermap, bindex,
cur);
return cont;
}
}
}
cont = _dispatch_alloc_continuation_from_heap(_dispatch_main_heap);
if (likely(cont)) {
return cont;
}
}
return _dispatch_alloc_continuation_from_heap_slow();
}
#pragma mark -
#pragma mark dispatch_alloc_continuation_free
DISPATCH_NOINLINE
static void
_dispatch_alloc_maybe_madvise_page(dispatch_continuation_t c)
{
void *page = madvisable_page_base_for_continuation(c);
if (!page) {
// page can't be madvised; maybe it contains non-continuations
return;
}
// Are all the continuations in this page unallocated?
volatile bitmap_t *page_bitmaps;
get_maps_and_indices_for_continuation((dispatch_continuation_t)page, NULL,
NULL, (bitmap_t **)&page_bitmaps, NULL);
unsigned int i;
for (i = 0; i < BITMAPS_PER_PAGE; i++) {
if (page_bitmaps[i] != 0) {
return;
}
}
// They are all unallocated, so we could madvise the page. Try to
// take ownership of them all.
int last_locked = 0;
do {
if (!os_atomic_cmpxchg(&page_bitmaps[last_locked], BITMAP_C(0),
BITMAP_ALL_ONES, relaxed)) {
// We didn't get one; since there is a cont allocated in
// the page, we can't madvise. Give up and unlock all.
goto unlock;
}
} while (++last_locked < (signed)BITMAPS_PER_PAGE);
#if DISPATCH_DEBUG
//fprintf(stderr, "%s: madvised page %p for cont %p (next = %p), "
// "[%u+1]=%u bitmaps at %p\n", __func__, page, c, c->do_next,
// last_locked-1, BITMAPS_PER_PAGE, &page_bitmaps[0]);
// Scribble to expose use-after-free bugs
// madvise (syscall) flushes these stores
memset(page, DISPATCH_ALLOCATOR_SCRIBBLE, DISPATCH_ALLOCATOR_PAGE_SIZE);
#endif
(void)dispatch_assume_zero(madvise(page, DISPATCH_ALLOCATOR_PAGE_SIZE,
MADV_FREE));
unlock:
while (last_locked > 1) {
page_bitmaps[--last_locked] = BITMAP_C(0);
}
if (last_locked) {
os_atomic_store(&page_bitmaps[0], BITMAP_C(0), relaxed);
}
return;
}
DISPATCH_ALLOC_NOINLINE
static void
_dispatch_alloc_continuation_free(dispatch_continuation_t c)
{
bitmap_t *b, *s;
unsigned int b_idx, idx;
c->dc_flags = 0;
get_maps_and_indices_for_continuation(c, &s, &b_idx, &b, &idx);
bool bitmap_now_empty = bitmap_clear_bit(b, idx, CLEAR_EXCLUSIVELY);
if (unlikely(s)) {
(void)bitmap_clear_bit(s, b_idx, CLEAR_NONEXCLUSIVELY);
}
// We only try to madvise(2) pages outside of the first page.
// (Allocations in the first page do not have a supermap entry.)
if (unlikely(bitmap_now_empty && s)) {
return _dispatch_alloc_maybe_madvise_page(c);
}
}
#pragma mark -
#pragma mark dispatch_alloc_init
#if DISPATCH_CONTINUATION_MALLOC || DISPATCH_DEBUG
static void
_dispatch_alloc_init(void)
{
// Double-check our math. These are all compile time checks and don't
// generate code.
dispatch_static_assert(sizeof(bitmap_t) == BYTES_PER_BITMAP);
dispatch_static_assert(sizeof(bitmap_t) == BYTES_PER_SUPERMAP);
dispatch_static_assert(sizeof(struct dispatch_magazine_header_s) ==
SIZEOF_HEADER);
dispatch_static_assert(sizeof(struct dispatch_continuation_s) <=
DISPATCH_CONTINUATION_SIZE);
// Magazines should be the right size, so they pack neatly into an array of
// heaps.
dispatch_static_assert(sizeof(struct dispatch_magazine_s) ==
BYTES_PER_MAGAZINE);
// The header and maps sizes should match what we computed.
dispatch_static_assert(SIZEOF_HEADER ==
sizeof(((struct dispatch_magazine_s *)0x0)->header));
dispatch_static_assert(SIZEOF_MAPS ==
sizeof(((struct dispatch_magazine_s *)0x0)->maps));
// The main array of continuations should start at the second page,
// self-aligned.
dispatch_static_assert(offsetof(struct dispatch_magazine_s, conts) %
(CONTINUATIONS_PER_BITMAP * DISPATCH_CONTINUATION_SIZE) == 0);
dispatch_static_assert(offsetof(struct dispatch_magazine_s, conts) ==
DISPATCH_ALLOCATOR_PAGE_SIZE);
#if PACK_FIRST_PAGE_WITH_CONTINUATIONS
// The continuations in the first page should actually fit within the first
// page.
dispatch_static_assert(offsetof(struct dispatch_magazine_s, fp_conts) <
DISPATCH_ALLOCATOR_PAGE_SIZE);
dispatch_static_assert(offsetof(struct dispatch_magazine_s, fp_conts) %
DISPATCH_CONTINUATION_SIZE == 0);
dispatch_static_assert(offsetof(struct dispatch_magazine_s, fp_conts) +
sizeof(((struct dispatch_magazine_s *)0x0)->fp_conts) ==
DISPATCH_ALLOCATOR_PAGE_SIZE);
#endif // PACK_FIRST_PAGE_WITH_CONTINUATIONS
// Make sure our alignment will be correct: that is, that we are correctly
// aligning to both.
dispatch_static_assert(ROUND_UP_TO_BITMAP_ALIGNMENT(ROUND_UP_TO_BITMAP_ALIGNMENT_AND_CONTINUATION_SIZE(1)) ==
ROUND_UP_TO_BITMAP_ALIGNMENT_AND_CONTINUATION_SIZE(1));
dispatch_static_assert(ROUND_UP_TO_CONTINUATION_SIZE(ROUND_UP_TO_BITMAP_ALIGNMENT_AND_CONTINUATION_SIZE(1)) ==
ROUND_UP_TO_BITMAP_ALIGNMENT_AND_CONTINUATION_SIZE(1));
}
#endif // DISPATCH_CONTINUATION_MALLOC || DISPATCH_DEBUG
kern_return_t
_dispatch_allocator_enumerate(task_t remote_task,
const struct dispatch_allocator_layout_s *remote_dal,
vm_address_t zone_address, memory_reader_t reader,
void (^recorder)(vm_address_t, void *, size_t, bool *stop))
{
const size_t heap_size = remote_dal->dal_magazine_size;
const size_t dc_size = remote_dal->dal_allocation_size;
const size_t dc_flags_offset = remote_dal->dal_allocation_isa_offset;
bool stop = false;
void *heap;
while (zone_address) {
// FIXME: improve this by not faulting everything and driving it through
// the bitmap.
kern_return_t kr = reader(remote_task, zone_address, heap_size, &heap);
size_t offs = remote_dal->dal_first_allocation_offset;
if (kr) return kr;
while (offs < heap_size) {
void *isa = *(void **)(heap + offs + dc_flags_offset);
if (isa && isa != remote_dal->dal_deferred_free_isa) {
recorder(zone_address + offs, heap + offs, dc_size, &stop);
if (stop) return KERN_SUCCESS;
}
offs += dc_size;
}
zone_address = (vm_address_t)((dispatch_heap_t)heap)->header.dh_next;
}
return KERN_SUCCESS;
}
#endif // DISPATCH_ALLOCATOR
#pragma mark -
#pragma mark dispatch_malloc
#if DISPATCH_CONTINUATION_MALLOC
#if DISPATCH_USE_MALLOCZONE
static malloc_zone_t *_dispatch_ccache_zone;
#define calloc(n, s) malloc_zone_calloc(_dispatch_ccache_zone, (n), (s))
#define free(c) malloc_zone_free(_dispatch_ccache_zone, (c))
static void
_dispatch_malloc_init(void)
{
_dispatch_ccache_zone = malloc_create_zone(0, 0);
dispatch_assert(_dispatch_ccache_zone);
malloc_set_zone_name(_dispatch_ccache_zone, "DispatchContinuations");
}
#else
#define _dispatch_malloc_init() ((void)0)
#endif // DISPATCH_USE_MALLOCZONE
static dispatch_continuation_t
_dispatch_malloc_continuation_alloc(void)
{
dispatch_continuation_t dc;
size_t alloc_size = ROUND_UP_TO_CACHELINE_SIZE(sizeof(*dc));
while (unlikely(!(dc = calloc(1, alloc_size)))) {
_dispatch_temporary_resource_shortage();
}
return dc;
}
static inline void
_dispatch_malloc_continuation_free(dispatch_continuation_t c)
{
free(c);
}
#endif // DISPATCH_CONTINUATION_MALLOC
#pragma mark -
#pragma mark dispatch_continuation_alloc
#if DISPATCH_ALLOCATOR
#if DISPATCH_CONTINUATION_MALLOC
#if !DISPATCH_USE_NANOZONE
#define malloc_engaged_nano() false
#endif // !DISPATCH_USE_NANOZONE
DISPATCH_STATIC_GLOBAL(bool _dispatch_use_dispatch_alloc);
#else
#define _dispatch_use_dispatch_alloc 1
#endif // DISPATCH_CONTINUATION_MALLOC
#endif // DISPATCH_ALLOCATOR
#if (DISPATCH_ALLOCATOR && (DISPATCH_CONTINUATION_MALLOC || DISPATCH_DEBUG)) \
|| (DISPATCH_CONTINUATION_MALLOC && DISPATCH_USE_MALLOCZONE)
DISPATCH_STATIC_GLOBAL(dispatch_once_t _dispatch_continuation_alloc_init_pred);
static void
_dispatch_continuation_alloc_init(void *ctxt DISPATCH_UNUSED)
{
#if DISPATCH_ALLOCATOR
#if DISPATCH_CONTINUATION_MALLOC
bool use_dispatch_alloc = !malloc_engaged_nano();
char *e = getenv("LIBDISPATCH_CONTINUATION_ALLOCATOR");
if (e) {
use_dispatch_alloc = atoi(e);
}
_dispatch_use_dispatch_alloc = use_dispatch_alloc;
#endif // DISPATCH_CONTINUATION_MALLOC
if (_dispatch_use_dispatch_alloc)
return _dispatch_alloc_init();
#endif // DISPATCH_ALLOCATOR
#if DISPATCH_CONTINUATION_MALLOC
return _dispatch_malloc_init();
#endif // DISPATCH_ALLOCATOR
}
static inline void
_dispatch_continuation_alloc_once(void)
{
dispatch_once_f(&_dispatch_continuation_alloc_init_pred,
NULL, _dispatch_continuation_alloc_init);
}
#else
static inline void _dispatch_continuation_alloc_once(void) {}
#endif // DISPATCH_ALLOCATOR ... || DISPATCH_CONTINUATION_MALLOC ...
dispatch_continuation_t
_dispatch_continuation_alloc_from_heap(void)
{
_dispatch_continuation_alloc_once();
#if DISPATCH_ALLOCATOR
if (_dispatch_use_dispatch_alloc)
return _dispatch_alloc_continuation_alloc();
#endif
#if DISPATCH_CONTINUATION_MALLOC
return _dispatch_malloc_continuation_alloc();
#endif
}
void
_dispatch_continuation_free_to_heap(dispatch_continuation_t c)
{
#if DISPATCH_ALLOCATOR
if (_dispatch_use_dispatch_alloc)
return _dispatch_alloc_continuation_free(c);
#endif
#if DISPATCH_CONTINUATION_MALLOC
return _dispatch_malloc_continuation_free(c);
#endif
}

View File

@@ -0,0 +1,296 @@
/*
* Copyright (c) 2012-2013 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_ALLOCATOR_INTERNAL__
#define __DISPATCH_ALLOCATOR_INTERNAL__
#ifndef DISPATCH_ALLOCATOR
#if TARGET_OS_MAC && (defined(__LP64__) || TARGET_OS_IPHONE)
#define DISPATCH_ALLOCATOR 1
#endif
#endif
#ifndef DISPATCH_USE_NANOZONE
#if TARGET_OS_MAC && defined(__LP64__)
#define DISPATCH_USE_NANOZONE 1
#endif
#endif
#ifndef DISPATCH_USE_MALLOCZONE
#if (TARGET_OS_MAC && !DISPATCH_USE_NANOZONE) || \
(!TARGET_OS_MAC && HAVE_MALLOC_CREATE_ZONE)
#define DISPATCH_USE_MALLOCZONE 1
#endif
#endif
#ifndef DISPATCH_CONTINUATION_MALLOC
#if DISPATCH_USE_NANOZONE || !DISPATCH_ALLOCATOR
#define DISPATCH_CONTINUATION_MALLOC 1
#endif
#endif
#if !DISPATCH_ALLOCATOR && !DISPATCH_CONTINUATION_MALLOC
#error Invalid allocator configuration
#endif
#if DISPATCH_ALLOCATOR && DISPATCH_CONTINUATION_MALLOC
#define DISPATCH_ALLOC_NOINLINE DISPATCH_NOINLINE
#else
#define DISPATCH_ALLOC_NOINLINE
#endif
#pragma mark -
#pragma mark DISPATCH_ALLOCATOR
#if DISPATCH_ALLOCATOR
// Configuration here!
#define NUM_CPU dispatch_hw_config(logical_cpus)
#define MAGAZINES_PER_HEAP (NUM_CPU)
// Do you care about compaction or performance?
#if TARGET_OS_IPHONE
#define PACK_FIRST_PAGE_WITH_CONTINUATIONS 1
#else
#define PACK_FIRST_PAGE_WITH_CONTINUATIONS 0
#endif
#ifndef PAGE_MAX_SIZE
#define PAGE_MAX_SIZE PAGE_SIZE
#endif
#ifndef PAGE_MAX_MASK
#define PAGE_MAX_MASK PAGE_MASK
#endif
#define DISPATCH_ALLOCATOR_PAGE_SIZE PAGE_MAX_SIZE
#define DISPATCH_ALLOCATOR_PAGE_MASK PAGE_MAX_MASK
#if TARGET_OS_IPHONE
#define PAGES_PER_MAGAZINE 64
#else
#define PAGES_PER_MAGAZINE 512
#endif
// Use the largest type your platform is comfortable doing atomic ops with.
// TODO: rdar://11477843
typedef unsigned long bitmap_t;
#if DISPATCH_SIZEOF_PTR == 8
#define BYTES_PER_BITMAP 8
#else
#define BYTES_PER_BITMAP 4
#endif
#define BITMAP_C(v) ((bitmap_t)(v))
#define BITMAP_ALL_ONES (~BITMAP_C(0))
// Stop configuring.
#define CONTINUATIONS_PER_BITMAP (BYTES_PER_BITMAP * 8)
#define BITMAPS_PER_SUPERMAP (BYTES_PER_SUPERMAP * 8)
#define BYTES_PER_MAGAZINE (PAGES_PER_MAGAZINE * DISPATCH_ALLOCATOR_PAGE_SIZE)
#define CONSUMED_BYTES_PER_BITMAP (BYTES_PER_BITMAP + \
(DISPATCH_CONTINUATION_SIZE * CONTINUATIONS_PER_BITMAP))
#define BYTES_PER_SUPERMAP BYTES_PER_BITMAP
#define CONSUMED_BYTES_PER_SUPERMAP (BYTES_PER_SUPERMAP + \
(BITMAPS_PER_SUPERMAP * CONSUMED_BYTES_PER_BITMAP))
#define BYTES_PER_HEAP (BYTES_PER_MAGAZINE * MAGAZINES_PER_HEAP)
#define BYTES_PER_PAGE DISPATCH_ALLOCATOR_PAGE_SIZE
#define CONTINUATIONS_PER_PAGE (BYTES_PER_PAGE / DISPATCH_CONTINUATION_SIZE)
#define BITMAPS_PER_PAGE (CONTINUATIONS_PER_PAGE / CONTINUATIONS_PER_BITMAP)
// Assumption: metadata will be only in the first page.
#define SUPERMAPS_PER_MAGAZINE ((BYTES_PER_MAGAZINE - BYTES_PER_PAGE) / \
CONSUMED_BYTES_PER_SUPERMAP)
#define BITMAPS_PER_MAGAZINE (SUPERMAPS_PER_MAGAZINE * BITMAPS_PER_SUPERMAP)
#define CONTINUATIONS_PER_MAGAZINE \
(BITMAPS_PER_MAGAZINE * CONTINUATIONS_PER_BITMAP)
#define HEAP_MASK (~(uintptr_t)(BYTES_PER_HEAP - 1))
#define MAGAZINE_MASK (~(uintptr_t)(BYTES_PER_MAGAZINE - 1))
// this will round up such that first_bitmap_in_same_page() can mask the address
// of a bitmap_t in the maps to obtain the first bitmap for that same page
#define ROUND_UP_TO_BITMAP_ALIGNMENT(x) \
(((x) + ((BITMAPS_PER_PAGE * BYTES_PER_BITMAP) - 1u)) & \
~((BITMAPS_PER_PAGE * BYTES_PER_BITMAP) - 1u))
// Since these are both powers of two, we end up with not only the max alignment,
// but happily the least common multiple, which will be the greater of the two.
#define ROUND_UP_TO_BITMAP_ALIGNMENT_AND_CONTINUATION_SIZE(x) (ROUND_UP_TO_CONTINUATION_SIZE(ROUND_UP_TO_BITMAP_ALIGNMENT(x)))
#define PADDING_TO_BITMAP_ALIGNMENT_AND_CONTINUATION_SIZE(x) (ROUND_UP_TO_BITMAP_ALIGNMENT_AND_CONTINUATION_SIZE(x) - (x))
#define PADDING_TO_CONTINUATION_SIZE(x) (ROUND_UP_TO_CONTINUATION_SIZE(x) - (x))
#if DISPATCH_SIZEOF_PTR == 8
#define SIZEOF_HEADER 16
#else
#define SIZEOF_HEADER 8
#endif
#define SIZEOF_SUPERMAPS (BYTES_PER_SUPERMAP * SUPERMAPS_PER_MAGAZINE)
#define SIZEOF_MAPS (BYTES_PER_BITMAP * BITMAPS_PER_SUPERMAP * \
SUPERMAPS_PER_MAGAZINE)
// header is expected to end on supermap's required alignment
#define HEADER_TO_SUPERMAPS_PADDING 0
// we want to align the maps to a continuation size, but we must also have proper padding
// so that we can perform first_bitmap_in_same_page()
#define SUPERMAPS_TO_MAPS_PADDING (PADDING_TO_BITMAP_ALIGNMENT_AND_CONTINUATION_SIZE( \
SIZEOF_SUPERMAPS + HEADER_TO_SUPERMAPS_PADDING + SIZEOF_HEADER))
#define MAPS_TO_FPMAPS_PADDING (PADDING_TO_CONTINUATION_SIZE(SIZEOF_MAPS))
#define BYTES_LEFT_IN_FIRST_PAGE (BYTES_PER_PAGE - \
(SIZEOF_HEADER + HEADER_TO_SUPERMAPS_PADDING + SIZEOF_SUPERMAPS + \
SUPERMAPS_TO_MAPS_PADDING + SIZEOF_MAPS + MAPS_TO_FPMAPS_PADDING))
#if PACK_FIRST_PAGE_WITH_CONTINUATIONS
#define FULL_BITMAPS_IN_FIRST_PAGE \
(BYTES_LEFT_IN_FIRST_PAGE / CONSUMED_BYTES_PER_BITMAP)
#define REMAINDER_IN_FIRST_PAGE (BYTES_LEFT_IN_FIRST_PAGE - \
(FULL_BITMAPS_IN_FIRST_PAGE * CONSUMED_BYTES_PER_BITMAP) - \
(FULL_BITMAPS_IN_FIRST_PAGE ? 0 : \
ROUND_UP_TO_CONTINUATION_SIZE(BYTES_PER_BITMAP)))
#define REMAINDERED_CONTINUATIONS_IN_FIRST_PAGE \
(REMAINDER_IN_FIRST_PAGE / DISPATCH_CONTINUATION_SIZE)
#define CONTINUATIONS_IN_FIRST_PAGE (FULL_BITMAPS_IN_FIRST_PAGE * \
CONTINUATIONS_PER_BITMAP) + REMAINDERED_CONTINUATIONS_IN_FIRST_PAGE
#define BITMAPS_IN_FIRST_PAGE (FULL_BITMAPS_IN_FIRST_PAGE + \
(REMAINDERED_CONTINUATIONS_IN_FIRST_PAGE == 0 ? 0 : 1))
#define FPMAPS_TO_FPCONTS_PADDING (PADDING_TO_CONTINUATION_SIZE(\
BYTES_PER_BITMAP * BITMAPS_IN_FIRST_PAGE))
#else // PACK_FIRST_PAGE_WITH_CONTINUATIONS
#define MAPS_TO_CONTS_PADDING BYTES_LEFT_IN_FIRST_PAGE
#endif // PACK_FIRST_PAGE_WITH_CONTINUATIONS
#define AFTER_CONTS_PADDING (BYTES_PER_MAGAZINE - (BYTES_PER_PAGE + \
(DISPATCH_CONTINUATION_SIZE * CONTINUATIONS_PER_MAGAZINE)))
// This is the object our allocator allocates: a chunk of memory rounded up
// from sizeof(struct dispatch_continuation_s) to the cacheline size, so
// unrelated continuations don't share cachelines. It'd be nice if
// dispatch_continuation_s included this rounding/padding, but it doesn't.
typedef char padded_continuation[DISPATCH_CONTINUATION_SIZE];
// A dispatch_heap_t is the base address of an array of dispatch_magazine_s,
// one magazine per CPU.
typedef struct dispatch_magazine_s * dispatch_heap_t;
struct dispatch_magazine_header_s {
// Link to the next heap in the chain. Only used in magazine 0's header
dispatch_heap_t dh_next;
// Points to the first bitmap in the page where this CPU successfully
// allocated a continuation last time. Only used in the first heap.
bitmap_t *last_found_page;
};
// A magazine is a complex data structure. It must be exactly
// PAGES_PER_MAGAZINE * PAGE_SIZE bytes long, and that value must be a
// power of 2. (See magazine_for_continuation()).
struct dispatch_magazine_s {
// See above.
struct dispatch_magazine_header_s header;
// Align supermaps as needed.
#if HEADER_TO_SUPERMAPS_PADDING > 0
char _pad0[HEADER_TO_SUPERMAPS_PADDING];
#endif
// Second-level bitmap; each set bit means a bitmap_t in maps[][]
// is completely full (and can be skipped while searching).
bitmap_t supermaps[SUPERMAPS_PER_MAGAZINE];
// Align maps to a cacheline.
#if SUPERMAPS_TO_MAPS_PADDING > 0
char _pad1[SUPERMAPS_TO_MAPS_PADDING];
#endif
// Each bit in maps[][] is the free/used state of a member of conts[][][].
bitmap_t maps[SUPERMAPS_PER_MAGAZINE][BITMAPS_PER_SUPERMAP];
// Align fp_maps to a cacheline.
#if MAPS_TO_FPMAPS_PADDING > 0
char _pad2[MAPS_TO_FPMAPS_PADDING];
#endif
#if PACK_FIRST_PAGE_WITH_CONTINUATIONS
// Bitmaps for the continuations that live in the first page, which
// are treated specially (they have faster search code).
bitmap_t fp_maps[BITMAPS_IN_FIRST_PAGE];
// Align fp_conts to cacheline.
#if FPMAPS_TO_FPCONTS_PADDING > 0
char _pad3[FPMAPS_TO_FPCONTS_PADDING];
#endif
// Continuations that live in the first page.
padded_continuation fp_conts[CONTINUATIONS_IN_FIRST_PAGE];
#else // PACK_FIRST_PAGE_WITH_CONTINUATIONS
#if MAPS_TO_CONTS_PADDING > 0
char _pad4[MAPS_TO_CONTS_PADDING];
#endif
#endif // PACK_FIRST_PAGE_WITH_CONTINUATIONS
// This is the big array of continuations.
// This must start on a page boundary.
padded_continuation conts[SUPERMAPS_PER_MAGAZINE][BITMAPS_PER_SUPERMAP]
[CONTINUATIONS_PER_BITMAP];
// Fill the unused space to exactly BYTES_PER_MAGAZINE
#if AFTER_CONTS_PADDING > 0
char _pad5[AFTER_CONTS_PADDING];
#endif
};
#if DISPATCH_DEBUG
#define DISPATCH_ALLOCATOR_SCRIBBLE ((uintptr_t)0xAFAFAFAFAFAFAFAF)
#endif
kern_return_t _dispatch_allocator_enumerate(task_t remote_task,
const struct dispatch_allocator_layout_s *remote_allocator_layout,
vm_address_t zone_address, memory_reader_t reader,
void (^recorder)(vm_address_t, void *, size_t , bool *stop));
#endif // DISPATCH_ALLOCATOR
#if DISPATCH_ALLOCATOR
extern dispatch_heap_t _dispatch_main_heap;
#endif
#endif // __DISPATCH_ALLOCATOR_INTERNAL__

368
Telegram/ThirdParty/dispatch/src/apply.c vendored Normal file
View File

@@ -0,0 +1,368 @@
/*
* Copyright (c) 2008-2013 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"
typedef void (*dispatch_apply_function_t)(void *, size_t);
static char const * const _dispatch_apply_key = "apply";
#define DISPATCH_APPLY_INVOKE_REDIRECT 0x1
#define DISPATCH_APPLY_INVOKE_WAIT 0x2
DISPATCH_ALWAYS_INLINE
static inline void
_dispatch_apply_invoke2(dispatch_apply_t da, long invoke_flags)
{
size_t const iter = da->da_iterations;
size_t idx, done = 0;
idx = os_atomic_inc_orig2o(da, da_index, acquire);
if (unlikely(idx >= iter)) goto out;
// da_dc is only safe to access once the 'index lock' has been acquired
dispatch_apply_function_t const func = (void *)da->da_dc->dc_func;
void *const da_ctxt = da->da_dc->dc_ctxt;
_dispatch_perfmon_workitem_dec(); // this unit executes many items
// Handle nested dispatch_apply rdar://problem/9294578
dispatch_thread_context_s apply_ctxt = {
.dtc_key = _dispatch_apply_key,
.dtc_apply_nesting = da->da_nested,
};
_dispatch_thread_context_push(&apply_ctxt);
dispatch_thread_frame_s dtf;
dispatch_priority_t old_dbp = 0;
if (invoke_flags & DISPATCH_APPLY_INVOKE_REDIRECT) {
dispatch_queue_t dq = da->da_dc->dc_data;
_dispatch_thread_frame_push(&dtf, dq);
old_dbp = _dispatch_set_basepri(dq->dq_priority);
}
dispatch_invoke_flags_t flags = da->da_flags;
// Striding is the responsibility of the caller.
do {
dispatch_invoke_with_autoreleasepool(flags, {
_dispatch_client_callout2(da_ctxt, idx, func);
_dispatch_perfmon_workitem_inc();
done++;
idx = os_atomic_inc_orig2o(da, da_index, relaxed);
});
} while (likely(idx < iter));
if (invoke_flags & DISPATCH_APPLY_INVOKE_REDIRECT) {
_dispatch_reset_basepri(old_dbp);
_dispatch_thread_frame_pop(&dtf);
}
_dispatch_thread_context_pop(&apply_ctxt);
// The thread that finished the last workitem wakes up the possibly waiting
// thread that called dispatch_apply. They could be one and the same.
if (!os_atomic_sub2o(da, da_todo, done, release)) {
_dispatch_thread_event_signal(&da->da_event);
}
out:
if (invoke_flags & DISPATCH_APPLY_INVOKE_WAIT) {
_dispatch_thread_event_wait(&da->da_event);
_dispatch_thread_event_destroy(&da->da_event);
}
if (os_atomic_dec2o(da, da_thr_cnt, release) == 0) {
#if DISPATCH_INTROSPECTION
_dispatch_continuation_free(da->da_dc);
#endif
_dispatch_continuation_free((dispatch_continuation_t)da);
}
}
DISPATCH_NOINLINE
void
_dispatch_apply_invoke(void *ctxt)
{
_dispatch_apply_invoke2(ctxt, 0);
}
DISPATCH_NOINLINE
static void
_dispatch_apply_invoke_and_wait(void *ctxt)
{
_dispatch_apply_invoke2(ctxt, DISPATCH_APPLY_INVOKE_WAIT);
_dispatch_perfmon_workitem_inc();
}
DISPATCH_NOINLINE
void
_dispatch_apply_redirect_invoke(void *ctxt)
{
_dispatch_apply_invoke2(ctxt, DISPATCH_APPLY_INVOKE_REDIRECT);
}
DISPATCH_ALWAYS_INLINE
static inline dispatch_invoke_flags_t
_dispatch_apply_autorelease_frequency(dispatch_queue_t dq)
{
dispatch_invoke_flags_t qaf = 0;
while (dq && !qaf) {
qaf = _dispatch_queue_autorelease_frequency(dq);
dq = dq->do_targetq;
}
return qaf;
}
DISPATCH_NOINLINE
static void
_dispatch_apply_serial(void *ctxt)
{
dispatch_apply_t da = (dispatch_apply_t)ctxt;
dispatch_continuation_t dc = da->da_dc;
size_t const iter = da->da_iterations;
dispatch_invoke_flags_t flags;
size_t idx = 0;
_dispatch_perfmon_workitem_dec(); // this unit executes many items
flags = _dispatch_apply_autorelease_frequency(dc->dc_data);
do {
dispatch_invoke_with_autoreleasepool(flags, {
_dispatch_client_callout2(dc->dc_ctxt, idx, (void*)dc->dc_func);
_dispatch_perfmon_workitem_inc();
});
} while (++idx < iter);
#if DISPATCH_INTROSPECTION
_dispatch_continuation_free(da->da_dc);
#endif
_dispatch_continuation_free((dispatch_continuation_t)da);
}
DISPATCH_ALWAYS_INLINE
static inline void
_dispatch_apply_f(dispatch_queue_global_t dq, dispatch_apply_t da,
dispatch_function_t func)
{
int32_t i = 0;
dispatch_continuation_t head = NULL, tail = NULL;
pthread_priority_t pp = _dispatch_get_priority();
// The current thread does not need a continuation
int32_t continuation_cnt = da->da_thr_cnt - 1;
dispatch_assert(continuation_cnt);
for (i = 0; i < continuation_cnt; i++) {
dispatch_continuation_t next = _dispatch_continuation_alloc();
uintptr_t dc_flags = DC_FLAG_CONSUME;
_dispatch_continuation_init_f(next, dq, da, func,
DISPATCH_BLOCK_HAS_PRIORITY, dc_flags);
next->dc_priority = pp | _PTHREAD_PRIORITY_ENFORCE_FLAG;
next->do_next = head;
head = next;
if (!tail) {
tail = next;
}
}
_dispatch_thread_event_init(&da->da_event);
// FIXME: dq may not be the right queue for the priority of `head`
_dispatch_trace_item_push_list(dq, head, tail);
_dispatch_root_queue_push_inline(dq, head, tail, continuation_cnt);
// Call the first element directly
_dispatch_apply_invoke_and_wait(da);
}
DISPATCH_ALWAYS_INLINE DISPATCH_WARN_RESULT
static inline int32_t
_dispatch_queue_try_reserve_apply_width(dispatch_queue_t dq, int32_t da_width)
{
uint64_t old_state, new_state;
int32_t width;
if (unlikely(dq->dq_width == 1)) {
return 0;
}
os_atomic_rmw_loop2o(dq, dq_state, old_state, new_state, relaxed, {
width = (int32_t)_dq_state_available_width(old_state);
if (unlikely(!width)) {
os_atomic_rmw_loop_give_up(return 0);
}
if (width > da_width) {
width = da_width;
}
new_state = old_state + (uint64_t)width * DISPATCH_QUEUE_WIDTH_INTERVAL;
});
return width;
}
DISPATCH_ALWAYS_INLINE
static inline void
_dispatch_queue_relinquish_width(dispatch_queue_t top_dq,
dispatch_queue_t stop_dq, int32_t da_width)
{
uint64_t delta = (uint64_t)da_width * DISPATCH_QUEUE_WIDTH_INTERVAL;
dispatch_queue_t dq = top_dq;
while (dq != stop_dq) {
os_atomic_sub2o(dq, dq_state, delta, relaxed);
dq = dq->do_targetq;
}
}
DISPATCH_NOINLINE
static void
_dispatch_apply_redirect(void *ctxt)
{
dispatch_apply_t da = (dispatch_apply_t)ctxt;
int32_t da_width = da->da_thr_cnt - 1;
dispatch_queue_t top_dq = da->da_dc->dc_data, dq = top_dq;
do {
int32_t width = _dispatch_queue_try_reserve_apply_width(dq, da_width);
if (unlikely(da_width > width)) {
int32_t excess = da_width - width;
_dispatch_queue_relinquish_width(top_dq, dq, excess);
da_width = width;
if (unlikely(!da_width)) {
return _dispatch_apply_serial(da);
}
da->da_thr_cnt -= excess;
}
if (!da->da_flags) {
// find first queue in descending target queue order that has
// an autorelease frequency set, and use that as the frequency for
// this continuation.
da->da_flags = _dispatch_queue_autorelease_frequency(dq);
}
dq = dq->do_targetq;
} while (unlikely(dq->do_targetq));
_dispatch_apply_f(upcast(dq)._dgq, da, _dispatch_apply_redirect_invoke);
_dispatch_queue_relinquish_width(top_dq, dq, da_width);
}
#define DISPATCH_APPLY_MAX UINT16_MAX // must be < sqrt(SIZE_MAX)
DISPATCH_ALWAYS_INLINE
static inline dispatch_queue_global_t
_dispatch_apply_root_queue(dispatch_queue_t dq)
{
if (dq) {
while (unlikely(dq->do_targetq)) {
dq = dq->do_targetq;
}
// if the current root queue is a pthread root queue, select it
if (!_dispatch_is_in_root_queues_array(dq)) {
return upcast(dq)._dgq;
}
}
pthread_priority_t pp = _dispatch_get_priority();
dispatch_qos_t qos = _dispatch_qos_from_pp(pp);
return _dispatch_get_root_queue(qos ? qos : DISPATCH_QOS_DEFAULT, false);
}
DISPATCH_NOINLINE
void
dispatch_apply_f(size_t iterations, dispatch_queue_t _dq, void *ctxt,
void (*func)(void *, size_t))
{
if (unlikely(iterations == 0)) {
return;
}
dispatch_thread_context_t dtctxt =
_dispatch_thread_context_find(_dispatch_apply_key);
size_t nested = dtctxt ? dtctxt->dtc_apply_nesting : 0;
dispatch_queue_t old_dq = _dispatch_queue_get_current();
dispatch_queue_t dq;
if (likely(_dq == DISPATCH_APPLY_AUTO)) {
dq = _dispatch_apply_root_queue(old_dq)->_as_dq;
} else {
dq = _dq; // silence clang Nullability complaints
}
dispatch_qos_t qos = _dispatch_priority_qos(dq->dq_priority) ?:
_dispatch_priority_fallback_qos(dq->dq_priority);
if (unlikely(dq->do_targetq)) {
// if the queue passed-in is not a root queue, use the current QoS
// since the caller participates in the work anyway
qos = _dispatch_qos_from_pp(_dispatch_get_priority());
}
int32_t thr_cnt = (int32_t)_dispatch_qos_max_parallelism(qos,
DISPATCH_MAX_PARALLELISM_ACTIVE);
if (likely(!nested)) {
nested = iterations;
} else {
thr_cnt = nested < (size_t)thr_cnt ? thr_cnt / (int32_t)nested : 1;
nested = nested < DISPATCH_APPLY_MAX && iterations < DISPATCH_APPLY_MAX
? nested * iterations : DISPATCH_APPLY_MAX;
}
if (iterations < (size_t)thr_cnt) {
thr_cnt = (int32_t)iterations;
}
struct dispatch_continuation_s dc = {
.dc_func = (void*)func,
.dc_ctxt = ctxt,
.dc_data = dq,
};
dispatch_apply_t da = (__typeof__(da))_dispatch_continuation_alloc();
da->da_index = 0;
da->da_todo = iterations;
da->da_iterations = iterations;
da->da_nested = nested;
da->da_thr_cnt = thr_cnt;
#if DISPATCH_INTROSPECTION
da->da_dc = _dispatch_continuation_alloc();
*da->da_dc = dc;
da->da_dc->dc_flags = DC_FLAG_ALLOCATED;
#else
da->da_dc = &dc;
#endif
da->da_flags = 0;
if (unlikely(dq->dq_width == 1 || thr_cnt <= 1)) {
return dispatch_sync_f(dq, da, _dispatch_apply_serial);
}
if (unlikely(dq->do_targetq)) {
if (unlikely(dq == old_dq)) {
return dispatch_sync_f(dq, da, _dispatch_apply_serial);
} else {
return dispatch_sync_f(dq, da, _dispatch_apply_redirect);
}
}
dispatch_thread_frame_s dtf;
_dispatch_thread_frame_push(&dtf, dq);
_dispatch_apply_f(upcast(dq)._dgq, da, _dispatch_apply_invoke);
_dispatch_thread_frame_pop(&dtf);
}
#ifdef __BLOCKS__
void
dispatch_apply(size_t iterations, dispatch_queue_t dq, void (^work)(size_t))
{
dispatch_apply_f(iterations, dq, work,
(dispatch_apply_function_t)_dispatch_Block_invoke(work));
}
#endif

View File

@@ -0,0 +1,128 @@
/*
* Copyright (c) 2008-2013 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 {
#if HAVE_MACH_ABSOLUTE_TIME
mach_timebase_info_data_t tbi;
#endif
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;
size_t i = 0;
uint64_t start, delta;
#if DISPATCH_SIZEOF_PTR == 8 && !defined(_WIN32)
__uint128_t lcost;
#else
long double lcost;
#endif
#if HAVE_MACH_ABSOLUTE_TIME
kern_return_t kr;
kr = mach_timebase_info(&bdata->tbi);
dispatch_assert_zero(kr);
#endif
start = _dispatch_uptime();
do {
i++;
f(c);
} while (i < cnt);
delta = _dispatch_uptime() - start;
lcost = delta;
#if HAVE_MACH_ABSOLUTE_TIME
lcost *= bdata->tbi.numer;
lcost /= bdata->tbi.denom;
#endif
lcost /= cnt;
bdata->loop_cost = lcost > UINT64_MAX ? UINT64_MAX : (uint64_t)lcost;
}
#ifdef __BLOCKS__
uint64_t
dispatch_benchmark(size_t count, void (^block)(void))
{
return dispatch_benchmark_f(count, block, _dispatch_Block_invoke(block));
}
#endif
static void
_dispatch_benchmark_dummy_function(void *ctxt DISPATCH_UNUSED)
{
}
uint64_t
dispatch_benchmark_f(size_t count, register void *ctxt,
register void (*func)(void *))
{
static struct __dispatch_benchmark_data_s bdata = {
.func = _dispatch_benchmark_dummy_function,
.count = 10000000ul, // ten million
};
static dispatch_once_t pred;
uint64_t ns, start, delta;
#if DISPATCH_SIZEOF_PTR == 8 && !defined(_WIN32)
__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 (unlikely(count == 0)) {
return 0;
}
start = _dispatch_uptime();
do {
i++;
func(ctxt);
} while (i < count);
delta = _dispatch_uptime() - start;
conversion = delta;
#if HAVE_MACH_ABSOLUTE_TIME
conversion *= bdata.tbi.numer;
big_denom = bdata.tbi.denom;
#else
big_denom = delta;
#endif
big_denom *= count;
conversion /= big_denom;
ns = conversion > UINT64_MAX ? UINT64_MAX : (uint64_t)conversion;
return ns - bdata.loop_cost;
}

View File

@@ -0,0 +1,126 @@
/*
* Copyright (c) 2015 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@
*/
#ifdef __BLOCKS__
#if __cplusplus < 201103L
#error Must build with C++11 or later
#endif
#if __has_feature(cxx_exceptions)
#error Must build without C++ exceptions
#endif
#include "internal.h"
// NOTE: this file must not contain any atomic operations
#if DISPATCH_DEBUG && DISPATCH_BLOCK_PRIVATE_DATA_DEBUG
#define _dispatch_block_private_data_debug(msg, ...) \
_dispatch_debug("block_private[%p]: " msg, (this), ##__VA_ARGS__)
#else
#define _dispatch_block_private_data_debug(msg, ...)
#endif
#pragma mark -
#pragma mark _dispatch_block_create
// rdar://20766742 C++ helpers to enable block capture of vouchers and groups
struct dispatch_block_private_data_s {
DISPATCH_BLOCK_PRIVATE_DATA_HEADER();
static void* operator new(size_t) = delete;
static void* operator new [] (size_t) = delete;
explicit inline DISPATCH_ALWAYS_INLINE dispatch_block_private_data_s(
dispatch_block_flags_t flags, voucher_t voucher,
pthread_priority_t priority, dispatch_block_t block) noexcept :
dbpd_magic(), dbpd_flags(flags), dbpd_atomic_flags(),
dbpd_performed(), dbpd_priority(priority), dbpd_voucher(voucher),
dbpd_block(block), dbpd_group(), dbpd_queue(), dbpd_thread()
{
// stack structure constructor, no releases on destruction
_dispatch_block_private_data_debug("create, block: %p", dbpd_block);
}
inline DISPATCH_ALWAYS_INLINE dispatch_block_private_data_s(
dispatch_block_private_data_s const &o) noexcept :
dbpd_magic(DISPATCH_BLOCK_PRIVATE_DATA_MAGIC),
dbpd_flags(o.dbpd_flags), dbpd_atomic_flags(), dbpd_performed(),
dbpd_priority(o.dbpd_priority), dbpd_voucher(o.dbpd_voucher),
dbpd_block(), dbpd_group(), dbpd_queue(), dbpd_thread()
{
// copy constructor, create copy with retained references
if (dbpd_voucher && dbpd_voucher != DISPATCH_NO_VOUCHER) {
voucher_retain(dbpd_voucher);
}
if (o.dbpd_block) {
dbpd_block = reinterpret_cast<dispatch_block_t>(
_dispatch_Block_copy(o.dbpd_block));
}
_dispatch_block_private_data_debug("copy from %p, block: %p from %p",
&o, dbpd_block, o.dbpd_block);
if (!o.dbpd_magic) return; // No group in initial copy of stack object
dbpd_group = _dispatch_group_create_and_enter();
}
inline DISPATCH_ALWAYS_INLINE ~dispatch_block_private_data_s() noexcept
{
_dispatch_block_private_data_debug("destroy%s, block: %p",
dbpd_magic ? "" : " (stack)", dbpd_block);
#if DISPATCH_INTROSPECTION
void *db = (char *) this - sizeof(struct Block_layout);
_dispatch_ktrace1(DISPATCH_QOS_TRACE_private_block_dispose, db);
#endif /* DISPATCH_INTROSPECTION */
if (dbpd_magic != DISPATCH_BLOCK_PRIVATE_DATA_MAGIC) return;
if (dbpd_group) {
if (!dbpd_performed) dispatch_group_leave(dbpd_group);
_os_object_release(dbpd_group->_as_os_obj);
}
if (dbpd_queue) {
_os_object_release_internal_n(dbpd_queue->_as_os_obj, 2);
}
if (dbpd_block) Block_release(dbpd_block);
if (dbpd_voucher && dbpd_voucher != DISPATCH_NO_VOUCHER) {
voucher_release(dbpd_voucher);
}
}
};
dispatch_block_t
_dispatch_block_create(dispatch_block_flags_t flags, voucher_t voucher,
pthread_priority_t pri, dispatch_block_t block)
{
struct dispatch_block_private_data_s dbpds(flags, voucher, pri, block);
return reinterpret_cast<dispatch_block_t>(_dispatch_Block_copy(^{
// Capture stack object: invokes copy constructor (17094902)
(void)dbpds;
_dispatch_block_invoke_direct(&dbpds);
}));
}
extern "C" {
// The compiler hides the name of the function it generates, and changes it if
// we try to reference it directly, but the linker still sees it.
extern void DISPATCH_BLOCK_SPECIAL_INVOKE(void *)
__asm__(OS_STRINGIFY(__USER_LABEL_PREFIX__) "___dispatch_block_create_block_invoke");
void (*const _dispatch_block_special_invoke)(void*) = DISPATCH_BLOCK_SPECIAL_INVOKE;
}
#endif // __BLOCKS__

740
Telegram/ThirdParty/dispatch/src/data.c vendored Normal file
View File

@@ -0,0 +1,740 @@
/*
* Copyright (c) 2009-2013 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"
/*
* Dispatch data objects are dispatch objects with standard retain/release
* memory management. A dispatch data object either points to a number of other
* dispatch data objects or is a leaf data object.
* A composite data object specifies the total size of data it represents
* and list of constituent records.
*
*******************************************************************************
*
* CURRENT IMPLEMENTATION DETAILS
*
* There are actually 3 kinds of composite objects
* - trivial subranges
* - unflattened composite data objects
* - flattened composite data objects
*
* LEAVES (num_records == 0, destructor != nil)
*
* Those objects have a pointer to represented memory in `buf`.
*
* UNFLATTENED (num_records > 1, buf == nil, destructor == nil)
*
* This is the generic case of a composite object.
*
* FLATTENED (num_records > 1, buf != nil, destructor == nil)
*
* Those objects are non trivial composite objects whose `buf` pointer
* is a contiguous representation (copied) of the memory it represents.
*
* Such objects are created when used as an NSData and -bytes is called and
* where the dispatch data object is an unflattened composite object.
* The underlying implementation is dispatch_data_get_flattened_bytes_4libxpc.
*
* TRIVIAL SUBRANGES (num_records == 1, buf == nil, destructor == nil)
*
* Those objects point to a single leaf, never to flattened objects.
*
*******************************************************************************
*
* Non trivial invariants:
*
* It is forbidden to point into a composite data object and ignore entire
* records from it. (for example by having `from` longer than the first
* record length).
*
* dispatch_data_t's are either leaves, or composite objects pointing to
* leaves. Depth is never greater than 1.
*
*******************************************************************************
*
* There are 4 dispatch_data_t constructors who may create non leaf objects,
* and ensure proper invariants.
*
* dispatch_data_copy_region()
* This function first sees through trivial subranges, and may in turn
* generate new trivial subranges.
*
* dispatch_data_create_map()
* This function either returns existing data objects, or a leaf.
*
* dispatch_data_create_subrange()
* This function treats flattened objects like unflattened ones,
* and recurses into trivial subranges, it can create trivial subranges.
*
* dispatch_data_create_concat()
* This function unwraps the top-level composite objects, trivial or not,
* and else concatenates the two arguments range lists, hence always creating
* unflattened objects, unless one of the arguments was empty.
*
*******************************************************************************
*/
#if DISPATCH_DATA_IS_BRIDGED_TO_NSDATA
#define _dispatch_data_retain(x) _dispatch_objc_retain(x)
#define _dispatch_data_release(x) _dispatch_objc_release(x)
#else
#define _dispatch_data_retain(x) dispatch_retain(x)
#define _dispatch_data_release(x) dispatch_release(x)
#endif
DISPATCH_ALWAYS_INLINE
static inline dispatch_data_t
_dispatch_data_alloc(size_t n, size_t extra)
{
dispatch_data_t data;
size_t size;
size_t base_size;
if (os_add_overflow(sizeof(struct dispatch_data_s), extra, &base_size)) {
return DISPATCH_OUT_OF_MEMORY;
}
if (os_mul_and_add_overflow(n, sizeof(range_record), base_size, &size)) {
return DISPATCH_OUT_OF_MEMORY;
}
data = _dispatch_object_alloc(DISPATCH_DATA_CLASS, size);
data->num_records = n;
#if !DISPATCH_DATA_IS_BRIDGED_TO_NSDATA
data->do_targetq = _dispatch_get_default_queue(false);
data->do_next = DISPATCH_OBJECT_LISTLESS;
#endif
return data;
}
static void
_dispatch_data_destroy_buffer(const void* buffer, size_t size,
dispatch_queue_t queue, dispatch_block_t destructor)
{
if (destructor == DISPATCH_DATA_DESTRUCTOR_FREE) {
free((void*)buffer);
} else if (destructor == DISPATCH_DATA_DESTRUCTOR_NONE) {
// do nothing
#if HAVE_MACH
} else if (destructor == DISPATCH_DATA_DESTRUCTOR_VM_DEALLOCATE) {
mach_vm_size_t vm_size = size;
mach_vm_address_t vm_addr = (uintptr_t)buffer;
mach_vm_deallocate(mach_task_self(), vm_addr, vm_size);
#else
(void)size;
#endif
} else {
if (!queue) {
queue = _dispatch_get_default_queue(false);
}
dispatch_async_f(queue, destructor, _dispatch_call_block_and_release);
}
}
DISPATCH_ALWAYS_INLINE
static inline void
_dispatch_data_init(dispatch_data_t data, const void *buffer, size_t size,
dispatch_queue_t queue, dispatch_block_t destructor)
{
data->buf = buffer;
data->size = size;
data->destructor = destructor;
if (queue) {
_dispatch_retain(queue);
data->do_targetq = queue;
}
}
void
_dispatch_data_init_with_bytes(dispatch_data_t data, const void *buffer,
size_t size, dispatch_block_t destructor)
{
if (!buffer || !size) {
if (destructor) {
_dispatch_data_destroy_buffer(buffer, size, NULL,
_dispatch_Block_copy(destructor));
}
buffer = NULL;
size = 0;
destructor = DISPATCH_DATA_DESTRUCTOR_NONE;
}
_dispatch_data_init(data, buffer, size, NULL, destructor);
}
dispatch_data_t
dispatch_data_create(const void* buffer, size_t size, dispatch_queue_t queue,
dispatch_block_t destructor)
{
dispatch_data_t data;
void *data_buf = NULL;
if (!buffer || !size) {
// Empty data requested so return the singleton empty object. Call
// destructor immediately in this case to ensure any unused associated
// storage is released.
if (destructor) {
_dispatch_data_destroy_buffer(buffer, size, queue,
_dispatch_Block_copy(destructor));
}
return dispatch_data_empty;
}
if (destructor == DISPATCH_DATA_DESTRUCTOR_DEFAULT) {
// The default destructor was provided, indicating the data should be
// copied.
data_buf = malloc(size);
if (unlikely(!data_buf)) {
return DISPATCH_OUT_OF_MEMORY;
}
buffer = memcpy(data_buf, buffer, size);
data = _dispatch_data_alloc(0, 0);
destructor = DISPATCH_DATA_DESTRUCTOR_FREE;
} else if (destructor == DISPATCH_DATA_DESTRUCTOR_INLINE) {
data = _dispatch_data_alloc(0, size);
buffer = memcpy((void*)data + sizeof(struct dispatch_data_s), buffer,
size);
destructor = DISPATCH_DATA_DESTRUCTOR_NONE;
} else {
data = _dispatch_data_alloc(0, 0);
destructor = _dispatch_Block_copy(destructor);
}
_dispatch_data_init(data, buffer, size, queue, destructor);
return data;
}
dispatch_data_t
dispatch_data_create_f(const void *buffer, size_t size, dispatch_queue_t queue,
dispatch_function_t destructor_function)
{
dispatch_block_t destructor = (dispatch_block_t)destructor_function;
if (destructor != DISPATCH_DATA_DESTRUCTOR_DEFAULT &&
destructor != DISPATCH_DATA_DESTRUCTOR_FREE &&
destructor != DISPATCH_DATA_DESTRUCTOR_NONE &&
#if HAVE_MACH
destructor != DISPATCH_DATA_DESTRUCTOR_VM_DEALLOCATE &&
#endif
destructor != DISPATCH_DATA_DESTRUCTOR_INLINE) {
destructor = ^{ destructor_function((void*)buffer); };
}
return dispatch_data_create(buffer, size, queue, destructor);
}
dispatch_data_t
dispatch_data_create_alloc(size_t size, void** buffer_ptr)
{
dispatch_data_t data = dispatch_data_empty;
void *buffer = NULL;
if (unlikely(!size)) {
goto out;
}
data = _dispatch_data_alloc(0, size);
buffer = (void*)data + sizeof(struct dispatch_data_s);
_dispatch_data_init(data, buffer, size, NULL,
DISPATCH_DATA_DESTRUCTOR_NONE);
out:
if (buffer_ptr) {
*buffer_ptr = buffer;
}
return data;
}
void
_dispatch_data_dispose(dispatch_data_t dd, DISPATCH_UNUSED bool *allow_free)
{
if (_dispatch_data_leaf(dd)) {
_dispatch_data_destroy_buffer(dd->buf, dd->size, dd->do_targetq,
dd->destructor);
} else {
size_t i;
for (i = 0; i < _dispatch_data_num_records(dd); ++i) {
_dispatch_data_release(dd->records[i].data_object);
}
free((void *)dd->buf);
}
}
#if DISPATCH_DATA_IS_BRIDGED_TO_NSDATA
void
_dispatch_data_set_target_queue(dispatch_data_t dd, dispatch_queue_t tq)
{
if (tq == DISPATCH_TARGET_QUEUE_DEFAULT) {
tq = _dispatch_get_default_queue(false);
}
_dispatch_object_set_target_queue_inline(dd, tq);
}
#endif // DISPATCH_DATA_IS_BRIDGED_TO_NSDATA
size_t
_dispatch_data_debug(dispatch_data_t dd, char* buf, size_t bufsiz)
{
size_t offset = 0;
offset += dsnprintf(&buf[offset], bufsiz - offset, "data[%p] = { ", dd);
if (_dispatch_data_leaf(dd)) {
offset += dsnprintf(&buf[offset], bufsiz - offset,
"leaf, size = %zd, buf = %p ", dd->size, dd->buf);
} else {
offset += dsnprintf(&buf[offset], bufsiz - offset,
"composite, size = %zd, num_records = %zd ", dd->size,
_dispatch_data_num_records(dd));
if (dd->buf) {
offset += dsnprintf(&buf[offset], bufsiz - offset,
", flatbuf = %p ", dd->buf);
}
size_t i;
for (i = 0; i < _dispatch_data_num_records(dd); ++i) {
range_record r = dd->records[i];
offset += dsnprintf(&buf[offset], bufsiz - offset, "record[%zd] = "
"{ from = %zd, length = %zd, data_object = %p }, ", i,
r.from, r.length, r.data_object);
}
}
offset += dsnprintf(&buf[offset], bufsiz - offset, "}");
return offset;
}
size_t
dispatch_data_get_size(dispatch_data_t dd)
{
return dd->size;
}
dispatch_data_t
dispatch_data_create_concat(dispatch_data_t dd1, dispatch_data_t dd2)
{
dispatch_data_t data;
size_t n;
if (!dd1->size) {
_dispatch_data_retain(dd2);
return dd2;
}
if (!dd2->size) {
_dispatch_data_retain(dd1);
return dd1;
}
if (os_add_overflow(_dispatch_data_num_records(dd1),
_dispatch_data_num_records(dd2), &n)) {
return DISPATCH_OUT_OF_MEMORY;
}
data = _dispatch_data_alloc(n, 0);
data->size = dd1->size + dd2->size;
// Copy the constituent records into the newly created data object
// Reference leaf objects as sub-objects
if (_dispatch_data_leaf(dd1)) {
data->records[0].from = 0;
data->records[0].length = dd1->size;
data->records[0].data_object = dd1;
} else {
memcpy(data->records, dd1->records, _dispatch_data_num_records(dd1) *
sizeof(range_record));
}
if (_dispatch_data_leaf(dd2)) {
data->records[_dispatch_data_num_records(dd1)].from = 0;
data->records[_dispatch_data_num_records(dd1)].length = dd2->size;
data->records[_dispatch_data_num_records(dd1)].data_object = dd2;
} else {
memcpy(data->records + _dispatch_data_num_records(dd1), dd2->records,
_dispatch_data_num_records(dd2) * sizeof(range_record));
}
size_t i;
for (i = 0; i < _dispatch_data_num_records(data); ++i) {
_dispatch_data_retain(data->records[i].data_object);
}
return data;
}
dispatch_data_t
dispatch_data_create_subrange(dispatch_data_t dd, size_t offset,
size_t length)
{
dispatch_data_t data;
if (offset >= dd->size || !length) {
return dispatch_data_empty;
} else if (length > dd->size - offset) {
length = dd->size - offset;
} else if (length == dd->size) {
_dispatch_data_retain(dd);
return dd;
}
/*
* we must only optimize leaves and not flattened objects
* because lots of users want to keep the end of a buffer and release
* as much memory as they can from the beginning of it
*
* Using the flatbuf here would be very wrong with respect to that goal
*/
if (_dispatch_data_leaf(dd)) {
data = _dispatch_data_alloc(1, 0);
data->size = length;
data->records[0].from = offset;
data->records[0].length = length;
data->records[0].data_object = dd;
_dispatch_data_retain(dd);
return data;
}
// Subrange of a composite dispatch data object
const size_t dd_num_records = _dispatch_data_num_records(dd);
bool to_the_end = (offset + length == dd->size);
size_t i = 0;
// find the record containing the specified offset
while (i < dd_num_records && offset >= dd->records[i].length) {
offset -= dd->records[i++].length;
}
// Crashing here indicates memory corruption of passed in data object
if (unlikely(i >= dd_num_records)) {
DISPATCH_INTERNAL_CRASH(i,
"dispatch_data_create_subrange out of bounds");
}
// if everything is from a single dispatch data object, avoid boxing it
if (offset + length <= dd->records[i].length) {
return dispatch_data_create_subrange(dd->records[i].data_object,
dd->records[i].from + offset, length);
}
// find the record containing the end of the current range
// and optimize the case when you just remove bytes at the origin
size_t count, last_length = 0;
if (to_the_end) {
count = dd_num_records - i;
} else {
last_length = length - (dd->records[i].length - offset);
count = 1;
while (i + count < dd_num_records) {
size_t record_length = dd->records[i + count++].length;
if (last_length <= record_length) {
break;
}
last_length -= record_length;
// Crashing here indicates memory corruption of passed in data object
if (unlikely(i + count >= dd_num_records)) {
DISPATCH_INTERNAL_CRASH(i + count,
"dispatch_data_create_subrange out of bounds");
}
}
}
data = _dispatch_data_alloc(count, 0);
data->size = length;
memcpy(data->records, dd->records + i, count * sizeof(range_record));
if (offset) {
data->records[0].from += offset;
data->records[0].length -= offset;
}
if (!to_the_end) {
data->records[count - 1].length = last_length;
}
for (i = 0; i < count; i++) {
_dispatch_data_retain(data->records[i].data_object);
}
return data;
}
static void*
_dispatch_data_flatten(dispatch_data_t dd)
{
void *buffer = malloc(dd->size);
// Composite data object, copy the represented buffers
if (buffer) {
dispatch_data_apply(dd, ^(dispatch_data_t region DISPATCH_UNUSED,
size_t off, const void* buf, size_t len) {
memcpy(buffer + off, buf, len);
return (bool)true;
});
}
return buffer;
}
// When mapping a leaf object or a subrange of a leaf object, return a direct
// pointer to the represented buffer. For all other data objects, copy the
// represented buffers into a contiguous area. In the future it might
// be possible to relocate the buffers instead (if not marked as locked).
dispatch_data_t
dispatch_data_create_map(dispatch_data_t dd, const void **buffer_ptr,
size_t *size_ptr)
{
dispatch_data_t data = NULL;
const void *buffer = NULL;
size_t size = dd->size;
if (!size) {
data = dispatch_data_empty;
goto out;
}
buffer = _dispatch_data_map_direct(dd, 0, NULL, NULL);
if (buffer) {
_dispatch_data_retain(dd);
data = dd;
goto out;
}
buffer = _dispatch_data_flatten(dd);
if (likely(buffer)) {
data = dispatch_data_create(buffer, size, NULL,
DISPATCH_DATA_DESTRUCTOR_FREE);
} else {
size = 0;
}
out:
if (buffer_ptr) {
*buffer_ptr = buffer;
}
if (size_ptr) {
*size_ptr = size;
}
return data;
}
const void *
dispatch_data_get_flattened_bytes_4libxpc(dispatch_data_t dd)
{
const void *buffer;
size_t offset = 0;
if (unlikely(!dd->size)) {
return NULL;
}
buffer = _dispatch_data_map_direct(dd, 0, &dd, &offset);
if (buffer) {
return buffer;
}
void *flatbuf = _dispatch_data_flatten(dd);
if (likely(flatbuf)) {
// we need a release so that readers see the content of the buffer
if (unlikely(!os_atomic_cmpxchgv2o(dd, buf, NULL, flatbuf,
&buffer, release))) {
free(flatbuf);
} else {
buffer = flatbuf;
}
} else {
return NULL;
}
return buffer + offset;
}
#if DISPATCH_USE_CLIENT_CALLOUT
DISPATCH_NOINLINE
#else
DISPATCH_ALWAYS_INLINE
#endif
static bool
_dispatch_data_apply_client_callout(void *ctxt, dispatch_data_t region, size_t offset,
const void *buffer, size_t size, dispatch_data_applier_function_t f)
{
return f(ctxt, region, offset, buffer, size);
}
static bool
_dispatch_data_apply(dispatch_data_t dd, size_t offset, size_t from,
size_t size, void *ctxt, dispatch_data_applier_function_t applier)
{
bool result = true;
const void *buffer;
buffer = _dispatch_data_map_direct(dd, 0, NULL, NULL);
if (buffer) {
return _dispatch_data_apply_client_callout(ctxt, dd,
offset, buffer + from, size, applier);
}
size_t i;
for (i = 0; i < _dispatch_data_num_records(dd) && result; ++i) {
result = _dispatch_data_apply(dd->records[i].data_object,
offset, dd->records[i].from, dd->records[i].length, ctxt,
applier);
offset += dd->records[i].length;
}
return result;
}
bool
dispatch_data_apply_f(dispatch_data_t dd, void *ctxt,
dispatch_data_applier_function_t applier)
{
if (!dd->size) {
return true;
}
return _dispatch_data_apply(dd, 0, 0, dd->size, ctxt, applier);
}
bool
dispatch_data_apply(dispatch_data_t dd, dispatch_data_applier_t applier)
{
if (!dd->size) {
return true;
}
return _dispatch_data_apply(dd, 0, 0, dd->size, applier,
(dispatch_data_applier_function_t)_dispatch_Block_invoke(applier));
}
static dispatch_data_t
_dispatch_data_copy_region(dispatch_data_t dd, size_t from, size_t size,
size_t location, size_t *offset_ptr)
{
dispatch_data_t reusable_dd = NULL;
size_t offset = 0;
if (from == 0 && size == dd->size) {
reusable_dd = dd;
}
if (_dispatch_data_map_direct(dd, from, &dd, &from)) {
if (reusable_dd) {
_dispatch_data_retain(reusable_dd);
return reusable_dd;
}
_dispatch_data_retain(dd);
if (from == 0 && size == dd->size) {
return dd;
}
dispatch_data_t data = _dispatch_data_alloc(1, 0);
data->size = size;
data->records[0].from = from;
data->records[0].length = size;
data->records[0].data_object = dd;
return data;
}
size_t i;
for (i = 0; i < _dispatch_data_num_records(dd); ++i) {
size_t length = dd->records[i].length;
if (from >= length) {
from -= length;
continue;
}
length -= from;
if (location >= offset + length) {
offset += length;
from = 0;
continue;
}
from += dd->records[i].from;
dd = dd->records[i].data_object;
*offset_ptr += offset;
location -= offset;
return _dispatch_data_copy_region(dd, from, length, location, offset_ptr);
}
DISPATCH_INTERNAL_CRASH(*offset_ptr+offset,
"dispatch_data_copy_region out of bounds");
}
// Returs either a leaf object or an object composed of a single leaf object
dispatch_data_t
dispatch_data_copy_region(dispatch_data_t dd, size_t location,
size_t *offset_ptr)
{
if (location >= dd->size) {
*offset_ptr = dd->size;
return dispatch_data_empty;
}
*offset_ptr = 0;
return _dispatch_data_copy_region(dd, 0, dd->size, location, offset_ptr);
}
#if HAVE_MACH
#ifndef MAP_MEM_VM_COPY
#define MAP_MEM_VM_COPY 0x200000 // <rdar://problem/13336613>
#endif
mach_port_t
dispatch_data_make_memory_entry(dispatch_data_t dd)
{
mach_port_t mep = MACH_PORT_NULL;
memory_object_size_t mos;
mach_vm_size_t vm_size = dd->size;
mach_vm_address_t vm_addr;
vm_prot_t flags;
kern_return_t kr;
bool copy = (dd->destructor != DISPATCH_DATA_DESTRUCTOR_VM_DEALLOCATE);
retry:
if (copy) {
vm_addr = vm_page_size;
kr = mach_vm_allocate(mach_task_self(), &vm_addr, vm_size,
VM_FLAGS_ANYWHERE);
if (kr) {
if (kr != KERN_NO_SPACE) {
(void)dispatch_assume_zero(kr);
}
return mep;
}
dispatch_data_apply(dd, ^(dispatch_data_t region DISPATCH_UNUSED,
size_t off, const void* buf, size_t len) {
memcpy((void*)(vm_addr + off), buf, len);
return (bool)true;
});
} else {
vm_addr = (uintptr_t)dd->buf;
}
flags = VM_PROT_DEFAULT|VM_PROT_IS_MASK|MAP_MEM_VM_COPY;
mos = vm_size;
kr = mach_make_memory_entry_64(mach_task_self(), &mos, vm_addr, flags,
&mep, MACH_PORT_NULL);
if (kr == KERN_INVALID_VALUE) {
// Fallback in case MAP_MEM_VM_COPY is not supported
flags &= ~MAP_MEM_VM_COPY;
kr = mach_make_memory_entry_64(mach_task_self(), &mos, vm_addr, flags,
&mep, MACH_PORT_NULL);
}
if (dispatch_assume_zero(kr)) {
mep = MACH_PORT_NULL;
} else if (mos < vm_size) {
// Memory object was truncated, e.g. due to lack of MAP_MEM_VM_COPY
kr = mach_port_deallocate(mach_task_self(), mep);
(void)dispatch_assume_zero(kr);
if (!copy) {
copy = true;
goto retry;
}
mep = MACH_PORT_NULL;
}
if (copy) {
kr = mach_vm_deallocate(mach_task_self(), vm_addr, vm_size);
(void)dispatch_assume_zero(kr);
}
return mep;
}
#endif // HAVE_MACH

202
Telegram/ThirdParty/dispatch/src/data.m vendored Normal file
View File

@@ -0,0 +1,202 @@
/*
* Copyright (c) 2012-2013 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"
#if DISPATCH_DATA_IS_BRIDGED_TO_NSDATA
#if _OS_OBJECT_OBJC_ARC
#error "Cannot build with ARC"
#endif
#include <Foundation/NSString.h>
// NOTE: this file must not contain any atomic operations
@interface DISPATCH_CLASS(data) () <DISPATCH_CLASS(data)>
@property (readonly,nonatomic) NSUInteger length;
@property (readonly,nonatomic) const void *bytes NS_RETURNS_INNER_POINTER;
- (id)initWithBytes:(void *)bytes length:(NSUInteger)length copy:(BOOL)copy
freeWhenDone:(BOOL)freeBytes bytesAreVM:(BOOL)vm;
- (BOOL)_bytesAreVM;
- (BOOL)_isCompact;
@end
@interface DISPATCH_CLASS(data_empty) : DISPATCH_CLASS(data)
@end
@implementation DISPATCH_CLASS(data)
+ (id)allocWithZone:(NSZone *) DISPATCH_UNUSED zone {
return _dispatch_objc_alloc(self, sizeof(struct dispatch_data_s));
}
- (id)init {
return [self initWithBytes:NULL length:0 copy:NO freeWhenDone:NO
bytesAreVM:NO];
}
- (id)initWithBytes:(void *)bytes length:(NSUInteger)length copy:(BOOL)copy
freeWhenDone:(BOOL)freeBytes bytesAreVM:(BOOL)vm {
dispatch_block_t destructor;
if (copy) {
destructor = DISPATCH_DATA_DESTRUCTOR_DEFAULT;
} else if (freeBytes) {
if (vm) {
destructor = DISPATCH_DATA_DESTRUCTOR_VM_DEALLOCATE;
} else {
destructor = DISPATCH_DATA_DESTRUCTOR_FREE;
}
} else {
destructor = DISPATCH_DATA_DESTRUCTOR_NONE;
}
_dispatch_data_init_with_bytes(self, bytes, length, destructor);
return self;
}
- (void)dealloc {
struct dispatch_data_s *dd = (void*)self;
_dispatch_data_dispose(self, NULL);
dispatch_queue_t tq = dd->do_targetq;
dispatch_function_t func = dd->finalizer;
void *ctxt = dd->ctxt;
[super dealloc];
if (func && ctxt) {
if (!tq) {
tq = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0);
}
dispatch_async_f(tq, ctxt, func);
}
if (tq) {
_os_object_release_internal((_os_object_t)tq);
}
}
- (BOOL)_bytesAreVM {
struct dispatch_data_s *dd = (void*)self;
return dd->destructor == DISPATCH_DATA_DESTRUCTOR_VM_DEALLOCATE;
}
- (void)_setContext:(void*)context {
struct dispatch_data_s *dd = (void*)self;
dd->ctxt = context;
}
- (void*)_getContext {
struct dispatch_data_s *dd = (void*)self;
return dd->ctxt;
}
- (void)_setFinalizer:(dispatch_function_t)finalizer {
struct dispatch_data_s *dd = (void*)self;
dd->finalizer = finalizer;
}
- (void)_setTargetQueue:(dispatch_queue_t)queue {
struct dispatch_data_s *dd = (void*)self;
return _dispatch_data_set_target_queue(dd, queue);
}
- (NSString *)debugDescription {
Class nsstring = objc_lookUpClass("NSString");
if (!nsstring) return nil;
char buf[2048];
_dispatch_data_debug(self, buf, sizeof(buf));
NSString *format = [nsstring stringWithUTF8String:"<%s: %s>"];
if (!format) return nil;
return [nsstring stringWithFormat:format, object_getClassName(self), buf];
}
- (NSUInteger)length {
struct dispatch_data_s *dd = (void*)self;
return dd->size;
}
- (const void *)bytes {
return dispatch_data_get_flattened_bytes_4libxpc(self);
}
- (BOOL)_isCompact {
struct dispatch_data_s *dd = (void*)self;
return !dd->size || _dispatch_data_map_direct(dd, 0, NULL, NULL) != NULL;
}
- (void)_suspend {
}
- (void)_resume {
}
- (void)_activate {
}
@end
@implementation DISPATCH_CLASS(data_empty)
// Force non-lazy class realization rdar://10640168
+ (void)load {
}
- (id)retain {
return (id)self;
}
- (oneway void)release {
}
- (id)autorelease {
return (id)self;
}
- (NSUInteger)retainCount {
return ULONG_MAX;
}
+ (id)allocWithZone:(NSZone *) DISPATCH_UNUSED zone {
return (id)&_dispatch_data_empty;
}
- (void)_setContext:(void*) DISPATCH_UNUSED context {
}
- (void*)_getContext {
return NULL;
}
- (void)_setFinalizer:(dispatch_function_t) DISPATCH_UNUSED finalizer {
}
- (void)_setTargetQueue:(dispatch_queue_t) DISPATCH_UNUSED queue {
}
- (void)_suspend {
}
- (void)_resume {
}
- (void)_activate {
}
@end
#endif // USE_OBJC

Some files were not shown because too many files have changed in this diff Show More