mirror of
https://github.com/gnustep/libs-base.git
synced 2025-05-30 16:30:41 +00:00
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:
parent
3b8bbb00ba
commit
abfe4e2a04
29 changed files with 1611 additions and 640 deletions
39
ChangeLog
39
ChangeLog
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -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
72
Source/GSAtomic.h
Normal 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_
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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_
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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];
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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];
|
||||
|
|
321
Source/NSLock.m
321
Source/NSLock.m
|
@ -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 */
|
||||
|
||||
|
|
|
@ -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];
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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, ¶m);
|
||||
param.sched_priority = pri;
|
||||
pthread_setschedparam(pthread_self(), policy, ¶m);
|
||||
res = pthread_getschedparam(pthread_self(), &policy, ¶m);
|
||||
if (res == 0) {
|
||||
param.sched_priority = pri;
|
||||
res = pthread_setschedparam(pthread_self(), policy, ¶m);
|
||||
}
|
||||
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, ¶m);
|
||||
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, ¶m);
|
||||
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)
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
112
Source/NSZone.m
112
Source/NSZone.m
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
604
configure
vendored
|
@ -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
|
||||
|
|
334
configure.ac
334
configure.ac
|
@ -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)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue