{
int res = 0;
if (kwq->kw_pre_intrcount != 0 &&
- kwq->kw_pre_intrtype == type &&
- is_seqlower_eq(lockseq, kwq->kw_pre_intrseq)) {
+ kwq->kw_pre_intrtype == type &&
+ (kwq->kw_pre_intrseq == 0 || is_seqlower_eq(lockseq, kwq->kw_pre_intrseq))) {
kwq->kw_pre_intrcount--;
*retval = kwq->kw_pre_intrretbits;
if (kwq->kw_pre_intrcount == 0) {
int diff;
uint32_t count = 0;
uint32_t curgen = lgenval & PTHRW_COUNT_MASK;
-
+ int clearedkflags = 0;
+
error = ksyn_wqfind(rwlock, lgenval, ugenval, rw_wc, flags, (KSYN_WQTYPE_INDROP | KSYN_WQTYPE_RWLOCK), &kwq);
if (error != 0) {
return(error);
/* no prepost and all threads are in place, reset the bit */
if ((isinit != 0) && ((kwq->kw_kflags & KSYN_KWF_INITCLEARED) != 0)){
kwq->kw_kflags &= ~KSYN_KWF_INITCLEARED;
+ clearedkflags = 1;
}
/* can handle unlock now */
/* update bits?? */
*retval = updatebits;
}
-
+
+ // <rdar://problem/22244050> If any of the wakeups failed because they already
+ // returned to userspace because of a signal then we need to ensure that the
+ // reset state is not cleared when that thread returns. Otherwise,
+ // _pthread_rwlock_lock will clear the interrupted state before it is read.
+ if (clearedkflags != 0 && kwq->kw_pre_intrcount > 0) {
+ kwq->kw_kflags |= KSYN_KWF_INITCLEARED;
+ }
ksyn_wqunlock(kwq);
ksyn_wqrelease(kwq, 0, (KSYN_WQTYPE_INDROP | KSYN_WQTYPE_RWLOCK));
6EB232C81B0EB29D005915CE /* pthread_mutex_up.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = pthread_mutex_up.c; sourceTree = "<group>"; };
6EB232C91B0EB29D005915CE /* resolver.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = resolver.c; sourceTree = "<group>"; };
6EB232CA1B0EB29D005915CE /* resolver.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = resolver.h; sourceTree = "<group>"; };
+ 720A46E21B8D125900AB7950 /* Makefile.common */ = {isa = PBXFileReference; lastKnownFileType = text; path = Makefile.common; sourceTree = "<group>"; };
74E594A41613AAF4006C417B /* libpthread_eOS.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libpthread_eOS.a; sourceTree = BUILT_PRODUCTS_DIR; };
9207EB711AA6E008006FFC86 /* wq_kevent_stress.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = wq_kevent_stress.c; sourceTree = "<group>"; };
9240BF321AA669C4003C99B4 /* wqtrace.lua */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = wqtrace.lua; path = tools/wqtrace.lua; sourceTree = SOURCE_ROOT; };
C9A960B618452CDD00AE10C8 /* install-lldbmacros.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = "install-lldbmacros.sh"; sourceTree = "<group>"; };
C9C2212D15FA978D00447568 /* pthread.aliases */ = {isa = PBXFileReference; lastKnownFileType = text; path = pthread.aliases; sourceTree = "<group>"; };
C9C533841607C928009988FA /* kern_internal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = kern_internal.h; sourceTree = "<group>"; };
+ C9C5F7381B8CE2D600C873EF /* rwlock-22244050.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = "rwlock-22244050.c"; sourceTree = "<group>"; };
C9CA27D91602813000259F78 /* pthread.kext */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = pthread.kext; sourceTree = BUILT_PRODUCTS_DIR; };
C9CA27DC1602813000259F78 /* Kernel.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Kernel.framework; path = System/Library/Frameworks/Kernel.framework; sourceTree = SDKROOT; };
C9D9E8FE1626248800448CED /* pthread-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "pthread-Info.plist"; sourceTree = "<group>"; };
9264D6821A9D3E010094346B /* tests */ = {
isa = PBXGroup;
children = (
+ 720A46E21B8D125900AB7950 /* Makefile.common */,
9264D6881A9D3E010094346B /* Makefile */,
9264D6831A9D3E010094346B /* atfork.c */,
9264D6841A9D3E010094346B /* cond.c */,
9264D6891A9D3E010094346B /* maxwidth.c */,
9264D68A1A9D3E010094346B /* mutex.c */,
9264D68B1A9D3E010094346B /* once.c */,
+ C9C5F7381B8CE2D600C873EF /* rwlock-22244050.c */,
9264D68C1A9D3E010094346B /* rwlock-signal.c */,
9264D68D1A9D3E010094346B /* rwlock.c */,
9264D68E1A9D3E010094346B /* tsd.c */,
};
/* End PBXHeadersBuildPhase section */
+/* Begin PBXLegacyTarget section */
+ 720A46DE1B8D0B7700AB7950 /* Tests */ = {
+ isa = PBXLegacyTarget;
+ buildArgumentsString = "$(ACTION)";
+ buildConfigurationList = 720A46E11B8D0B7700AB7950 /* Build configuration list for PBXLegacyTarget "Tests" */;
+ buildPhases = (
+ );
+ buildToolPath = /usr/bin/make;
+ buildWorkingDirectory = tests;
+ dependencies = (
+ );
+ name = Tests;
+ passBuildSettingsInEnvironment = 1;
+ productName = Test;
+ };
+/* End PBXLegacyTarget section */
+
/* Begin PBXNativeTarget section */
6E8C16511B14F08A00C8987C /* libsystem_pthread.dylib introspection */ = {
isa = PBXNativeTarget;
attributes = {
LastUpgradeCheck = 0700;
ORGANIZATIONNAME = "";
+ TargetAttributes = {
+ 720A46DE1B8D0B7700AB7950 = {
+ CreatedOnToolsVersion = 7.0;
+ };
+ };
};
buildConfigurationList = C9A325DC15B7347000270056 /* Build configuration list for PBXProject "libpthread" */;
compatibilityVersion = "Xcode 3.2";
C90E7AAC15DC3D3300A06D48 /* All */,
C91D01B5162892FF0002E29A /* Kext */,
C98832C115DEB44000B3308E /* Embedded */,
+ 720A46DE1B8D0B7700AB7950 /* Tests */,
6E8C16511B14F08A00C8987C /* libsystem_pthread.dylib introspection */,
C9A325E115B7347000270056 /* libsystem_pthread.dylib */,
C90E7A9E15DC3C3800A06D48 /* libpthread.a */,
};
name = Debug;
};
+ 720A46DF1B8D0B7700AB7950 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ COPY_PHASE_STRIP = NO;
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ ENABLE_NS_ASSERTIONS = NO;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_NO_COMMON_BLOCKS = YES;
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ MTL_ENABLE_DEBUG_INFO = NO;
+ OTHER_CFLAGS = "";
+ OTHER_LDFLAGS = "";
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SDKROOT = macosx.internal;
+ };
+ name = Release;
+ };
+ 720A46E01B8D0B7700AB7950 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ COPY_PHASE_STRIP = NO;
+ DEBUGGING_SYMBOLS = YES;
+ DEBUG_INFORMATION_FORMAT = dwarf;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ ENABLE_TESTABILITY = YES;
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
+ GCC_NO_COMMON_BLOCKS = YES;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "DEBUG=1",
+ "$(inherited)",
+ );
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ MTL_ENABLE_DEBUG_INFO = YES;
+ ONLY_ACTIVE_ARCH = YES;
+ OTHER_CFLAGS = "";
+ OTHER_LDFLAGS = "";
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SDKROOT = macosx.internal;
+ };
+ name = Debug;
+ };
74E594A31613AAF4006C417B /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = C99EA612161F8288003EBC56 /* eos.xcconfig */;
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
+ 720A46E11B8D0B7700AB7950 /* Build configuration list for PBXLegacyTarget "Tests" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 720A46DF1B8D0B7700AB7950 /* Release */,
+ 720A46E01B8D0B7700AB7950 /* Debug */,
+ );
+ defaultConfigurationIsVisible = 0;
+ };
74E594A21613AAF4006C417B /* Build configuration list for PBXNativeTarget "libpthread.a eOS" */ = {
isa = XCConfigurationList;
buildConfigurations = (
#if defined(__LP64__)
uint32_t _pad;
#endif
- uint32_t m_tid[2]; // thread id of thread that has mutex locked, misaligned locks may span to first field of m_seq
- uint32_t m_seq[3];
+ uint32_t m_tid[2]; // thread id of thread that has mutex locked
+ uint32_t m_seq[2]; // mutex sequence id
+ uint32_t m_mis[2]; // for misaligned locks m_tid/m_seq will span into here
#if defined(__LP64__)
- uint32_t _reserved;
+ uint32_t _reserved[4];
+#else
+ uint32_t _reserved[1];
#endif
- void *reserved2[2];
} _pthread_mutex;
#endif
} _pthread_rwlock;
+#include "pthread.h"
#include "pthread_spis.h"
+_Static_assert(sizeof(_pthread_mutex) == sizeof(pthread_mutex_t),
+ "Incorrect _pthread_mutex structure size");
+
// Internal references to pthread_self() use TSD slot 0 directly.
inline static pthread_t __attribute__((__pure__))
_pthread_self_direct(void)
#define PLOCKSTAT_MUTEX_RELEASE(x, y)
#endif /* PLOCKSTAT */
+#define PTHREAD_MUTEX_INIT_UNUSED 1
+
extern int __unix_conforming;
#ifndef BUILDING_VARIANT
MUTEX_GETSEQ_ADDR(_pthread_mutex *mutex,
volatile uint64_t **seqaddr)
{
- // addr of m_seq[1] for misaligned, m_seq[0] for aligned mutex struct
- *seqaddr = (volatile uint64_t *)(((uintptr_t)&mutex->m_seq[1]) & ~0x7ul);
+ // 64-bit aligned address inside m_seq array (&m_seq[0] for aligned mutex)
+ // We don't require more than byte alignment on OS X. rdar://22278325
+ *seqaddr = (volatile uint64_t*)(((uintptr_t)mutex->m_seq + 0x7ul) & ~0x7ul);
}
PTHREAD_ALWAYS_INLINE
MUTEX_GETTID_ADDR(_pthread_mutex *mutex,
volatile uint64_t **tidaddr)
{
- // addr of m_tid[1] for misaligned, m_tid[0] for aligned mutex struct
- *tidaddr = (volatile uint64_t *)(((uintptr_t)&mutex->m_tid[1]) & ~0x7ul);
+ // 64-bit aligned address inside m_tid array (&m_tid[0] for aligned mutex)
+ // We don't require more than byte alignment on OS X. rdar://22278325
+ *tidaddr = (volatile uint64_t*)(((uintptr_t)mutex->m_tid + 0x7ul) & ~0x7ul);
}
#ifndef BUILDING_VARIANT /* [ */
static inline int
-_pthread_mutex_init(_pthread_mutex *mutex, const pthread_mutexattr_t *attr, uint32_t static_type)
+_pthread_mutex_init(_pthread_mutex *mutex, const pthread_mutexattr_t *attr,
+ uint32_t static_type)
{
+ mutex->mtxopts.value = 0;
+ mutex->mtxopts.options.mutex = 1;
if (attr) {
if (attr->sig != _PTHREAD_MUTEX_ATTR_SIG) {
return EINVAL;
}
mutex->mtxopts.options.pshared = _PTHREAD_DEFAULT_PSHARED;
}
-
- mutex->mtxopts.options.notify = 0;
- mutex->mtxopts.options.unused = 0;
- mutex->mtxopts.options.hold = 0;
- mutex->mtxopts.options.mutex = 1;
- mutex->mtxopts.options.lock_count = 0;
-
- mutex->m_tid[0] = 0;
- mutex->m_tid[1] = 0;
- mutex->m_seq[0] = 0;
- mutex->m_seq[1] = 0;
- mutex->m_seq[2] = 0;
- mutex->prioceiling = 0;
mutex->priority = 0;
- mutex->mtxopts.options.misalign = (((uintptr_t)&mutex->m_seq[0]) & 0x7ul) != 0;
- if (mutex->mtxopts.options.misalign) {
- mutex->m_tid[0] = ~0u;
- } else {
- mutex->m_seq[2] = ~0u;
+ volatile uint64_t *seqaddr;
+ MUTEX_GETSEQ_ADDR(mutex, &seqaddr);
+ volatile uint64_t *tidaddr;
+ MUTEX_GETTID_ADDR(mutex, &tidaddr);
+#if PTHREAD_MUTEX_INIT_UNUSED
+ if ((uint32_t*)tidaddr != mutex->m_tid) {
+ mutex->mtxopts.options.misalign = 1;
+ __builtin_memset(mutex->m_tid, 0xff, sizeof(mutex->m_tid));
}
+ __builtin_memset(mutex->m_mis, 0xff, sizeof(mutex->m_mis));
+#endif // PTHREAD_MUTEX_INIT_UNUSED
+ *tidaddr = 0;
+ *seqaddr = 0;
long sig = _PTHREAD_MUTEX_SIG;
if (mutex->mtxopts.options.type == PTHREAD_MUTEX_NORMAL &&
sig = _PTHREAD_MUTEX_SIG_fast;
}
- // unused, purely for detecting copied mutexes and smashes during debugging:
- mutex->reserved2[0] = ~(uintptr_t)mutex; // use ~ to hide from leaks
- mutex->reserved2[1] = (uintptr_t)sig;
+#if PTHREAD_MUTEX_INIT_UNUSED
+ // For detecting copied mutexes and smashes during debugging
+ uint32_t sig32 = (uint32_t)sig;
+#if defined(__LP64__)
+ uintptr_t guard = ~(uintptr_t)mutex; // use ~ to hide from leaks
+ __builtin_memcpy(mutex->_reserved, &guard, sizeof(guard));
+ mutex->_reserved[2] = sig32;
+ mutex->_reserved[3] = sig32;
+ mutex->_pad = sig32;
+#else
+ mutex->_reserved[0] = sig32;
+#endif
+#endif // PTHREAD_MUTEX_INIT_UNUSED
// Ensure all contents are properly set before setting signature.
#if defined(__LP64__)
TARGETS := $(patsubst %.c,%,$(SOURCES))
TESTS := $(patsubst %,test-%,$(TARGETS))
-CFLAGS := -I$(SDKROOT)/System/Library/Frameworks/System.framework/PrivateHeaders
+include Makefile.common
+
+CFLAGS += -I$(SDKROOT)/System/Library/Frameworks/System.framework/PrivateHeaders
+
+%: %.c
+ $(CC) -o $(BUILDDIR)/$@ $< $(CFLAGS)
all: $(TARGETS)
clean:
rm -f $(TARGETS)
+setup:
+ mkdir -p $(BUILDDIR)
+
+
+# B&I Targets
+
+installhdrs:
+
+install: setup all
+
+
.PHONY: all test check clean $(TESTS)
--- /dev/null
+# Code 'borrowed' from xnu/tools/tests Makefile structure.
+#
+# This provides a somewhat flexible framework (albeit, not perfect)
+# for building tests for multiple platforms using the correct toolset
+#
+# Please contact: nwertman@apple.com with any questions
+
+
+ifneq ($(SRCROOT),)
+SRCDIR=$(SRCROOT)
+else
+SRCDIR?=$(shell /bin/pwd)
+endif
+
+ifneq ($(OBJROOT),)
+OBJDIR?=$(OBJROOT)
+else
+OBJDIR?=$(SRCDIR)/build/obj
+endif
+
+ifneq ($(DSTROOT),)
+BUILDDIR?=$(DSTROOT)/AppleInternal/CoreOS/tests/$(PROJECT)
+else
+BUILDDIR?=$(SRCDIR)/build/dst
+endif
+
+#
+# Common definitions for test directories
+#
+
+XCRUN := /usr/bin/xcrun
+SDKROOT ?= macosx.internal
+
+# SDKROOT may be passed as a shorthand like "iphoneos.internal". We
+# must resolve these to a full path and override SDKROOT.
+
+SDKROOT_RESOLVED := $(shell $(XCRUN) -sdk $(SDKROOT) -show-sdk-path)
+ifeq ($(strip $(SDKROOT)_$(SDKROOT_RESOLVED)),/_)
+SDKROOT_RESOLVED := /
+endif
+override SDKROOT = $(SDKROOT_RESOLVED)
+
+SDKVERSION := $(shell $(XCRUN) -sdk $(SDKROOT) -show-sdk-version)
+
+PLATFORMPATH := $(shell $(XCRUN) -sdk $(SDKROOT) -show-sdk-platform-path)
+PLATFORM := $(shell echo $(PLATFORMPATH) | sed 's,^.*/\([^/]*\)\.platform$$,\1,')
+
+ifeq ($(PLATFORM),watchOS)
+PLATFORM := WatchOS
+endif
+
+SUPPORTED_EMBEDDED_PLATFORMS := iPhoneOS iPhoneOSNano tvOS AppleTVOS WatchOS
+Embedded = $(if $(filter $(SUPPORTED_EMBEDDED_PLATFORMS),$(PLATFORM)),YES,NO)
+
+#
+# Deployment target flag
+#
+ifeq ($(PLATFORM),MacOSX)
+DEPLOYMENT_TARGET_FLAGS = -mmacosx-version-min=$(SDKVERSION)
+else ifeq ($(PLATFORM),WatchOS)
+DEPLOYMENT_TARGET_FLAGS = -mwatchos-version-min=$(SDKVERSION)
+else ifeq ($(PLATFORM),tvOS)
+DEPLOYMENT_TARGET_FLAGS = -mtvos-version-min=$(SDKVERSION)
+else ifeq ($(PLATFORM),AppleTVOS)
+DEPLOYMENT_TARGET_FLAGS = -mtvos-version-min=$(SDKVERSION)
+else ifneq ($(filter $(SUPPORTED_EMBEDDED_PLATFORMS),$(PLATFORM)),)
+DEPLOYMENT_TARGET_FLAGS = -miphoneos-version-min=$(SDKVERSION)
+else ifneq ($(filter $(SUPPORTED_SIMULATOR_PLATFORMS),$(PLATFORM)),)
+DEPLOYMENT_TARGET_FLAGS =
+else
+DEPLOYMENT_TARGET_FLAGS =
+endif
+
+DEPLOYMENT_TARGET_DEFINES = -DPLATFORM_$(PLATFORM)
+
+
+
+# setup the TARGETSDK and SDKROOT variables
+TARGETSDK:=$(SDKROOT)
+SDKROOTPATH:=$(SDKROOT)
+
+# make sure we have a build directory
+$(shell [ -d "$(BUILDDIR)" ] || mkdir -p $(BUILDDIR))
+
+#arch configs if not provided
+ifdef RC_ARCHS
+ARCH_CONFIGS:=$(RC_ARCHS)
+endif
+
+ifeq ($(ARCH_CONFIGS),)
+ARCH_CONFIGS:=
+ifeq ($(Embedded),YES)
+ARCH_CONFIGS:=$(shell $(XCRUN) -sdk $(TARGETSDK) otool -f -v $(SDKROOT)/usr/lib/system/libsystem_kernel.dylib | grep architecture | cut -d' ' -f 2 | tr '\n' ' ')
+else
+ARCH_CONFIGS:=x86_64 i386
+endif
+endif
+
+ARCH_CONFIGS_32:=$(filter-out %64,$(ARCH_CONFIGS))
+ARCH_CONFIGS_64:=$(filter %64,$(ARCH_CONFIGS))
+
+ARCH_FLAGS:=$(foreach argarch,$(ARCH_CONFIGS),-arch $(argarch) )
+
+
+#setup the compiler flags.
+CC:=$(shell $(XCRUN) -sdk "$(TARGETSDK)" -find clang)
+MIG:=$(shell $(XCRUN) -sdk "$(TARGETSDK)" -find mig)
+CODESIGN:=$(shell $(XCRUN) -sdk "$(TARGETSDK)" -find codesign)
+CODESIGN_ALLOCATE:=$(shell $(XCRUN) -sdk "$(TARGETSDK)" -find codesign_allocate)
+PLUTIL:=$(shell $(XCRUN) -sdk "$(TARGETSDK)" -find plutil)
+
+CFLAGS=-I$(BUILDDIR) -I. -isysroot $(SDKROOTPATH) $(ARCH_FLAGS)
+
+ifeq ($(Embedded),YES)
+TARGET_NAME=ios
+CONFIG_EMBED_DEFINE:= -DCONFIG_EMBEDDED=1
+else
+TARGET_NAME=osx
+CONFIG_EMBED_DEFINE:=
+endif
+
+MORECFLAGS=$(CONFIG_EMBED_DEFINE)
\ No newline at end of file
--- /dev/null
+#include <pthread.h>
+#include <stdio.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <libkern/OSAtomic.h>
+
+pthread_t thr;
+pthread_rwlock_t lock;
+OSSpinLock slock = 0;
+int i = 0;
+
+void sighandler(int sig)
+{
+ if (sig == SIGUSR1) {
+ OSSpinLockLock(&slock);
+ OSSpinLockUnlock(&slock);
+ } else {
+ // ALARM
+ fprintf(stderr, "FAIL (%d)\n", i);
+ exit(1);
+ }
+}
+
+void* thread(void *arg)
+{
+ pthread_rwlock_rdlock(&lock);
+ pthread_rwlock_unlock(&lock);
+ return NULL;
+}
+
+int main(int argc, const char *argv[])
+{
+ pthread_rwlock_init(&lock, NULL);
+ signal(SIGUSR1, sighandler);
+ signal(SIGALRM, sighandler);
+
+ alarm(30);
+
+ while (i++ < 10000) {
+ pthread_rwlock_wrlock(&lock);
+ pthread_create(&thr, NULL, thread, NULL);
+ OSSpinLockLock(&slock);
+ pthread_kill(thr, SIGUSR1);
+ pthread_rwlock_unlock(&lock);
+ OSSpinLockUnlock(&slock);
+ }
+
+ fprintf(stderr, "PASS\n");
+ return 0;
+}