locking updates (fine grained locking rather than global lock)

This commit is contained in:
rfm 2024-05-30 10:40:52 +01:00
parent 430629b097
commit 241e2a47ca
24 changed files with 176 additions and 732 deletions

View file

@ -1,3 +1,33 @@
2024-04-30 Richard Frith-Macdonald <rfm@gnu.org>
* Headers/Foundation/NSObject.h:
* Headers/GNUstepBase/GSLock.h:
* Headers/GNUstepBase/NSLock+GNUstepBase.h:
* Source/Additions/GNUmakefile:
* Source/Additions/GSLock.m:
* Source/Additions/NSError+GNUstepBase.m:
* Source/Additions/NSLock+GNUstepBase.m:
* Source/Additions/NSObject+GNUstepBase.m:
* Source/Additions/Unicode.m:
* Source/DocMakefile:
* Source/GSLocale.m:
* Source/NSDistributedNotificationCenter.m:
* Source/NSFileManager.m:
* Source/NSHTTPCookieStorage.m:
* Source/NSKeyValueObserving.m:
* Source/NSLog.m:
* Source/NSObject.m:
* Source/NSPortNameServer.m:
* Source/NSTask.m:
* Source/NSThread.m:
* Source/NSURLCache.m:
* Source/NSURLCredentialStorage.m:
* Source/ObjectiveC2/properties.m:
Remove deprecated locking code. Use lightweight and more fine-grained
locking for simple cases protecting short regions. Retain a global
lock for more complex siutations where there is a significant chance of
deadlock.
2024-04-26 Richard Frith-Macdonald <rfm@gnu.org>
* ChangeLog: Update for new release

View file

@ -502,10 +502,6 @@ NSIncrementExtraRefCount(id anObject);
#if OS_API_VERSION(GS_API_NONE, GS_API_NONE)
/** DEPRECATED to be removed in next release.
*/
GS_EXPORT NSRecursiveLock *gnustep_global_lock;
@interface NSObject (NEXTSTEP)
- (id) error:(const char *)aString, ...;
/* - (const char *) name;

View file

@ -1,71 +0,0 @@
/** Some extra locking classes
Copyright (C) 2003 Free Software Foundation, Inc.
Written by: Richard Frith-Macdonald <rfm@gnu.org>
This file is part of the GNUstep Base Library.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free
Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02111 USA.
AutogsdocSource: Additions/GSLock.m
*/
#ifndef INCLUDED_GS_LOCK_H
#define INCLUDED_GS_LOCK_H
#ifndef NeXT_Foundation_LIBRARY
#import <Foundation/NSLock.h>
#else
#import <Foundation/Foundation.h>
#endif
#import "GNUstepBase/GSObjCRuntime.h"
#if defined(__cplusplus)
extern "C" {
#endif
@class NSNotification;
/** DEPRECATED ... to be removed in next release
*/
GS_EXPORT_CLASS
@interface GSLazyLock : NSLock
{
int locked;
}
- (void) _becomeThreaded: (NSNotification*)n;
@end
GS_EXPORT_CLASS
@interface GSLazyRecursiveLock : NSRecursiveLock
{
int counter;
}
- (void) _becomeThreaded: (NSNotification*)n;
@end
/** DEPRECATED ... to be removed in next release
*/
GS_EXPORT NSRecursiveLock *gnustep_global_lock;
#if defined(__cplusplus)
}
#endif
#endif /* INCLUDED_GS_LOCK_H */

View file

