Use native threading and locking APIs on Windows

Removes dependency on pthread library and uses fast Slim Reader/Writer (SRW) locks for NSLock/NSRecursiveLock/NSCondition/NSConditionLock as well as all internal locks. Adds GS_MUTEX_*() macros in GSPThread.h, that are being used for all internal locking instead of pthread APIs.

Also adds support for thread priorities on Windows, fixes method signature of +[NSThread setThreadPriority:] to match Apple platforms, and adds error handling in same method.
This commit is contained in:
Frederik Seiffert 2021-07-28 16:17:47 +02:00 committed by Frederik Seiffert
parent 3b8bbb00ba
commit abfe4e2a04
29 changed files with 1611 additions and 640 deletions

View file

@ -21,6 +21,45 @@
Changes to add support for 64bit transitions used by v2+ of the
timezone format.
2021-07-14 Frederik Seiffert <frederik@algoriddim.com>
* Headers/Foundation/NSLock.h:
* Headers/Foundation/NSThread.h:
* Headers/GNUstepBase/GSConfig.h.in:
* Headers/GNUstepBase/config.h.in:
* Source/Additions/GCObject.m:
* Source/Additions/GSObjCRuntime.m:
* Source/Additions/Unicode.m:
* Source/GSAtomic.h:
* Source/GSFFCallInvocation.m:
* Source/GSFFIInvocation.m:
* Source/GSPThread.h:
* Source/NSArray.m:
* Source/NSCharacterSet.m:
* Source/NSDebug.m:
* Source/NSException.m:
* Source/NSLock.m:
* Source/NSObject.m:
* Source/NSScanner.m:
* Source/NSString.m:
* Source/NSThread.m:
* Source/NSTimeZone.m:
* Source/NSZone.m:
* Tests/base/NSThread/GNUmakefile.preamble:
* Tests/base/NSThread/late_unregister.m:
* Tests/base/NSThread/lazy_thread.m:
* config/config.initialize.m:
* configure:
* configure.ac:
Use native threading and locking APIs on Windows, removing dependency
on pthread library and using fast Slim Reader/Writer (SRW) locks for
NSLock/NSRecursiveLock/NSCondition/NSConditionLock as well as all
internal locks. Adds GS_MUTEX_*() macros in GSPThread.h, that are being
used for all internal locking instead of pthread APIs.
Also adds support for thread priorities on Windows, fixes method
signature of +[NSThread setThreadPriority:] to match Apple platforms,
and adds error handling in same method.
2021-07-16 Frederik Seiffert <frederik@algoriddim.com>
* Source/GSICUString.h:

View file

@ -74,7 +74,7 @@ GS_EXPORT_CLASS
{
#if GS_EXPOSE(NSLock)
@protected
gs_mutex_t _mutex;
gs_mutex_public_t _mutex;
NSString *_name;
#endif
}
@ -126,8 +126,8 @@ GS_EXPORT_CLASS
{
#if GS_EXPOSE(NSCondition)
@protected
gs_cond_t _condition;
gs_mutex_t _mutex;
gs_cond_public_t _condition;
gs_mutex_public_t _mutex;
NSString *_name;
#endif
}
@ -278,7 +278,7 @@ GS_EXPORT_CLASS
{
#if GS_EXPOSE(NSRecursiveLock)
@protected
gs_mutex_t _mutex;
gs_mutex_public_t _mutex;
NSString *_name;
#endif
}

View file

@ -134,7 +134,7 @@ GS_EXPORT_CLASS
#if OS_API_VERSION(MAC_OS_X_VERSION_10_2,GS_API_LATEST) \
&& GS_API_VERSION( 10200,GS_API_LATEST)
+ (void) setThreadPriority: (double)pri;
+ (BOOL) setThreadPriority: (double)pri;
+ (double) threadPriority;
#endif

View file

@ -254,10 +254,13 @@ typedef gsuaddr gsaddr;
*/
typedef struct {
uint8_t dummy[@GS_SIZEOF_COND_T@];
} gs_cond_t __attribute__((aligned (@GS_ALIGNOF_COND_T@)));
} gs_cond_public_t __attribute__((aligned (@GS_ALIGNOF_COND_T@)));
typedef struct {
uint8_t dummy[@GS_SIZEOF_COND_MUTEX_T@];
} gs_cond_mutex_public_t __attribute__((aligned (@GS_ALIGNOF_COND_MUTEX_T@)));
typedef struct {
uint8_t dummy[@GS_SIZEOF_MUTEX_T@];
} gs_mutex_t __attribute__((aligned (@GS_ALIGNOF_MUTEX_T@)));
} gs_mutex_public_t __attribute__((aligned (@GS_ALIGNOF_MUTEX_T@)));
#define OBJC2RUNTIME @OBJC2RUNTIME@
#define BASE_NATIVE_OBJC_EXCEPTIONS @BASE_NATIVE_OBJC_EXCEPTIONS@
@ -272,6 +275,7 @@ typedef struct {
#define GS_USE_LIBDISPATCH_RUNLOOP @HAVE_LIBDISPATCH_RUNLOOP@
#define GS_HAVE_NSURLSESSION @GS_HAVE_NSURLSESSION@
#define GS_HAVE_OBJC_ROOT_CLASS_ATTR @GS_HAVE_OBJC_ROOT_CLASS_ATTR@
#define GS_USE_WIN32_THREADS_AND_LOCKS @HAVE_WIN32_THREADS_AND_LOCKS@
#ifndef __has_include
# define __has_include(x) 0

View file

@ -3,12 +3,21 @@
/* Define if building universal (internal helper macro) */
#undef AC_APPLE_UNIVERSAL_BUILD
/* The normal alignment of `CONDITION_VARIABLE', in bytes. */
#undef ALIGNOF_CONDITION_VARIABLE
/* The normal alignment of `gs_mutex_t', in bytes. */
#undef ALIGNOF_GS_MUTEX_T
/* The normal alignment of `pthread_cond_t', in bytes. */
#undef ALIGNOF_PTHREAD_COND_T
/* The normal alignment of `pthread_mutex_t', in bytes. */
#undef ALIGNOF_PTHREAD_MUTEX_T
/* The normal alignment of `SRWLOCK', in bytes. */
#undef ALIGNOF_SRWLOCK
/* Define if SO_REUSEADDR is broken on this system */
#undef BROKEN_SO_REUSEADDR
@ -858,12 +867,18 @@
/* Define to 1 if the `setpgrp' function takes no argument. */
#undef SETPGRP_VOID
/* The size of `CONDITION_VARIABLE', as computed by sizeof. */
#undef SIZEOF_CONDITION_VARIABLE
/* The size of `double', as computed by sizeof. */
#undef SIZEOF_DOUBLE
/* The size of `float', as computed by sizeof. */
#undef SIZEOF_FLOAT
/* The size of `gs_mutex_t', as computed by sizeof. */
#undef SIZEOF_GS_MUTEX_T
/* The size of `int', as computed by sizeof. */
#undef SIZEOF_INT
@ -882,6 +897,9 @@
/* The size of `short', as computed by sizeof. */
#undef SIZEOF_SHORT
/* The size of `SRWLOCK', as computed by sizeof. */
#undef SIZEOF_SRWLOCK
/* The size of `void*', as computed by sizeof. */
#undef SIZEOF_VOIDP

View file

@ -37,7 +37,7 @@
#import "GNUstepBase/GCObject.h"
#include <pthread.h>
#import "../GSPThread.h"
/*
* The head of a linked list of all garbage collecting objects is a
@ -65,27 +65,20 @@
static GCObject *allObjects = nil;
static BOOL isCollecting = NO;
#ifdef NeXT_RUNTIME
static void *allocationLock = NULL;
#define pthread_mutex_lock(lock)
#define pthread_mutex_unlock(lock)
#else
static pthread_mutex_t *allocationLock = NULL;
#endif
static gs_mutex_t *allocationLock = NULL;
+ (void) _becomeMultiThreaded: (NSNotification *)aNotification
{
if (allocationLock == NULL)
{
# ifndef NeXT_RUNTIME
allocationLock = malloc(sizeof(pthread_mutex_t));
allocationLock = malloc(sizeof(gs_mutex_t));
if (allocationLock == NULL)
{
abort();
}
pthread_mutex_init(allocationLock, NULL);
GS_MUTEX_INIT(*allocationLock);
# endif
}
}
@ -100,7 +93,7 @@ static pthread_mutex_t *allocationLock = NULL;
if (allocationLock != 0)
{
pthread_mutex_lock(allocationLock);
GS_MUTEX_LOCK(*allocationLock);
}
o->gc.next = allObjects;
o->gc.previous = allObjects->gc.previous;
@ -109,7 +102,7 @@ static pthread_mutex_t *allocationLock = NULL;
o->gc.flags.refCount = 1;
if (allocationLock != 0)
{
pthread_mutex_unlock(allocationLock);
GS_MUTEX_UNLOCK(*allocationLock);
}
return o;
@ -150,13 +143,13 @@ static pthread_mutex_t *allocationLock = NULL;
if (allocationLock != 0)
{
pthread_mutex_lock(allocationLock);
GS_MUTEX_LOCK(*allocationLock);
}
if (isCollecting == YES)
{
if (allocationLock != 0)
{
pthread_mutex_unlock(allocationLock);
GS_MUTEX_UNLOCK(*allocationLock);
}
return; // Don't allow recursion.
}
@ -216,7 +209,7 @@ static pthread_mutex_t *allocationLock = NULL;
isCollecting = NO;
if (allocationLock != 0)
{
pthread_mutex_unlock(allocationLock);
GS_MUTEX_UNLOCK(*allocationLock);
}
}
@ -267,7 +260,7 @@ static pthread_mutex_t *allocationLock = NULL;
if (allocationLock != 0)
{
pthread_mutex_lock(allocationLock);
GS_MUTEX_LOCK(*allocationLock);
}
// p = anObject->gc.previous;
// n = anObject->gc.next;
@ -279,7 +272,7 @@ static pthread_mutex_t *allocationLock = NULL;
[n gcSetPreviousObject: p];
if (allocationLock != 0)
{
pthread_mutex_unlock(allocationLock);
GS_MUTEX_UNLOCK(*allocationLock);
}
}
@ -294,7 +287,7 @@ static pthread_mutex_t *allocationLock = NULL;
if (allocationLock != 0)
{
pthread_mutex_lock(allocationLock);
GS_MUTEX_LOCK(*allocationLock);
}
o->gc.next = allObjects;
o->gc.previous = allObjects->gc.previous;
@ -303,7 +296,7 @@ static pthread_mutex_t *allocationLock = NULL;
o->gc.flags.refCount = 1;
if (allocationLock != 0)
{
pthread_mutex_unlock(allocationLock);
GS_MUTEX_UNLOCK(*allocationLock);
}
return o;
}
@ -321,7 +314,7 @@ static pthread_mutex_t *allocationLock = NULL;
if (allocationLock != 0)
{
pthread_mutex_lock(allocationLock);
GS_MUTEX_LOCK(*allocationLock);
}
// p = anObject->gc.previous;
// n = anObject->gc.next;
@ -333,7 +326,7 @@ static pthread_mutex_t *allocationLock = NULL;
[n gcSetPreviousObject: p];
if (allocationLock != 0)
{
pthread_mutex_unlock(allocationLock);
GS_MUTEX_UNLOCK(*allocationLock);
}
[super dealloc];
}
@ -416,7 +409,7 @@ static pthread_mutex_t *allocationLock = NULL;
{
if (allocationLock != 0)
{
pthread_mutex_lock(allocationLock);
GS_MUTEX_LOCK(*allocationLock);
}
if (gc.flags.refCount > 0 && gc.flags.refCount-- == 1)
{
@ -425,7 +418,7 @@ static pthread_mutex_t *allocationLock = NULL;
}
if (allocationLock != 0)
{
pthread_mutex_unlock(allocationLock);
GS_MUTEX_UNLOCK(*allocationLock);
}
}
@ -436,12 +429,12 @@ static pthread_mutex_t *allocationLock = NULL;
{
if (allocationLock != 0)
{
pthread_mutex_lock(allocationLock);
GS_MUTEX_LOCK(*allocationLock);
}
gc.flags.refCount++;
if (allocationLock != 0)
{
pthread_mutex_unlock(allocationLock);
GS_MUTEX_UNLOCK(*allocationLock);
}
return self;
}

View file

@ -48,16 +48,15 @@
#import "GNUstepBase/NSObject+GNUstepBase.h"
#import "../GSPrivate.h"
#import "../GSPThread.h"
#include <objc/Protocol.h>
#include <stdio.h>
#include <ctype.h>
#ifndef NeXT_RUNTIME
#include <pthread.h>
#endif
#ifdef __GNUSTEP_RUNTIME__
GS_IMPORT
extern struct objc_slot *objc_get_slot(Class, SEL);
#endif
@ -728,18 +727,17 @@ gs_string_hash(const char *s)
#define GSI_MAP_VTYPES GSUNION_PTR
#include "GNUstepBase/GSIMap.h"
#include <pthread.h>
static GSIMapTable_t protocol_by_name;
static BOOL protocol_by_name_init = NO;
static pthread_mutex_t protocol_by_name_lock = PTHREAD_MUTEX_INITIALIZER;
static gs_mutex_t protocol_by_name_lock = GS_MUTEX_INIT_STATIC;
/* Not sure about the semantics of inlining
functions with static variables. */
static void
gs_init_protocol_lock(void)
{
pthread_mutex_lock(&protocol_by_name_lock);
GS_MUTEX_LOCK(protocol_by_name_lock);
if (protocol_by_name_init == NO)
{
GSIMapInitWithZoneAndCapacity (&protocol_by_name,
@ -747,7 +745,7 @@ gs_init_protocol_lock(void)
128);
protocol_by_name_init = YES;
}
pthread_mutex_unlock(&protocol_by_name_lock);
GS_MUTEX_UNLOCK(protocol_by_name_lock);
}
void
@ -762,7 +760,7 @@ GSRegisterProtocol(Protocol *proto)
{
GSIMapNode node;
pthread_mutex_lock(&protocol_by_name_lock);
GS_MUTEX_LOCK(protocol_by_name_lock);
node = GSIMapNodeForKey(&protocol_by_name,
(GSIMapKey)protocol_getName(proto));
if (node == 0)
@ -771,7 +769,7 @@ GSRegisterProtocol(Protocol *proto)
(GSIMapKey)(void*)protocol_getName(proto),
(GSIMapVal)(void*)proto);
}
pthread_mutex_unlock(&protocol_by_name_lock);
GS_MUTEX_UNLOCK(protocol_by_name_lock);
}
}
@ -793,7 +791,7 @@ GSProtocolFromName(const char *name)
}
else
{
pthread_mutex_lock(&protocol_by_name_lock);
GS_MUTEX_LOCK(protocol_by_name_lock);
node = GSIMapNodeForKey(&protocol_by_name, (GSIMapKey) name);
if (node)
@ -812,7 +810,7 @@ GSProtocolFromName(const char *name)
(GSIMapVal)(void*)p);
}
}
pthread_mutex_unlock(&protocol_by_name_lock);
GS_MUTEX_UNLOCK(protocol_by_name_lock);
}

View file

@ -137,7 +137,7 @@ internal_unicode_enc(void)
#define UNICODE_UTF32 ""
#endif
static pthread_mutex_t local_lock = PTHREAD_MUTEX_INITIALIZER;
static gs_mutex_t local_lock = GS_MUTEX_INIT_STATIC;
typedef unsigned char unc;
static NSStringEncoding defEnc = GSUndefinedEncoding;
@ -279,7 +279,7 @@ static void GSSetupEncodingTable(void)
{
if (encodingTable == 0)
{
(void)pthread_mutex_lock(&local_lock);
GS_MUTEX_LOCK(local_lock);
if (encodingTable == 0)
{
static struct _strenc_ **encTable = 0;
@ -355,7 +355,7 @@ static void GSSetupEncodingTable(void)
}
encodingTable = encTable;
}
(void)pthread_mutex_unlock(&local_lock);
GS_MUTEX_UNLOCK(local_lock);
}
}
@ -2735,7 +2735,7 @@ GSPrivateAvailableEncodings()
if (_availableEncodings == 0)
{
GSSetupEncodingTable();
(void)pthread_mutex_lock(&local_lock);
GS_MUTEX_LOCK(local_lock);
if (_availableEncodings == 0)
{
NSStringEncoding *encodings;
@ -2761,7 +2761,7 @@ GSPrivateAvailableEncodings()
encodings[pos] = 0;
_availableEncodings = encodings;
}
(void)pthread_mutex_unlock(&local_lock);
GS_MUTEX_UNLOCK(local_lock);
}
return _availableEncodings;
}
@ -2903,10 +2903,10 @@ GSPrivateDefaultCStringEncoding()
GSSetupEncodingTable();
(void)pthread_mutex_lock(&local_lock);
GS_MUTEX_LOCK(local_lock);
if (defEnc != GSUndefinedEncoding)
{
(void)pthread_mutex_unlock(&local_lock);
GS_MUTEX_UNLOCK(local_lock);
return defEnc;
}
@ -2950,7 +2950,7 @@ GSPrivateDefaultCStringEncoding()
defEnc = NSISOLatin1StringEncoding;
}
(void)pthread_mutex_unlock(&local_lock);
GS_MUTEX_UNLOCK(local_lock);
}
return defEnc;
}

72
Source/GSAtomic.h Normal file
View file

@ -0,0 +1,72 @@
/*
* Provides atomic load and store functions using either native C11 atomic
* types and operations if available, or otherwise using fallback
* implementations (e.g. with GCC where stdatomic.h is not useable from
* Objective-C).
*
* Adopted from FreeBSD's stdatomic.h.
*/
#ifndef _GSAtomic_h_
#define _GSAtomic_h_
#ifndef __has_extension
#define __has_extension(x) 0
#endif
#if __has_extension(c_atomic) || __has_extension(cxx_atomic)
/*
* Use native C11 atomic operations. _Atomic() should be defined by the
* compiler.
*/
#define atomic_load_explicit(object, order) \
__c11_atomic_load(object, order)
#define atomic_store_explicit(object, desired, order) \
__c11_atomic_store(object, desired, order)
#else
/*
* No native support for _Atomic(). Place object in structure to prevent
* most forms of direct non-atomic access.
*/
#define _Atomic(T) struct { T volatile __val; }
#if __has_builtin(__sync_swap)
/* Clang provides a full-barrier atomic exchange - use it if available. */
#define atomic_exchange_explicit(object, desired, order) \
((void)(order), __sync_swap(&(object)->__val, desired))
#else
/*
* __sync_lock_test_and_set() is only an acquire barrier in theory (although in
* practice it is usually a full barrier) so we need an explicit barrier before
* it.
*/
#define atomic_exchange_explicit(object, desired, order) \
__extension__ ({ \
__typeof__(object) __o = (object); \
__typeof__(desired) __d = (desired); \
(void)(order); \
__sync_synchronize(); \
__sync_lock_test_and_set(&(__o)->__val, __d); \
})
#endif
#define atomic_load_explicit(object, order) \
((void)(order), __sync_fetch_and_add(&(object)->__val, 0))
#define atomic_store_explicit(object, desired, order) \
((void)atomic_exchange_explicit(object, desired, order))
#endif
#ifndef __ATOMIC_SEQ_CST
#define __ATOMIC_SEQ_CST 5
#endif
/*
* Convenience functions.
*/
#define atomic_load(object) \
atomic_load_explicit(object, __ATOMIC_SEQ_CST)
#define atomic_store(object, desired) \
atomic_store_explicit(object, desired, __ATOMIC_SEQ_CST)
#endif // _GSAtomic_h_

View file

@ -26,6 +26,7 @@
#import "Foundation/NSCoder.h"
#import "Foundation/NSDistantObject.h"
#import "GSInvocation.h"
#import "GSPThread.h"
#import <avcall.h>
#import <callback.h>
#import "callframe.h"
@ -34,10 +35,6 @@
# include <objc/encoding.h>
#endif
#include <pthread.h>
#import "GSInvocation.h"
#ifndef GS_STATIC_INLINE
#define GS_STATIC_INLINE static inline
#endif
@ -140,7 +137,7 @@ static GSIMapTable_t ff_callback_map;
/* Lock that protects the ff_callback_map */
static pthread_mutex_t ff_callback_map_lock = PTHREAD_MUTEX_INITIALIZER;
static gs_mutex_t ff_callback_map_lock = GS_MUTEX_INIT_STATIC;
/* Static pre-computed return type info */
@ -486,7 +483,7 @@ static IMP gs_objc_msg_forward (SEL sel)
GSIMapNode node;
// Lock
pthread_mutex_lock (&ff_callback_map_lock);
GS_MUTEX_LOCK(ff_callback_map_lock);
node = GSIMapNodeForKey (&ff_callback_map,
(GSIMapKey) ((void *) &returnInfo));
@ -512,7 +509,7 @@ static IMP gs_objc_msg_forward (SEL sel)
(GSIMapVal) forwarding_callback);
}
// Unlock
pthread_mutex_unlock (&ff_callback_map_lock);
GS_MUTEX_UNLOCK(ff_callback_map_lock);
}
return forwarding_callback;
}

View file

