From 33b735c5330b5a97d029bccfff9a7d78ef1f2149 Mon Sep 17 00:00:00 2001 From: David Grove Date: Fri, 4 Dec 2015 21:19:36 +0000 Subject: [PATCH 1/3] libdispatch now builds on Linux and ping/pong test runs successfully. Set of changes to stub out missing functionality and adapt to Linux. Key changes are: (1) introduction of linux_base.h and linux_stubs.[h,c] to contain stubbed out type definitions and functions. (2) Copied in BSD's sys/queue.h to shims/sys_queue.h to provide _SAFE macros that are not available in Linux version of sys/queue.h (3) made inclusion of os/base.h conditional (4) worked around pthread_workqueue only providing 4 levels of priority by skipping initializing of two pairs of queues: DISPATCH_ROOT_QUEUE_IDX_BACKGROUND_QOS and DISPATCH_ROOT_QUEUE_IDX_USER_INTERACTIVE_QOS (5) temporarily stubbed out a few functions in transpose.c until an approach to the ByteSwap headers is finalized. These are marked with #ifdef LINUX_PORT_HDD (6) partial fix to a bug in semaphore.c where the linux clause was returning a stack address instead of mallocing memory. The fix is only partial because the memory should be freed when the semaphore is destroyed (not done). Small changes (a) augmented various .gitignore files for generated artifacts (b) a few additional functions bodies disabled with #ifdef LINUX_PORT_HDD (need better fixes, but functions may not be called). --- .gitignore | 13 + configure.ac | 18 +- m4/.gitignore | 5 + os/Makefile.am | 3 +- os/linux_base.h | 142 ++++++ os/object.h | 4 + private/voucher_activity_private.h | 2 + private/voucher_private.h | 4 + src/.gitignore | 5 + src/Makefile.am | 2 + src/init.c | 7 +- src/internal.h | 4 + src/io.c | 12 +- src/queue.c | 22 +- src/semaphore.c | 18 +- src/shims.h | 4 + src/shims/linux_stubs.c | 104 ++++ src/shims/linux_stubs.h | 37 ++ src/shims/sys_queue.h | 753 +++++++++++++++++++++++++++++ src/source.c | 10 + src/transform.c | 34 +- 21 files changed, 1174 insertions(+), 29 deletions(-) create mode 100644 m4/.gitignore create mode 100644 os/linux_base.h create mode 100644 src/.gitignore create mode 100644 src/shims/linux_stubs.c create mode 100644 src/shims/linux_stubs.h create mode 100644 src/shims/sys_queue.h diff --git a/.gitignore b/.gitignore index 7c7e9588c..20254db67 100644 --- a/.gitignore +++ b/.gitignore @@ -16,3 +16,16 @@ project.xcworkspace Build .build +# build files generated by autotools +Makefile +Makefile.in +config.log +configure +aclocal.m4 +autom4te.cache +config.log +config.status +config +configure +libtool + diff --git a/configure.ac b/configure.ac index fc0664d33..3f8aea44a 100644 --- a/configure.ac +++ b/configure.ac @@ -297,15 +297,17 @@ AS_IF([test "x$dispatch_cv_cc_omit_leaf_fp" != "xno"], [ ]) AC_SUBST([OMIT_LEAF_FP_FLAGS]) -AC_CACHE_CHECK([for darwin linker], [dispatch_cv_ld_darwin], [ - saveLDFLAGS="$LDFLAGS" - LDFLAGS="$LDFLAGS -dynamiclib -compatibility_version 1.2.3 -current_version 4.5.6 -dead_strip" - AC_LINK_IFELSE([AC_LANG_PROGRAM([ - extern int foo; int foo;], [foo = 0;])], - [dispatch_cv_ld_darwin="yes"], [dispatch_cv_ld_darwin="no"]) - LDFLAGS="$saveLDFLAGS" +AS_IF([test "x$have_mach" = "xtrue"], [ + AC_CACHE_CHECK([for darwin linker], [dispatch_cv_ld_darwin], [ + saveLDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS -dynamiclib -compatibility_version 1.2.3 -current_version 4.5.6 -dead_strip" + AC_LINK_IFELSE([AC_LANG_PROGRAM([ + extern int foo; int foo;], [foo = 0;])], + [dispatch_cv_ld_darwin="yes"], [dispatch_cv_ld_darwin="no"]) + LDFLAGS="$saveLDFLAGS" + ]) ]) -AM_CONDITIONAL(HAVE_DARWIN_LD, [test "x$dispatch_cv_ld_darwin" != "xno"]) +AM_CONDITIONAL(HAVE_DARWIN_LD, [test "x$dispatch_cv_ld_darwin" == "xyes"]) # # Temporary: some versions of clang do not mark __builtin_trap() as diff --git a/m4/.gitignore b/m4/.gitignore new file mode 100644 index 000000000..38066ddf7 --- /dev/null +++ b/m4/.gitignore @@ -0,0 +1,5 @@ +libtool.m4 +ltoptions.m4 +ltsugar.m4 +ltversion.m4 +lt~obsolete.m4 diff --git a/os/Makefile.am b/os/Makefile.am index 2189f16b1..4978d9cfd 100644 --- a/os/Makefile.am +++ b/os/Makefile.am @@ -5,7 +5,8 @@ osdir=$(includedir)/os os_HEADERS= \ - object.h + object.h \ + linux_base.h noinst_HEADERS= \ object_private.h diff --git a/os/linux_base.h b/os/linux_base.h new file mode 100644 index 000000000..971d85e00 --- /dev/null +++ b/os/linux_base.h @@ -0,0 +1,142 @@ +/* + * @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_LINUX_BASE__ +#define __OS_LINUX_BASE__ + +// #include + +// marker for hacks we have made to make progress +#define __LINUX_PORT_HDD__ 1 + +/* + * Stub out defines for some mach types and related macros + */ + +typedef uint32_t mach_port_t; + +#define MACH_PORT_NULL (0) +#define MACH_PORT_DEAD (-1) + +#define EVFILT_MACHPORT (-8) + +typedef uint32_t mach_error_t; + +typedef uint32_t mach_vm_size_t; + +typedef uint32_t mach_msg_return_t; + +typedef uintptr_t mach_vm_address_t; + +typedef uint32_t dispatch_mach_msg_t; + +typedef uint32_t dispatch_mach_t; + +typedef uint32_t dispatch_mach_reason_t; + +typedef uint32_t voucher_activity_mode_t; + +typedef uint32_t voucher_activity_trace_id_t; + +typedef uint32_t voucher_activity_id_t; + +typedef uint32_t _voucher_activity_buffer_hook_t;; + +typedef uint32_t voucher_activity_flag_t; + +typedef struct +{ +} mach_msg_header_t; + + +typedef void (*dispatch_mach_handler_function_t)(void*, dispatch_mach_reason_t, + dispatch_mach_msg_t, mach_error_t); + +typedef void (*dispatch_mach_msg_destructor_t)(void*); + +typedef uint32_t voucher_activity_mode_t; + +struct voucher_offsets_s { + uint32_t vo_version; +}; + + +/* + * Stub out defines for other missing types + */ + +// Pulled from OS X man page for kevent +struct kevent64_s { + uint64_t ident; /* identifier for this event */ + int16_t filter; /* filter for event */ + uint16_t flags; /* general flags */ + uint32_t fflags; /* filter-specific flags */ + int64_t data; /* filter-specific data */ + uint64_t udata; /* opaque user data identifier */ + uint64_t ext[2]; /* filter-specific extensions */ +}; + + +// PAGE_SIZE and SIZE_T_MAX should not be hardcoded like this here. +#define PAGE_SIZE (4096) +#define SIZE_T_MAX (0x7fffffff) + +// Define to 0 the NOTE_ values that are not present on Linux. +// Revisit this...would it be better to ifdef out the uses instead?? +#define NOTE_VM_PRESSURE 0 +#define NOTE_ABSOLUTE 0 +#define NOTE_NSECONDS 0 +#define NOTE_LEEWAY 0 +#define NOTE_CRITICAL 0 +#define NOTE_BACKGROUND 0 + +/* + * 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 + + +// These and similar macros come from Availabilty.h on OS X +// Need a better way to do this long term. +#define __OSX_AVAILABLE_BUT_DEPRECATED(a,b,c,d) // +#define __OSX_AVAILABLE_BUT_DEPRECATED_MSG(a,b,c,d,msg) // + + +// Print a warning when an unported code path executes. +#define LINUX_PORT_ERROR() do { printf("LINUX_PORT_ERROR_CALLED %s:%d: %s\n",__FILE__,__LINE__,__FUNCTION__); } while (0) + + +#endif /* __OS_LINUX_BASE__ */ diff --git a/os/object.h b/os/object.h index e07aaec67..4e141c3c5 100644 --- a/os/object.h +++ b/os/object.h @@ -24,7 +24,11 @@ #ifdef __APPLE__ #include #endif +#ifndef __linux__ #include +#else +#include +#endif /*! * @header diff --git a/private/voucher_activity_private.h b/private/voucher_activity_private.h index 08f32c610..d04514916 100644 --- a/private/voucher_activity_private.h +++ b/private/voucher_activity_private.h @@ -21,7 +21,9 @@ #ifndef __OS_VOUCHER_ACTIVITY_PRIVATE__ #define __OS_VOUCHER_ACTIVITY_PRIVATE__ +#ifndef __linux__ #include +#endif #include #if !defined(__DISPATCH_BUILDING_DISPATCH__) #include diff --git a/private/voucher_private.h b/private/voucher_private.h index ddce6920d..1d2ee914f 100644 --- a/private/voucher_private.h +++ b/private/voucher_private.h @@ -21,7 +21,9 @@ #ifndef __OS_VOUCHER_PRIVATE__ #define __OS_VOUCHER_PRIVATE__ +#ifndef __linux__ #include +#endif #include #define OS_VOUCHER_SPI_VERSION 20141203 @@ -400,7 +402,9 @@ dispatch_queue_create_with_accounting_override_voucher(const char *label, * voucher ports directly. */ +#ifdef __APPLE__ #include +#endif /*! * @function voucher_create_with_mach_msg diff --git a/src/.gitignore b/src/.gitignore new file mode 100644 index 000000000..65f9ee2aa --- /dev/null +++ b/src/.gitignore @@ -0,0 +1,5 @@ +provider.h +.libs +*.lo +*.la + diff --git a/src/Makefile.am b/src/Makefile.am index 007279ed8..bce643252 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -39,6 +39,8 @@ libdispatch_la_SOURCES= \ shims/atomic_sfb.h \ shims/getprogname.h \ shims/hw_config.h \ + shims/linux_stubs.c \ + shims/linux_stubs.h \ shims/perfmon.h \ shims/time.h \ shims/tsd.h \ diff --git a/src/init.c b/src/init.c index 3e6226d60..92619e71b 100644 --- a/src/init.c +++ b/src/init.c @@ -162,7 +162,9 @@ const struct dispatch_tsd_indexes_s dispatch_tsd_indexes = { .dti_qos_class_index = dispatch_priority_key, }; #else // DISPATCH_USE_DIRECT_TSD +#ifndef __LINUX_PORT_HDD__ #error Not implemented on this platform +#endif #endif // DISPATCH_USE_DIRECT_TSD // 6618342 Contact the team that owns the Instrument DTrace probe before @@ -1157,7 +1159,10 @@ const struct dispatch_source_type_s _dispatch_source_type_vnode = { .flags = EV_CLEAR|EV_UDATA_SPECIFIC, }, .mask = NOTE_DELETE|NOTE_WRITE|NOTE_EXTEND|NOTE_ATTRIB|NOTE_LINK| - NOTE_RENAME|NOTE_REVOKE + NOTE_RENAME +#if HAVE_DECL_NOTE_REVOKE + |NOTE_REVOKE +#endif #if HAVE_DECL_NOTE_NONE |NOTE_NONE #endif diff --git a/src/internal.h b/src/internal.h index 98626c643..0106b8263 100644 --- a/src/internal.h +++ b/src/internal.h @@ -208,7 +208,11 @@ DISPATCH_EXPORT DISPATCH_NOTHROW void dispatch_atfork_child(void); #if !TARGET_OS_WIN32 #include #include +#ifdef __linux__ +#include +#else #include +#endif #include #include #include diff --git a/src/io.c b/src/io.c index 0ad5b5373..2386d3209 100644 --- a/src/io.c +++ b/src/io.c @@ -387,9 +387,11 @@ dispatch_io_create_with_path(dispatch_io_type_t type, const char *path, int err = 0; struct stat st; _dispatch_io_syscall_switch_noerr(err, - (path_data->oflag & O_NOFOLLOW) == O_NOFOLLOW || - (path_data->oflag & O_SYMLINK) == O_SYMLINK ? - lstat(path_data->path, &st) : stat(path_data->path, &st), + (path_data->oflag & O_NOFOLLOW) == O_NOFOLLOW +#ifndef __linux__ + || (path_data->oflag & O_SYMLINK) == O_SYMLINK +#endif + ? lstat(path_data->path, &st) : stat(path_data->path, &st), case 0: err = _dispatch_io_validate_type(channel, st.st_mode); break; @@ -2064,6 +2066,9 @@ _dispatch_disk_perform(void *ctxt) static void _dispatch_operation_advise(dispatch_operation_t op, size_t chunk_size) { +#ifndef F_RDADVISE + LINUX_PORT_ERROR(); +#else int err; struct radvisory advise; // No point in issuing a read advise for the next chunk if we are already @@ -2090,6 +2095,7 @@ _dispatch_operation_advise(dispatch_operation_t op, size_t chunk_size) // TODO: set disk status on error default: (void)dispatch_assume_zero(err); break; ); +#endif } static int diff --git a/src/queue.c b/src/queue.c index cdf011d50..fe5c9e1a5 100644 --- a/src/queue.c +++ b/src/queue.c @@ -199,6 +199,14 @@ struct dispatch_root_queue_context_s { }; typedef struct dispatch_root_queue_context_s *dispatch_root_queue_context_t; +#ifdef __linux__ +#define WORKQ_BG_PRIOQUEUE_CONDITIONAL (-1) +#define WORKQ_HIGH_PRIOQUEUE_CONDITIONAL (-1) +#else +#define WORKQ_BG_PRIOQUEUE_CONDITIONAL WORKQ_BG_PRIOQUEUE +#define WORKQ_HIGH_PRIOQUEUE_CONDITIONAL WORKQ_HIGH_PRIOQUEUE +#endif + DISPATCH_CACHELINE_ALIGN static struct dispatch_root_queue_context_s _dispatch_root_queue_contexts[] = { [DISPATCH_ROOT_QUEUE_IDX_MAINTENANCE_QOS] = {{{ @@ -226,7 +234,7 @@ static struct dispatch_root_queue_context_s _dispatch_root_queue_contexts[] = { [DISPATCH_ROOT_QUEUE_IDX_BACKGROUND_QOS] = {{{ #if HAVE_PTHREAD_WORKQUEUES .dgq_qos = _DISPATCH_QOS_CLASS_BACKGROUND, - .dgq_wq_priority = WORKQ_BG_PRIOQUEUE, + .dgq_wq_priority = WORKQ_BG_PRIOQUEUE_CONDITIONAL, .dgq_wq_options = 0, #endif #if DISPATCH_ENABLE_THREAD_POOL @@ -237,7 +245,7 @@ static struct dispatch_root_queue_context_s _dispatch_root_queue_contexts[] = { [DISPATCH_ROOT_QUEUE_IDX_BACKGROUND_QOS_OVERCOMMIT] = {{{ #if HAVE_PTHREAD_WORKQUEUES .dgq_qos = _DISPATCH_QOS_CLASS_BACKGROUND, - .dgq_wq_priority = WORKQ_BG_PRIOQUEUE, + .dgq_wq_priority = WORKQ_BG_PRIOQUEUE_CONDITIONAL, .dgq_wq_options = WORKQ_ADDTHREADS_OPTION_OVERCOMMIT, #endif #if DISPATCH_ENABLE_THREAD_POOL @@ -314,7 +322,7 @@ static struct dispatch_root_queue_context_s _dispatch_root_queue_contexts[] = { [DISPATCH_ROOT_QUEUE_IDX_USER_INTERACTIVE_QOS] = {{{ #if HAVE_PTHREAD_WORKQUEUES .dgq_qos = _DISPATCH_QOS_CLASS_USER_INTERACTIVE, - .dgq_wq_priority = WORKQ_HIGH_PRIOQUEUE, + .dgq_wq_priority = WORKQ_HIGH_PRIOQUEUE_CONDITIONAL, .dgq_wq_options = 0, #endif #if DISPATCH_ENABLE_THREAD_POOL @@ -325,7 +333,7 @@ static struct dispatch_root_queue_context_s _dispatch_root_queue_contexts[] = { [DISPATCH_ROOT_QUEUE_IDX_USER_INTERACTIVE_QOS_OVERCOMMIT] = {{{ #if HAVE_PTHREAD_WORKQUEUES .dgq_qos = _DISPATCH_QOS_CLASS_USER_INTERACTIVE, - .dgq_wq_priority = WORKQ_HIGH_PRIOQUEUE, + .dgq_wq_priority = WORKQ_HIGH_PRIOQUEUE_CONDITIONAL, .dgq_wq_options = WORKQ_ADDTHREADS_OPTION_OVERCOMMIT, #endif #if DISPATCH_ENABLE_THREAD_POOL @@ -810,7 +818,7 @@ _dispatch_root_queues_init_workq(void) dispatch_root_queue_context_t qc; qc = &_dispatch_root_queue_contexts[i]; #if DISPATCH_USE_LEGACY_WORKQUEUE_FALLBACK - if (!disable_wq) { + if (!disable_wq && qc->dgq_wq_priority != -1) { r = pthread_workqueue_attr_setqueuepriority_np(&pwq_attr, qc->dgq_wq_priority); (void)dispatch_assume_zero(r); @@ -867,7 +875,7 @@ _dispatch_root_queue_init_pthread_pool(dispatch_root_queue_context_t qc, (void)dispatch_assume(pqc->dpq_thread_mediator.dsema_port); #elif USE_POSIX_SEM /* XXXRW: POSIX semaphores don't support LIFO? */ - int ret = sem_init(&pqc->dpq_thread_mediator.dsema_sem), 0, 0); + int ret = sem_init(&(pqc->dpq_thread_mediator.dsema_sem), 0, 0); (void)dispatch_assume_zero(ret); #endif } @@ -3045,6 +3053,8 @@ _dispatch_barrier_sync_slow(dispatch_queue_t dq, void (^work)(void)) work = _dispatch_Block_copy(work); func = _dispatch_call_block_and_release; } +#else + } #endif _dispatch_barrier_sync_f(dq, work, func, pp); } diff --git a/src/semaphore.c b/src/semaphore.c index f356fb876..85ef4231f 100644 --- a/src/semaphore.c +++ b/src/semaphore.c @@ -712,10 +712,10 @@ _dispatch_thread_semaphore_create(void) } return s4; #elif USE_POSIX_SEM - sem_t s4; - int ret = sem_init(&s4, 0, 0); + sem_t* s4 = malloc(sizeof(sem_t)); + int ret = sem_init(s4, 0, 0); DISPATCH_SEMAPHORE_VERIFY_RET(ret); - return s4; + return (_dispatch_thread_semaphore_t)s4; #elif USE_WIN32_SEM HANDLE tmp; while (!dispatch_assume(tmp = CreateSemaphore(NULL, 0, LONG_MAX, NULL))) { @@ -738,8 +738,8 @@ _dispatch_thread_semaphore_dispose(_dispatch_thread_semaphore_t sema) DISPATCH_VERIFY_MIG(kr); DISPATCH_SEMAPHORE_VERIFY_KR(kr); #elif USE_POSIX_SEM - sem_t s4 = (sem_t)sema; - int ret = sem_destroy(&s4); + sem_t *s4 = (sem_t*)sema; + int ret = sem_destroy(s4); DISPATCH_SEMAPHORE_VERIFY_RET(ret); #elif USE_WIN32_SEM // XXX: signal the semaphore? @@ -762,8 +762,8 @@ _dispatch_thread_semaphore_signal(_dispatch_thread_semaphore_t sema) kern_return_t kr = semaphore_signal(s4); DISPATCH_SEMAPHORE_VERIFY_KR(kr); #elif USE_POSIX_SEM - sem_t s4 = (sem_t)sema; - int ret = sem_post(&s4); + sem_t *s4 = (sem_t*)sema; + int ret = sem_post(s4); DISPATCH_SEMAPHORE_VERIFY_RET(ret); #elif USE_WIN32_SEM int ret; @@ -788,10 +788,10 @@ _dispatch_thread_semaphore_wait(_dispatch_thread_semaphore_t sema) } while (slowpath(kr == KERN_ABORTED)); DISPATCH_SEMAPHORE_VERIFY_KR(kr); #elif USE_POSIX_SEM - sem_t s4 = (sem_t)sema; + sem_t *s4 = (sem_t*)sema; int ret; do { - ret = sem_wait(&s4); + ret = sem_wait(s4); } while (slowpath(ret != 0)); DISPATCH_SEMAPHORE_VERIFY_RET(ret); #elif USE_WIN32_SEM diff --git a/src/shims.h b/src/shims.h index ae7f1c3d7..d90b775cb 100644 --- a/src/shims.h +++ b/src/shims.h @@ -159,6 +159,10 @@ void __builtin_trap(void); #define DISPATCH_ATOMIC_UP 1 #endif +#ifdef __linux__ +#include "shims/linux_stubs.h" +#endif + #include "shims/atomic.h" #include "shims/atomic_sfb.h" #include "shims/tsd.h" diff --git a/src/shims/linux_stubs.c b/src/shims/linux_stubs.c new file mode 100644 index 000000000..52eb92c22 --- /dev/null +++ b/src/shims/linux_stubs.c @@ -0,0 +1,104 @@ +/* + * @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@ + */ + + +/* + * This file contains stubbed out functions we are using during + * the initial linux port. When the port is complete, this file + * should be empty (and thus removed). + */ + +#include + +#include + +#include "pthread.h" + +#define program_invocation_short_name "hi" + +#include "os/linux_base.h" +#include "internal.h" + + +#undef LINUX_PORT_ERROR +#define LINUX_PORT_ERROR() do { printf("LINUX_PORT_ERROR_CALLED %s:%d: %s\n",__FILE__,__LINE__,__FUNCTION__); abort(); } while (0) + +void _dispatch_mach_msg_dispose() { LINUX_PORT_ERROR(); } + +unsigned long _dispatch_mach_probe(dispatch_mach_t dm) { + LINUX_PORT_ERROR(); +} + +dispatch_block_t _dispatch_block_create(dispatch_block_flags_t flags, + voucher_t voucher, pthread_priority_t priority, + dispatch_block_t block) { + LINUX_PORT_ERROR(); +} + +void _dispatch_mach_invoke() { LINUX_PORT_ERROR(); } + +size_t _dispatch_mach_msg_debug(dispatch_mach_msg_t dmsg, char* buf, size_t bufsiz) { + LINUX_PORT_ERROR(); +} +void _dispatch_mach_dispose() { LINUX_PORT_ERROR(); } +void _dispatch_mach_msg_invoke() { LINUX_PORT_ERROR(); } + +unsigned long _dispatch_runloop_queue_probe(dispatch_queue_t dq) { + LINUX_PORT_ERROR(); +} +void _dispatch_runloop_queue_xref_dispose() { LINUX_PORT_ERROR(); } + +void strlcpy() { LINUX_PORT_ERROR(); } +void _dispatch_runloop_queue_dispose() { LINUX_PORT_ERROR(); } +char* mach_error_string(mach_msg_return_t x) { + LINUX_PORT_ERROR(); +} + +void mach_vm_deallocate() { LINUX_PORT_ERROR(); } + +mach_port_t pthread_mach_thread_np() { + return (mach_port_t)pthread_self(); +} + +mach_port_t mach_task_self() { + return (mach_port_t)pthread_self(); +} + +int sysctlbyname(const char *name, void *oldp, size_t *oldlenp, + void *newp, size_t newlen) { + LINUX_PORT_ERROR(); +} + +int kevent64(int kq, const struct kevent *changelist, int nchanges, struct kevent *eventlist, int nevents,unsigned int flags, const struct timespec *timeout) +{ + return kevent(kq,changelist,nchanges,eventlist,nevents,timeout); +} + +/* + * Stubbed out static data + */ + +pthread_key_t dispatch_voucher_key; +pthread_key_t dispatch_pthread_root_queue_observer_hooks_key; + +unsigned short dispatch_timer__program_semaphore; +unsigned short dispatch_timer__wake_semaphore; +unsigned short dispatch_timer__fire_semaphore; +unsigned short dispatch_timer__configure_semaphore; +void (*_dispatch_block_special_invoke)(void*); +struct dispatch_queue_attr_s _dispatch_queue_attr_concurrent; diff --git a/src/shims/linux_stubs.h b/src/shims/linux_stubs.h new file mode 100644 index 000000000..2f3433949 --- /dev/null +++ b/src/shims/linux_stubs.h @@ -0,0 +1,37 @@ +/* + * @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@ + */ + +// forward declarations for functions we are stubbing out +// in the intial linux port. + +#ifndef __DISPATCH__STUBS__INTERNAL +#define __DISPATCH__STUBS__INTERNAL + +int sysctlbyname(const char *name, void *oldp, size_t *oldlenp, + void *newp, size_t newlen); + +mach_port_t pthread_mach_thread_np(); + +mach_port_t mach_task_self(); + +void mach_vm_deallocate(mach_port_t, mach_vm_address_t, mach_vm_size_t); + +char* mach_error_string(mach_msg_return_t); +#endif + + diff --git a/src/shims/sys_queue.h b/src/shims/sys_queue.h new file mode 100644 index 000000000..f7deb69fc --- /dev/null +++ b/src/shims/sys_queue.h @@ -0,0 +1,753 @@ +/*- + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)queue.h 8.5 (Berkeley) 8/20/94 + * $FreeBSD$ + */ + +#ifndef __DISPATCH_SHIMS_SYS_QUEUE_H_ +#define __DISPATCH_SHIMS_SYS_QUEUE_H_ + +#include + +/* + * This file defines four types of data structures: singly-linked lists, + * singly-linked tail queues, lists and tail queues. + * + * A singly-linked list is headed by a single forward pointer. The elements + * are singly linked for minimum space and pointer manipulation overhead at + * the expense of O(n) removal for arbitrary elements. New elements can be + * added to the list after an existing element or at the head of the list. + * Elements being removed from the head of the list should use the explicit + * macro for this purpose for optimum efficiency. A singly-linked list may + * only be traversed in the forward direction. Singly-linked lists are ideal + * for applications with large datasets and few or no removals or for + * implementing a LIFO queue. + * + * A singly-linked tail queue is headed by a pair of pointers, one to the + * head of the list and the other to the tail of the list. The elements are + * singly linked for minimum space and pointer manipulation overhead at the + * expense of O(n) removal for arbitrary elements. New elements can be added + * to the list after an existing element, at the head of the list, or at the + * end of the list. Elements being removed from the head of the tail queue + * should use the explicit macro for this purpose for optimum efficiency. + * A singly-linked tail queue may only be traversed in the forward direction. + * Singly-linked tail queues are ideal for applications with large datasets + * and few or no removals or for implementing a FIFO queue. + * + * A list is headed by a single forward pointer (or an array of forward + * pointers for a hash table header). The elements are doubly linked + * so that an arbitrary element can be removed without a need to + * traverse the list. New elements can be added to the list before + * or after an existing element or at the head of the list. A list + * may be traversed in either direction. + * + * A tail queue is headed by a pair of pointers, one to the head of the + * list and the other to the tail of the list. The elements are doubly + * linked so that an arbitrary element can be removed without a need to + * traverse the list. New elements can be added to the list before or + * after an existing element, at the head of the list, or at the end of + * the list. A tail queue may be traversed in either direction. + * + * For details on the use of these macros, see the queue(3) manual page. + * + * + * SLIST LIST STAILQ TAILQ + * _HEAD + + + + + * _CLASS_HEAD + + + + + * _HEAD_INITIALIZER + + + + + * _ENTRY + + + + + * _CLASS_ENTRY + + + + + * _INIT + + + + + * _EMPTY + + + + + * _FIRST + + + + + * _NEXT + + + + + * _PREV - + - + + * _LAST - - + + + * _FOREACH + + + + + * _FOREACH_FROM + + + + + * _FOREACH_SAFE + + + + + * _FOREACH_FROM_SAFE + + + + + * _FOREACH_REVERSE - - - + + * _FOREACH_REVERSE_FROM - - - + + * _FOREACH_REVERSE_SAFE - - - + + * _FOREACH_REVERSE_FROM_SAFE - - - + + * _INSERT_HEAD + + + + + * _INSERT_BEFORE - + - + + * _INSERT_AFTER + + + + + * _INSERT_TAIL - - + + + * _CONCAT - - + + + * _REMOVE_AFTER + - + - + * _REMOVE_HEAD + - + - + * _REMOVE + + + + + * _SWAP + + + + + * + */ +#ifdef QUEUE_MACRO_DEBUG +/* Store the last 2 places the queue element or head was altered */ +struct qm_trace { + unsigned long lastline; + unsigned long prevline; + const char *lastfile; + const char *prevfile; +}; + +#define TRACEBUF struct qm_trace trace; +#define TRACEBUF_INITIALIZER { __LINE__, 0, __FILE__, NULL } , +#define TRASHIT(x) do {(x) = (void *)-1;} while (0) +#define QMD_SAVELINK(name, link) void **name = (void *)&(link) + +#define QMD_TRACE_HEAD(head) do { \ + (head)->trace.prevline = (head)->trace.lastline; \ + (head)->trace.prevfile = (head)->trace.lastfile; \ + (head)->trace.lastline = __LINE__; \ + (head)->trace.lastfile = __FILE__; \ +} while (0) + +#define QMD_TRACE_ELEM(elem) do { \ + (elem)->trace.prevline = (elem)->trace.lastline; \ + (elem)->trace.prevfile = (elem)->trace.lastfile; \ + (elem)->trace.lastline = __LINE__; \ + (elem)->trace.lastfile = __FILE__; \ +} while (0) + +#else +#define QMD_TRACE_ELEM(elem) +#define QMD_TRACE_HEAD(head) +#define QMD_SAVELINK(name, link) +#define TRACEBUF +#define TRACEBUF_INITIALIZER +#define TRASHIT(x) +#endif /* QUEUE_MACRO_DEBUG */ + +#ifdef __cplusplus +/* + * In C++ there can be structure lists and class lists: + */ +#define QUEUE_TYPEOF(type) type +#else +#define QUEUE_TYPEOF(type) struct type +#endif + +/* + * Singly-linked List declarations. + */ +#define SLIST_HEAD(name, type) \ +struct name { \ + struct type *slh_first; /* first element */ \ +} + +#define SLIST_CLASS_HEAD(name, type) \ +struct name { \ + class type *slh_first; /* first element */ \ +} + +#define SLIST_HEAD_INITIALIZER(head) \ + { NULL } + +#define SLIST_ENTRY(type) \ +struct { \ + struct type *sle_next; /* next element */ \ +} + +#define SLIST_CLASS_ENTRY(type) \ +struct { \ + class type *sle_next; /* next element */ \ +} + +/* + * Singly-linked List functions. + */ +#define SLIST_EMPTY(head) ((head)->slh_first == NULL) + +#define SLIST_FIRST(head) ((head)->slh_first) + +#define SLIST_FOREACH(var, head, field) \ + for ((var) = SLIST_FIRST((head)); \ + (var); \ + (var) = SLIST_NEXT((var), field)) + +#define SLIST_FOREACH_FROM(var, head, field) \ + for ((var) = ((var) ? (var) : SLIST_FIRST((head))); \ + (var); \ + (var) = SLIST_NEXT((var), field)) + +#define SLIST_FOREACH_SAFE(var, head, field, tvar) \ + for ((var) = SLIST_FIRST((head)); \ + (var) && ((tvar) = SLIST_NEXT((var), field), 1); \ + (var) = (tvar)) + +#define SLIST_FOREACH_FROM_SAFE(var, head, field, tvar) \ + for ((var) = ((var) ? (var) : SLIST_FIRST((head))); \ + (var) && ((tvar) = SLIST_NEXT((var), field), 1); \ + (var) = (tvar)) + +#define SLIST_FOREACH_PREVPTR(var, varp, head, field) \ + for ((varp) = &SLIST_FIRST((head)); \ + ((var) = *(varp)) != NULL; \ + (varp) = &SLIST_NEXT((var), field)) + +#define SLIST_INIT(head) do { \ + SLIST_FIRST((head)) = NULL; \ +} while (0) + +#define SLIST_INSERT_AFTER(slistelm, elm, field) do { \ + SLIST_NEXT((elm), field) = SLIST_NEXT((slistelm), field); \ + SLIST_NEXT((slistelm), field) = (elm); \ +} while (0) + +#define SLIST_INSERT_HEAD(head, elm, field) do { \ + SLIST_NEXT((elm), field) = SLIST_FIRST((head)); \ + SLIST_FIRST((head)) = (elm); \ +} while (0) + +#define SLIST_NEXT(elm, field) ((elm)->field.sle_next) + +#define SLIST_REMOVE(head, elm, type, field) do { \ + QMD_SAVELINK(oldnext, (elm)->field.sle_next); \ + if (SLIST_FIRST((head)) == (elm)) { \ + SLIST_REMOVE_HEAD((head), field); \ + } \ + else { \ + QUEUE_TYPEOF(type) *curelm = SLIST_FIRST(head); \ + while (SLIST_NEXT(curelm, field) != (elm)) \ + curelm = SLIST_NEXT(curelm, field); \ + SLIST_REMOVE_AFTER(curelm, field); \ + } \ + TRASHIT(*oldnext); \ +} while (0) + +#define SLIST_REMOVE_AFTER(elm, field) do { \ + SLIST_NEXT(elm, field) = \ + SLIST_NEXT(SLIST_NEXT(elm, field), field); \ +} while (0) + +#define SLIST_REMOVE_HEAD(head, field) do { \ + SLIST_FIRST((head)) = SLIST_NEXT(SLIST_FIRST((head)), field); \ +} while (0) + +#define SLIST_SWAP(head1, head2, type) do { \ + QUEUE_TYPEOF(type) *swap_first = SLIST_FIRST(head1); \ + SLIST_FIRST(head1) = SLIST_FIRST(head2); \ + SLIST_FIRST(head2) = swap_first; \ +} while (0) + +/* + * Singly-linked Tail queue declarations. + */ +#define STAILQ_HEAD(name, type) \ +struct name { \ + struct type *stqh_first;/* first element */ \ + struct type **stqh_last;/* addr of last next element */ \ +} + +#define STAILQ_CLASS_HEAD(name, type) \ +struct name { \ + class type *stqh_first; /* first element */ \ + class type **stqh_last; /* addr of last next element */ \ +} + +#define STAILQ_HEAD_INITIALIZER(head) \ + { NULL, &(head).stqh_first } + +#define STAILQ_ENTRY(type) \ +struct { \ + struct type *stqe_next; /* next element */ \ +} + +#define STAILQ_CLASS_ENTRY(type) \ +struct { \ + class type *stqe_next; /* next element */ \ +} + +/* + * Singly-linked Tail queue functions. + */ +#define STAILQ_CONCAT(head1, head2) do { \ + if (!STAILQ_EMPTY((head2))) { \ + *(head1)->stqh_last = (head2)->stqh_first; \ + (head1)->stqh_last = (head2)->stqh_last; \ + STAILQ_INIT((head2)); \ + } \ +} while (0) + +#define STAILQ_EMPTY(head) ((head)->stqh_first == NULL) + +#define STAILQ_FIRST(head) ((head)->stqh_first) + +#define STAILQ_FOREACH(var, head, field) \ + for((var) = STAILQ_FIRST((head)); \ + (var); \ + (var) = STAILQ_NEXT((var), field)) + +#define STAILQ_FOREACH_FROM(var, head, field) \ + for ((var) = ((var) ? (var) : STAILQ_FIRST((head))); \ + (var); \ + (var) = STAILQ_NEXT((var), field)) + +#define STAILQ_FOREACH_SAFE(var, head, field, tvar) \ + for ((var) = STAILQ_FIRST((head)); \ + (var) && ((tvar) = STAILQ_NEXT((var), field), 1); \ + (var) = (tvar)) + +#define STAILQ_FOREACH_FROM_SAFE(var, head, field, tvar) \ + for ((var) = ((var) ? (var) : STAILQ_FIRST((head))); \ + (var) && ((tvar) = STAILQ_NEXT((var), field), 1); \ + (var) = (tvar)) + +#define STAILQ_INIT(head) do { \ + STAILQ_FIRST((head)) = NULL; \ + (head)->stqh_last = &STAILQ_FIRST((head)); \ +} while (0) + +#define STAILQ_INSERT_AFTER(head, tqelm, elm, field) do { \ + if ((STAILQ_NEXT((elm), field) = STAILQ_NEXT((tqelm), field)) == NULL)\ + (head)->stqh_last = &STAILQ_NEXT((elm), field); \ + STAILQ_NEXT((tqelm), field) = (elm); \ +} while (0) + +#define STAILQ_INSERT_HEAD(head, elm, field) do { \ + if ((STAILQ_NEXT((elm), field) = STAILQ_FIRST((head))) == NULL) \ + (head)->stqh_last = &STAILQ_NEXT((elm), field); \ + STAILQ_FIRST((head)) = (elm); \ +} while (0) + +#define STAILQ_INSERT_TAIL(head, elm, field) do { \ + STAILQ_NEXT((elm), field) = NULL; \ + *(head)->stqh_last = (elm); \ + (head)->stqh_last = &STAILQ_NEXT((elm), field); \ +} while (0) + +#define STAILQ_LAST(head, type, field) \ + (STAILQ_EMPTY((head)) ? NULL : \ + __containerof((head)->stqh_last, \ + QUEUE_TYPEOF(type), field.stqe_next)) + +#define STAILQ_NEXT(elm, field) ((elm)->field.stqe_next) + +#define STAILQ_REMOVE(head, elm, type, field) do { \ + QMD_SAVELINK(oldnext, (elm)->field.stqe_next); \ + if (STAILQ_FIRST((head)) == (elm)) { \ + STAILQ_REMOVE_HEAD((head), field); \ + } \ + else { \ + QUEUE_TYPEOF(type) *curelm = STAILQ_FIRST(head); \ + while (STAILQ_NEXT(curelm, field) != (elm)) \ + curelm = STAILQ_NEXT(curelm, field); \ + STAILQ_REMOVE_AFTER(head, curelm, field); \ + } \ + TRASHIT(*oldnext); \ +} while (0) + +#define STAILQ_REMOVE_AFTER(head, elm, field) do { \ + if ((STAILQ_NEXT(elm, field) = \ + STAILQ_NEXT(STAILQ_NEXT(elm, field), field)) == NULL) \ + (head)->stqh_last = &STAILQ_NEXT((elm), field); \ +} while (0) + +#define STAILQ_REMOVE_HEAD(head, field) do { \ + if ((STAILQ_FIRST((head)) = \ + STAILQ_NEXT(STAILQ_FIRST((head)), field)) == NULL) \ + (head)->stqh_last = &STAILQ_FIRST((head)); \ +} while (0) + +#define STAILQ_SWAP(head1, head2, type) do { \ + QUEUE_TYPEOF(type) *swap_first = STAILQ_FIRST(head1); \ + QUEUE_TYPEOF(type) **swap_last = (head1)->stqh_last; \ + STAILQ_FIRST(head1) = STAILQ_FIRST(head2); \ + (head1)->stqh_last = (head2)->stqh_last; \ + STAILQ_FIRST(head2) = swap_first; \ + (head2)->stqh_last = swap_last; \ + if (STAILQ_EMPTY(head1)) \ + (head1)->stqh_last = &STAILQ_FIRST(head1); \ + if (STAILQ_EMPTY(head2)) \ + (head2)->stqh_last = &STAILQ_FIRST(head2); \ +} while (0) + + +/* + * List declarations. + */ +#define LIST_HEAD(name, type) \ +struct name { \ + struct type *lh_first; /* first element */ \ +} + +#define LIST_CLASS_HEAD(name, type) \ +struct name { \ + class type *lh_first; /* first element */ \ +} + +#define LIST_HEAD_INITIALIZER(head) \ + { NULL } + +#define LIST_ENTRY(type) \ +struct { \ + struct type *le_next; /* next element */ \ + struct type **le_prev; /* address of previous next element */ \ +} + +#define LIST_CLASS_ENTRY(type) \ +struct { \ + class type *le_next; /* next element */ \ + class type **le_prev; /* address of previous next element */ \ +} + +/* + * List functions. + */ + +#if (defined(_KERNEL) && defined(INVARIANTS)) +#define QMD_LIST_CHECK_HEAD(head, field) do { \ + if (LIST_FIRST((head)) != NULL && \ + LIST_FIRST((head))->field.le_prev != \ + &LIST_FIRST((head))) \ + panic("Bad list head %p first->prev != head", (head)); \ +} while (0) + +#define QMD_LIST_CHECK_NEXT(elm, field) do { \ + if (LIST_NEXT((elm), field) != NULL && \ + LIST_NEXT((elm), field)->field.le_prev != \ + &((elm)->field.le_next)) \ + panic("Bad link elm %p next->prev != elm", (elm)); \ +} while (0) + +#define QMD_LIST_CHECK_PREV(elm, field) do { \ + if (*(elm)->field.le_prev != (elm)) \ + panic("Bad link elm %p prev->next != elm", (elm)); \ +} while (0) +#else +#define QMD_LIST_CHECK_HEAD(head, field) +#define QMD_LIST_CHECK_NEXT(elm, field) +#define QMD_LIST_CHECK_PREV(elm, field) +#endif /* (_KERNEL && INVARIANTS) */ + +#define LIST_EMPTY(head) ((head)->lh_first == NULL) + +#define LIST_FIRST(head) ((head)->lh_first) + +#define LIST_FOREACH(var, head, field) \ + for ((var) = LIST_FIRST((head)); \ + (var); \ + (var) = LIST_NEXT((var), field)) + +#define LIST_FOREACH_FROM(var, head, field) \ + for ((var) = ((var) ? (var) : LIST_FIRST((head))); \ + (var); \ + (var) = LIST_NEXT((var), field)) + +#define LIST_FOREACH_SAFE(var, head, field, tvar) \ + for ((var) = LIST_FIRST((head)); \ + (var) && ((tvar) = LIST_NEXT((var), field), 1); \ + (var) = (tvar)) + +#define LIST_FOREACH_FROM_SAFE(var, head, field, tvar) \ + for ((var) = ((var) ? (var) : LIST_FIRST((head))); \ + (var) && ((tvar) = LIST_NEXT((var), field), 1); \ + (var) = (tvar)) + +#define LIST_INIT(head) do { \ + LIST_FIRST((head)) = NULL; \ +} while (0) + +#define LIST_INSERT_AFTER(listelm, elm, field) do { \ + QMD_LIST_CHECK_NEXT(listelm, field); \ + if ((LIST_NEXT((elm), field) = LIST_NEXT((listelm), field)) != NULL)\ + LIST_NEXT((listelm), field)->field.le_prev = \ + &LIST_NEXT((elm), field); \ + LIST_NEXT((listelm), field) = (elm); \ + (elm)->field.le_prev = &LIST_NEXT((listelm), field); \ +} while (0) + +#define LIST_INSERT_BEFORE(listelm, elm, field) do { \ + QMD_LIST_CHECK_PREV(listelm, field); \ + (elm)->field.le_prev = (listelm)->field.le_prev; \ + LIST_NEXT((elm), field) = (listelm); \ + *(listelm)->field.le_prev = (elm); \ + (listelm)->field.le_prev = &LIST_NEXT((elm), field); \ +} while (0) + +#define LIST_INSERT_HEAD(head, elm, field) do { \ + QMD_LIST_CHECK_HEAD((head), field); \ + if ((LIST_NEXT((elm), field) = LIST_FIRST((head))) != NULL) \ + LIST_FIRST((head))->field.le_prev = &LIST_NEXT((elm), field);\ + LIST_FIRST((head)) = (elm); \ + (elm)->field.le_prev = &LIST_FIRST((head)); \ +} while (0) + +#define LIST_NEXT(elm, field) ((elm)->field.le_next) + +#define LIST_PREV(elm, head, type, field) \ + ((elm)->field.le_prev == &LIST_FIRST((head)) ? NULL : \ + __containerof((elm)->field.le_prev, \ + QUEUE_TYPEOF(type), field.le_next)) + +#define LIST_REMOVE(elm, field) do { \ + QMD_SAVELINK(oldnext, (elm)->field.le_next); \ + QMD_SAVELINK(oldprev, (elm)->field.le_prev); \ + QMD_LIST_CHECK_NEXT(elm, field); \ + QMD_LIST_CHECK_PREV(elm, field); \ + if (LIST_NEXT((elm), field) != NULL) \ + LIST_NEXT((elm), field)->field.le_prev = \ + (elm)->field.le_prev; \ + *(elm)->field.le_prev = LIST_NEXT((elm), field); \ + TRASHIT(*oldnext); \ + TRASHIT(*oldprev); \ +} while (0) + +#define LIST_SWAP(head1, head2, type, field) do { \ + QUEUE_TYPEOF(type) *swap_tmp = LIST_FIRST(head1); \ + LIST_FIRST((head1)) = LIST_FIRST((head2)); \ + LIST_FIRST((head2)) = swap_tmp; \ + if ((swap_tmp = LIST_FIRST((head1))) != NULL) \ + swap_tmp->field.le_prev = &LIST_FIRST((head1)); \ + if ((swap_tmp = LIST_FIRST((head2))) != NULL) \ + swap_tmp->field.le_prev = &LIST_FIRST((head2)); \ +} while (0) + +/* + * Tail queue declarations. + */ +#define TAILQ_HEAD(name, type) \ +struct name { \ + struct type *tqh_first; /* first element */ \ + struct type **tqh_last; /* addr of last next element */ \ + TRACEBUF \ +} + +#define TAILQ_CLASS_HEAD(name, type) \ +struct name { \ + class type *tqh_first; /* first element */ \ + class type **tqh_last; /* addr of last next element */ \ + TRACEBUF \ +} + +#define TAILQ_HEAD_INITIALIZER(head) \ + { NULL, &(head).tqh_first, TRACEBUF_INITIALIZER } + +#define TAILQ_ENTRY(type) \ +struct { \ + struct type *tqe_next; /* next element */ \ + struct type **tqe_prev; /* address of previous next element */ \ + TRACEBUF \ +} + +#define TAILQ_CLASS_ENTRY(type) \ +struct { \ + class type *tqe_next; /* next element */ \ + class type **tqe_prev; /* address of previous next element */ \ + TRACEBUF \ +} + +/* + * Tail queue functions. + */ +#if (defined(_KERNEL) && defined(INVARIANTS)) +#define QMD_TAILQ_CHECK_HEAD(head, field) do { \ + if (!TAILQ_EMPTY(head) && \ + TAILQ_FIRST((head))->field.tqe_prev != \ + &TAILQ_FIRST((head))) \ + panic("Bad tailq head %p first->prev != head", (head)); \ +} while (0) + +#define QMD_TAILQ_CHECK_TAIL(head, field) do { \ + if (*(head)->tqh_last != NULL) \ + panic("Bad tailq NEXT(%p->tqh_last) != NULL", (head)); \ +} while (0) + +#define QMD_TAILQ_CHECK_NEXT(elm, field) do { \ + if (TAILQ_NEXT((elm), field) != NULL && \ + TAILQ_NEXT((elm), field)->field.tqe_prev != \ + &((elm)->field.tqe_next)) \ + panic("Bad link elm %p next->prev != elm", (elm)); \ +} while (0) + +#define QMD_TAILQ_CHECK_PREV(elm, field) do { \ + if (*(elm)->field.tqe_prev != (elm)) \ + panic("Bad link elm %p prev->next != elm", (elm)); \ +} while (0) +#else +#define QMD_TAILQ_CHECK_HEAD(head, field) +#define QMD_TAILQ_CHECK_TAIL(head, headname) +#define QMD_TAILQ_CHECK_NEXT(elm, field) +#define QMD_TAILQ_CHECK_PREV(elm, field) +#endif /* (_KERNEL && INVARIANTS) */ + +#define TAILQ_CONCAT(head1, head2, field) do { \ + if (!TAILQ_EMPTY(head2)) { \ + *(head1)->tqh_last = (head2)->tqh_first; \ + (head2)->tqh_first->field.tqe_prev = (head1)->tqh_last; \ + (head1)->tqh_last = (head2)->tqh_last; \ + TAILQ_INIT((head2)); \ + QMD_TRACE_HEAD(head1); \ + QMD_TRACE_HEAD(head2); \ + } \ +} while (0) + +#define TAILQ_EMPTY(head) ((head)->tqh_first == NULL) + +#define TAILQ_FIRST(head) ((head)->tqh_first) + +#define TAILQ_FOREACH(var, head, field) \ + for ((var) = TAILQ_FIRST((head)); \ + (var); \ + (var) = TAILQ_NEXT((var), field)) + +#define TAILQ_FOREACH_FROM(var, head, field) \ + for ((var) = ((var) ? (var) : TAILQ_FIRST((head))); \ + (var); \ + (var) = TAILQ_NEXT((var), field)) + +#define TAILQ_FOREACH_SAFE(var, head, field, tvar) \ + for ((var) = TAILQ_FIRST((head)); \ + (var) && ((tvar) = TAILQ_NEXT((var), field), 1); \ + (var) = (tvar)) + +#define TAILQ_FOREACH_FROM_SAFE(var, head, field, tvar) \ + for ((var) = ((var) ? (var) : TAILQ_FIRST((head))); \ + (var) && ((tvar) = TAILQ_NEXT((var), field), 1); \ + (var) = (tvar)) + +#define TAILQ_FOREACH_REVERSE(var, head, headname, field) \ + for ((var) = TAILQ_LAST((head), headname); \ + (var); \ + (var) = TAILQ_PREV((var), headname, field)) + +#define TAILQ_FOREACH_REVERSE_FROM(var, head, headname, field) \ + for ((var) = ((var) ? (var) : TAILQ_LAST((head), headname)); \ + (var); \ + (var) = TAILQ_PREV((var), headname, field)) + +#define TAILQ_FOREACH_REVERSE_SAFE(var, head, headname, field, tvar) \ + for ((var) = TAILQ_LAST((head), headname); \ + (var) && ((tvar) = TAILQ_PREV((var), headname, field), 1); \ + (var) = (tvar)) + +#define TAILQ_FOREACH_REVERSE_FROM_SAFE(var, head, headname, field, tvar) \ + for ((var) = ((var) ? (var) : TAILQ_LAST((head), headname)); \ + (var) && ((tvar) = TAILQ_PREV((var), headname, field), 1); \ + (var) = (tvar)) + +#define TAILQ_INIT(head) do { \ + TAILQ_FIRST((head)) = NULL; \ + (head)->tqh_last = &TAILQ_FIRST((head)); \ + QMD_TRACE_HEAD(head); \ +} while (0) + +#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \ + QMD_TAILQ_CHECK_NEXT(listelm, field); \ + if ((TAILQ_NEXT((elm), field) = TAILQ_NEXT((listelm), field)) != NULL)\ + TAILQ_NEXT((elm), field)->field.tqe_prev = \ + &TAILQ_NEXT((elm), field); \ + else { \ + (head)->tqh_last = &TAILQ_NEXT((elm), field); \ + QMD_TRACE_HEAD(head); \ + } \ + TAILQ_NEXT((listelm), field) = (elm); \ + (elm)->field.tqe_prev = &TAILQ_NEXT((listelm), field); \ + QMD_TRACE_ELEM(&(elm)->field); \ + QMD_TRACE_ELEM(&(listelm)->field); \ +} while (0) + +#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \ + QMD_TAILQ_CHECK_PREV(listelm, field); \ + (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \ + TAILQ_NEXT((elm), field) = (listelm); \ + *(listelm)->field.tqe_prev = (elm); \ + (listelm)->field.tqe_prev = &TAILQ_NEXT((elm), field); \ + QMD_TRACE_ELEM(&(elm)->field); \ + QMD_TRACE_ELEM(&(listelm)->field); \ +} while (0) + +#define TAILQ_INSERT_HEAD(head, elm, field) do { \ + QMD_TAILQ_CHECK_HEAD(head, field); \ + if ((TAILQ_NEXT((elm), field) = TAILQ_FIRST((head))) != NULL) \ + TAILQ_FIRST((head))->field.tqe_prev = \ + &TAILQ_NEXT((elm), field); \ + else \ + (head)->tqh_last = &TAILQ_NEXT((elm), field); \ + TAILQ_FIRST((head)) = (elm); \ + (elm)->field.tqe_prev = &TAILQ_FIRST((head)); \ + QMD_TRACE_HEAD(head); \ + QMD_TRACE_ELEM(&(elm)->field); \ +} while (0) + +#define TAILQ_INSERT_TAIL(head, elm, field) do { \ + QMD_TAILQ_CHECK_TAIL(head, field); \ + TAILQ_NEXT((elm), field) = NULL; \ + (elm)->field.tqe_prev = (head)->tqh_last; \ + *(head)->tqh_last = (elm); \ + (head)->tqh_last = &TAILQ_NEXT((elm), field); \ + QMD_TRACE_HEAD(head); \ + QMD_TRACE_ELEM(&(elm)->field); \ +} while (0) + +#define TAILQ_LAST(head, headname) \ + (*(((struct headname *)((head)->tqh_last))->tqh_last)) + +#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next) + +#define TAILQ_PREV(elm, headname, field) \ + (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last)) + +#define TAILQ_REMOVE(head, elm, field) do { \ + QMD_SAVELINK(oldnext, (elm)->field.tqe_next); \ + QMD_SAVELINK(oldprev, (elm)->field.tqe_prev); \ + QMD_TAILQ_CHECK_NEXT(elm, field); \ + QMD_TAILQ_CHECK_PREV(elm, field); \ + if ((TAILQ_NEXT((elm), field)) != NULL) \ + TAILQ_NEXT((elm), field)->field.tqe_prev = \ + (elm)->field.tqe_prev; \ + else { \ + (head)->tqh_last = (elm)->field.tqe_prev; \ + QMD_TRACE_HEAD(head); \ + } \ + *(elm)->field.tqe_prev = TAILQ_NEXT((elm), field); \ + TRASHIT(*oldnext); \ + TRASHIT(*oldprev); \ + QMD_TRACE_ELEM(&(elm)->field); \ +} while (0) + +#define TAILQ_SWAP(head1, head2, type, field) do { \ + QUEUE_TYPEOF(type) *swap_first = (head1)->tqh_first; \ + QUEUE_TYPEOF(type) **swap_last = (head1)->tqh_last; \ + (head1)->tqh_first = (head2)->tqh_first; \ + (head1)->tqh_last = (head2)->tqh_last; \ + (head2)->tqh_first = swap_first; \ + (head2)->tqh_last = swap_last; \ + if ((swap_first = (head1)->tqh_first) != NULL) \ + swap_first->field.tqe_prev = &(head1)->tqh_first; \ + else \ + (head1)->tqh_last = &(head1)->tqh_first; \ + if ((swap_first = (head2)->tqh_first) != NULL) \ + swap_first->field.tqe_prev = &(head2)->tqh_first; \ + else \ + (head2)->tqh_last = &(head2)->tqh_first; \ +} while (0) + +#endif /* !_DISPATCH_SHIMS_SYS_QUEUE_H_ */ diff --git a/src/source.c b/src/source.c index 18087a211..ac92b03f1 100644 --- a/src/source.c +++ b/src/source.c @@ -4735,6 +4735,10 @@ _dispatch_source_debug(dispatch_source_t ds, char* buf, size_t bufsiz) static size_t _dispatch_mach_debug_attr(dispatch_mach_t dm, char* buf, size_t bufsiz) { +#ifdef __LINUX_PORT_HDD__ + LINUX_PORT_ERROR(); + return (size_t)0; +#else dispatch_queue_t target = dm->do_targetq; return dsnprintf(buf, bufsiz, "target = %s[%p], receive = 0x%x, " "send = 0x%x, send-possible = 0x%x%s, checkin = 0x%x%s, " @@ -4748,10 +4752,15 @@ _dispatch_mach_debug_attr(dispatch_mach_t dm, char* buf, size_t bufsiz) dm->dm_refs->dm_checkin ? " (pending)" : "", dm->dm_refs->dm_sending, dm->dm_refs->dm_disconnect_cnt, (bool)(dm->ds_atomic_flags & DSF_CANCELED)); +#endif } size_t _dispatch_mach_debug(dispatch_mach_t dm, char* buf, size_t bufsiz) { +#ifdef __LINUX_PORT_HDD__ + LINUX_PORT_ERROR(); + return (size_t)0; +#else size_t offset = 0; offset += dsnprintf(&buf[offset], bufsiz - offset, "%s[%p] = { ", dm->dq_label && !dm->dm_cancel_handler_called ? dm->dq_label : @@ -4760,6 +4769,7 @@ _dispatch_mach_debug(dispatch_mach_t dm, char* buf, size_t bufsiz) offset += _dispatch_mach_debug_attr(dm, &buf[offset], bufsiz - offset); offset += dsnprintf(&buf[offset], bufsiz - offset, "}"); return offset; +#endif } #if DISPATCH_DEBUG diff --git a/src/transform.c b/src/transform.c index e6fa4017e..98da41fef 100644 --- a/src/transform.c +++ b/src/transform.c @@ -20,7 +20,9 @@ #include "internal.h" +#ifdef __APPLE__ #include +#endif #if defined(__LITTLE_ENDIAN__) #define DISPATCH_DATA_FORMAT_TYPE_UTF16_HOST DISPATCH_DATA_FORMAT_TYPE_UTF16LE @@ -195,19 +197,29 @@ _dispatch_transform_detect_utf(dispatch_data_t data) static uint16_t _dispatch_transform_swap_to_host(uint16_t x, int32_t byteOrder) { +#ifdef __LINUX_PORT_HDD__ + LINUX_PORT_ERROR(); + return x; +#else if (byteOrder == OSLittleEndian) { - return OSSwapLittleToHostInt16(x); + return OSSwapLittleToHostInt16(x); } return OSSwapBigToHostInt16(x); +#endif } static uint16_t _dispatch_transform_swap_from_host(uint16_t x, int32_t byteOrder) { +#ifdef __LINUX_PORT_HDD__ + LINUX_PORT_ERROR(); + return x; +#else if (byteOrder == OSLittleEndian) { return OSSwapHostToLittleInt16(x); } return OSSwapHostToBigInt16(x); +#endif } #pragma mark - @@ -519,25 +531,45 @@ _dispatch_transform_from_utf16(dispatch_data_t data, int32_t byteOrder) static dispatch_data_t _dispatch_transform_from_utf16le(dispatch_data_t data) { +#ifdef __LINUX_PORT_HDD__ + LINUX_PORT_ERROR(); + return (dispatch_data_t)0; +#else return _dispatch_transform_from_utf16(data, OSLittleEndian); +#endif } static dispatch_data_t _dispatch_transform_from_utf16be(dispatch_data_t data) { +#ifdef __LINUX_PORT_HDD__ + LINUX_PORT_ERROR(); + return (dispatch_data_t)0; +#else return _dispatch_transform_from_utf16(data, OSBigEndian); +#endif } static dispatch_data_t _dispatch_transform_to_utf16le(dispatch_data_t data) { +#ifdef __LINUX_PORT_HDD__ + LINUX_PORT_ERROR(); + return (dispatch_data_t)0; +#else return _dispatch_transform_to_utf16(data, OSLittleEndian); +#endif } static dispatch_data_t _dispatch_transform_to_utf16be(dispatch_data_t data) { +#ifdef __LINUX_PORT_HDD__ + LINUX_PORT_ERROR(); + return (dispatch_data_t)0; +#else return _dispatch_transform_to_utf16(data, OSBigEndian); +#endif } #pragma mark - From 26b558b0dd50d8a8787422cbbc1906c5431bb671 Mon Sep 17 00:00:00 2001 From: David Grove Date: Fri, 4 Dec 2015 21:55:59 +0000 Subject: [PATCH 2/3] define WORKQ_PRIO_INVALID constant --- src/queue.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/queue.c b/src/queue.c index fe5c9e1a5..182b6c191 100644 --- a/src/queue.c +++ b/src/queue.c @@ -199,9 +199,10 @@ struct dispatch_root_queue_context_s { }; typedef struct dispatch_root_queue_context_s *dispatch_root_queue_context_t; +#define WORKQ_PRIO_INVALID (-1) #ifdef __linux__ -#define WORKQ_BG_PRIOQUEUE_CONDITIONAL (-1) -#define WORKQ_HIGH_PRIOQUEUE_CONDITIONAL (-1) +#define WORKQ_BG_PRIOQUEUE_CONDITIONAL WORKQ_PRIO_INVALID +#define WORKQ_HIGH_PRIOQUEUE_CONDITIONAL WORKQ_PRIO_INVALID #else #define WORKQ_BG_PRIOQUEUE_CONDITIONAL WORKQ_BG_PRIOQUEUE #define WORKQ_HIGH_PRIOQUEUE_CONDITIONAL WORKQ_HIGH_PRIOQUEUE @@ -818,7 +819,7 @@ _dispatch_root_queues_init_workq(void) dispatch_root_queue_context_t qc; qc = &_dispatch_root_queue_contexts[i]; #if DISPATCH_USE_LEGACY_WORKQUEUE_FALLBACK - if (!disable_wq && qc->dgq_wq_priority != -1) { + if (!disable_wq && qc->dgq_wq_priority != WORKQ_PRIO_INVALID) { r = pthread_workqueue_attr_setqueuepriority_np(&pwq_attr, qc->dgq_wq_priority); (void)dispatch_assume_zero(r); From 61715e46f5a140b578394ac7406fb87120c67917 Mon Sep 17 00:00:00 2001 From: David Grove Date: Fri, 4 Dec 2015 22:01:35 +0000 Subject: [PATCH 3/3] Add free to offset malloc in semaphore_create --- src/semaphore.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/semaphore.c b/src/semaphore.c index 85ef4231f..ab08702f5 100644 --- a/src/semaphore.c +++ b/src/semaphore.c @@ -740,6 +740,7 @@ _dispatch_thread_semaphore_dispose(_dispatch_thread_semaphore_t sema) #elif USE_POSIX_SEM sem_t *s4 = (sem_t*)sema; int ret = sem_destroy(s4); + free(s4); DISPATCH_SEMAPHORE_VERIFY_RET(ret); #elif USE_WIN32_SEM // XXX: signal the semaphore?