@ -1,126 +0,0 @@
/** Declaration of extension methods for base additions
Copyright (C) 2003-2010 Free Software Foundation, Inc.
Written by: Richard Frith-Macdonald <rfm@gnu.org>
and: Adam Fedor <fedor@gnu.org>
This file is part of the GNUstep Base Library.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free
Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02111 USA.
*/
#ifndef INCLUDED_NSLock_GNUstepBase_h
#define INCLUDED_NSLock_GNUstepBase_h
#import <GNUstepBase/GSVersionMacros.h>
#import <Foundation/NSLock.h>
#if defined(__cplusplus)
extern "C" {
#endif
#if OS_API_VERSION(GS_API_NONE,GS_API_LATEST)
/**
* Returns IDENT which will be initialized
* to an instance of a CLASSNAME in a thread safe manner.
* If IDENT has been previously initialized
* this macro merely returns IDENT.
* IDENT is considered uninitialized, if it contains nil.
* CLASSNAME must be either NSLock, NSRecursiveLock or one
* of their subclasses.
* See [NSLock(GNUstepBase)+newLockAt:] for details.
* This macro is intended for code that cannot insure
* that a lock can be initialized in thread safe manner otherwise.
* <example>
* NSLock *my_lock = nil;
*
* void function (void)
* {
* [GS_INITIALIZED_LOCK(my_lock, NSLock) lock];
* do_work ();
* [my_lock unlock];
* }
*
* </example>
*/
#define GS_INITIALIZED_LOCK(IDENT,CLASSNAME) \
(IDENT != nil ? (id)IDENT : (id)[CLASSNAME newLockAt: &IDENT])
@interface NSLock (GNUstepBase)
/**
* Initializes the id pointed to by location
* with a new instance of the receiver's class
* in a thread safe manner, unless
* it has been previously initialized.
* Returns the contents pointed to by location.
* The location is considered unintialized if it contains nil.
* <br/>
* This method is used in the GS_INITIALIZED_LOCK macro
* to initialize lock variables when it cannot be insured
* that they can be initialized in a thread safe environment.
* <example>
* NSLock *my_lock = nil;
*
* void function (void)
* {
* [GS_INITIALIZED_LOCK(my_lock, NSLock) lock];
* do_work ();
* [my_lock unlock];
* }
*
* </example>
*/
+ (id) newLockAt: (id *)location;
@end
@interface NSRecursiveLock (GNUstepBase)
/**
* Initializes the id pointed to by location
* with a new instance of the receiver's class
* in a thread safe manner, unless
* it has been previously initialized.
* Returns the contents pointed to by location.
* The location is considered unintialized if it contains nil.
* <br/>
* This method is used in the GS_INITIALIZED_LOCK macro
* to initialize lock variables when it cannot be insured
* that they can be initialized in a thread safe environment.
* <example>
* NSLock *my_lock = nil;
*
* void function (void)
* {
* [GS_INITIALIZED_LOCK(my_lock, NSLock) lock];
* do_work ();
* [my_lock unlock];
* }
*
* </example>
*/
+ (id) newLockAt: (id *)location;
@end
#endif /* OS_API_VERSION */
#if defined(__cplusplus)
}
#endif
#endif /* INCLUDED_NSLock_GNUstepBase_h */

View file

@ -39,7 +39,6 @@ Additions_OBJC_FILES =\
GCObject.m \
GCArray.m \
GCDictionary.m \
GSLock.m \
GSMime.m \
GSXML.m \
GSFunctions.m \
@ -53,7 +52,6 @@ Additions_OBJC_FILES =\
NSError+GNUstepBase.m \
NSHashTable+GNUstepBase.m \
NSFileHandle+GNUstepBase.m \
NSLock+GNUstepBase.m \
NSMutableString+GNUstepBase.m \
NSNumber+GNUstepBase.m \
NSObject+GNUstepBase.m \

View file