@ -34,8 +34,8 @@
#import "Foundation/NSDistantObject.h"
#import "Foundation/NSData.h"
#import "GSInvocation.h"
#import "GSPThread.h"
#import "GNUstepBase/GSObjCRuntime.h"
#import <pthread.h>
#import "cifframe.h"
#import "GSPrivate.h"
@ -190,18 +190,18 @@ IMP gs_objc_msg_forward (SEL sel)
return gs_objc_msg_forward2 (nil, sel);
}
#ifdef __GNUSTEP_RUNTIME__
pthread_key_t thread_slot_key;
gs_thread_key_t thread_slot_key;
static struct objc_slot *
gs_objc_msg_forward3(id receiver, SEL op)
{
/* The slot has its version set to 0, so it can not be cached. This makes it
* safe to free it when the thread exits. */
struct objc_slot *slot = pthread_getspecific(thread_slot_key);
struct objc_slot *slot = GS_THREAD_KEY_GET(thread_slot_key);
if (NULL == slot)
{
slot = calloc(sizeof(struct objc_slot), 1);
pthread_setspecific(thread_slot_key, slot);
GS_THREAD_KEY_SET(thread_slot_key, slot);
}
slot->method = gs_objc_msg_forward2(receiver, op);
return slot;
@ -259,7 +259,7 @@ static id gs_objc_proxy_lookup(id receiver, SEL op)
+ (void) load
{
#ifdef __GNUSTEP_RUNTIME__
pthread_key_create(&thread_slot_key, free);
GS_THREAD_KEY_INIT(thread_slot_key, free);
__objc_msg_forward3 = gs_objc_msg_forward3;
__objc_msg_forward2 = gs_objc_msg_forward2;
objc_proxy_lookup = gs_objc_proxy_lookup;

View file

@ -23,26 +23,97 @@
#ifndef _GSPThread_h_
#define _GSPThread_h_
#if GS_USE_WIN32_THREADS_AND_LOCKS
#include <windows.h>
#include <process.h>
#include "GSAtomic.h"
typedef enum {
gs_mutex_attr_normal = 0,
gs_mutex_attr_errorcheck = 1,
gs_mutex_attr_recursive = 2
} gs_mutex_attr_t;
typedef struct {
SRWLOCK lock;
_Atomic(DWORD) owner;
DWORD depth;
gs_mutex_attr_t attr;
} gs_mutex_t;
typedef SRWLOCK gs_cond_mutex_t;
typedef CONDITION_VARIABLE gs_cond_t;
/*
* Locking primitives.
*/
#define GS_MUTEX_INIT_STATIC {.lock = SRWLOCK_INIT, .attr = gs_mutex_attr_normal}
#define GS_MUTEX_INIT(x) gs_mutex_init(&(x), gs_mutex_attr_normal)
#define GS_MUTEX_INIT_RECURSIVE(x) gs_mutex_init(&(x), gs_mutex_attr_recursive)
#define GS_MUTEX_LOCK(x) gs_mutex_lock(&(x))
#define GS_MUTEX_TRYLOCK(x) gs_mutex_trylock(&(x))
#define GS_MUTEX_UNLOCK(x) gs_mutex_unlock(&(x))
#define GS_MUTEX_DESTROY(x)
#define GS_COND_WAIT(cond, mutex) gs_cond_wait(cond, mutex)
#define GS_COND_SIGNAL(cond) WakeConditionVariable(&(cond))
#define GS_COND_BROADCAST(cond) WakeAllConditionVariable(&(cond))
/* Pthread-like locking primitives defined in NSLock.m */
void gs_mutex_init(gs_mutex_t *l, gs_mutex_attr_t attr);
int gs_mutex_lock(gs_mutex_t *l);
int gs_mutex_trylock(gs_mutex_t *l);
int gs_mutex_unlock(gs_mutex_t *l);
int gs_cond_wait(gs_cond_t *cond, gs_mutex_t *mutex);
int gs_cond_timedwait(gs_cond_t *cond, gs_mutex_t *mutex, DWORD millisecs);
/*
* Threading primitives.
*
* Use Fiber Local Storage (FLS), as in contrast to Thread Local Storage (TLS)
* they provide a destructor callback and will just manipulate the FLS
* associated with the current thread if fibers are not being used.
*/
#define GS_THREAD_KEY_INIT(key, dtor) \
((key = FlsAlloc(dtor)) != FLS_OUT_OF_INDEXES)
#define GS_THREAD_KEY_GET(key) FlsGetValue(key)
#define GS_THREAD_KEY_SET(key, val) FlsSetValue(key, val)
#define GS_THREAD_ID_SELF() GetCurrentThreadId()
#define GS_YIELD() Sleep(0)
typedef DWORD gs_thread_key_t;
typedef DWORD gs_thread_id_t;
#else /* GS_USE_WIN32_THREADS_AND_LOCKS */
#include <pthread.h>
#import "Foundation/NSLock.h"
typedef pthread_mutex_t gs_mutex_t;
typedef pthread_mutex_t gs_cond_mutex_t;
typedef pthread_cond_t gs_cond_t;
@class GSStackTrace;
@class NSArray;
@class NSMapTable;
/*
* Locking primitives
*/
#define GS_MUTEX_INIT_STATIC PTHREAD_MUTEX_INITIALIZER
#define GS_MUTEX_INIT(x) pthread_mutex_init(&(x), NULL)
/*
* Macro to initialize recursive mutexes in a portable way. Adopted from
* libobjc2 (lock.h).
*/
# ifdef PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
# define GS_INIT_RECURSIVE_MUTEX(x) \
# define GS_MUTEX_INIT_RECURSIVE(x) \
x = (pthread_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP
# elif defined(PTHREAD_RECURSIVE_MUTEX_INITIALIZER)
# define GS_INIT_RECURSIVE_MUTEX(x) \
# define GS_MUTEX_INIT_RECURSIVE(x) \
x = (pthread_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER
# else
# define GS_INIT_RECURSIVE_MUTEX(x) GSPThreadInitRecursiveMutex(&(x))
# define GS_MUTEX_INIT_RECURSIVE(x) GSPThreadInitRecursiveMutex(&(x))
static inline void GSPThreadInitRecursiveMutex(pthread_mutex_t *x)
{
@ -54,6 +125,39 @@ static inline void GSPThreadInitRecursiveMutex(pthread_mutex_t *x)
}
# endif // PTHREAD_RECURSIVE_MUTEX_INITIALIZER(_NP)
#define GS_MUTEX_LOCK(x) pthread_mutex_lock(&(x))
#define GS_MUTEX_TRYLOCK(x) pthread_mutex_trylock(&(x))
#define GS_MUTEX_UNLOCK(x) pthread_mutex_unlock(&(x))
#define GS_MUTEX_DESTROY(x) pthread_mutex_destroy(&(x))
#define GS_COND_WAIT(cond, mutex) pthread_cond_wait(cond, mutex)
#define GS_COND_SIGNAL(cond) pthread_cond_signal(&(cond))
#define GS_COND_BROADCAST(cond) pthread_cond_broadcast(&(cond))
/*
* Threading primitives.
*/
#define GS_THREAD_KEY_INIT(key, dtor) (pthread_key_create(&(key), dtor) == 0)
#define GS_THREAD_KEY_GET(key) pthread_getspecific(key)
#define GS_THREAD_KEY_SET(key, val) pthread_setspecific(key, val)
#define GS_THREAD_ID_SELF() pthread_self()
#define GS_YIELD() sched_yield()
typedef pthread_key_t gs_thread_key_t;
typedef pthread_t gs_thread_id_t;
#endif /* GS_USE_WIN32_THREADS_AND_LOCKS */
#ifdef __OBJC__ /* Enables including file in autoconf check */
#import "Foundation/NSLock.h"
@class GSStackTrace;
@class NSArray;
@class NSMapTable;
/* Class to obtain/encapsulate a stack trace for exception reporting and/or
* lock tracing.
@ -109,4 +213,6 @@ static inline void GSPThreadInitRecursiveMutex(pthread_mutex_t *x)
- (GSStackTrace*) stack;
@end
#endif // __OBJC__
#endif // _GSPThread_h_

View file

@ -86,7 +86,7 @@ static Class GSPlaceholderArrayClass;
static GSPlaceholderArray *defaultPlaceholderArray;
static NSMapTable *placeholderMap;
static pthread_mutex_t placeholderLock = PTHREAD_MUTEX_INITIALIZER;
static gs_mutex_t placeholderLock = GS_MUTEX_INIT_STATIC;
/**
@ -167,7 +167,7 @@ static SEL rlSel;
* locate the correct placeholder in the (lock protected)
* table of placeholders.
*/
(void)pthread_mutex_lock(&placeholderLock);
GS_MUTEX_LOCK(placeholderLock);
obj = (id)NSMapGet(placeholderMap, (void*)z);
if (obj == nil)
{
@ -178,7 +178,7 @@ static SEL rlSel;
obj = (id)NSAllocateObject(GSPlaceholderArrayClass, 0, z);
NSMapInsert(placeholderMap, (void*)z, (void*)obj);
}
(void)pthread_mutex_unlock(&placeholderLock);
GS_MUTEX_UNLOCK(placeholderLock);
return obj;
}
}

View file

@ -736,9 +736,9 @@ static Class concreteMutableClass = nil;
length: (unsigned)length
number: (int)number
{
static pthread_mutex_t cache_lock = PTHREAD_MUTEX_INITIALIZER;
static gs_mutex_t cache_lock = GS_MUTEX_INIT_STATIC;
pthread_mutex_lock(&cache_lock);
GS_MUTEX_LOCK(cache_lock);
if (cache_set[number] == nil && bytes != 0)
{
NSData *bitmap;
@ -751,7 +751,7 @@ static Class concreteMutableClass = nil;
[[NSObject leakAt: &cache_set[number]] release];
RELEASE(bitmap);
}
pthread_mutex_unlock(&cache_lock);
GS_MUTEX_UNLOCK(cache_lock);
return cache_set[number];
}

View file

@ -93,7 +93,7 @@ static table_entry* the_table = 0;
static BOOL debug_allocation = NO;
static BOOL debug_byte_size = NO;
static pthread_mutex_t uniqueLock;
static gs_mutex_t uniqueLock;
static void _GSDebugAllocationFetch(list_entry *items, BOOL difference);
static void _GSDebugAllocationFetchAll(list_entry *items);
@ -106,8 +106,8 @@ static void (*_GSDebugAllocationAddFunc)(Class c, id o)
static void (*_GSDebugAllocationRemoveFunc)(Class c, id o)
= _GSDebugAllocationRemove;
#define doLock() pthread_mutex_lock(&uniqueLock)
#define unLock() pthread_mutex_unlock(&uniqueLock)
#define doLock() GS_MUTEX_LOCK(uniqueLock)
#define unLock() GS_MUTEX_UNLOCK(uniqueLock)
@interface GSDebugAlloc : NSObject
+ (void) initialize;
@ -116,7 +116,7 @@ static void (*_GSDebugAllocationRemoveFunc)(Class c, id o)
@implementation GSDebugAlloc
+ (void) initialize
{
GS_INIT_RECURSIVE_MUTEX(uniqueLock);
GS_MUTEX_INIT_RECURSIVE(uniqueLock);
}
@end

View file

@ -491,7 +491,7 @@ static void find_address (bfd *abfd, asection *section,
@end
static pthread_mutex_t modLock;
static gs_mutex_t modLock;
static NSMutableDictionary *stackModules = nil;
// initialize stack trace info
@ -500,7 +500,7 @@ GSLoadModule(NSString *fileName)
{
GSBinaryFileInfo *module = nil;
(void)pthread_mutex_lock(&modLock);
GS_MUTEX_LOCK(modLock);
if (stackModules == nil)
{
@ -549,7 +549,7 @@ GSLoadModule(NSString *fileName)
}
}
}
(void)pthread_mutex_unlock(&modLock);
GS_MUTEX_UNLOCK(modLock);
if (module == (id)[NSNull null])
{
@ -564,9 +564,9 @@ GSListModules()
NSArray *result;
GSLoadModule(nil); // initialise
(void)pthread_mutex_lock(&modLock);
GS_MUTEX_LOCK(modLock);
result = [stackModules allValues];
(void)pthread_mutex_unlock(&modLock);
GS_MUTEX_UNLOCK(modLock);
return result;
}
@ -615,7 +615,7 @@ static SymInitializeType initSym = 0;
static SymSetOptionsType optSym = 0;
static SymFromAddrType fromSym = 0;
static HANDLE hProcess = 0;
static pthread_mutex_t traceLock;
static gs_mutex_t traceLock;
#define MAXFRAMES 62 /* Limitation of windows-xp */
#else
#define MAXFRAMES 128 /* 1KB buffer on 64bit machine */
@ -902,7 +902,7 @@ GSPrivateReturnAddresses(NSUInteger **returns)
#if defined(_WIN32) && !defined(USE_BFD)
NSUInteger addr[MAXFRAMES];
(void)pthread_mutex_lock(&traceLock);
GS_MUTEX_LOCK(traceLock);
if (0 == hProcess)
{
hProcess = GetCurrentProcess();
@ -916,7 +916,7 @@ GSPrivateReturnAddresses(NSUInteger **returns)
{
fprintf(stderr, "Failed to load kernel32.dll with error: %d\n",
(int)GetLastError());
(void)pthread_mutex_unlock(&traceLock);
GS_MUTEX_UNLOCK(traceLock);
return 0;
}
capture = (CaptureStackBackTraceType)GetProcAddress(
@ -925,7 +925,7 @@ GSPrivateReturnAddresses(NSUInteger **returns)
{
fprintf(stderr, "Failed to find RtlCaptureStackBackTrace: %d\n",
(int)GetLastError());
(void)pthread_mutex_unlock(&traceLock);
GS_MUTEX_UNLOCK(traceLock);
return 0;
}
hModule = LoadLibrary("dbghelp.dll");
@ -933,7 +933,7 @@ GSPrivateReturnAddresses(NSUInteger **returns)
{
fprintf(stderr, "Failed to load dbghelp.dll with error: %d\n",
(int)GetLastError());
(void)pthread_mutex_unlock(&traceLock);
GS_MUTEX_UNLOCK(traceLock);
return 0;
}
optSym = (SymSetOptionsType)GetProcAddress(
@ -942,7 +942,7 @@ GSPrivateReturnAddresses(NSUInteger **returns)
{
fprintf(stderr, "Failed to find SymSetOptions: %d\n",
(int)GetLastError());
(void)pthread_mutex_unlock(&traceLock);
GS_MUTEX_UNLOCK(traceLock);
return 0;
}
initSym = (SymInitializeType)GetProcAddress(
@ -951,7 +951,7 @@ GSPrivateReturnAddresses(NSUInteger **returns)
{
fprintf(stderr, "Failed to find SymInitialize: %d\n",
(int)GetLastError());
(void)pthread_mutex_unlock(&traceLock);
GS_MUTEX_UNLOCK(traceLock);
return 0;
}
fromSym = (SymFromAddrType)GetProcAddress(
@ -960,7 +960,7 @@ GSPrivateReturnAddresses(NSUInteger **returns)
{
fprintf(stderr, "Failed to find SymFromAddr: %d\n",
(int)GetLastError());
(void)pthread_mutex_unlock(&traceLock);
GS_MUTEX_UNLOCK(traceLock);
return 0;
}
}
@ -972,13 +972,13 @@ GSPrivateReturnAddresses(NSUInteger **returns)
fprintf(stderr, "SymInitialize failed with error: %d\n",
(int)GetLastError());
fromSym = 0;
(void)pthread_mutex_unlock(&traceLock);
GS_MUTEX_UNLOCK(traceLock);
return 0;
}
}
if (0 == capture)
{
(void)pthread_mutex_unlock(&traceLock);
GS_MUTEX_UNLOCK(traceLock);
return 0;
}
@ -989,7 +989,7 @@ GSPrivateReturnAddresses(NSUInteger **returns)
memcpy(*returns, addr, numReturns * sizeof(void*));
}
(void)pthread_mutex_unlock(&traceLock);
GS_MUTEX_UNLOCK(traceLock);
#elif defined(HAVE_BACKTRACE)
void *addr[MAXFRAMES*sizeof(void*)];
@ -1112,10 +1112,10 @@ GSPrivateReturnAddresses(NSUInteger **returns)
+ (void) initialize
{
#if defined(_WIN32) && !defined(USE_BFD)
GS_INIT_RECURSIVE_MUTEX(traceLock);
GS_MUTEX_INIT_RECURSIVE(traceLock);
#endif
#if defined(USE_BFD)
GS_INIT_RECURSIVE_MUTEX(modLock);
GS_MUTEX_INIT_RECURSIVE(modLock);
#endif
}
@ -1257,7 +1257,7 @@ GSPrivateReturnAddresses(NSUInteger **returns)
symbol->MaxNameLen = 1024;
symbol->SizeOfStruct = sizeof(SYMBOL_INFO);
(void)pthread_mutex_lock(&traceLock);
GS_MUTEX_LOCK(traceLock);
for (i = 0; i < count; i++)
{
NSUInteger addr = (NSUInteger)*ptrs++;
@ -1273,7 +1273,7 @@ GSPrivateReturnAddresses(NSUInteger **returns)
@"unknown - %p", symbol->Name, addr];
}
}
(void)pthread_mutex_unlock(&traceLock);
GS_MUTEX_UNLOCK(traceLock);
free(symbol);
symbols = [[NSArray alloc] initWithObjects: syms count: count];

View file

@ -24,25 +24,25 @@
#import "common.h"
#include <pthread.h>
#import "GSPrivate.h"
#define gs_cond_t pthread_cond_t
#define gs_mutex_t pthread_mutex_t
#include <math.h>
#define EXPOSE_NSLock_IVARS 1
#define EXPOSE_NSRecursiveLock_IVARS 1
#define EXPOSE_NSCondition_IVARS 1
#define EXPOSE_NSConditionLock_IVARS 1
#define gs_cond_public_t gs_cond_t
#define gs_cond_mutex_public_t gs_cond_mutex_t
#define gs_mutex_public_t gs_mutex_t
#import "GSPrivate.h"
#import "GSPThread.h"
#include <math.h>
#import "common.h"
#import "Foundation/NSLock.h"
#import "Foundation/NSException.h"
#import "Foundation/NSThread.h"
#import "GSPThread.h"
#define class_createInstance(C,E) NSAllocateObject(C,E,NSDefaultMallocZone())
static Class baseConditionClass = Nil;
@ -178,13 +178,13 @@ static BOOL traceLocks = NO;
#define MFINALIZE \
- (void) finalize\
{\
pthread_mutex_destroy(&_mutex);\
GS_MUTEX_DESTROY(_mutex);\
}
#define MLOCK \
- (void) lock\
{\
int err = pthread_mutex_lock(&_mutex);\
int err = GS_MUTEX_LOCK(_mutex);\
if (EDEADLK == err)\
{\
(*_NSLock_error_handler)(self, _cmd, YES, @"deadlock");\
@ -200,13 +200,13 @@ static BOOL traceLocks = NO;
{\
do\
{\
int err = pthread_mutex_trylock(&_mutex);\
int err = GS_MUTEX_TRYLOCK(_mutex);\
if (0 == err)\
{\
{\
CHK(Hold) \
return YES;\
}\
sched_yield();\
return YES;\
}\
GS_YIELD();\
} while ([limit timeIntervalSinceNow] > 0);\
return NO;\
}
@ -230,7 +230,7 @@ static BOOL traceLocks = NO;
#define MTRYLOCK \
- (BOOL) tryLock\
{\
int err = pthread_mutex_trylock(&_mutex);\
int err = GS_MUTEX_TRYLOCK(_mutex);\
if (0 == err) \
{ \
CHK(Hold) \
@ -245,7 +245,7 @@ static BOOL traceLocks = NO;
#define MUNLOCK \
- (void) unlock\
{\
if (0 != pthread_mutex_unlock(&_mutex))\
if (0 != GS_MUTEX_UNLOCK(_mutex))\
{\
[NSException raise: NSLockException\
format: @"failed to unlock mutex"];\
@ -253,10 +253,12 @@ static BOOL traceLocks = NO;
CHK(Drop) \
}
static pthread_mutex_t deadlock;
static gs_mutex_t deadlock;
#if !GS_USE_WIN32_THREADS_AND_LOCKS
static pthread_mutexattr_t attr_normal;
static pthread_mutexattr_t attr_reporting;
static pthread_mutexattr_t attr_recursive;
#endif
/*
* OS X 10.5 compatibility function to allow debugging deadlock conditions.
@ -267,7 +269,7 @@ void _NSLockError(id obj, SEL _cmd, BOOL stop, NSString *msg)
msg, obj);
NSLog(@"*** Break on _NSLockError() to debug.");
if (YES == stop)
pthread_mutex_lock(&deadlock);
GS_MUTEX_LOCK(deadlock);
}
NSLock_error_handler *_NSLock_error_handler = _NSLockError;
@ -295,6 +297,7 @@ NSString *NSLockException = @"NSLockException";
{
beenHere = YES;
#if !GS_USE_WIN32_THREADS_AND_LOCKS
/* Initialise attributes for the different types of mutex.
* We do it once, since attributes can be shared between multiple
* mutexes.
@ -312,14 +315,19 @@ NSString *NSLockException = @"NSLockException";
pthread_mutexattr_settype(&attr_reporting, PTHREAD_MUTEX_ERRORCHECK);
pthread_mutexattr_init(&attr_recursive);
pthread_mutexattr_settype(&attr_recursive, PTHREAD_MUTEX_RECURSIVE);
#endif
/* To emulate OSX behavior, we need to be able both to detect deadlocks
* (so we can log them), and also hang the thread when one occurs.
* the simple way to do that is to set up a locked mutex we can
* force a deadlock on.
*/
#if GS_USE_WIN32_THREADS_AND_LOCKS
gs_mutex_init(&deadlock, gs_mutex_attr_normal);
#else
pthread_mutex_init(&deadlock, &attr_normal);
pthread_mutex_lock(&deadlock);
#endif
GS_MUTEX_LOCK(deadlock);
baseConditionClass = [NSCondition class];
baseConditionLockClass = [NSConditionLock class];
@ -349,10 +357,14 @@ MFINALIZE
{
if (nil != (self = [super init]))
{
#if GS_USE_WIN32_THREADS_AND_LOCKS
gs_mutex_init(&_mutex, gs_mutex_attr_errorcheck);
#else
if (0 != pthread_mutex_init(&_mutex, &attr_reporting))
{
DESTROY(self);
}
{
DESTROY(self);
}
#endif
}
return self;
}
@ -364,17 +376,17 @@ MLOCK
{
do
{
int err = pthread_mutex_trylock(&_mutex);
int err = GS_MUTEX_TRYLOCK(_mutex);
if (0 == err)
{
{
CHK(Hold)
return YES;
}
return YES;
}
if (EDEADLK == err)
{
(*_NSLock_error_handler)(self, _cmd, NO, @"deadlock");
}
sched_yield();
{
(*_NSLock_error_handler)(self, _cmd, NO, @"deadlock");
}
GS_YIELD();
} while ([limit timeIntervalSinceNow] > 0);
return NO;
}
@ -410,10 +422,14 @@ MFINALIZE
{
if (nil != (self = [super init]))
{
#if GS_USE_WIN32_THREADS_AND_LOCKS
gs_mutex_init(&_mutex, gs_mutex_attr_recursive);
#else
if (0 != pthread_mutex_init(&_mutex, &attr_recursive))
{
DESTROY(self);
}
{
DESTROY(self);
}
#endif
}
return self;
}
@ -445,7 +461,7 @@ MUNLOCK
- (void) broadcast
{
pthread_cond_broadcast(&_condition);
GS_COND_BROADCAST(_condition);
}
MDEALLOC
@ -453,23 +469,30 @@ MDESCRIPTION
- (void) finalize
{
#if !GS_USE_WIN32_THREADS_AND_LOCKS
pthread_cond_destroy(&_condition);
pthread_mutex_destroy(&_mutex);
#endif
GS_MUTEX_DESTROY(_mutex);
}
- (id) init
{
if (nil != (self = [super init]))
{
#if GS_USE_WIN32_THREADS_AND_LOCKS
InitializeConditionVariable(&_condition);
gs_mutex_init(&_mutex, gs_mutex_attr_errorcheck);
#else
if (0 != pthread_cond_init(&_condition, NULL))
{
DESTROY(self);
}
{
DESTROY(self);
}
else if (0 != pthread_mutex_init(&_mutex, &attr_reporting))
{
pthread_cond_destroy(&_condition);
DESTROY(self);
}
{
pthread_cond_destroy(&_condition);
DESTROY(self);
}
#endif
}
return self;
}
@ -481,7 +504,7 @@ MNAME
- (void) signal
{
pthread_cond_signal(&_condition);
GS_COND_SIGNAL(_condition);
}
MSTACK
@ -490,15 +513,25 @@ MUNLOCK
- (void) wait
{
pthread_cond_wait(&_condition, &_mutex);
GS_COND_WAIT(&_condition, &_mutex);
}
- (BOOL) waitUntilDate: (NSDate*)limit
{
int retVal = 0;
#if GS_USE_WIN32_THREADS_AND_LOCKS
NSTimeInterval ti = [limit timeIntervalSinceNow];
if (ti < 0) {
ti = 0.0; // handle timeout in the past
}
retVal = gs_cond_timedwait(&_condition, &_mutex, ti * 1000.0);
#else
NSTimeInterval ti = [limit timeIntervalSince1970];
double secs, subsecs;
struct timespec timeout;
int retVal = 0;
// Split the float into seconds and fractions of a second
subsecs = modf(ti, &secs);
@ -510,6 +543,8 @@ MUNLOCK
*/
retVal = pthread_cond_timedwait(&_condition, &_mutex, &timeout);
#endif /* GS_USE_WIN32_THREADS_AND_LOCKS */
if (retVal == 0)
{
return YES;
@ -518,10 +553,8 @@ MUNLOCK
{
return NO;
}
if (retVal == EINVAL)
{
NSLog(@"Invalid arguments to pthread_cond_timedwait");
}
NSLog(@"Error calling pthread_cond_timedwait: %d", retVal);
return NO;
}
@ -694,7 +727,7 @@ MSTACK
NSThread *t = GSCurrentThread(); \
int err; \
CHKT(t,Wait) \
err = pthread_mutex_lock(&_mutex);\
err = GS_MUTEX_LOCK(_mutex);\
if (EDEADLK == err)\
{\
CHKT(t,Drop) \
@ -735,17 +768,28 @@ MTRYLOCK
NSThread *t = GSCurrentThread();
CHKT(t,Drop)
CHKT(t,Wait)
pthread_cond_wait(&_condition, &_mutex);
GS_COND_WAIT(&_condition, &_mutex);
CHKT(t,Hold)
}
- (BOOL) waitUntilDate: (NSDate*)limit
{
int retVal = 0;
NSThread *t = GSCurrentThread();
#if GS_USE_WIN32_THREADS_AND_LOCKS
NSTimeInterval ti = [limit timeIntervalSinceNow];
if (ti < 0) {
ti = 0.0; // handle timeout in the past
}
CHKT(t,Drop)
retVal = gs_cond_timedwait(&_condition, &_mutex, ti * 1000.0);
#else
NSTimeInterval ti = [limit timeIntervalSince1970];
NSThread *t = GSCurrentThread();
double secs, subsecs;
struct timespec timeout;
int retVal = 0;
// Split the float into seconds and fractions of a second
subsecs = modf(ti, &secs);
@ -758,6 +802,8 @@ MTRYLOCK
CHKT(t,Drop)
retVal = pthread_cond_timedwait(&_condition, &_mutex, &timeout);
#endif /* GS_USE_WIN32_THREADS_AND_LOCKS */
if (retVal == 0)
{
CHKT(t,Hold)
@ -769,10 +815,7 @@ MTRYLOCK
return NO;
}
if (retVal == EINVAL)
{
NSLog(@"Invalid arguments to pthread_cond_timedwait");
}
NSLog(@"Error calling pthread_cond_timedwait: %d", retVal);
return NO;
}
@ -854,3 +897,165 @@ MUNLOCK
}
@end
/*
* Pthread-like locking primitives using Windows SRWLock. Provides
* normal, recursive, and error-checked locks.
*/
#if GS_USE_WIN32_THREADS_AND_LOCKS
void
gs_mutex_init(gs_mutex_t *mutex, gs_mutex_attr_t attr)
{
memset(mutex, 0, sizeof(gs_mutex_t));
InitializeSRWLock(&mutex->lock);
mutex->attr = attr;
}
int
gs_mutex_lock(gs_mutex_t *mutex)
{
DWORD thisThread = GetCurrentThreadId();
DWORD ownerThread;
// fast path if lock is not taken
if (TryAcquireSRWLockExclusive(&mutex->lock))
{
assert(mutex->depth == 0);
mutex->depth = 1;
atomic_store(&mutex->owner, thisThread);
return 0;
}
// needs to be atomic because another thread can concurrently set it
ownerThread = atomic_load(&mutex->owner);
if (ownerThread == thisThread)
{
// this thread already owns this lock
switch (mutex->attr)
{
case gs_mutex_attr_normal:
// deadlock
assert(mutex->depth == 1);
AcquireSRWLockExclusive(&mutex->lock);
assert(false); // not reached
return 0;
case gs_mutex_attr_errorcheck:
// return deadlock error
assert(mutex->depth == 1);
return EDEADLK;
case gs_mutex_attr_recursive:
// recursive lock
mutex->depth++;
return 0;
}
}
// wait for another thread to release the lock
AcquireSRWLockExclusive(&mutex->lock);
assert(mutex->depth == 0);
mutex->depth = 1;
atomic_store(&mutex->owner, thisThread);
return 0;
}
int
gs_mutex_trylock(gs_mutex_t *mutex)
{
DWORD thisThread = GetCurrentThreadId();
DWORD ownerThread;
if (TryAcquireSRWLockExclusive(&mutex->lock))
{
assert(mutex->depth == 0);
mutex->depth = 1;
atomic_store(&mutex->owner, thisThread);
return 0;
}
// needs to be atomic because another thread can concurrently set it
ownerThread = atomic_load(&mutex->owner);
if (ownerThread == thisThread && mutex->attr == gs_mutex_attr_recursive)
{
// this thread already owns this lock and it's recursive
assert(mutex->depth > 0);
mutex->depth++;
return 0;
}
// lock is taken
return EBUSY;
}
int
gs_mutex_unlock(gs_mutex_t *mutex)
{
switch (mutex->attr)
{
case gs_mutex_attr_normal:
break;
case gs_mutex_attr_errorcheck:
case gs_mutex_attr_recursive: {
// return error if lock is not held by this thread
DWORD thisThread = GetCurrentThreadId();
DWORD ownerThread = atomic_load(&mutex->owner);
if (ownerThread != thisThread) {
return EPERM;
}
break;
}
}
if (mutex->attr == gs_mutex_attr_recursive && mutex->depth > 1)
{
// recursive lock releasing inner lock
mutex->depth--;
return 0;
}
else
{
assert(mutex->depth == 1);
mutex->depth = 0;
atomic_store(&mutex->owner, 0);
ReleaseSRWLockExclusive(&mutex->lock);
return 0;
}
}
// NB: timeout specified in milliseconds relative to now
int
gs_cond_timedwait(gs_cond_t *cond, gs_mutex_t *mutex, DWORD millisecs)
{
int retVal = 0;
assert(mutex->depth == 1);
mutex->depth = 0;
atomic_store(&mutex->owner, 0);
if (!SleepConditionVariableSRW(cond, &mutex->lock, millisecs, 0))
{
DWORD lastError = GetLastError();
if (lastError == ERROR_TIMEOUT) {
retVal = ETIMEDOUT;
} else {
retVal = lastError;
}
}
assert(mutex->depth == 0);
mutex->depth = 1;
atomic_store(&mutex->owner, GetCurrentThreadId());
return retVal;
}
inline int
gs_cond_wait(gs_cond_t *cond, gs_mutex_t *mutex)
{
return gs_cond_timedwait(cond, mutex, INFINITE);
}
#endif /* GS_USE_WIN32_THREADS_AND_LOCKS */

View file

@ -131,7 +131,7 @@ GS_ROOT_CLASS @interface NSZombie
/* allocationLock is needed when for protecting the map table of zombie
* information and if atomic operations are not available.
*/
static pthread_mutex_t allocationLock = PTHREAD_MUTEX_INITIALIZER;
static gs_mutex_t allocationLock = GS_MUTEX_INIT_STATIC;
BOOL NSZombieEnabled = NO;
BOOL NSDeallocateZombies = NO;
@ -146,12 +146,12 @@ static void GSMakeZombie(NSObject *o, Class c)
object_setClass(o, zombieClass);
if (0 != zombieMap)
{
pthread_mutex_lock(&allocationLock);
GS_MUTEX_LOCK(allocationLock);
if (0 != zombieMap)
{
NSMapInsert(zombieMap, (void*)o, (void*)c);
}
pthread_mutex_unlock(&allocationLock);
GS_MUTEX_UNLOCK(allocationLock);
}
}
#endif
@ -162,12 +162,12 @@ static void GSLogZombie(id o, SEL sel)
if (0 != zombieMap)
{
pthread_mutex_lock(&allocationLock);
GS_MUTEX_LOCK(allocationLock);
if (0 != zombieMap)
{
c = NSMapGet(zombieMap, (void*)o);
}
pthread_mutex_unlock(&allocationLock);
GS_MUTEX_UNLOCK(allocationLock);
}
if (c == 0)
{
@ -395,6 +395,8 @@ GSAtomicDecrement(gsatomic_t X)
#if !defined(GSATOMICREAD)
#include <pthread.h>
typedef int gsrefcount_t; // No atomics, use a simple integer
/* Having just one allocationLock for all leads to lock contention
@ -841,12 +843,12 @@ NSDeallocateObject(id anObject)
#ifdef OBJC_CAP_ARC
if (0 != zombieMap)
{
pthread_mutex_lock(&allocationLock);
GS_MUTEX_LOCK(allocationLock);
if (0 != zombieMap)
{
NSMapInsert(zombieMap, (void*)anObject, (void*)aClass);
}
pthread_mutex_unlock(&allocationLock);
GS_MUTEX_UNLOCK(allocationLock);
}
if (NSDeallocateZombies == YES)
{
@ -1117,10 +1119,10 @@ static id gs_weak_load(id obj)
+ (void) _atExit
{
NSMapTable *m = nil;
pthread_mutex_lock(&allocationLock);
GS_MUTEX_LOCK(allocationLock);
m = zombieMap;
zombieMap = nil;
pthread_mutex_unlock(&allocationLock);
GS_MUTEX_UNLOCK(allocationLock);
DESTROY(m);
}
@ -2500,12 +2502,12 @@ static id gs_weak_load(id obj)
if (0 != zombieMap)
{
pthread_mutex_lock(&allocationLock);
GS_MUTEX_LOCK(allocationLock);
if (0 != zombieMap)
{
c = NSMapGet(zombieMap, (void*)self);
}
pthread_mutex_unlock(&allocationLock);
GS_MUTEX_UNLOCK(allocationLock);
}
return c;
}
@ -2527,9 +2529,9 @@ static id gs_weak_load(id obj)
{
return nil;
}
pthread_mutex_lock(&allocationLock);
GS_MUTEX_LOCK(allocationLock);
c = zombieMap ? NSMapGet(zombieMap, (void*)self) : Nil;
pthread_mutex_unlock(&allocationLock);
GS_MUTEX_UNLOCK(allocationLock);
return [c instanceMethodSignatureForSelector: aSelector];
}

View file

@ -246,11 +246,11 @@ typedef GSString *ivars;
*/
+ (BOOL) _scanDouble: (double*)value from: (NSString*)str
{
static pthread_mutex_t myLock = PTHREAD_MUTEX_INITIALIZER;
static gs_mutex_t myLock = GS_MUTEX_INIT_STATIC;
static NSScanner *doubleScanner = nil;
BOOL ok = NO;
pthread_mutex_lock(&myLock);
GS_MUTEX_LOCK(myLock);
if (nil == doubleScanner)
{
doubleScanner = [[self alloc] initWithString: _empty];
@ -258,7 +258,7 @@ typedef GSString *ivars;
[doubleScanner _setString: str];
ok = [doubleScanner scanDouble: value];
[doubleScanner _setString: _empty]; // Release scanned string
pthread_mutex_unlock(&myLock);
GS_MUTEX_UNLOCK(myLock);
return ok;
}

View file

@ -153,7 +153,7 @@ static Class GSPlaceholderStringClass;
static GSPlaceholderString *defaultPlaceholderString;
static NSMapTable *placeholderMap;
static pthread_mutex_t placeholderLock = PTHREAD_MUTEX_INITIALIZER;
static gs_mutex_t placeholderLock = GS_MUTEX_INIT_STATIC;
static SEL cMemberSel = 0;
@ -305,14 +305,14 @@ pathSeps(void)
{
if (rPathSeps == nil)
{
(void)pthread_mutex_lock(&placeholderLock);
GS_MUTEX_LOCK(placeholderLock);
if (rPathSeps == nil)
{
rPathSeps
= [NSCharacterSet characterSetWithCharactersInString: @"/\\"];
rPathSeps = [NSObject leakAt: &rPathSeps];
}
(void)pthread_mutex_unlock(&placeholderLock);
GS_MUTEX_UNLOCK(placeholderLock);
}
return rPathSeps;
}
@ -320,14 +320,14 @@ pathSeps(void)
{
if (uPathSeps == nil)
{
(void)pthread_mutex_lock(&placeholderLock);
GS_MUTEX_LOCK(placeholderLock);
if (uPathSeps == nil)
{
uPathSeps
= [NSCharacterSet characterSetWithCharactersInString: @"/"];
uPathSeps = [NSObject leakAt: &uPathSeps];
}
(void)pthread_mutex_unlock(&placeholderLock);
GS_MUTEX_UNLOCK(placeholderLock);
}
return uPathSeps;
}
@ -335,14 +335,14 @@ pathSeps(void)
{
if (wPathSeps == nil)
{
(void)pthread_mutex_lock(&placeholderLock);
GS_MUTEX_LOCK(placeholderLock);
if (wPathSeps == nil)
{
wPathSeps
= [NSCharacterSet characterSetWithCharactersInString: @"\\"];
wPathSeps = [NSObject leakAt: &wPathSeps];
}
(void)pthread_mutex_unlock(&placeholderLock);
GS_MUTEX_UNLOCK(placeholderLock);
}
return wPathSeps;
}
@ -897,7 +897,7 @@ GSICUCollatorOpen(NSStringCompareOptions mask, NSLocale *locale)
* locate the correct placeholder in the (lock protected)
* table of placeholders.
*/
(void)pthread_mutex_lock(&placeholderLock);
GS_MUTEX_LOCK(placeholderLock);
obj = (id)NSMapGet(placeholderMap, (void*)z);
if (obj == nil)
{
@ -908,7 +908,7 @@ GSICUCollatorOpen(NSStringCompareOptions mask, NSLocale *locale)
obj = (id)[GSPlaceholderStringClass allocWithZone: z];
NSMapInsert(placeholderMap, (void*)z, (void*)obj);
}
(void)pthread_mutex_unlock(&placeholderLock);
GS_MUTEX_UNLOCK(placeholderLock);
return obj;
}
}

View file

@ -37,7 +37,7 @@
// Dummy implementatation
// cleaner than IFDEF'ing the code everywhere
#if !(HAVE_PTHREAD_SPIN_LOCK)
#ifndef HAVE_PTHREAD_SPIN_LOCK
typedef volatile int pthread_spinlock_t;
int pthread_spin_init(pthread_spinlock_t *lock, int pshared)
{
@ -58,7 +58,11 @@ int pthread_spin_lock(pthread_spinlock_t *lock)
{
// If it is already 1, let another thread play with the CPU for a
// bit then try again.
#if defined(_WIN32)
Sleep(0);
#else
sleep(0);
#endif
}
}
#else
@ -78,7 +82,7 @@ int pthread_spin_destroy(pthread_spinlock_t *lock)
{
return 0;
}
#endif
#endif /* HAVE_PTHREAD_SPIN_LOCK */
/** Structure for holding lock information for a thread.
*/
@ -90,7 +94,7 @@ typedef struct {
#define EXPOSE_NSThread_IVARS 1
#define GS_NSThread_IVARS \
pthread_t _pthreadID; \
gs_thread_id_t _pthreadID; \
NSUInteger _threadID; \
GSLockInfo _lockInfo
@ -326,7 +330,7 @@ GSSleepUntilIntervalSinceReferenceDate(NSTimeInterval when)
/* We don't need to wait, but since we are willing to wait at this
* point, we should let other threads have preference over this one.
*/
sched_yield();
GS_YIELD();
return;
}
@ -458,12 +462,12 @@ static BOOL entered_multi_threaded_state = NO;
static NSThread *defaultThread;
static BOOL keyInitialized = NO;
static pthread_key_t thread_object_key;
static gs_thread_key_t thread_object_key;
static NSHashTable *_activeBlocked = nil;
static NSHashTable *_activeThreads = nil;
static pthread_mutex_t _activeLock = PTHREAD_MUTEX_INITIALIZER;
static gs_mutex_t _activeLock = GS_MUTEX_INIT_STATIC;
/**
* pthread_t is an opaque type. It might be a scalar type or
@ -473,10 +477,10 @@ static pthread_mutex_t _activeLock = PTHREAD_MUTEX_INITIALIZER;
* This follows the CoreFoundation 'create rule' and returns an object with
* a reference count of 1.
*/
static inline NSValue* NSValueCreateFromPthread(pthread_t thread)
static inline NSValue* NSValueCreateFromPthread(gs_thread_id_t thread)
{
return [[NSValue alloc] initWithBytes: &thread
objCType: @encode(pthread_t)];
objCType: @encode(gs_thread_id_t)];
}
/**
@ -484,14 +488,14 @@ static inline NSValue* NSValueCreateFromPthread(pthread_t thread)
* from an NSValue.
*/
static inline void
_getPthreadFromNSValue(const void *value, pthread_t *thread_ptr)
_getPthreadFromNSValue(const void *value, gs_thread_id_t *thread_ptr)
{
const char *enc;
NSCAssert(thread_ptr, @"No storage for thread reference");
# ifndef NS_BLOCK_ASSERTIONS
enc = [(NSValue*)value objCType];
NSCAssert(enc != NULL && (0 == strcmp(@encode(pthread_t),enc)),
NSCAssert(enc != NULL && (0 == strcmp(@encode(gs_thread_id_t),enc)),
@"Invalid NSValue container for thread reference");
# endif
[(NSValue*)value getValue: (void*)thread_ptr];
@ -506,12 +510,17 @@ _boxedPthreadIsEqual(NSMapTable *t,
const void *boxed,
const void *boxedOther)
{
pthread_t thread;
pthread_t otherThread;
gs_thread_id_t thread;
gs_thread_id_t otherThread;
_getPthreadFromNSValue(boxed, &thread);
_getPthreadFromNSValue(boxedOther, &otherThread);
#if GS_USE_WIN32_THREADS_AND_LOCKS
return thread == otherThread;
#else
return pthread_equal(thread, otherThread);
#endif
}
/**
@ -576,7 +585,7 @@ static const NSMapTableKeyCallBacks _boxedPthreadKeyCallBacks =
* thred if called from within the late-cleanup function.
*/
static NSMapTable *_exitingThreads = nil;
static pthread_mutex_t _exitingThreadsLock = PTHREAD_MUTEX_INITIALIZER;
static gs_mutex_t _exitingThreadsLock = GS_MUTEX_INIT_STATIC;
/**
@ -588,7 +597,7 @@ static pthread_mutex_t _exitingThreadsLock = PTHREAD_MUTEX_INITIALIZER;
static inline void _willLateUnregisterThread(NSValue *boxedThread,
NSThread *specific)
{
pthread_mutex_lock(&_exitingThreadsLock);
GS_MUTEX_LOCK(_exitingThreadsLock);
/* The map table is created lazily/late so that the NSThread
* +initialize method can be called without causing other
* classes to be initialized.
@ -603,7 +612,7 @@ static inline void _willLateUnregisterThread(NSValue *boxedThread,
}
NSMapInsert(_exitingThreads, (const void*)boxedThread,
(const void*)specific);
pthread_mutex_unlock(&_exitingThreadsLock);
GS_MUTEX_UNLOCK(_exitingThreadsLock);
}
/**
@ -617,12 +626,12 @@ static inline void _didLateUnregisterCurrentThread(NSValue *boxedThread)
* because the exception handler stores information in the current
* thread variables ... which causes recursion.
*/
pthread_mutex_lock(&_exitingThreadsLock);
GS_MUTEX_LOCK(_exitingThreadsLock);
if (nil != _exitingThreads)
{
NSMapRemove(_exitingThreads, (const void*)boxedThread);
}
pthread_mutex_unlock(&_exitingThreadsLock);
GS_MUTEX_UNLOCK(_exitingThreadsLock);
}
/*
@ -654,14 +663,14 @@ static void exitedThread(void *thread)
/* On some systems this is called with a null thread pointer,
* so try to get the NSThread object for the current thread.
*/
thread = pthread_getspecific(thread_object_key);
thread = GS_THREAD_KEY_GET(thread_object_key);
if (0 == thread)
{
return; // no thread info
}
}
RETAIN((NSThread*)thread);
ref = NSValueCreateFromPthread(pthread_self());
ref = NSValueCreateFromPthread(GS_THREAD_ID_SELF());
_willLateUnregisterThread(ref, (NSThread*)thread);
{
@ -701,17 +710,17 @@ GSCurrentThread(void)
if (NO == keyInitialized)
{
if (pthread_key_create(&thread_object_key, exitedThread))
if (!GS_THREAD_KEY_INIT(thread_object_key, exitedThread))
{
[NSException raise: NSInternalInconsistencyException
format: @"Unable to create thread key!"];
}
keyInitialized = YES;
}
thr = pthread_getspecific(thread_object_key);
thr = GS_THREAD_KEY_GET(thread_object_key);
if (nil == thr)
{
NSValue *selfThread = NSValueCreateFromPthread(pthread_self());
NSValue *selfThread = NSValueCreateFromPthread(GS_THREAD_ID_SELF());
/* NB this locked section cannot be protected by an exception handler
* because the exception handler stores information in the current
@ -719,15 +728,15 @@ GSCurrentThread(void)
*/
if (nil != _exitingThreads)
{
pthread_mutex_lock(&_exitingThreadsLock);
GS_MUTEX_LOCK(_exitingThreadsLock);
thr = NSMapGet(_exitingThreads, (const void*)selfThread);
pthread_mutex_unlock(&_exitingThreadsLock);
GS_MUTEX_UNLOCK(_exitingThreadsLock);
}
DESTROY(selfThread);
if (nil == thr)
{
GSRegisterCurrentThread();
thr = pthread_getspecific(thread_object_key);
thr = GS_THREAD_KEY_GET(thread_object_key);
if ((nil == defaultThread) && IS_MAIN_PTHREAD)
{
defaultThread = RETAIN(thr);
@ -763,7 +772,7 @@ GSCurrentThreadDictionary(void)
static void
gnustep_base_thread_callback(void)
{
static pthread_mutex_t threadLock = PTHREAD_MUTEX_INITIALIZER;
static gs_mutex_t threadLock = GS_MUTEX_INIT_STATIC;
/*
* Protect this function with locking ... to avoid any possibility
* of multiple threads registering with the system simultaneously,
@ -772,7 +781,7 @@ gnustep_base_thread_callback(void)
*/
if (entered_multi_threaded_state == NO)
{
pthread_mutex_lock(&threadLock);
GS_MUTEX_LOCK(threadLock);
if (entered_multi_threaded_state == NO)
{
/*
@ -823,7 +832,7 @@ gnustep_base_thread_callback(void)
NS_ENDHANDLER
LEAVE_POOL
}
pthread_mutex_unlock(&threadLock);
GS_MUTEX_UNLOCK(threadLock);
}
}
@ -834,9 +843,9 @@ gnustep_base_thread_callback(void)
* pthread specific memory before we do anything which might need to
* check what the current thread is (like getting the ID)!
*/
pthread_setspecific(thread_object_key, self);
GS_THREAD_KEY_SET(thread_object_key, self);
threadID = GSPrivateThreadID();
pthread_mutex_lock(&_activeLock);
GS_MUTEX_LOCK(_activeLock);
/* The hash table is created lazily/late so that the NSThread
* +initialize method can be called without causing other
* classes to be initialized.
@ -850,7 +859,7 @@ gnustep_base_thread_callback(void)
NSNonRetainedObjectHashCallBacks, 100);
}
NSHashInsert(_activeThreads, (const void*)self);
pthread_mutex_unlock(&_activeLock);
GS_MUTEX_UNLOCK(_activeLock);
}
@end
@ -888,7 +897,7 @@ unregisterActiveThread(NSThread *thread)
[(GSRunLoopThreadInfo*)thread->_runLoopInfo invalidate];
LEAVE_POOL
RELEASE(thread);
pthread_setspecific(thread_object_key, nil);
GS_THREAD_KEY_SET(thread_object_key, nil);
}
}
@ -906,7 +915,7 @@ unregisterActiveThread(NSThread *thread)
+ (BOOL) _createThreadForCurrentPthread
{
NSThread *t = pthread_getspecific(thread_object_key);
NSThread *t = GS_THREAD_KEY_GET(thread_object_key);
if (t == nil)
{
@ -962,7 +971,11 @@ unregisterActiveThread(NSThread *thread)
}
else
{
#if GS_USE_WIN32_THREADS_AND_LOCKS
_endthread();
#else
pthread_exit(NULL);
#endif
}
}
}
@ -976,7 +989,7 @@ unregisterActiveThread(NSThread *thread)
{
if (NO == keyInitialized)
{
if (pthread_key_create(&thread_object_key, exitedThread))
if (!GS_THREAD_KEY_INIT(thread_object_key, exitedThread))
{
[NSException raise: NSInternalInconsistencyException
format: @"Unable to create thread key!"];
@ -1014,9 +1027,34 @@ unregisterActiveThread(NSThread *thread)
* range 0.0 (lowest) to 1.0 (highest) which is mapped to the underlying
* system priorities.
*/
+ (void) setThreadPriority: (double)pri
+ (BOOL) setThreadPriority: (double)pri
{
#if defined(_POSIX_THREAD_PRIORITY_SCHEDULING) && (_POSIX_THREAD_PRIORITY_SCHEDULING > 0)
#if GS_USE_WIN32_THREADS_AND_LOCKS
// convert [0.0,1.0] priority to Windows defines
int winPri;
if (pri <= 0.0) {
winPri = THREAD_PRIORITY_IDLE;
} else if (pri <= 0.25) {
winPri = THREAD_PRIORITY_LOWEST;
} else if (pri < 0.5) {
winPri = THREAD_PRIORITY_BELOW_NORMAL;
} else if (pri >= 1.0) {
winPri = THREAD_PRIORITY_TIME_CRITICAL;
} else if (pri >= 0.75) {
winPri = THREAD_PRIORITY_HIGHEST;
} else if (pri > 0.5) {
winPri = THREAD_PRIORITY_ABOVE_NORMAL;
} else {
winPri = THREAD_PRIORITY_NORMAL;
}
if (!SetThreadPriority(GetCurrentThread(), winPri)) {
NSLog(@"Failed to set thread priority %d: %@", winPri, [NSError _last]);
return NO;
}
return YES;
#elif defined(_POSIX_THREAD_PRIORITY_SCHEDULING) && (_POSIX_THREAD_PRIORITY_SCHEDULING > 0)
int res;
int policy;
struct sched_param param;
@ -1028,9 +1066,18 @@ unregisterActiveThread(NSThread *thread)
pri *= (PTHREAD_MAX_PRIORITY - PTHREAD_MIN_PRIORITY);
pri += PTHREAD_MIN_PRIORITY;
pthread_getschedparam(pthread_self(), &policy, &param);
param.sched_priority = pri;
pthread_setschedparam(pthread_self(), policy, &param);
res = pthread_getschedparam(pthread_self(), &policy, &param);
if (res == 0) {
param.sched_priority = pri;
res = pthread_setschedparam(pthread_self(), policy, &param);
}
if (res != 0) {
NSLog(@"Failed to set thread priority %f: %d", pri, res);
return NO;
}
return YES;
#else
return NO;
#endif
}
@ -1054,21 +1101,61 @@ unregisterActiveThread(NSThread *thread)
+ (double) threadPriority
{
double pri = 0;
#if defined(_POSIX_THREAD_PRIORITY_SCHEDULING) && (_POSIX_THREAD_PRIORITY_SCHEDULING > 0)
#if GS_USE_WIN32_THREADS_AND_LOCKS
// convert [0.0,1.0] priority to Windows defines
int winPri = GetThreadPriority(GetCurrentThread());
if (winPri == THREAD_PRIORITY_ERROR_RETURN) {
NSLog(@"Failed to get thread priority: %@", [NSError _last]);
return pri;
}
switch (winPri)
{
case THREAD_PRIORITY_IDLE:
pri = 0.0;
break;
case THREAD_PRIORITY_LOWEST:
pri = 0.2;
break;
case THREAD_PRIORITY_BELOW_NORMAL:
pri = 0.4;
break;
case THREAD_PRIORITY_TIME_CRITICAL:
pri = 1.0;
break;
case THREAD_PRIORITY_HIGHEST:
pri = 0.8;
break;
case THREAD_PRIORITY_ABOVE_NORMAL:
pri = 0.6;
break;
case THREAD_PRIORITY_NORMAL:
pri = 0.5;
break;
default:
NSLog(@"Unknown thread priority: %d", winPri);
break;
}
#elif defined(_POSIX_THREAD_PRIORITY_SCHEDULING) && (_POSIX_THREAD_PRIORITY_SCHEDULING > 0)
int res;
int policy;
struct sched_param param;
pthread_getschedparam(pthread_self(), &policy, &param);
pri = param.sched_priority;
// Scale pri based on the range of the host system.
pri -= PTHREAD_MIN_PRIORITY;
pri /= (PTHREAD_MAX_PRIORITY - PTHREAD_MIN_PRIORITY);
res = pthread_getschedparam(pthread_self(), &policy, &param);
if (res == 0) {
pri = param.sched_priority;
// Scale pri based on the range of the host system.
pri -= PTHREAD_MIN_PRIORITY;
pri /= (PTHREAD_MAX_PRIORITY - PTHREAD_MIN_PRIORITY);
} else {
NSLog(@"Failed to get thread priority: %d", res);
}
#else
#warning Your pthread implementation does not support thread priorities
#endif
return pri;
return pri;
}
@ -1132,9 +1219,9 @@ unregisterActiveThread(NSThread *thread)
DESTROY(_gcontext);
if (_activeThreads)
{
pthread_mutex_lock(&_activeLock);
GS_MUTEX_LOCK(_activeLock);
NSHashRemove(_activeThreads, self);
pthread_mutex_unlock(&_activeLock);
GS_MUTEX_UNLOCK(_activeLock);
}
if (GS_EXISTS_INTERNAL)
{
@ -1311,7 +1398,12 @@ unregisterActiveThread(NSThread *thread)
/**
* Trampoline function called to launch the thread
*/
static void *
static
#if GS_USE_WIN32_THREADS_AND_LOCKS
void __cdecl
#else
void *
#endif
nsthreadLauncher(void *thread)
{
NSThread *t = (NSThread*)thread;
@ -1335,12 +1427,16 @@ nsthreadLauncher(void *thread)
[NSThread exit];
// Not reached
#if !GS_USE_WIN32_THREADS_AND_LOCKS
return NULL;
#endif
}
- (void) start
{
#if !GS_USE_WIN32_THREADS_AND_LOCKS
pthread_attr_t attr;
#endif
if (_active == YES)
{
@ -1377,6 +1473,16 @@ nsthreadLauncher(void *thread)
_active = YES;
errno = 0;
#if GS_USE_WIN32_THREADS_AND_LOCKS
if (_beginthread(nsthreadLauncher, _stackSize, self) == -1)
{
DESTROY(self);
[NSException raise: NSInternalInconsistencyException
format: @"Unable to detach thread (last error %d)",
errno];
}
#else
pthread_attr_init(&attr);
/* Create this thread detached, because we never use the return state from
* threads.
@ -1396,6 +1502,7 @@ nsthreadLauncher(void *thread)
format: @"Unable to detach thread (last error %@)",
[NSError _last]];
}
#endif
}
/**
@ -1563,7 +1670,7 @@ lockInfoErr(NSString *str)
* This also ensures that no more than one thread can be checking for
* deadlocks at a time (no interference between checks).
*/
pthread_mutex_lock(&_activeLock);
GS_MUTEX_LOCK(_activeLock);
/* As we isolate dependencies (a thread holding the lock another thread
* is waiting for) we disable locking in each thread and record the
@ -1695,7 +1802,7 @@ lockInfoErr(NSString *str)
/* Finished check ... re-enable thread activity changes.
*/
pthread_mutex_unlock(&_activeLock);
GS_MUTEX_UNLOCK(_activeLock);
if (nil != dependencies)

View file

@ -289,7 +289,7 @@ static NSMutableDictionary *abbreviationDictionary = nil;
static NSMutableDictionary *abbreviationMap = nil;
/* Lock for creating time zones. */
static pthread_mutex_t zone_mutex;
static gs_mutex_t zone_mutex;
static Class NSTimeZoneClass;
static Class GSPlaceholderTimeZoneClass;
@ -387,14 +387,14 @@ static NSString *_time_zone_path(NSString *subpath, NSString *type)
* Return a cached time zone if possible.
* NB. if data of cached zone does not match new data ... don't use cache
*/
pthread_mutex_lock(&zone_mutex);
GS_MUTEX_LOCK(zone_mutex);
zone = [zoneDictionary objectForKey: name];
if (data != nil && [data isEqual: [zone data]] == NO)
{
zone = nil;
}
IF_NO_GC(RETAIN(zone));
pthread_mutex_unlock(&zone_mutex);
GS_MUTEX_UNLOCK(zone_mutex);
if (zone == nil)
{
@ -657,9 +657,9 @@ static NSMapTable *absolutes = 0;
{
if (offset != uninitialisedOffset)
{
pthread_mutex_lock(&zone_mutex);
GS_MUTEX_LOCK(zone_mutex);
NSMapRemove(absolutes, (void*)(uintptr_t)offset);
pthread_mutex_unlock(&zone_mutex);
GS_MUTEX_UNLOCK(zone_mutex);
}
RELEASE(name);
RELEASE(detail);
@ -715,7 +715,7 @@ static NSMapTable *absolutes = 0;
}
}
pthread_mutex_lock(&zone_mutex);
GS_MUTEX_LOCK(zone_mutex);
z = (GSAbsTimeZone*)NSMapGet(absolutes, (void*)(uintptr_t)anOffset);
if (z != nil)
{
@ -766,7 +766,7 @@ static NSMapTable *absolutes = 0;
commonAbsolutes[index] = RETAIN(self);
}
}
pthread_mutex_unlock(&zone_mutex);
GS_MUTEX_UNLOCK(zone_mutex);
return z;
}
@ -986,7 +986,7 @@ static NSMapTable *absolutes = 0;
{
return abbreviationDictionary;
}
pthread_mutex_lock(&zone_mutex);
GS_MUTEX_LOCK(zone_mutex);
if (abbreviationDictionary == nil)
{
NSAutoreleasePool *pool = [NSAutoreleasePool new];
@ -1043,7 +1043,7 @@ static NSMapTable *absolutes = 0;
}
[pool drain];
}
pthread_mutex_unlock(&zone_mutex);
GS_MUTEX_UNLOCK(zone_mutex);
return abbreviationDictionary;
}
@ -1061,7 +1061,7 @@ static NSMapTable *absolutes = 0;
{
return abbreviationMap;
}
pthread_mutex_lock(&zone_mutex);
GS_MUTEX_LOCK(zone_mutex);
if (abbreviationMap == nil)
{
NSAutoreleasePool *pool = [NSAutoreleasePool new];
@ -1095,7 +1095,7 @@ static NSMapTable *absolutes = 0;
#endif
if (file == NULL)
{
pthread_mutex_unlock(&zone_mutex);
GS_MUTEX_UNLOCK(zone_mutex);
[NSException
raise: NSInternalInconsistencyException
format: @"Failed to open time zone abbreviation map."];
@ -1186,7 +1186,7 @@ static NSMapTable *absolutes = 0;
}
[pool drain];
}
pthread_mutex_unlock(&zone_mutex);
GS_MUTEX_UNLOCK(zone_mutex);
return abbreviationMap;
}
@ -1204,7 +1204,7 @@ static NSMapTable *absolutes = 0;
return namesArray;
}
pthread_mutex_lock(&zone_mutex);
GS_MUTEX_LOCK(zone_mutex);
if (namesArray == nil)
{
unsigned i;
@ -1230,7 +1230,7 @@ static NSMapTable *absolutes = 0;
RELEASE(ma);
}
}
pthread_mutex_unlock(&zone_mutex);
GS_MUTEX_UNLOCK(zone_mutex);
return namesArray;
}
@ -1260,7 +1260,7 @@ static NSMapTable *absolutes = 0;
* locate the correct placeholder in the (lock protected)
* table of placeholders.
*/
pthread_mutex_lock(&zone_mutex);
GS_MUTEX_LOCK(zone_mutex);
obj = (id)NSMapGet(placeholderMap, (void*)z);
if (obj == nil)
{
@ -1271,7 +1271,7 @@ static NSMapTable *absolutes = 0;
obj = (id)NSAllocateObject(GSPlaceholderTimeZoneClass, 0, z);
NSMapInsert(placeholderMap, (void*)z, (void*)obj);
}
pthread_mutex_unlock(&zone_mutex);
GS_MUTEX_UNLOCK(zone_mutex);
return obj;
}
}
@ -1288,7 +1288,7 @@ static NSMapTable *absolutes = 0;
{
NSTimeZone *zone;
pthread_mutex_lock(&zone_mutex);
GS_MUTEX_LOCK(zone_mutex);
if (defaultTimeZone == nil)
{
zone = [self systemTimeZone];
@ -1297,7 +1297,7 @@ static NSMapTable *absolutes = 0;
{
zone = AUTORELEASE(RETAIN(defaultTimeZone));
}
pthread_mutex_unlock(&zone_mutex);
GS_MUTEX_UNLOCK(zone_mutex);
return zone;
}
@ -1306,7 +1306,7 @@ static NSMapTable *absolutes = 0;
if (self == [NSTimeZone class])
{
NSTimeZoneClass = self;
GS_INIT_RECURSIVE_MUTEX(zone_mutex);
GS_MUTEX_INIT_RECURSIVE(zone_mutex);
GSPlaceholderTimeZoneClass = [GSPlaceholderTimeZone class];
zoneDictionary = [[NSMutableDictionary alloc] init];
[[NSObject leakAt: &zoneDictionary] release];
@ -1351,9 +1351,9 @@ static NSMapTable *absolutes = 0;
*/
+ (void) resetSystemTimeZone
{
pthread_mutex_lock(&zone_mutex);
GS_MUTEX_LOCK(zone_mutex);
DESTROY(systemTimeZone);
pthread_mutex_unlock(&zone_mutex);
GS_MUTEX_UNLOCK(zone_mutex);
[[NSNotificationCenter defaultCenter]
postNotificationName: NSSystemTimeZoneDidChangeNotification
object: nil];
@ -1374,9 +1374,9 @@ static NSMapTable *absolutes = 0;
{
aTimeZone = [self systemTimeZone];
}
pthread_mutex_lock(&zone_mutex);
GS_MUTEX_LOCK(zone_mutex);
ASSIGN(defaultTimeZone, aTimeZone);
pthread_mutex_unlock(&zone_mutex);
GS_MUTEX_UNLOCK(zone_mutex);
}
}
@ -1387,7 +1387,7 @@ static NSMapTable *absolutes = 0;
{
NSTimeZone *zone = nil;
pthread_mutex_lock(&zone_mutex);
GS_MUTEX_LOCK(zone_mutex);
if (systemTimeZone == nil)
{
NSFileManager *dflt = [NSFileManager defaultManager];
@ -1727,7 +1727,7 @@ localZoneString, [zone name], sign, s/3600, (s/60)%60);
ASSIGN(systemTimeZone, zone);
}
zone = AUTORELEASE(RETAIN(systemTimeZone));
pthread_mutex_unlock(&zone_mutex);
GS_MUTEX_UNLOCK(zone_mutex);
return zone;
}
@ -1746,7 +1746,7 @@ localZoneString, [zone name], sign, s/3600, (s/60)%60);
{
return regionsArray;
}
pthread_mutex_lock(&zone_mutex);
GS_MUTEX_LOCK(zone_mutex);
if (regionsArray == nil)
{
NSAutoreleasePool *pool = [NSAutoreleasePool new];
@ -1778,7 +1778,7 @@ localZoneString, [zone name], sign, s/3600, (s/60)%60);
#endif
if (fp == NULL)
{
pthread_mutex_unlock(&zone_mutex);
GS_MUTEX_UNLOCK(zone_mutex);
[NSException
raise: NSInternalInconsistencyException
format: @"Failed to open time zone regions array file."];
@ -1878,7 +1878,7 @@ localZoneString, [zone name], sign, s/3600, (s/60)%60);
regionsArray = [[NSArray alloc] initWithObjects: temp_array count: 24];
[pool drain];
}
pthread_mutex_unlock(&zone_mutex);
GS_MUTEX_UNLOCK(zone_mutex);
return regionsArray;
}
@ -1921,9 +1921,9 @@ localZoneString, [zone name], sign, s/3600, (s/60)%60);
}
else
{
pthread_mutex_lock(&zone_mutex);
GS_MUTEX_LOCK(zone_mutex);
zone = (NSTimeZone*)NSMapGet(absolutes, (void*)(uintptr_t)seconds);
pthread_mutex_unlock(&zone_mutex);
GS_MUTEX_UNLOCK(zone_mutex);
}
if (nil == zone)
{
@ -2403,7 +2403,7 @@ static NSString *zoneDirs[] = {
if (beenHere == NO && tzdir == nil)
{
pthread_mutex_lock(&zone_mutex);
GS_MUTEX_LOCK(zone_mutex);
if (beenHere == NO && tzdir == nil)
{
NSFileManager *mgr = [NSFileManager defaultManager];
@ -2424,7 +2424,7 @@ static NSString *zoneDirs[] = {
}
beenHere = YES;
}
pthread_mutex_unlock(&zone_mutex);
GS_MUTEX_UNLOCK(zone_mutex);
}
/* Use the system zone info if possible, otherwise, use our installed
info. */
@ -3198,9 +3198,9 @@ newDetailInZoneForType(GSTimeZone *zone, TypeInfo *type)
}
}
pthread_mutex_lock(&zone_mutex);
GS_MUTEX_LOCK(zone_mutex);
[zoneDictionary setObject: self forKey: timeZoneName];
pthread_mutex_unlock(&zone_mutex);
GS_MUTEX_UNLOCK(zone_mutex);
}
NS_HANDLER
{

View file

@ -93,7 +93,7 @@
#import "GSPrivate.h"
#import "GSPThread.h"
static pthread_mutex_t zoneLock = PTHREAD_MUTEX_INITIALIZER;
static gs_mutex_t zoneLock = GS_MUTEX_INIT_STATIC;
/**
* Try to get more memory - the normal process has failed.
@ -205,12 +205,12 @@ NSSetZoneName (NSZone *zone, NSString *name)
{
if (!zone)
zone = NSDefaultMallocZone();
pthread_mutex_lock(&zoneLock);
GS_MUTEX_LOCK(zoneLock);
name = [name copy];
if (zone->name != nil)
[zone->name release];
zone->name = name;
pthread_mutex_unlock(&zoneLock);
GS_MUTEX_UNLOCK(zoneLock);
}
GS_DECLARE NSString*
@ -303,7 +303,7 @@ struct _ffree_free_link
struct _ffree_zone_struct
{
NSZone common;
pthread_mutex_t lock;
gs_mutex_t lock;
ff_block *blocks; // Linked list of blocks
ff_link *segheadlist[MAX_SEG]; // Segregated list, holds heads
ff_link *segtaillist[MAX_SEG]; // Segregated list, holds tails
@ -452,7 +452,7 @@ chunkPrev(ff_block *ptr)
struct _nfree_zone_struct
{
NSZone common;
pthread_mutex_t lock;
gs_mutex_t lock;
/* Linked list of blocks in decreasing order of free space,
except maybe for the first block. */
nf_block *blocks;
@ -542,7 +542,7 @@ fmalloc (NSZone *zone, size_t size)
ff_block *chunkhead;
void *result;
pthread_mutex_lock(&(zptr->lock));
GS_MUTEX_LOCK(zptr->lock);
bufsize = zptr->bufsize;
while ((i < bufsize) && (chunksize > size_buf[i]))
i++;
@ -581,7 +581,7 @@ fmalloc (NSZone *zone, size_t size)
chunkhead = get_chunk(zptr, chunksize);
if (chunkhead == NULL)
{
pthread_mutex_unlock(&(zptr->lock));
GS_MUTEX_UNLOCK(zptr->lock);
if (zone->name != nil)
[NSException raise: NSMallocException
format: @"Zone %@ has run out of memory", zone->name];
@ -600,7 +600,7 @@ fmalloc (NSZone *zone, size_t size)
*((char*)chunkhead->next) = (char)42;
chunkSetLive(chunkhead);
result = chunkToPointer(chunkhead);
pthread_mutex_unlock(&(zptr->lock));
GS_MUTEX_UNLOCK(zptr->lock);
return result;
}
@ -624,7 +624,7 @@ frealloc (NSZone *zone, void *ptr, size_t size)
if (ptr == NULL)
return fmalloc(zone, size);
chunkhead = pointerToChunk(ptr);
pthread_mutex_lock(&(zptr->lock));
GS_MUTEX_LOCK(zptr->lock);
realsize = chunkSize(chunkhead);
NSAssert(chunkIsInUse(chunkhead), NSInternalInconsistencyException);
@ -680,7 +680,7 @@ frealloc (NSZone *zone, void *ptr, size_t size)
newchunk = get_chunk(zptr, chunksize);
if (newchunk == NULL)
{
pthread_mutex_unlock(&(zptr->lock));
GS_MUTEX_UNLOCK(zptr->lock);
if (zone->name != nil)
[NSException raise: NSMallocException
format: @"Zone %@ has run out of memory",
@ -698,7 +698,7 @@ frealloc (NSZone *zone, void *ptr, size_t size)
*((char*)chunkhead->next) = (char)42;
chunkSetLive(chunkhead);
result = chunkToPointer(chunkhead);
pthread_mutex_unlock(&(zptr->lock));
GS_MUTEX_UNLOCK(zptr->lock);
return result;
}
@ -708,14 +708,14 @@ ffree (NSZone *zone, void *ptr)
{
ff_block *chunk;
NSAssert(NSZoneFromPointer(ptr) == zone, NSInternalInconsistencyException);
pthread_mutex_lock(&(((ffree_zone*)zone)->lock));
GS_MUTEX_LOCK(((ffree_zone*)zone)->lock);
chunk = pointerToChunk(ptr);
if (chunkIsLive(chunk) == 0)
[NSException raise: NSMallocException
format: @"Attempt to free freed memory"];
NSAssert(*((char*)chunk->next) == (char)42, NSInternalInconsistencyException);
add_buf((ffree_zone*)zone, chunk);
pthread_mutex_unlock(&(((ffree_zone*)zone)->lock));
GS_MUTEX_UNLOCK(((ffree_zone*)zone)->lock);
}
static BOOL
@ -725,7 +725,7 @@ frecycle1(NSZone *zone)
ff_block *block;
ff_block *nextblock;
pthread_mutex_lock(&(zptr->lock));
GS_MUTEX_LOCK(zptr->lock);
flush_buf(zptr);
block = zptr->blocks;
while (block != NULL)
@ -747,10 +747,10 @@ frecycle1(NSZone *zone)
}
block = nextblock;
}
pthread_mutex_unlock(&(zptr->lock));
GS_MUTEX_UNLOCK(zptr->lock);
if (zptr->blocks == 0)
{
pthread_mutex_destroy(&(zptr->lock));
GS_MUTEX_DESTROY(zptr->lock);
return YES;
}
return NO;
@ -760,7 +760,7 @@ frecycle1(NSZone *zone)
static void
frecycle (NSZone *zone)
{
pthread_mutex_lock(&zoneLock);
GS_MUTEX_LOCK(zoneLock);
if (zone->name != nil)
{
NSString *name = zone->name;
@ -776,17 +776,17 @@ frecycle (NSZone *zone)
zone->free = rffree;
zone->recycle = rrecycle;
}
pthread_mutex_unlock(&zoneLock);
GS_MUTEX_UNLOCK(zoneLock);
}
static void
rffree (NSZone *zone, void *ptr)
{
ffree(zone, ptr);
pthread_mutex_lock(&zoneLock);
GS_MUTEX_LOCK(zoneLock);
if (frecycle1(zone))
destroy_zone(zone);
pthread_mutex_unlock(&zoneLock);
GS_MUTEX_UNLOCK(zoneLock);
}
@ -799,7 +799,7 @@ fcheck (NSZone *zone)
ffree_zone *zptr = (ffree_zone*)zone;
ff_block *block;
pthread_mutex_lock(&(zptr->lock));
GS_MUTEX_LOCK(zptr->lock);
/* Check integrity of each block the zone owns. */
block = zptr->blocks;
while (block != NULL)
@ -892,11 +892,11 @@ fcheck (NSZone *zone)
if ((zptr->size_buf[i] != chunkSize(chunk)) || !chunkIsInUse(chunk))
goto inconsistent;
}
pthread_mutex_unlock(&(zptr->lock));
GS_MUTEX_UNLOCK(zptr->lock);
return YES;
inconsistent: // Jump here if an inconsistency was found.
pthread_mutex_unlock(&(zptr->lock));
GS_MUTEX_UNLOCK(zptr->lock);
return NO;
}
@ -907,7 +907,7 @@ flookup (NSZone *zone, void *ptr)
ff_block *block;
BOOL found = NO;
pthread_mutex_lock(&(zptr->lock));
GS_MUTEX_LOCK(zptr->lock);
for (block = zptr->blocks; block != NULL; block = block->next)
{
if (ptr >= (void*)block && ptr < (void*)chunkNext(block))
@ -916,7 +916,7 @@ flookup (NSZone *zone, void *ptr)
break;
}
}
pthread_mutex_unlock(&(zptr->lock));
GS_MUTEX_UNLOCK(zptr->lock);
return found;
}
@ -935,7 +935,7 @@ fstats (NSZone *zone)
stats.bytes_used = 0;
stats.chunks_free = 0;
stats.bytes_free = 0;
pthread_mutex_lock(&(zptr->lock));
GS_MUTEX_LOCK(zptr->lock);
block = zptr->blocks;
/* Go through each block. */
while (block != NULL)
@ -970,7 +970,7 @@ fstats (NSZone *zone)
stats.bytes_used -= zptr->size_buf[i];
stats.bytes_free += zptr->size_buf[i];
}
pthread_mutex_unlock(&(zptr->lock));
GS_MUTEX_UNLOCK(zptr->lock);
/* Remove overhead. */
stats.bytes_used -= FBSZ*stats.chunks_used;
return stats;
@ -1291,7 +1291,7 @@ nmalloc (NSZone *zone, size_t size)
nf_block *block;
size_t top;
pthread_mutex_lock(&(zptr->lock));
GS_MUTEX_LOCK(zptr->lock);
block = zptr->blocks;
top = block->top;
freesize = block->size-top;
@ -1326,7 +1326,7 @@ nmalloc (NSZone *zone, size_t size)
block = malloc(blocksize);
if (block == NULL)
{
pthread_mutex_unlock(&(zptr->lock));
GS_MUTEX_UNLOCK(zptr->lock);
if (zone->name != nil)
[NSException raise: NSMallocException
format: @"Zone %@ has run out of memory",
@ -1344,7 +1344,7 @@ nmalloc (NSZone *zone, size_t size)
block->top += chunksize;
}
zptr->use++;
pthread_mutex_unlock(&(zptr->lock));
GS_MUTEX_UNLOCK(zptr->lock);
return chunkhead;
}
@ -1355,7 +1355,7 @@ nrecycle1 (NSZone *zone)
{
nfree_zone *zptr = (nfree_zone*)zone;
pthread_mutex_lock(&(zptr->lock));
GS_MUTEX_LOCK(zptr->lock);
if (zptr->use == 0)
{
nf_block *nextblock;
@ -1369,10 +1369,10 @@ nrecycle1 (NSZone *zone)
}
zptr->blocks = 0;
}
pthread_mutex_unlock(&(zptr->lock));
GS_MUTEX_UNLOCK(zptr->lock);
if (zptr->blocks == 0)
{
pthread_mutex_destroy(&(zptr->lock));
GS_MUTEX_DESTROY(zptr->lock);
return YES;
}
return NO;
@ -1382,7 +1382,7 @@ nrecycle1 (NSZone *zone)
static void
nrecycle (NSZone *zone)
{
pthread_mutex_lock(&zoneLock);
GS_MUTEX_LOCK(zoneLock);
if (zone->name != nil)
{
NSString *name = zone->name;
@ -1398,7 +1398,7 @@ nrecycle (NSZone *zone)
zone->free = rnfree;
zone->recycle = rrecycle;
}
pthread_mutex_unlock(&zoneLock);
GS_MUTEX_UNLOCK(zoneLock);
}
static void*
@ -1409,7 +1409,7 @@ nrealloc (NSZone *zone, void *ptr, size_t size)
if (ptr != 0)
{
pthread_mutex_lock(&(zptr->lock));
GS_MUTEX_LOCK(zptr->lock);
if (tmp)
{
nf_block *block;
@ -1429,7 +1429,7 @@ nrealloc (NSZone *zone, void *ptr, size_t size)
}
}
zptr->use--;
pthread_mutex_unlock(&(zptr->lock));
GS_MUTEX_UNLOCK(zptr->lock);
}
return tmp;
}
@ -1445,9 +1445,9 @@ nfree (NSZone *zone, void *ptr)
{
nfree_zone *zptr = (nfree_zone*)zone;
pthread_mutex_lock(&(zptr->lock));
GS_MUTEX_LOCK(zptr->lock);
zptr->use--;
pthread_mutex_unlock(&(zptr->lock));
GS_MUTEX_UNLOCK(zptr->lock);
}
static void
@ -1458,10 +1458,10 @@ rnfree (NSZone *zone, void *ptr)
nfree(zone, ptr);
if (zptr->use == 0)
{
pthread_mutex_lock(&zoneLock);
GS_MUTEX_LOCK(zoneLock);
nrecycle1(zone);
destroy_zone(zone);
pthread_mutex_unlock(&zoneLock);
GS_MUTEX_UNLOCK(zoneLock);
}
}
@ -1473,19 +1473,19 @@ ncheck (NSZone *zone)
nfree_zone *zptr = (nfree_zone*)zone;
nf_block *block;
pthread_mutex_lock(&(zptr->lock));
GS_MUTEX_LOCK(zptr->lock);
block = zptr->blocks;
while (block != NULL)
{
if (block->size < block->top)
{
pthread_mutex_unlock(&(zptr->lock));
GS_MUTEX_UNLOCK(zptr->lock);
return NO;
}
block = block->next;
}
/* FIXME: Do more checking? */
pthread_mutex_unlock(&(zptr->lock));
GS_MUTEX_UNLOCK(zptr->lock);
return YES;
}
@ -1496,7 +1496,7 @@ nlookup (NSZone *zone, void *ptr)
nf_block *block;
BOOL found = NO;
pthread_mutex_lock(&(zptr->lock));
GS_MUTEX_LOCK(zptr->lock);
for (block = zptr->blocks; block != NULL; block = block->next)
{
if (ptr >= (void*)block && ptr < ((void*)block)+block->size)
@ -1505,7 +1505,7 @@ nlookup (NSZone *zone, void *ptr)
break;
}
}
pthread_mutex_unlock(&(zptr->lock));
GS_MUTEX_UNLOCK(zptr->lock);
return found;
}
@ -1523,7 +1523,7 @@ nstats (NSZone *zone)
stats.bytes_used = 0;
stats.chunks_free = 0;
stats.bytes_free = 0;
pthread_mutex_lock(&(zptr->lock));
GS_MUTEX_LOCK(zptr->lock);
block = zptr->blocks;
while (block != NULL)
{
@ -1544,7 +1544,7 @@ nstats (NSZone *zone)
}
block = block->next;
}
pthread_mutex_unlock(&(zptr->lock));
GS_MUTEX_UNLOCK(zptr->lock);
return stats;
}
@ -1585,7 +1585,7 @@ NSZoneFromPointer(void *ptr)
/*
* See if we can find the zone in our list of all zones.
*/
pthread_mutex_lock(&zoneLock);
GS_MUTEX_LOCK(zoneLock);
for (zone = zone_list; zone != 0; zone = zone->next)
{
if ((zone->lookup)(zone, ptr) == YES)
@ -1593,7 +1593,7 @@ NSZoneFromPointer(void *ptr)
break;
}
}
pthread_mutex_unlock(&zoneLock);
GS_MUTEX_UNLOCK(zoneLock);
return (zone == 0) ? &default_zone : zone;
}
@ -1631,7 +1631,7 @@ NSCreateZone (NSUInteger start, NSUInteger gran, BOOL canFree)
zone->common.stats = fstats;
zone->common.gran = granularity;
zone->common.name = nil;
GS_INIT_RECURSIVE_MUTEX(zone->lock);
GS_MUTEX_INIT_RECURSIVE(zone->lock);
for (i = 0; i < MAX_SEG; i++)
{
zone->segheadlist[i] = NULL;
@ -1641,7 +1641,7 @@ NSCreateZone (NSUInteger start, NSUInteger gran, BOOL canFree)
zone->blocks = malloc(startsize + 2*FBSZ);
if (zone->blocks == NULL)
{
pthread_mutex_destroy(&(zone->lock));
GS_MUTEX_DESTROY(zone->lock);
free(zone);
[NSException raise: NSMallocException
format: @"No memory to create zone"];
@ -1686,12 +1686,12 @@ NSCreateZone (NSUInteger start, NSUInteger gran, BOOL canFree)
zone->common.stats = nstats;
zone->common.gran = granularity;
zone->common.name = nil;
GS_INIT_RECURSIVE_MUTEX(zone->lock);
GS_MUTEX_INIT_RECURSIVE(zone->lock);
zone->blocks = malloc(startsize);
zone->use = 0;
if (zone->blocks == NULL)
{
pthread_mutex_destroy(&(zone->lock));
GS_MUTEX_DESTROY(zone->lock);
free(zone);
[NSException raise: NSMallocException
format: @"No memory to create zone"];
@ -1704,10 +1704,10 @@ NSCreateZone (NSUInteger start, NSUInteger gran, BOOL canFree)
newZone = (NSZone*)zone;
}
pthread_mutex_lock(&zoneLock);
GS_MUTEX_LOCK(zoneLock);
newZone->next = zone_list;
zone_list = newZone;
pthread_mutex_unlock(&zoneLock);
GS_MUTEX_UNLOCK(zoneLock);
return newZone;
}

View file

@ -1 +1,8 @@
ADDITIONAL_TOOL_LIBS += -lpthread
ifneq ($(GNUSTEP_TARGET_OS), mingw32)
ifneq ($(GNUSTEP_TARGET_OS), mingw64)
ifneq ($(GNUSTEP_TARGET_OS), windows)
ADDITIONAL_TOOL_LIBS += -lpthread
endif
endif
endif

View file

@ -2,10 +2,12 @@
#import <Foundation/NSThread.h>
#import <Foundation/NSLock.h>
#import <Foundation/NSNotification.h>
#if defined(_WIN32)
#include <process.h>
#else
#include <pthread.h>
#endif
@interface ThreadExpectation : NSObject <NSLocking>
{
@ -98,10 +100,17 @@
}
@end
void *thread(void *expectation)
#if defined(_WIN32)
void __cdecl
#else
void *
#endif
thread(void *expectation)
{
[(ThreadExpectation*)expectation inThread: [NSThread currentThread]];
return nil;
#if !defined(_WIN32)
return NULL;
#endif
}
@ -116,13 +125,18 @@ void *thread(void *expectation)
*/
int main(void)
{
NSAutoreleasePool *arp = [NSAutoreleasePool new];
ThreadExpectation *expectation = [ThreadExpectation new];
#if defined(_WIN32)
_beginthread(thread, 0, expectation);
#else
pthread_t thr;
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
NSAutoreleasePool *arp = [NSAutoreleasePool new];
ThreadExpectation *expectation = [ThreadExpectation new];
pthread_create(&thr, &attr, thread, expectation);
#endif
NSDate *start = [NSDate date];
[expectation lock];

View file

@ -1,27 +1,54 @@
#import "ObjectTesting.h"
#import <Foundation/NSThread.h>
#include <pthread.h>
void *thread(void *ignored)
#if defined(_WIN32)
#include <process.h>
#else
#include <pthread.h>
#endif
static NSThread *threadResult = nil;
#if defined(_WIN32)
unsigned int __stdcall
#else
void *
#endif
thread(void *ignored)
{
return [NSThread currentThread];
threadResult = [NSThread currentThread];
return 0;
}
int main(void)
{
NSAutoreleasePool *arp = [NSAutoreleasePool new];
#if defined(_WIN32)
HANDLE thr;
thr = (HANDLE)_beginthreadex(NULL, 0, thread, NULL, 0, NULL);
WaitForSingleObject(thr, INFINITE);
CloseHandle(thr);
#else
pthread_t thr;
void *ret;
pthread_create(&thr, NULL, thread, NULL);
pthread_join(thr, &ret);
PASS(ret != 0, "NSThread lazily created from POSIX thread");
pthread_join(thr, NULL);
#endif
PASS(threadResult != 0, "NSThread lazily created from native thread");
testHopeful = YES;
PASS((ret != 0) && (ret != [NSThread mainThread]),
PASS((threadResult != 0) && (threadResult != [NSThread mainThread]),
"Spawned thread is not main thread");
#if defined(_WIN32)
thr = (HANDLE)_beginthreadex(NULL, 0, thread, NULL, 0, NULL);
WaitForSingleObject(thr, INFINITE);
CloseHandle(thr);
#else
pthread_create(&thr, NULL, thread, NULL);
pthread_join(thr, &ret);
PASS(ret != 0, "NSThread lazily created from POSIX thread");
PASS((ret != 0) && (ret != [NSThread mainThread]),
pthread_join(thr, NULL);
#endif
PASS(threadResult != 0, "NSThread lazily created from native thread");
PASS((threadResult != 0) && (threadResult != [NSThread mainThread]),
"Spawned thread is not main thread");
NSThread *t = [NSThread currentThread];
@ -29,7 +56,14 @@ int main(void)
NSLog(@"Thread description is '%@'", t);
NSRange r = [[t description] rangeOfString: @"name = xxxtestxxx"];
PASS(r.length > 0, "thread description contains name");
PASS([NSThread threadPriority] == 0.5, "default thread priority is 0.5");
PASS([NSThread setThreadPriority:0.8], "change thread priority to 0.8");
PASS([NSThread threadPriority] == 0.8, "thread priority was changed to 0.8");
PASS([NSThread setThreadPriority:0.2], "change thread priority to 0.2");
PASS([NSThread threadPriority] == 0.2, "thread priority was changed to 0.2");
DESTROY(arp);
return 0;
}

View file

@ -2,13 +2,24 @@
*/
#include "objc-common.g"
#include <pthread.h>
#include <stdio.h>
#if defined(_WIN32)
# define mySleep(X) usleep(1000*(X))
#include <process.h>
typedef unsigned thread_id_t;
#define CREATE_THREAD(threadId, start, arg) \
_beginthreadex(NULL, 0, start, arg, 0, &threadId) != 0
#define mySleep(X) usleep(1000*(X))
#else
# define mySleep(X) sleep(X)
#include <pthread.h>
typedef pthread_t thread_id_t;
#define CREATE_THREAD(threadId, start, arg) \
pthread_create(&threadId, 0, start, arg) == 0
#define mySleep(X) sleep(X)
#endif
#if _MSC_VER
@ -65,11 +76,11 @@ test(void *arg)
int
main()
{
pthread_t t1;
pthread_t t2;
thread_id_t t1;
thread_id_t t2;
unsigned counter;
if (0 == pthread_create(&t1, 0, test, 0))
if (CREATE_THREAD(t1, test, 0))
{
for (counter = 0; 0 == initialize_entered && counter < 5; counter++)
{
@ -82,7 +93,7 @@ main()
return 1;
}
if (0 == pthread_create(&t2, 0, test, 0))
if (CREATE_THREAD(t2, test, 0))
{
/* Wait long enough for t2 to try calling +class
*/

604
configure vendored
View file

@ -680,9 +680,12 @@ NX_CONST_STRING_CLASS
NX_CONST_STRING_OBJCFLAGS
GS_HAVE_OBJC_ROOT_CLASS_ATTR
GS_ALIGNOF_COND_T
GS_ALIGNOF_COND_MUTEX_T
GS_ALIGNOF_MUTEX_T
GS_SIZEOF_COND_T
GS_SIZEOF_COND_MUTEX_T
GS_SIZEOF_MUTEX_T
HAVE_WIN32_THREADS_AND_LOCKS
DYNAMIC_LINKER
BUGGY_PTR_LIMITS
GS_UINTPTR_MAX
@ -3008,7 +3011,7 @@ then
fi
if test x"$GNUSTEP_TARGET_CONFIG_FILE" = x""; then
case "$target_os" in
mingw*|windows*)
mingw*|windows)
GNUSTEP_TARGET_CONFIG_FILE=./GNUstep.conf ;;
*)
GNUSTEP_TARGET_CONFIG_FILE="$GNUSTEP_MAKE_CONFIG" ;;
@ -3026,7 +3029,7 @@ $as_echo "$GNUSTEP_TARGET_CONFIG_FILE" >&6; }
# location (used by gnustep-make when building).
#-----------------------------------------------------------------
case "$target_os" in
mingw*|windows*) enable_env_config=no;;
mingw*|windows) enable_env_config=no;;
*) enable_env_config=yes;;
esac
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the GNUstep.conf file path can be set in the environment" >&5
@ -3306,7 +3309,7 @@ GNUSTEP_BASE_DOMAIN=$result
# paths (relative to libgnustep-base.dll).
#
case "$target_os" in
mingw*|windows*)
mingw*|windows)
# TODO: Improve this hack.
# According to Wikipedia, this is the default for Windows 2000,
# Windows XP and Windows Server 2003. For Windows Vista this will
@ -7251,10 +7254,39 @@ fi
done
#--------------------------------------------------------------------
# Windows: check if we have native threading APIs and SRW locks
#--------------------------------------------------------------------
HAVE_WIN32_THREADS_AND_LOCKS=0
case "$target_os" in
mingw*|windows)
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for native Windows threads and locks" >&5
$as_echo_n "checking for native Windows threads and locks... " >&6; }
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
#define GS_USE_WIN32_THREADS_AND_LOCKS 1
#include "$srcdir/Source/GSPThread.h"
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
HAVE_WIN32_THREADS_AND_LOCKS=1
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
;;
esac
#--------------------------------------------------------------------
# Check for pthread.h
#--------------------------------------------------------------------
for ac_header in pthread.h
if test $HAVE_WIN32_THREADS_AND_LOCKS = 0; then
for ac_header in pthread.h
do :
ac_fn_c_check_header_mongrel "$LINENO" "pthread.h" "ac_cv_header_pthread_h" "$ac_includes_default"
if test "x$ac_cv_header_pthread_h" = xyes; then :
@ -7266,12 +7298,12 @@ fi
done
for ac_header in pthread_np.h
for ac_header in pthread_np.h
do :
ac_fn_c_check_header_compile "$LINENO" "pthread_np.h" "ac_cv_header_pthread_np_h" "$ac_includes_default
#ifdef HAVE_PTHREAD_H
#include <pthread.h>
#endif
#ifdef HAVE_PTHREAD_H
#include <pthread.h>
#endif
"
if test "x$ac_cv_header_pthread_np_h" = xyes; then :
@ -7283,8 +7315,8 @@ fi
done
if test $ac_cv_header_pthread_h = yes ; then
# The cast to long int works around a bug in the HP C Compiler
if test $ac_cv_header_pthread_h = yes ; then
# The cast to long int works around a bug in the HP C Compiler
# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
# This bug is HP SR number 8606223364.
@ -7294,7 +7326,7 @@ if ${ac_cv_sizeof_pthread_mutex_t+:} false; then :
$as_echo_n "(cached) " >&6
else
if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (pthread_mutex_t))" "ac_cv_sizeof_pthread_mutex_t" "$ac_includes_default
#include <pthread.h>
#include <pthread.h>
"; then :
else
@ -7319,27 +7351,31 @@ cat >>confdefs.h <<_ACEOF
_ACEOF
GS_SIZEOF_MUTEX_T=$ac_cv_sizeof_pthread_mutex_t
if test $ac_cv_sizeof_pthread_mutex_t = 0 ; then
as_fn_error $? "Unable to find size of pthread_mutex_t (required)." "$LINENO" 5
fi
GS_SIZEOF_MUTEX_T=$ac_cv_sizeof_pthread_mutex_t
if test $ac_cv_sizeof_pthread_mutex_t = 0 ; then
as_fn_error $? "Unable to find size of pthread_mutex_t (required)." "$LINENO" 5
fi
# pthread_mutex_t.__data.__owner is non-standard since pthread_mutex_t is
# nominally an opaque type. We must not rely on this for anything other
# than debug output!
ac_fn_c_check_member "$LINENO" "pthread_mutex_t" "__data.__owner" "ac_cv_member_pthread_mutex_t___data___owner" "$ac_includes_default
#include <pthread.h>
GS_SIZEOF_COND_MUTEX_T=$ac_cv_sizeof_pthread_mutex_t
# pthread_mutex_t.__data.__owner is non-standard since pthread_mutex_t is
# nominally an opaque type. We must not rely on this for anything other
# than debug output!
ac_fn_c_check_member "$LINENO" "pthread_mutex_t" "__data.__owner" "ac_cv_member_pthread_mutex_t___data___owner" "$ac_includes_default
#include <pthread.h>
"
if test "x$ac_cv_member_pthread_mutex_t___data___owner" = xyes; then :
fi
if test $ac_cv_member_pthread_mutex_t___data___owner = yes ; then
if test $ac_cv_member_pthread_mutex_t___data___owner = yes ; then
$as_echo "#define HAVE_PTHREAD_MUTEX_OWNER 1" >>confdefs.h
fi
# The cast to long int works around a bug in the HP C Compiler
fi
# The cast to long int works around a bug in the HP C Compiler
# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
# This bug is HP SR number 8606223364.
@ -7349,7 +7385,7 @@ if ${ac_cv_sizeof_pthread_cond_t+:} false; then :
$as_echo_n "(cached) " >&6
else
if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (pthread_cond_t))" "ac_cv_sizeof_pthread_cond_t" "$ac_includes_default
#include <pthread.h>
#include <pthread.h>
"; then :
else
@ -7374,12 +7410,13 @@ cat >>confdefs.h <<_ACEOF
_ACEOF
if test $ac_cv_sizeof_pthread_cond_t = 0 ; then
as_fn_error $? "Unable to find size of pthread_cond_t (required)." "$LINENO" 5
fi
GS_SIZEOF_COND_T=$ac_cv_sizeof_pthread_cond_t
if test $ac_cv_sizeof_pthread_cond_t = 0 ; then
as_fn_error $? "Unable to find size of pthread_cond_t (required)." "$LINENO" 5
fi
GS_SIZEOF_COND_T=$ac_cv_sizeof_pthread_cond_t
# The cast to long int works around a bug in the HP C Compiler,
# The cast to long int works around a bug in the HP C Compiler,
# see AC_CHECK_SIZEOF for more information.
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking alignment of pthread_mutex_t" >&5
$as_echo_n "checking alignment of pthread_mutex_t... " >&6; }
@ -7387,7 +7424,7 @@ if ${ac_cv_alignof_pthread_mutex_t+:} false; then :
$as_echo_n "(cached) " >&6
else
if ac_fn_c_compute_int "$LINENO" "(long int) offsetof (ac__type_alignof_, y)" "ac_cv_alignof_pthread_mutex_t" "$ac_includes_default
#include <pthread.h>
#include <pthread.h>
#ifndef offsetof
# define offsetof(type, member) ((char *) &((type *) 0)->member - (char *) 0)
@ -7416,12 +7453,15 @@ cat >>confdefs.h <<_ACEOF
_ACEOF
GS_ALIGNOF_MUTEX_T=$ac_cv_alignof_pthread_mutex_t
if test $ac_cv_alignof_pthread_mutex_t = 0 ; then
as_fn_error $? "Unable to find align of pthread_mutex_t (required)." "$LINENO" 5
fi
GS_ALIGNOF_MUTEX_T=$ac_cv_alignof_pthread_mutex_t
if test $ac_cv_alignof_pthread_mutex_t = 0 ; then
as_fn_error $? "Unable to find align of pthread_mutex_t (required)." "$LINENO" 5
fi
# The cast to long int works around a bug in the HP C Compiler,
GS_ALIGNOF_COND_MUTEX_T=$ac_cv_alignof_pthread_mutex_t
# The cast to long int works around a bug in the HP C Compiler,
# see AC_CHECK_SIZEOF for more information.
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking alignment of pthread_cond_t" >&5
$as_echo_n "checking alignment of pthread_cond_t... " >&6; }
@ -7429,7 +7469,7 @@ if ${ac_cv_alignof_pthread_cond_t+:} false; then :
$as_echo_n "(cached) " >&6
else
if ac_fn_c_compute_int "$LINENO" "(long int) offsetof (ac__type_alignof_, y)" "ac_cv_alignof_pthread_cond_t" "$ac_includes_default
#include <pthread.h>
#include <pthread.h>
#ifndef offsetof
# define offsetof(type, member) ((char *) &((type *) 0)->member - (char *) 0)
@ -7458,15 +7498,15 @@ cat >>confdefs.h <<_ACEOF
_ACEOF
if test $ac_cv_alignof_pthread_cond_t = 0 ; then
as_fn_error $? "Unable to find align of pthread_cond_t (required)." "$LINENO" 5
fi
GS_ALIGNOF_COND_T=$ac_cv_alignof_pthread_cond_t
if test $ac_cv_alignof_pthread_cond_t = 0 ; then
as_fn_error $? "Unable to find align of pthread_cond_t (required)." "$LINENO" 5
fi
GS_ALIGNOF_COND_T=$ac_cv_alignof_pthread_cond_t
else
as_fn_error $? "Unable to find pthread.h (needed for thread support)." "$LINENO" 5
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_join in -lpthread" >&5
else
as_fn_error $? "Unable to find pthread.h (needed for thread support)." "$LINENO" 5
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_join in -lpthread" >&5
$as_echo_n "checking for pthread_join in -lpthread... " >&6; }
if ${ac_cv_lib_pthread_pthread_join+:} false; then :
$as_echo_n "(cached) " >&6
@ -7508,20 +7548,13 @@ else
pthread_ok=no
fi
ismingw=no
checkinlibc=no
case "$target_os" in
mingw*) ismingw=yes;;
windows) iswindows=yes;;
nto*) checkinlibc=yes;;
qnx*) checkinlibc=yes;;
*android*) checkinlibc=yes;;
esac
if test $pthread_ok = yes ; then
LIBS="$LIBS -lpthread"
else
if test $ismingw = yes ; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_join in -lpthreadGC2" >&5
if test $pthread_ok = yes ; then
LIBS="$LIBS -lpthread"
else
case "$target_os" in
mingw*)
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_join in -lpthreadGC2" >&5
$as_echo_n "checking for pthread_join in -lpthreadGC2... " >&6; }
if ${ac_cv_lib_pthreadGC2_pthread_join+:} false; then :
$as_echo_n "(cached) " >&6
@ -7563,12 +7596,12 @@ else
pthread_ok=no
fi
if test $pthread_ok = yes ; then
LIBS="$LIBS -lpthreadGC2"
fi
fi
if test $iswindows = yes ; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_join in -lpthreadVC2" >&5
if test $pthread_ok = yes ; then
LIBS="$LIBS -lpthreadGC2"
fi
;;
windows)
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_join in -lpthreadVC2" >&5
$as_echo_n "checking for pthread_join in -lpthreadVC2... " >&6; }
if ${ac_cv_lib_pthreadVC2_pthread_join+:} false; then :
$as_echo_n "(cached) " >&6
@ -7610,13 +7643,13 @@ else
pthread_ok=no
fi
if test $pthread_ok = yes ; then
LIBS="$LIBS -lpthreadVC2"
fi
fi
# Android and QNX have pthread in libc instead of libpthread
if test $checkinlibc = yes ; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_join in -lc" >&5
if test $pthread_ok = yes ; then
LIBS="$LIBS -lpthreadVC2"
fi
;;
nto*|qnx*|*android*)
# Android and QNX have pthread in libc instead of libpthread
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_join in -lc" >&5
$as_echo_n "checking for pthread_join in -lc... " >&6; }
if ${ac_cv_lib_c_pthread_join+:} false; then :
$as_echo_n "(cached) " >&6
@ -7658,17 +7691,18 @@ else
pthread_ok=no
fi
if test $pthread_ok = yes ; then
LIBS="$LIBS -lc"
fi
if test $pthread_ok = yes ; then
LIBS="$LIBS -lc"
fi
;;
esac
fi
if test $pthread_ok = no ; then
as_fn_error $? "Unable to find pthread library (needed for thread support)." "$LINENO" 5
fi
fi
if test $pthread_ok = no ; then
as_fn_error $? "Unable to find pthread library (needed for thread support)." "$LINENO" 5
fi
# Check threading extensions
for ac_func in pthread_getthreadid_np pthread_main_np
# Check threading extensions
for ac_func in pthread_getthreadid_np pthread_main_np
do :
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
@ -7681,8 +7715,8 @@ fi
done
# Typically need librt on Solaris for sched_yield
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for sched_yield in -lrt" >&5
# Typically need librt on Solaris for sched_yield
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for sched_yield in -lrt" >&5
$as_echo_n "checking for sched_yield in -lrt... " >&6; }
if ${ac_cv_lib_rt_sched_yield+:} false; then :
$as_echo_n "(cached) " >&6
@ -7728,62 +7762,8 @@ _ACEOF
fi
#--------------------------------------------------------------------
# One of these function needed by NSThread.m and objc initialize test
#--------------------------------------------------------------------
for ac_func in nanosleep usleep Sleep
do :
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
cat >>confdefs.h <<_ACEOF
#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
_ACEOF
fi
done
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for objc_root_class attribute support" >&5
$as_echo_n "checking for objc_root_class attribute support... " >&6; }
saved_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS -Werror $OBJCFLAGS -x objective-c"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
__attribute__((objc_root_class)) @interface RootObject
@end
@implementation RootObject
@end
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: found" >&5
$as_echo "found" >&6; }
gs_objc_root_class_attr=1
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: not present" >&5
$as_echo "not present" >&6; }
gs_objc_root_class_attr=0
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
GS_HAVE_OBJC_ROOT_CLASS_ATTR=$gs_objc_root_class_attr
cat >>confdefs.h <<_ACEOF
#define HAVE_OBJC_ROOT_CLASS_ATTRIBUTE $gs_objc_root_class_attr
_ACEOF
CFLAGS=$saved_CFLAGS
#--------------------------------------------------------------------
# Check if we can name pthreads
#--------------------------------------------------------------------
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_setname_np()" >&5
# Check if we can name pthreads
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_setname_np()" >&5
$as_echo_n "checking for pthread_setname_np()... " >&6; }
if ${gs_cv_pthread_setname_np+:} false; then :
$as_echo_n "(cached) " >&6
@ -7843,28 +7823,26 @@ rm -f core conftest.err conftest.$ac_objext \
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gs_cv_pthread_setname_np" >&5
$as_echo "$gs_cv_pthread_setname_np" >&6; }
case $gs_cv_pthread_setname_np in
darwin)
case $gs_cv_pthread_setname_np in
darwin)
$as_echo "#define PTHREAD_SETNAME(a) pthread_setname_np(a)" >>confdefs.h
;;
glibc)
;;
glibc)
$as_echo "#define PTHREAD_SETNAME(a) pthread_setname_np(pthread_self(),a)" >>confdefs.h
;;
netbsd)
;;
netbsd)
$as_echo "#define PTHREAD_SETNAME(a) pthread_setname_np(pthread_self(),\"%s\",a)" >>confdefs.h
;;
esac
;;
esac
#--------------------------------------------------------------------
# Check if we have spinlock support
#--------------------------------------------------------------------
for ac_func in pthread_spin_lock
# Check if we have spinlock support
for ac_func in pthread_spin_lock
do :
ac_fn_c_check_func "$LINENO" "pthread_spin_lock" "ac_cv_func_pthread_spin_lock"
if test "x$ac_cv_func_pthread_spin_lock" = xyes; then :
@ -7875,6 +7853,315 @@ _ACEOF
fi
done
fi
#--------------------------------------------------------------------
# Check Win32 lock sizes
#--------------------------------------------------------------------
if test $HAVE_WIN32_THREADS_AND_LOCKS = 1; then
# The cast to long int works around a bug in the HP C Compiler
# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
# This bug is HP SR number 8606223364.
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of gs_mutex_t" >&5
$as_echo_n "checking size of gs_mutex_t... " >&6; }
if ${ac_cv_sizeof_gs_mutex_t+:} false; then :
$as_echo_n "(cached) " >&6
else
if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (gs_mutex_t))" "ac_cv_sizeof_gs_mutex_t" "$ac_includes_default
#define GS_USE_WIN32_THREADS_AND_LOCKS 1
#include \"Source/GSPThread.h\"
"; then :
else
if test "$ac_cv_type_gs_mutex_t" = yes; then
{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error 77 "cannot compute sizeof (gs_mutex_t)
See \`config.log' for more details" "$LINENO" 5; }
else
ac_cv_sizeof_gs_mutex_t=0
fi
fi
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_gs_mutex_t" >&5
$as_echo "$ac_cv_sizeof_gs_mutex_t" >&6; }
cat >>confdefs.h <<_ACEOF
#define SIZEOF_GS_MUTEX_T $ac_cv_sizeof_gs_mutex_t
_ACEOF
GS_SIZEOF_MUTEX_T=$ac_cv_sizeof_gs_mutex_t
if test $ac_cv_sizeof_gs_mutex_t = 0 ; then
as_fn_error $? "Unable to find size of gs_mutex_t (required)." "$LINENO" 5
fi
# The cast to long int works around a bug in the HP C Compiler,
# see AC_CHECK_SIZEOF for more information.
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking alignment of gs_mutex_t" >&5
$as_echo_n "checking alignment of gs_mutex_t... " >&6; }
if ${ac_cv_alignof_gs_mutex_t+:} false; then :
$as_echo_n "(cached) " >&6
else
if ac_fn_c_compute_int "$LINENO" "(long int) offsetof (ac__type_alignof_, y)" "ac_cv_alignof_gs_mutex_t" "$ac_includes_default
#define GS_USE_WIN32_THREADS_AND_LOCKS 1
#include \"Source/GSPThread.h\"
#ifndef offsetof
# define offsetof(type, member) ((char *) &((type *) 0)->member - (char *) 0)
#endif
typedef struct { char x; gs_mutex_t y; } ac__type_alignof_;"; then :
else
if test "$ac_cv_type_gs_mutex_t" = yes; then
{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error 77 "cannot compute alignment of gs_mutex_t
See \`config.log' for more details" "$LINENO" 5; }
else
ac_cv_alignof_gs_mutex_t=0
fi
fi
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_alignof_gs_mutex_t" >&5
$as_echo "$ac_cv_alignof_gs_mutex_t" >&6; }
cat >>confdefs.h <<_ACEOF
#define ALIGNOF_GS_MUTEX_T $ac_cv_alignof_gs_mutex_t
_ACEOF
GS_ALIGNOF_MUTEX_T=$ac_cv_alignof_gs_mutex_t
if test $ac_cv_alignof_gs_mutex_t = 0 ; then
as_fn_error $? "Unable to find align of gs_mutex_t (required)." "$LINENO" 5
fi
# The cast to long int works around a bug in the HP C Compiler
# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
# This bug is HP SR number 8606223364.
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of CONDITION_VARIABLE" >&5
$as_echo_n "checking size of CONDITION_VARIABLE... " >&6; }
if ${ac_cv_sizeof_CONDITION_VARIABLE+:} false; then :
$as_echo_n "(cached) " >&6
else
if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (CONDITION_VARIABLE))" "ac_cv_sizeof_CONDITION_VARIABLE" "$ac_includes_default
#include <windows.h>
"; then :
else
if test "$ac_cv_type_CONDITION_VARIABLE" = yes; then
{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error 77 "cannot compute sizeof (CONDITION_VARIABLE)
See \`config.log' for more details" "$LINENO" 5; }
else
ac_cv_sizeof_CONDITION_VARIABLE=0
fi
fi
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_CONDITION_VARIABLE" >&5
$as_echo "$ac_cv_sizeof_CONDITION_VARIABLE" >&6; }
cat >>confdefs.h <<_ACEOF
#define SIZEOF_CONDITION_VARIABLE $ac_cv_sizeof_CONDITION_VARIABLE
_ACEOF
GS_SIZEOF_COND_T=$ac_cv_sizeof_CONDITION_VARIABLE
if test $ac_cv_sizeof_CONDITION_VARIABLE = 0 ; then
as_fn_error $? "Unable to find size of CONDITION_VARIABLE (required)." "$LINENO" 5
fi
# The cast to long int works around a bug in the HP C Compiler,
# see AC_CHECK_SIZEOF for more information.
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking alignment of CONDITION_VARIABLE" >&5
$as_echo_n "checking alignment of CONDITION_VARIABLE... " >&6; }
if ${ac_cv_alignof_CONDITION_VARIABLE+:} false; then :
$as_echo_n "(cached) " >&6
else
if ac_fn_c_compute_int "$LINENO" "(long int) offsetof (ac__type_alignof_, y)" "ac_cv_alignof_CONDITION_VARIABLE" "$ac_includes_default
#include <windows.h>
#ifndef offsetof
# define offsetof(type, member) ((char *) &((type *) 0)->member - (char *) 0)
#endif
typedef struct { char x; CONDITION_VARIABLE y; } ac__type_alignof_;"; then :
else
if test "$ac_cv_type_CONDITION_VARIABLE" = yes; then
{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error 77 "cannot compute alignment of CONDITION_VARIABLE
See \`config.log' for more details" "$LINENO" 5; }
else
ac_cv_alignof_CONDITION_VARIABLE=0
fi
fi
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_alignof_CONDITION_VARIABLE" >&5
$as_echo "$ac_cv_alignof_CONDITION_VARIABLE" >&6; }
cat >>confdefs.h <<_ACEOF
#define ALIGNOF_CONDITION_VARIABLE $ac_cv_alignof_CONDITION_VARIABLE
_ACEOF
GS_ALIGNOF_COND_T=$ac_cv_alignof_CONDITION_VARIABLE
if test $ac_cv_alignof_CONDITION_VARIABLE = 0 ; then
as_fn_error $? "Unable to find align of CONDITION_VARIABLE (required)." "$LINENO" 5
fi
# The cast to long int works around a bug in the HP C Compiler
# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
# This bug is HP SR number 8606223364.
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of SRWLOCK" >&5
$as_echo_n "checking size of SRWLOCK... " >&6; }
if ${ac_cv_sizeof_SRWLOCK+:} false; then :
$as_echo_n "(cached) " >&6
else
if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (SRWLOCK))" "ac_cv_sizeof_SRWLOCK" "$ac_includes_default
#include <windows.h>
"; then :
else
if test "$ac_cv_type_SRWLOCK" = yes; then
{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error 77 "cannot compute sizeof (SRWLOCK)
See \`config.log' for more details" "$LINENO" 5; }
else
ac_cv_sizeof_SRWLOCK=0
fi
fi
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_SRWLOCK" >&5
$as_echo "$ac_cv_sizeof_SRWLOCK" >&6; }
cat >>confdefs.h <<_ACEOF
#define SIZEOF_SRWLOCK $ac_cv_sizeof_SRWLOCK
_ACEOF
GS_SIZEOF_COND_MUTEX_T=$ac_cv_sizeof_SRWLOCK
if test $ac_cv_sizeof_SRWLOCK = 0 ; then
as_fn_error $? "Unable to find size of SRWLOCK (required)." "$LINENO" 5
fi
# The cast to long int works around a bug in the HP C Compiler,
# see AC_CHECK_SIZEOF for more information.
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking alignment of SRWLOCK" >&5
$as_echo_n "checking alignment of SRWLOCK... " >&6; }
if ${ac_cv_alignof_SRWLOCK+:} false; then :
$as_echo_n "(cached) " >&6
else
if ac_fn_c_compute_int "$LINENO" "(long int) offsetof (ac__type_alignof_, y)" "ac_cv_alignof_SRWLOCK" "$ac_includes_default
#include <windows.h>
#ifndef offsetof
# define offsetof(type, member) ((char *) &((type *) 0)->member - (char *) 0)
#endif
typedef struct { char x; SRWLOCK y; } ac__type_alignof_;"; then :
else
if test "$ac_cv_type_SRWLOCK" = yes; then
{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
as_fn_error 77 "cannot compute alignment of SRWLOCK
See \`config.log' for more details" "$LINENO" 5; }
else
ac_cv_alignof_SRWLOCK=0
fi
fi
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_alignof_SRWLOCK" >&5
$as_echo "$ac_cv_alignof_SRWLOCK" >&6; }
cat >>confdefs.h <<_ACEOF
#define ALIGNOF_SRWLOCK $ac_cv_alignof_SRWLOCK
_ACEOF
GS_ALIGNOF_COND_MUTEX_T=$ac_cv_alignof_SRWLOCK
if test $ac_cv_alignof_SRWLOCK = 0 ; then
as_fn_error $? "Unable to find align of SRWLOCK (required)." "$LINENO" 5
fi
fi
#--------------------------------------------------------------------
# One of these function needed by NSThread.m and objc initialize test
#--------------------------------------------------------------------
for ac_func in nanosleep usleep Sleep
do :
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
cat >>confdefs.h <<_ACEOF
#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
_ACEOF
fi
done
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for objc_root_class attribute support" >&5
$as_echo_n "checking for objc_root_class attribute support... " >&6; }
saved_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS -Werror $OBJCFLAGS -x objective-c"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
__attribute__((objc_root_class)) @interface RootObject
@end
@implementation RootObject
@end
_ACEOF
if ac_fn_c_try_compile "$LINENO"; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: found" >&5
$as_echo "found" >&6; }
gs_objc_root_class_attr=1
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: not present" >&5
$as_echo "not present" >&6; }
gs_objc_root_class_attr=0
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
GS_HAVE_OBJC_ROOT_CLASS_ATTR=$gs_objc_root_class_attr
cat >>confdefs.h <<_ACEOF
#define HAVE_OBJC_ROOT_CLASS_ATTRIBUTE $gs_objc_root_class_attr
_ACEOF
CFLAGS=$saved_CFLAGS
#--------------------------------------------------------------------
# Check whether we can get the system thread ID
@ -9141,8 +9428,9 @@ $as_echo "#define HAVE_BFD_SECTION_VMA 1" >>confdefs.h
fi
if test $ismingw = yes ; then
for ac_header in dbghelp.h
case "$target_os" in
mingw*)
for ac_header in dbghelp.h
do :
ac_fn_c_check_header_mongrel "$LINENO" "dbghelp.h" "ac_cv_header_dbghelp_h" "$ac_includes_default"
if test "x$ac_cv_header_dbghelp_h" = xyes; then :
@ -9154,8 +9442,9 @@ fi
done
else
for ac_header in execinfo.h
;;
*)
for ac_header in execinfo.h
do :
ac_fn_c_check_header_mongrel "$LINENO" "execinfo.h" "ac_cv_header_execinfo_h" "$ac_includes_default"
if test "x$ac_cv_header_execinfo_h" = xyes; then :
@ -9167,7 +9456,7 @@ fi
done
for ac_func in backtrace
for ac_func in backtrace
do :
ac_fn_c_check_func "$LINENO" "backtrace" "ac_cv_func_backtrace"
if test "x$ac_cv_func_backtrace" = xyes; then :
@ -9178,7 +9467,8 @@ _ACEOF
fi
done
fi
;;
esac
for ac_func in __builtin_extract_return_address
do :
@ -10774,7 +11064,7 @@ $as_echo "$as_me: WARNING: Using libkvm which is known to be buggy on some syste
fi
fi
case "$target_os" in
mingw*|windows*) enable_fake_main=no; GS_FAKE_MAIN=0;;
mingw*|windows) enable_fake_main=no; GS_FAKE_MAIN=0;;
esac
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_fake_main" >&5

View file

@ -235,7 +235,7 @@ then
fi
if test x"$GNUSTEP_TARGET_CONFIG_FILE" = x""; then
case "$target_os" in
mingw*|windows*)
mingw*|windows)
GNUSTEP_TARGET_CONFIG_FILE=./GNUstep.conf ;;
*)
GNUSTEP_TARGET_CONFIG_FILE="$GNUSTEP_MAKE_CONFIG" ;;
@ -252,7 +252,7 @@ AC_MSG_RESULT($GNUSTEP_TARGET_CONFIG_FILE)
# location (used by gnustep-make when building).
#-----------------------------------------------------------------
case "$target_os" in
mingw*|windows*) enable_env_config=no;;
mingw*|windows) enable_env_config=no;;
*) enable_env_config=yes;;
esac
AC_MSG_CHECKING([whether the GNUstep.conf file path can be set in the environment])
@ -534,7 +534,7 @@ AC_SUBST(GNUSTEP_BASE_DOMAIN)
# paths (relative to libgnustep-base.dll).
#
case "$target_os" in
mingw*|windows*)
mingw*|windows)
# TODO: Improve this hack.
# According to Wikipedia, this is the default for Windows 2000,
# Windows XP and Windows Server 2003. For Windows Vista this will
@ -1702,99 +1702,209 @@ fi
AC_CHECK_FUNCS(getaddrinfo)
#--------------------------------------------------------------------
# Windows: check if we have native threading APIs and SRW locks
#--------------------------------------------------------------------
HAVE_WIN32_THREADS_AND_LOCKS=0
case "$target_os" in
mingw*|windows)
AC_MSG_CHECKING(for native Windows threads and locks)
AC_COMPILE_IFELSE(
[AC_LANG_SOURCE([
#define GS_USE_WIN32_THREADS_AND_LOCKS 1
#include "$srcdir/Source/GSPThread.h"
])],
AC_MSG_RESULT([yes])
HAVE_WIN32_THREADS_AND_LOCKS=1,
AC_MSG_RESULT([no]))
;;
esac
AC_SUBST(HAVE_WIN32_THREADS_AND_LOCKS)
#--------------------------------------------------------------------
# Check for pthread.h
#--------------------------------------------------------------------
AC_CHECK_HEADERS([pthread.h])
AC_CHECK_HEADERS([pthread_np.h],[],[],[AC_INCLUDES_DEFAULT
#ifdef HAVE_PTHREAD_H
#include <pthread.h>
#endif
])
if test $ac_cv_header_pthread_h = yes ; then
AC_CHECK_SIZEOF(pthread_mutex_t,,[AC_INCLUDES_DEFAULT
#include <pthread.h>])
GS_SIZEOF_MUTEX_T=$ac_cv_sizeof_pthread_mutex_t
if test $ac_cv_sizeof_pthread_mutex_t = 0 ; then
AC_MSG_ERROR([Unable to find size of pthread_mutex_t (required).])
if test $HAVE_WIN32_THREADS_AND_LOCKS = 0; then
AC_CHECK_HEADERS([pthread.h])
AC_CHECK_HEADERS([pthread_np.h],[],[],[AC_INCLUDES_DEFAULT
#ifdef HAVE_PTHREAD_H
#include <pthread.h>
#endif
])
if test $ac_cv_header_pthread_h = yes ; then
AC_CHECK_SIZEOF(pthread_mutex_t,,[AC_INCLUDES_DEFAULT
#include <pthread.h>])
GS_SIZEOF_MUTEX_T=$ac_cv_sizeof_pthread_mutex_t
if test $ac_cv_sizeof_pthread_mutex_t = 0 ; then
AC_MSG_ERROR([Unable to find size of pthread_mutex_t (required).])
fi
AC_SUBST(GS_SIZEOF_MUTEX_T)
GS_SIZEOF_COND_MUTEX_T=$ac_cv_sizeof_pthread_mutex_t
AC_SUBST(GS_SIZEOF_COND_MUTEX_T)
# pthread_mutex_t.__data.__owner is non-standard since pthread_mutex_t is
# nominally an opaque type. We must not rely on this for anything other
# than debug output!
AC_CHECK_MEMBER([pthread_mutex_t.__data.__owner],,,[AC_INCLUDES_DEFAULT
#include <pthread.h>])
if test $ac_cv_member_pthread_mutex_t___data___owner = yes ; then
AC_DEFINE(HAVE_PTHREAD_MUTEX_OWNER, 1,
[Define if you have pthread_mutex_t.__data.__owner])
fi
AC_CHECK_SIZEOF(pthread_cond_t,,[AC_INCLUDES_DEFAULT
#include <pthread.h>])
if test $ac_cv_sizeof_pthread_cond_t = 0 ; then
AC_MSG_ERROR([Unable to find size of pthread_cond_t (required).])
fi
GS_SIZEOF_COND_T=$ac_cv_sizeof_pthread_cond_t
AC_SUBST(GS_SIZEOF_COND_T)
AC_CHECK_ALIGNOF(pthread_mutex_t,[AC_INCLUDES_DEFAULT
#include <pthread.h>])
GS_ALIGNOF_MUTEX_T=$ac_cv_alignof_pthread_mutex_t
if test $ac_cv_alignof_pthread_mutex_t = 0 ; then
AC_MSG_ERROR([Unable to find align of pthread_mutex_t (required).])
fi
AC_SUBST(GS_ALIGNOF_MUTEX_T)
GS_ALIGNOF_COND_MUTEX_T=$ac_cv_alignof_pthread_mutex_t
AC_SUBST(GS_ALIGNOF_COND_MUTEX_T)
AC_CHECK_ALIGNOF(pthread_cond_t,[AC_INCLUDES_DEFAULT
#include <pthread.h>])
if test $ac_cv_alignof_pthread_cond_t = 0 ; then
AC_MSG_ERROR([Unable to find align of pthread_cond_t (required).])
fi
GS_ALIGNOF_COND_T=$ac_cv_alignof_pthread_cond_t
AC_SUBST(GS_ALIGNOF_COND_T)
else
AC_MSG_ERROR([Unable to find pthread.h (needed for thread support).])
fi
AC_CHECK_LIB(pthread, pthread_join, pthread_ok=yes, pthread_ok=no)
if test $pthread_ok = yes ; then
LIBS="$LIBS -lpthread"
else
case "$target_os" in
mingw*)
AC_CHECK_LIB(pthreadGC2, pthread_join, pthread_ok=yes, pthread_ok=no)
if test $pthread_ok = yes ; then
LIBS="$LIBS -lpthreadGC2"
fi
;;
windows)
AC_CHECK_LIB(pthreadVC2, pthread_join, pthread_ok=yes, pthread_ok=no)
if test $pthread_ok = yes ; then
LIBS="$LIBS -lpthreadVC2"
fi
;;
nto*|qnx*|*android*)
# Android and QNX have pthread in libc instead of libpthread
AC_CHECK_LIB(c, pthread_join, pthread_ok=yes, pthread_ok=no)
if test $pthread_ok = yes ; then
LIBS="$LIBS -lc"
fi
;;
esac
fi
if test $pthread_ok = no ; then
AC_MSG_ERROR([Unable to find pthread library (needed for thread support).])
fi
# Check threading extensions
AC_CHECK_FUNCS(pthread_getthreadid_np pthread_main_np)
# Typically need librt on Solaris for sched_yield
AC_CHECK_LIB(rt, sched_yield)
# Check if we can name pthreads
AC_CACHE_CHECK([for pthread_setname_np()], gs_cv_pthread_setname_np,
[AC_LINK_IFELSE(
[AC_LANG_PROGRAM([#include <pthread.h>],
[pthread_setname_np("name");])],
[gs_cv_pthread_setname_np=darwin],
[AC_LINK_IFELSE(
[AC_LANG_PROGRAM([#include <pthread.h>],
[pthread_setname_np(pthread_self(), "name");])],
[gs_cv_pthread_setname_np=glibc],
[AC_LINK_IFELSE(
[AC_LANG_PROGRAM([#include <pthread.h>],
[pthread_setname_np(pthread_self(), "%s", "name");])],
[gs_cv_pthread_setname_np=netbsd],
[gs_cv_pthread_setname_np=none])])])])
case $gs_cv_pthread_setname_np in
darwin)
AC_DEFINE(PTHREAD_SETNAME(a), pthread_setname_np(a),
[Description: Define set name function for pthread with one arg])
;;
glibc)
AC_DEFINE(PTHREAD_SETNAME(a), pthread_setname_np(pthread_self(),a),
[Description: Define setname function for pthread with two args])
;;
netbsd)
AC_DEFINE(PTHREAD_SETNAME(a), pthread_setname_np(pthread_self(),"%s",a),
[Description: Define setname function for pthread with three args])
;;
esac
# Check if we have spinlock support
AC_CHECK_FUNCS(pthread_spin_lock)
fi
#--------------------------------------------------------------------
# Check Win32 lock sizes
#--------------------------------------------------------------------
if test $HAVE_WIN32_THREADS_AND_LOCKS = 1; then
AC_CHECK_SIZEOF(gs_mutex_t,,[AC_INCLUDES_DEFAULT
#define GS_USE_WIN32_THREADS_AND_LOCKS 1
#include "Source/GSPThread.h"])
GS_SIZEOF_MUTEX_T=$ac_cv_sizeof_gs_mutex_t
if test $ac_cv_sizeof_gs_mutex_t = 0 ; then
AC_MSG_ERROR([Unable to find size of gs_mutex_t (required).])
fi
AC_SUBST(GS_SIZEOF_MUTEX_T)
# pthread_mutex_t.__data.__owner is non-standard since pthread_mutex_t is
# nominally an opaque type. We must not rely on this for anything other
# than debug output!
AC_CHECK_MEMBER([pthread_mutex_t.__data.__owner],,,[AC_INCLUDES_DEFAULT
#include <pthread.h>])
if test $ac_cv_member_pthread_mutex_t___data___owner = yes ; then
AC_DEFINE(HAVE_PTHREAD_MUTEX_OWNER, 1,
[Define if you have pthread_mutex_t.__data.__owner])
fi
AC_CHECK_SIZEOF(pthread_cond_t,,[AC_INCLUDES_DEFAULT
#include <pthread.h>])
if test $ac_cv_sizeof_pthread_cond_t = 0 ; then
AC_MSG_ERROR([Unable to find size of pthread_cond_t (required).])
fi
GS_SIZEOF_COND_T=$ac_cv_sizeof_pthread_cond_t
AC_SUBST(GS_SIZEOF_COND_T)
AC_CHECK_ALIGNOF(pthread_mutex_t,[AC_INCLUDES_DEFAULT
#include <pthread.h>])
GS_ALIGNOF_MUTEX_T=$ac_cv_alignof_pthread_mutex_t
if test $ac_cv_alignof_pthread_mutex_t = 0 ; then
AC_MSG_ERROR([Unable to find align of pthread_mutex_t (required).])
AC_CHECK_ALIGNOF(gs_mutex_t,[AC_INCLUDES_DEFAULT
#define GS_USE_WIN32_THREADS_AND_LOCKS 1
#include "Source/GSPThread.h"])
GS_ALIGNOF_MUTEX_T=$ac_cv_alignof_gs_mutex_t
if test $ac_cv_alignof_gs_mutex_t = 0 ; then
AC_MSG_ERROR([Unable to find align of gs_mutex_t (required).])
fi
AC_SUBST(GS_ALIGNOF_MUTEX_T)
AC_CHECK_ALIGNOF(pthread_cond_t,[AC_INCLUDES_DEFAULT
#include <pthread.h>])
if test $ac_cv_alignof_pthread_cond_t = 0 ; then
AC_MSG_ERROR([Unable to find align of pthread_cond_t (required).])
AC_CHECK_SIZEOF(CONDITION_VARIABLE,,[AC_INCLUDES_DEFAULT
#include <windows.h>])
GS_SIZEOF_COND_T=$ac_cv_sizeof_CONDITION_VARIABLE
if test $ac_cv_sizeof_CONDITION_VARIABLE = 0 ; then
AC_MSG_ERROR([Unable to find size of CONDITION_VARIABLE (required).])
fi
AC_SUBST(GS_SIZEOF_COND_T)
AC_CHECK_ALIGNOF(CONDITION_VARIABLE,[AC_INCLUDES_DEFAULT
#include <windows.h>])
GS_ALIGNOF_COND_T=$ac_cv_alignof_CONDITION_VARIABLE
if test $ac_cv_alignof_CONDITION_VARIABLE = 0 ; then
AC_MSG_ERROR([Unable to find align of CONDITION_VARIABLE (required).])
fi
GS_ALIGNOF_COND_T=$ac_cv_alignof_pthread_cond_t
AC_SUBST(GS_ALIGNOF_COND_T)
else
AC_MSG_ERROR([Unable to find pthread.h (needed for thread support).])
fi
AC_CHECK_LIB(pthread, pthread_join, pthread_ok=yes, pthread_ok=no)
ismingw=no
checkinlibc=no
case "$target_os" in
mingw*) ismingw=yes;;
windows) iswindows=yes;;
nto*) checkinlibc=yes;;
qnx*) checkinlibc=yes;;
*android*) checkinlibc=yes;;
esac
if test $pthread_ok = yes ; then
LIBS="$LIBS -lpthread"
else
if test $ismingw = yes ; then
AC_CHECK_LIB(pthreadGC2, pthread_join, pthread_ok=yes, pthread_ok=no)
if test $pthread_ok = yes ; then
LIBS="$LIBS -lpthreadGC2"
fi
AC_CHECK_SIZEOF(SRWLOCK,,[AC_INCLUDES_DEFAULT
#include <windows.h>])
GS_SIZEOF_COND_MUTEX_T=$ac_cv_sizeof_SRWLOCK
if test $ac_cv_sizeof_SRWLOCK = 0 ; then
AC_MSG_ERROR([Unable to find size of SRWLOCK (required).])
fi
if test $iswindows = yes ; then
AC_CHECK_LIB(pthreadVC2, pthread_join, pthread_ok=yes, pthread_ok=no)
if test $pthread_ok = yes ; then
LIBS="$LIBS -lpthreadVC2"
fi
fi
# Android and QNX have pthread in libc instead of libpthread
if test $checkinlibc = yes ; then
AC_CHECK_LIB(c, pthread_join, pthread_ok=yes, pthread_ok=no)
if test $pthread_ok = yes ; then
LIBS="$LIBS -lc"
fi
AC_SUBST(GS_SIZEOF_COND_MUTEX_T)
AC_CHECK_ALIGNOF(SRWLOCK,[AC_INCLUDES_DEFAULT
#include <windows.h>])
GS_ALIGNOF_COND_MUTEX_T=$ac_cv_alignof_SRWLOCK
if test $ac_cv_alignof_SRWLOCK = 0 ; then
AC_MSG_ERROR([Unable to find align of SRWLOCK (required).])
fi
AC_SUBST(GS_ALIGNOF_COND_MUTEX_T)
fi
if test $pthread_ok = no ; then
AC_MSG_ERROR([Unable to find pthread library (needed for thread support).])
fi
# Check threading extensions
AC_CHECK_FUNCS(pthread_getthreadid_np pthread_main_np)
# Typically need librt on Solaris for sched_yield
AC_CHECK_LIB(rt, sched_yield)
#--------------------------------------------------------------------
# One of these function needed by NSThread.m and objc initialize test
@ -1821,45 +1931,6 @@ AC_DEFINE_UNQUOTED(HAVE_OBJC_ROOT_CLASS_ATTRIBUTE,$gs_objc_root_class_attr,
[Says whether the objc_root_class attribute works])
CFLAGS=$saved_CFLAGS
#--------------------------------------------------------------------
# Check if we can name pthreads
#--------------------------------------------------------------------
AC_CACHE_CHECK([for pthread_setname_np()], gs_cv_pthread_setname_np,
[AC_LINK_IFELSE(
[AC_LANG_PROGRAM([#include <pthread.h>],
[pthread_setname_np("name");])],
[gs_cv_pthread_setname_np=darwin],
[AC_LINK_IFELSE(
[AC_LANG_PROGRAM([#include <pthread.h>],
[pthread_setname_np(pthread_self(), "name");])],
[gs_cv_pthread_setname_np=glibc],
[AC_LINK_IFELSE(
[AC_LANG_PROGRAM([#include <pthread.h>],
[pthread_setname_np(pthread_self(), "%s", "name");])],
[gs_cv_pthread_setname_np=netbsd],
[gs_cv_pthread_setname_np=none])])])])
case $gs_cv_pthread_setname_np in
darwin)
AC_DEFINE(PTHREAD_SETNAME(a), pthread_setname_np(a),
[Description: Define set name function for pthread with one arg])
;;
glibc)
AC_DEFINE(PTHREAD_SETNAME(a), pthread_setname_np(pthread_self(),a),
[Description: Define setname function for pthread with two args])
;;
netbsd)
AC_DEFINE(PTHREAD_SETNAME(a), pthread_setname_np(pthread_self(),"%s",a),
[Description: Define setname function for pthread with three args])
;;
esac
#--------------------------------------------------------------------
# Check if we have spinlock support
#--------------------------------------------------------------------
AC_CHECK_FUNCS(pthread_spin_lock)
#--------------------------------------------------------------------
# Check whether we can get the system thread ID
#--------------------------------------------------------------------
@ -2362,12 +2433,15 @@ if test $bfd_section_vma = 1; then
fi
if test $ismingw = yes ; then
AC_CHECK_HEADERS(dbghelp.h)
else
AC_CHECK_HEADERS(execinfo.h)
AC_CHECK_FUNCS(backtrace)
fi
case "$target_os" in
mingw*)
AC_CHECK_HEADERS(dbghelp.h)
;;
*)
AC_CHECK_HEADERS(execinfo.h)
AC_CHECK_FUNCS(backtrace)
;;
esac
AC_CHECK_FUNCS(__builtin_extract_return_address)
@ -2815,7 +2889,7 @@ elif test "$enable_pass_arguments" = "no"; then
fi
fi
case "$target_os" in
mingw*|windows*) enable_fake_main=no; GS_FAKE_MAIN=0;;
mingw*|windows) enable_fake_main=no; GS_FAKE_MAIN=0;;
esac
AC_SUBST(GS_FAKE_MAIN)
AC_MSG_RESULT($enable_fake_main)