@ -1,305 +0,0 @@
/** Implementation for GSLock
Copyright (C) 2003 Free Software Foundation, Inc.
Written by: Richard Frith-Macdonald <rfm@gnu.org>
Date: October 2003
This file is part of the GNUstep Base Library.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free
Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02111 USA.
*/
#import "common.h"
#define EXPOSE_GSLock_IVARS 1
#import "Foundation/NSException.h"
#import "Foundation/NSLock.h"
#import "Foundation/NSNotification.h"
#import "Foundation/NSThread.h"
#import "GNUstepBase/GSLock.h"
/**
* This implements a class which, when used in single-threaded mode,
* acts like a lock while avoiding the overheads of actually using
* a real lock. However, when the programm in which the class is
* used becomes multi-threaded, all instances of this class transform
* themselves into real locks in the correct state (locked/unlocked)
* corresponding to whether the lazy lock was locked or not at the
* point where the program became multi threadeed.<br />
* Use of this class allows you to write thread-safe code which avoids
* locking inefficiencies when used in a single threaded application,
* without having to worry about dealing with the issue yourself.
*/
@implementation GSLazyLock
/**
* Do not use this method ... it is used internally to handle the transition
* from a single threaded system to a multi threaded one.
*/
- (void) _becomeThreaded: (NSNotification*)n
{
[[NSNotificationCenter defaultCenter] removeObserver: self];
object_setClass(self, [NSLock class]);
if (locked == YES)
{
if ([self tryLock] == NO)
{
[NSException raise: NSInternalInconsistencyException
format: @"Failed to lock mutex"];
}
}
/*
* While we have changed 'isa', it's possible someone might have
* cached our old method implementations, so we set the 'locked'
* ivar to a value to tell the old method implementations to use
* the superclass implementatins.
*/
locked = -1;
}
- (void) dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver: self];
[super dealloc];
}
- (id) init
{
self = [super init];
if ([NSThread isMultiThreaded] == YES)
{
DESTROY(self);
return (GSLazyLock*)[NSLock new];
}
else if (self != nil)
{
locked = NO;
[[NSNotificationCenter defaultCenter]
addObserver: self
selector: @selector(_becomeThreaded:)
name: NSWillBecomeMultiThreadedNotification
object: nil];
}
return self;
}
- (void) lock
{
if (locked == NO)
{
locked = YES;
}
else if (locked == YES)
{
[NSException raise: NSGenericException
format: @"lock: when already locked"];
}
else
{
[super lock];
}
}
- (BOOL) lockBeforeDate: (NSDate*)limit
{
BOOL result;
if (locked == NO)
{
result = YES;
}
else if (locked == YES)
{
result = NO;
[NSException raise: NSGenericException
format: @"lock: when already locked"];
}
else
{
result = [super lockBeforeDate: limit];
}
return result;
}
- (BOOL) tryLock
{
if (locked == NO)
{
locked = YES;
return YES;
}
else if (locked == YES)
{
return NO;
}
else
{
return [super tryLock];
}
}
- (void) unlock
{
if (locked == YES)
{
locked = NO;
}
else if (locked == NO)
{
[NSException raise: NSGenericException
format: @"unlock: when already unlocked"];
}
else
{
[super unlock];
}
}
@end
/**
* This implements a class which, when used in single-threaded mode,
* acts like a recursive lock while avoiding the overheads of using
* a real lock. However, when the programm in which the class is
* used becomes multi-threaded, all instances of this class transform
* themselves into real locks in the correct state (locked/unlocked)
* corresponding to whether the lazy recursive lock was locked or not
* at the point where the program became multi threadeed.<br />
* Use of this class allows you to write thread-safe code which avoids
* locking inefficiencies when used in a single threaded application,
* without having to worry about dealing with the issue yourself.
*/
@implementation GSLazyRecursiveLock
/**
* Do not use this method ... it is used internally to handle the transition
* from a single threaded system to a multi threaded one.
*/
- (void) _becomeThreaded: (NSNotification*)n
{
[[NSNotificationCenter defaultCenter] removeObserver: self];
object_setClass(self, [NSRecursiveLock class]);
while (counter-- > 0)
{
if ([self tryLock] == NO)
{
[NSException raise: NSInternalInconsistencyException
format: @"Failed to lock mutex"];
}
}
/*
* While we have changed 'isa', it's possible someone might have
* cached our old method implementations, so we set the 'locked'
* ivar to a value to tell the old method implementations to use
* the superclass implementatins.
*/
counter = -1;
}
- (void) dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver: self];
[super dealloc];
}
- (id) init
{
self = [super init];
if ([NSThread isMultiThreaded] == YES)
{
DESTROY(self);
return (GSLazyRecursiveLock*)[NSRecursiveLock new];
}
else
{
if (self != nil)
{
[[NSNotificationCenter defaultCenter]
addObserver: self
selector: @selector(_becomeThreaded:)
name: NSWillBecomeMultiThreadedNotification
object: nil];
}
}
return self;
}
- (void) lock
{
if (counter >= 0)
{
counter++;
}
else
{
[super lock];
}
}
- (BOOL) lockBeforeDate: (NSDate*)limit
{
if (counter >= 0)
{
counter++;
return YES;
}
else
{
return [super lockBeforeDate: limit];
}
}
- (BOOL) tryLock
{
if (counter >= 0)
{
counter++;
return YES;
}
else
{
return [super tryLock];
}
}
- (void) unlock
{
if (counter > 0)
{
counter--;
}
else if (counter == 0)
{
[NSException raise: NSGenericException
format: @"unlock: failed to unlock mutex"];
}
else
{
[super unlock];
}
}
@end
/* Global lock to be used by classes when operating on any global
data that invoke other methods which also access global; thus,
creating the potential for deadlock. */
NSRecursiveLock *gnustep_global_lock = nil;

View file

@ -48,7 +48,7 @@ strerror_r(int eno, char *buf, int len)
const char *ptr;
int result;
[gnustep_global_lock lock];
[GSPrivateGlobalLock() lock];
ptr = strerror(eno);
if (ptr == 0)
{
@ -61,7 +61,7 @@ strerror_r(int eno, char *buf, int len)
result = 0;
}
buf[len - 1] = '\0';
[gnustep_global_lock unlock];
[GSPrivateGlobalLock() unlock];
return result;
}
#else

View file

@ -1,100 +0,0 @@
/* Implementation of extension methods to base additions
Copyright (C) 2010 Free Software Foundation, Inc.
Written by: Richard Frith-Macdonald <rfm@gnu.org>
This file is part of the GNUstep Base Library.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free
Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02111 USA.
*/
#import "common.h"
#import "Foundation/NSException.h"
#import "GNUstepBase/NSLock+GNUstepBase.h"
#import "GNUstepBase/GSLock.h"
/**
* GNUstep specific (non-standard) additions to the NSLock class.
*/
static GSLazyRecursiveLock *local_lock = nil;
/* This class only exists to provide a thread safe mechanism to
initialize local_lock as +initialize is called under a lock in ObjC
runtimes. User code should resort to GS_INITIALIZED_LOCK(), which
uses the +newLockAt: extension. */
@interface _GSLockInitializer : NSObject
@end
@implementation _GSLockInitializer
+ (void) initialize
{
if (local_lock == nil)
{
/* As we do not know whether creating custom locks may
implicitly create other locks, we use a recursive lock. */
local_lock = [GSLazyRecursiveLock new];
}
}
@end
static inline id
newLockAt(Class self, SEL _cmd, id *location)
{
if (location == 0)
{
[NSException raise: NSInvalidArgumentException
format: @"'%@' called with nil location",
NSStringFromSelector(_cmd)];
}
if (*location == nil)
{
if (local_lock == nil)
{
[_GSLockInitializer class];
}
[local_lock lock];
if (*location == nil)
{
*location = [[(id)self alloc] init];
}
[local_lock unlock];
}
return *location;
}
@implementation NSLock (GNUstepBase)
+ (id) newLockAt: (id *)location
{
return newLockAt(self, _cmd, location);
}
@end
@implementation NSRecursiveLock (GNUstepBase)
+ (id) newLockAt: (id *)location
{
return newLockAt(self, _cmd, location);
}
@end

View file

@ -23,6 +23,7 @@
*/
#import "common.h"
#import "GSPThread.h"
#import "Foundation/NSArray.h"
#import "Foundation/NSException.h"
#import "Foundation/NSHashTable.h"
@ -162,12 +163,14 @@ static inline void setup()
{
if (nil == exitLock)
{
[gnustep_global_lock lock];
static gs_mutex_t setupLock = GS_MUTEX_INIT_STATIC;
GS_MUTEX_LOCK(setupLock);
if (nil == exitLock)
{
exitLock = [NSLock new];
}
[gnustep_global_lock unlock];
GS_MUTEX_UNLOCK(setupLock);
}
}

View file

@ -3100,7 +3100,7 @@ GSPrivateNativeCStringEncoding()
char *old;
/* Take it from the system locale information. */
[gnustep_global_lock lock];
[GSPrivateGlobalLock() lock];
/* Initialise locale system by setting current locale from
* environment and then resetting it. Must be done before
* any call to nl_langinfo()
@ -3111,7 +3111,7 @@ GSPrivateNativeCStringEncoding()
}
strncpy(encbuf, nl_langinfo(CODESET), sizeof(encbuf)-1);
encbuf[sizeof(encbuf)-1] = '\0';
[gnustep_global_lock unlock];
[GSPrivateGlobalLock() unlock];
#else
encbuf[0] = '\0';
#endif

View file

@ -215,7 +215,6 @@ GSUnion.h \
GSIArray.h \
GSIMap.h \
GSLocale.h \
GSLock.h \
GSFunctions.h \
GSMime.h \
GSTLS.h \
@ -227,7 +226,6 @@ NSCalendarDate+GNUstepBase.h \
NSData+GNUstepBase.h \
NSDebug+GNUstepBase.h \
NSFileHandle+GNUstepBase.h \
NSLock+GNUstepBase.h \
NSMutableString+GNUstepBase.h \
NSNumber+GNUstepBase.h \
NSObject+GNUstepBase.h \

View file

@ -23,6 +23,7 @@
Boston, MA 02110 USA.
*/
#import "common.h"
#import "GSPrivate.h"
#import "GNUstepBase/GSLocale.h"
#import "Foundation/NSDictionary.h"
#import "Foundation/NSArray.h"
@ -109,7 +110,7 @@ GSDomainFromDefaultLocale(void)
/* Protect locale access with locks to prevent multiple threads using
* it and interfering with the buffer.
*/
[gnustep_global_lock lock];
[GSPrivateGlobalLock() lock];
/**
* Set the current locale to the system default, and backup
@ -231,7 +232,7 @@ GSDomainFromDefaultLocale(void)
*/
privateSetLocale(LC_ALL, backupLocale);
[gnustep_global_lock unlock];
[GSPrivateGlobalLock() unlock];
return saved;
}
@ -329,14 +330,14 @@ NSString *GSDefaultLanguageLocale()
#ifdef LC_MESSAGES
NSString *backup;
[gnustep_global_lock lock];
[GSPrivateGlobalLock() lock];
backup = privateSetLocale(LC_ALL, nil);
privateSetLocale(LC_ALL, @"");
locale = privateSetLocale(LC_MESSAGES, nil);
privateSetLocale(LC_ALL, backup);
[gnustep_global_lock unlock];
[GSPrivateGlobalLock() unlock];
#endif
#endif

View file

@ -26,6 +26,7 @@
*/
#import "common.h"
#define EXPOSE_NSDistributedNotificationCenter_IVARS 1
#import "Foundation/NSConnection.h"
#import "Foundation/NSDistantObject.h"
@ -44,6 +45,7 @@
#import "Foundation/NSPortNameServer.h"
#import "Foundation/NSThread.h"
#import "../Tools/gdnc.h"
#import "GSPThread.h"
@interface NSDistributedNotificationCenter (Private)
@ -103,6 +105,8 @@
static NSDistributedNotificationCenter *locCenter = nil;
static NSDistributedNotificationCenter *pubCenter = nil;
static NSDistributedNotificationCenter *netCenter = nil;
static gs_mutex_t classLock = GS_MUTEX_INIT_STATIC;
+ (id) allocWithZone: (NSZone*)z
{
@ -140,28 +144,28 @@ static NSDistributedNotificationCenter *netCenter = nil;
{
if (locCenter == nil)
{
[gnustep_global_lock lock];
if (locCenter == nil)
{
NS_DURING
{
NSDistributedNotificationCenter *tmp;
GS_MUTEX_LOCK(classLock);
if (locCenter == nil)
{
NS_DURING
{
NSDistributedNotificationCenter *tmp;
tmp = (NSDistributedNotificationCenter*)
NSAllocateObject(self, 0, NSDefaultMallocZone());
tmp->_centerLock = [NSRecursiveLock new];
tmp->_type = RETAIN(NSLocalNotificationCenterType);
locCenter = [NSObject leak: tmp];
[tmp release];
}
NS_HANDLER
{
[gnustep_global_lock unlock];
[localException raise];
}
NS_ENDHANDLER
}
[gnustep_global_lock unlock];
tmp = (NSDistributedNotificationCenter*)
NSAllocateObject(self, 0, NSDefaultMallocZone());
tmp->_centerLock = [NSRecursiveLock new];
tmp->_type = RETAIN(NSLocalNotificationCenterType);
locCenter = [NSObject leak: tmp];
[tmp release];
}
NS_HANDLER
{
GS_MUTEX_UNLOCK(classLock);
[localException raise];
}
NS_ENDHANDLER
}
GS_MUTEX_UNLOCK(classLock);
}
return locCenter;
}
@ -169,28 +173,28 @@ static NSDistributedNotificationCenter *netCenter = nil;
{
if (pubCenter == nil)
{
[gnustep_global_lock lock];
if (pubCenter == nil)
{
NS_DURING
{
NSDistributedNotificationCenter *tmp;
GS_MUTEX_LOCK(classLock);
if (pubCenter == nil)
{
NS_DURING
{
NSDistributedNotificationCenter *tmp;
tmp = (NSDistributedNotificationCenter*)
NSAllocateObject(self, 0, NSDefaultMallocZone());
tmp->_centerLock = [NSRecursiveLock new];
tmp->_type = RETAIN(GSPublicNotificationCenterType);
pubCenter = [NSObject leak: tmp];
[tmp release];
}
NS_HANDLER
{
[gnustep_global_lock unlock];
[localException raise];
}
NS_ENDHANDLER
}
[gnustep_global_lock unlock];
tmp = (NSDistributedNotificationCenter*)
NSAllocateObject(self, 0, NSDefaultMallocZone());
tmp->_centerLock = [NSRecursiveLock new];
tmp->_type = RETAIN(GSPublicNotificationCenterType);
pubCenter = [NSObject leak: tmp];
[tmp release];
}
NS_HANDLER
{
GS_MUTEX_UNLOCK(classLock);
[localException raise];
}
NS_ENDHANDLER
}
GS_MUTEX_UNLOCK(classLock);
}
return pubCenter;
}
@ -198,28 +202,28 @@ static NSDistributedNotificationCenter *netCenter = nil;
{
if (netCenter == nil)
{
[gnustep_global_lock lock];
if (netCenter == nil)
{
NS_DURING
{
NSDistributedNotificationCenter *tmp;
GS_MUTEX_LOCK(classLock);
if (netCenter == nil)
{
NS_DURING
{
NSDistributedNotificationCenter *tmp;
tmp = (NSDistributedNotificationCenter*)
NSAllocateObject(self, 0, NSDefaultMallocZone());
tmp->_centerLock = [NSRecursiveLock new];
tmp->_type = RETAIN(GSNetworkNotificationCenterType);
netCenter = [NSObject leak: tmp];
[tmp release];
}
NS_HANDLER
{
[gnustep_global_lock unlock];
[localException raise];
}
NS_ENDHANDLER
}
[gnustep_global_lock unlock];
tmp = (NSDistributedNotificationCenter*)
NSAllocateObject(self, 0, NSDefaultMallocZone());
tmp->_centerLock = [NSRecursiveLock new];
tmp->_type = RETAIN(GSNetworkNotificationCenterType);
netCenter = [NSObject leak: tmp];
[tmp release];
}
NS_HANDLER
{
GS_MUTEX_UNLOCK(classLock);
[localException raise];
}
NS_ENDHANDLER
}
GS_MUTEX_UNLOCK(classLock);
}
return netCenter;
}

View file

@ -348,8 +348,9 @@ exitedThread(void *lastErrorPtr)
// Getting the default manager
static NSFileManager* defaultManager = nil;
static NSFileManager *defaultManager = nil;
static NSStringEncoding defaultEncoding;
static gs_mutex_t classLock = GS_MUTEX_INIT_STATIC;
+ (NSFileManager*) defaultManager
{
@ -357,17 +358,17 @@ static NSStringEncoding defaultEncoding;
{
NS_DURING
{
[gnustep_global_lock lock];
GS_MUTEX_LOCK(classLock);
if (defaultManager == nil)
{
defaultManager = [[self alloc] init];
}
[gnustep_global_lock unlock];
GS_MUTEX_UNLOCK(classLock);
}
NS_HANDLER
{
// unlock then re-raise the exception
[gnustep_global_lock unlock];
GS_MUTEX_UNLOCK(classLock);
[localException raise];
}
NS_ENDHANDLER
@ -489,14 +490,14 @@ static NSStringEncoding defaultEncoding;
#if defined(HAVE_GETPWNAM)
struct passwd *pw;
[gnustep_global_lock lock];
GS_MUTEX_LOCK(classLock);
pw = getpwnam([str cStringUsingEncoding: defaultEncoding]);
if (pw != 0)
{
ok = (chown(lpath, pw->pw_uid, -1) == 0);
(void)chown(lpath, -1, pw->pw_gid);
}
[gnustep_global_lock unlock];
GS_MUTEX_UNLOCK(classLock);
#endif
#endif
#endif
@ -553,14 +554,14 @@ static NSStringEncoding defaultEncoding;
#ifdef HAVE_GETGRNAM
struct group *gp;
[gnustep_global_lock lock];
GS_MUTEX_LOCK(classLock);
gp = getgrnam([str cStringUsingEncoding: defaultEncoding]);
if (gp)
{
if (chown(lpath, -1, gp->gr_gid) == 0)
ok = YES;
}
[gnustep_global_lock unlock];
GS_MUTEX_UNLOCK(classLock);
#endif
#endif
#endif
@ -3929,14 +3930,14 @@ static NSSet *fileKeys = nil;
#if defined(HAVE_GETGRGID)
struct group *gp;
[gnustep_global_lock lock];
GS_MUTEX_LOCK(classLock);
gp = getgrgid(statbuf.st_gid);
if (gp != 0)
{
group = [NSString stringWithCString: gp->gr_name
encoding: defaultEncoding];
}
[gnustep_global_lock unlock];
GS_MUTEX_UNLOCK(classLock);
#endif
#endif
#endif
@ -4096,14 +4097,14 @@ static NSSet *fileKeys = nil;
#if defined(HAVE_GETPWUID)
struct passwd *pw;
[gnustep_global_lock lock];
GS_MUTEX_LOCK(classLock);
pw = getpwuid(statbuf.st_uid);
if (pw != 0)
{
owner = [NSString stringWithCString: pw->pw_name
encoding: defaultEncoding];
}
[gnustep_global_lock unlock];
GS_MUTEX_UNLOCK(classLock);
#endif
#endif
#endif /* HAVE_PWD_H */

View file

@ -24,6 +24,7 @@
#import "common.h"
#define EXPOSE_NSHTTPCookieStorage_IVARS 1
#import "GSPThread.h"
#import "GSURLPrivate.h"
#import "Foundation/NSSet.h"
#import "Foundation/NSArray.h"
@ -50,6 +51,7 @@ typedef struct {
@implementation NSHTTPCookieStorage
static NSHTTPCookieStorage *storage = nil;
static gs_mutex_t classLock = GS_MUTEX_INIT_STATIC;
+ (id) allocWithZone: (NSZone*)z
{
@ -60,7 +62,7 @@ static NSHTTPCookieStorage *storage = nil;
{
if (storage == nil)
{
[gnustep_global_lock lock];
GS_MUTEX_LOCK(classLock);
if (storage == nil)
{
NSHTTPCookieStorage *o;
@ -72,7 +74,7 @@ static NSHTTPCookieStorage *storage = nil;
[o init];
storage = o;
}
[gnustep_global_lock unlock];
GS_MUTEX_UNLOCK(classLock);
}
return storage;
}

View file

@ -43,6 +43,7 @@
#import "GNUstepBase/Unicode.h"
#import "GNUstepBase/GSLock.h"
#import "GSInvocation.h"
#import "GSPThread.h"
#if defined(USE_LIBFFI)
#import "cifframe.h"
@ -78,9 +79,11 @@ static id null;
static inline void
setup()
{
static gs_mutex_t setupLock = GS_MUTEX_INIT_STATIC;
if (nil == kvoLock)
{
[gnustep_global_lock lock];
GS_MUTEX_LOCK(setupLock);
if (nil == kvoLock)
{
kvoLock = [NSRecursiveLock new];
@ -93,7 +96,7 @@ setup()
NSOwnedPointerMapValueCallBacks, 128);
baseClass = NSClassFromString(@"GSKVOBase");
}
[gnustep_global_lock unlock];
GS_MUTEX_UNLOCK(setupLock);
}
}
/*

View file

@ -26,6 +26,7 @@
*/
#import "common.h"
#import "GSPThread.h"
#import "Foundation/NSDate.h"
#import "Foundation/NSCalendarDate.h"
#import "Foundation/NSTimeZone.h"
@ -101,14 +102,16 @@ GSLogLock()
{
if (myLock == nil)
{
[gnustep_global_lock lock];
static gs_mutex_t setupLock = GS_MUTEX_INIT_STATIC;
GS_MUTEX_LOCK(setupLock);
if (myLock == nil)
{
myLock = [NSRecursiveLock new];
lockImp = [myLock methodForSelector: @selector(lock)];
unlockImp = [myLock methodForSelector: @selector(unlock)];
}
[gnustep_global_lock unlock];
GS_MUTEX_UNLOCK(setupLock);
}
return myLock;
}

View file

@ -636,7 +636,8 @@ static id objc_retain_fast_np_internal(id anObject)
#endif /* GSATOMICREAD */
if (YES == tooFar)
{
static NSHashTable *overrun = nil;
static NSHashTable *overrun = nil;
static gs_mutex_t countLock = GS_MUTEX_INIT_STATIC;
/* We store this instance in a hash table so that we will only raise
* an exception for it once (and can therefore expect to log the instance
@ -644,7 +645,7 @@ static id objc_retain_fast_np_internal(id anObject)
* NB. The hash table does not retain the object, so the code in the
* lock protected region below should be safe anyway.
*/
[gnustep_global_lock lock];
GS_MUTEX_LOCK(countLock);
if (nil == overrun)
{
overrun = NSCreateHashTable(NSNonRetainedObjectHashCallBacks, 0);
@ -657,7 +658,7 @@ static id objc_retain_fast_np_internal(id anObject)
{
tooFar = NO;
}
[gnustep_global_lock lock];
GS_MUTEX_UNLOCK(countLock);
if (YES == tooFar)
{
NSString *base;
@ -1042,13 +1043,6 @@ static id gs_weak_load(id obj)
}
#endif
/* Create the global lock.
* NB. Ths is one of the first things we do ... setting up a new lock
* must not call any other Objective-C classes and must not involve
* any use of the autorelease system.
*/
gnustep_global_lock = [GSUntracedRecursiveLock new];
/* Behavior debugging ... enable with environment variable if needed.
*/
GSObjCBehaviorDebug(GSPrivateEnvironmentFlag("GNUSTEP_BEHAVIOR_DEBUG",
@ -1073,11 +1067,6 @@ static id gs_weak_load(id obj)
*/
NSConstantStringClass = [NSString constantStringClass];
/* Now that the string class (and autorelease) is set up, we can set
* the name of the lock to a string value safely.
*/
[gnustep_global_lock setName: @"gnustep_global_lock"];
/* Determine zombie management flags and set up a map to store
* information about zombie objects.
*/

View file

@ -26,6 +26,7 @@
*/
#import "common.h"
#import "GSPThread.h"
#import "Foundation/NSException.h"
#import "Foundation/NSEnumerator.h"
#import "Foundation/NSPort.h"
@ -74,7 +75,9 @@
if (nameServer == nil)
{
[gnustep_global_lock lock];
static gs_mutex_t classLock = GS_MUTEX_INIT_STATIC;
GS_MUTEX_LOCK(classLock);
if (nameServer == nil)
{
NSUserDefaults *defs = [NSUserDefaults standardUserDefaults];
@ -91,7 +94,7 @@
}
nameServer = RETAIN(o);
}
[gnustep_global_lock unlock];
GS_MUTEX_UNLOCK(classLock);
}
return nameServer;
}

View file

@ -25,6 +25,7 @@
*/
#import "common.h"
#import "GSPThread.h"
#define EXPOSE_NSTask_IVARS 1
#import "Foundation/FoundationErrors.h"
#import "Foundation/NSAutoreleasePool.h"
@ -250,7 +251,9 @@ pty_slave(const char* name)
{
if (self == [NSTask class])
{
[gnustep_global_lock lock];
static gs_mutex_t classLock = GS_MUTEX_INIT_STATIC;
GS_MUTEX_LOCK(classLock);
if (tasksLock == nil)
{
tasksLock = [NSRecursiveLock new];
@ -281,7 +284,7 @@ pty_slave(const char* name)
NSObjectMapValueCallBacks, 0);
[[NSObject leakAt: &activeTasks] release];
}
[gnustep_global_lock unlock];
GS_MUTEX_UNLOCK(classLock);
#ifndef _WIN32
signal(SIGCHLD, handleSignal);

View file

@ -378,11 +378,12 @@ GSSleepUntilIntervalSinceReferenceDate(NSTimeInterval when)
static NSArray *
commonModes(void)
{
static gs_mutex_t modesLock = GS_MUTEX_INIT_STATIC;
static NSArray *modes = nil;
if (modes == nil)
{
[gnustep_global_lock lock];
GS_MUTEX_LOCK(modesLock);
if (modes == nil)
{
Class c = NSClassFromString(@"NSApplication");
@ -398,7 +399,7 @@ commonModes(void)
NSDefaultRunLoopMode, NSConnectionReplyMode, nil];
}
}
[gnustep_global_lock unlock];
GS_MUTEX_UNLOCK(modesLock);
}
return modes;
}
@ -2094,12 +2095,14 @@ GSRunLoopInfoForThread(NSThread *aThread)
}
if (aThread->_runLoopInfo == nil)
{
[gnustep_global_lock lock];
static gs_mutex_t infoLock = GS_MUTEX_INIT_STATIC;
GS_MUTEX_LOCK(infoLock);
if (aThread->_runLoopInfo == nil)
{
aThread->_runLoopInfo = [GSRunLoopThreadInfo new];
}
[gnustep_global_lock unlock];
GS_MUTEX_UNLOCK(infoLock);
}
info = aThread->_runLoopInfo;
return info;

View file

@ -24,6 +24,8 @@
#import "common.h"
#import "GSPThread.h"
#if GS_HAVE_NSURLSESSION
#import <Foundation/NSURLSession.h>
#endif
@ -46,6 +48,7 @@ typedef struct {
static NSURLCache *shared = nil;
static gs_mutex_t cacheLock = GS_MUTEX_INIT_STATIC;
@implementation NSURLCache
@ -62,9 +65,9 @@ static NSURLCache *shared = nil;
+ (void) setSharedURLCache: (NSURLCache *)cache
{
[gnustep_global_lock lock];
GS_MUTEX_LOCK(cacheLock);
ASSIGN(shared, cache);
[gnustep_global_lock unlock];
GS_MUTEX_UNLOCK(cacheLock);
}
- (void) dealloc
@ -82,7 +85,7 @@ static NSURLCache *shared = nil;
{
NSURLCache *c;
[gnustep_global_lock lock];
GS_MUTEX_LOCK(cacheLock);
if (shared == nil)
{
NSString *path = nil;
@ -95,7 +98,7 @@ static NSURLCache *shared = nil;
}
c = RETAIN(shared);
[gnustep_global_lock unlock];
GS_MUTEX_UNLOCK(cacheLock);
return AUTORELEASE(c);
}

View file

@ -23,6 +23,7 @@
*/
#import "common.h"
#import "GSPThread.h"
#define EXPOSE_NSURLCredentialStorage_IVARS 1
#import "GSURLPrivate.h"
@ -46,9 +47,11 @@ static NSURLCredentialStorage *storage = nil;
+ (NSURLCredentialStorage *) sharedCredentialStorage
{
static gs_mutex_t classLock = GS_MUTEX_INIT_STATIC;
if (storage == nil)
{
[gnustep_global_lock lock];
GS_MUTEX_LOCK(classLock);
if (storage == nil)
{
NSURLCredentialStorage *o;
@ -63,7 +66,7 @@ static NSURLCredentialStorage *storage = nil;
= [NSMutableDictionary new];
storage = o;
}
[gnustep_global_lock unlock];
GS_MUTEX_UNLOCK(classLock);
}
return storage;
}

View file

@ -8,6 +8,7 @@
*/
#import "Foundation/NSException.h"
#import "Foundation/NSLock.h"
#import "GSPThread.h"
static NSRecursiveLock *propertyLock = nil;
static inline NSRecursiveLock*
@ -15,12 +16,14 @@ pLock()
{
if (propertyLock == nil)
{
[gnustep_global_lock lock];
static gs_mutex_t setupLock = GS_MUTEX_INIT_STATIC;
GS_MUTEX_LOCK(setupLock);
if (propertyLock == nil)
{
propertyLock = [NSRecursiveLock new];
}
[gnustep_global_lock unlock];
GS_MUTEX_UNLOCK(setupLock);
}
return propertyLock;
}