ObjFW  Check-in [95b1b31aa5]

Overview
Comment:Fall back to of_tlskey if __thread is unavailable.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 95b1b31aa5c375e66d7461806b216ea471c8fe8690662b992b5985665a139574
User & Date: js on 2012-07-14 22:21:24
Other Links: manifest | tags
Context
2012-07-15
00:38
Fix missing initialization of size. check-in: 335ba77462 user: js tags: trunk
2012-07-14
22:21
Fall back to of_tlskey if __thread is unavailable. check-in: 95b1b31aa5 user: js tags: trunk
21:02
Fix forgotten __thread. check-in: eade7d765c user: js tags: trunk
Changes

Modified configure.ac from [b1e49e08ab] to [525f5e59fb].

446
447
448
449
450
451
452

















453
454
455
456
457
458
459
	esac

	AC_DEFINE(OF_THREADS, 1, [Whether we have threads])
	AC_SUBST(OFTHREAD_M, "OFThread.m")
	AC_SUBST(OFTHREADTESTS_M, "OFThreadTests.m")
	AC_SUBST(OFHTTPREQUESTTESTS_M, "OFHTTPRequestTests.m")
	AC_SUBST(THREADING_H, "threading.h")


















	atomic_ops="none"

	AC_MSG_CHECKING(whether we have an atomic ops assembly implementation)
	AC_EGREP_CPP(yes, [
		#if defined(__GNUC__) && (defined(__i386__) || \
		    defined(__amd64__) || defined(__x86_64__))







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
	esac

	AC_DEFINE(OF_THREADS, 1, [Whether we have threads])
	AC_SUBST(OFTHREAD_M, "OFThread.m")
	AC_SUBST(OFTHREADTESTS_M, "OFThreadTests.m")
	AC_SUBST(OFHTTPREQUESTTESTS_M, "OFHTTPRequestTests.m")
	AC_SUBST(THREADING_H, "threading.h")

	AC_MSG_CHECKING(whether __thread works)
	AC_TRY_LINK([
		/* It seems __thread is buggy with GCC 4.1 */
		#if __GNUC__ == 4 && __GNUC_MINOR__ < 2
		# error buggy
		#endif

		__thread int x = 0;
	], [
		x++;
	], [
		AC_MSG_RESULT(yes)
		AC_DEFINE(OF_COMPILER_TLS, 1, [Whether __thread works])
	], [
		AC_MSG_RESULT(no)
	])

	atomic_ops="none"

	AC_MSG_CHECKING(whether we have an atomic ops assembly implementation)
	AC_EGREP_CPP(yes, [
		#if defined(__GNUC__) && (defined(__i386__) || \
		    defined(__amd64__) || defined(__x86_64__))

Modified src/OFAutoreleasePool.m from [9b9e08d0f0] to [20bd5ed7f7].

13
14
15
16
17
18
19


20
21
22






23
24
25
26
27
28
29

30



31
32












33
34




35
36
37
38
39
40
41
42




43
44
45
46
47
48
49
50




51
52
53

54





55
56
57
58
59
60
61
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#include "config.h"

#include <stdlib.h>



#import "OFAutoreleasePool.h"
#import "OFArray.h"







#import "OFNotImplementedException.h"

extern id _objc_rootAutorelease(id);
extern void* objc_autoreleasePoolPush(void);
extern void objc_autoreleasePoolPop(void*);


static __thread void *first = NULL;




@implementation OFAutoreleasePool












+ (id)addObject: (id)object
{




	if (first == NULL)
		[[OFAutoreleasePool alloc] init];

	return _objc_rootAutorelease(object);
}

+ (void)_releaseAll
{




	objc_autoreleasePoolPop(first);
}

- init
{
	self = [super init];

	@try {




		pool = objc_autoreleasePoolPush();

		if (first == NULL)

			first = pool;






		_objc_rootAutorelease(self);
	} @catch (id e) {
		[self release];
		@throw e;
	}








>
>



>
>
>
>
>
>







>

>
>
>


>
>
>
>
>
>
>
>
>
>
>
>


>
>
>
>








>
>
>
>








>
>
>
>



>

>
>
>
>
>







13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#include "config.h"

#include <stdlib.h>

#include <assert.h>

#import "OFAutoreleasePool.h"
#import "OFArray.h"

#ifndef OF_COMPILER_TLS
# import "threading.h"

# import "OFInitializationFailedException.h"
#endif

#import "OFNotImplementedException.h"

extern id _objc_rootAutorelease(id);
extern void* objc_autoreleasePoolPush(void);
extern void objc_autoreleasePoolPop(void*);

#ifdef OF_COMPILER_TLS
static __thread void *first = NULL;
#else
static of_tlskey_t firstKey;
#endif

@implementation OFAutoreleasePool
#ifndef OF_COMPILER_TLS
+ (void)initialize
{
	if (self != [OFAutoreleasePool class])
		return;

	if (!of_tlskey_new(&firstKey))
		@throw [OFInitializationFailedException
		    exceptionWithClass: self];
}
#endif

+ (id)addObject: (id)object
{
#ifndef OF_COMPILER_TLS
	void *first = of_tlskey_get(firstKey);
#endif

	if (first == NULL)
		[[OFAutoreleasePool alloc] init];

	return _objc_rootAutorelease(object);
}

+ (void)_releaseAll
{
#ifndef OF_COMPILER_TLS
	void *first = of_tlskey_get(firstKey);
#endif

	objc_autoreleasePoolPop(first);
}

- init
{
	self = [super init];

	@try {
#ifndef OF_COMPILER_TLS
		void *first = of_tlskey_get(firstKey);
#endif

		pool = objc_autoreleasePoolPush();

		if (first == NULL)
#ifdef OF_COMPILER_TLS
			first = pool;
#else
			if (!of_tlskey_set(firstKey, pool))
				@throw [OFInitializationFailedException
				    exceptionWithClass: [self class]];
#endif

		_objc_rootAutorelease(self);
	} @catch (id e) {
		[self release];
		@throw e;
	}

87
88
89
90
91
92
93

94
95




96
97
98
99
100
101
102
- (void)dealloc
{
	if (ignoreRelease)
		return;

	ignoreRelease = YES;


	if (first == pool)
		first = NULL;





	objc_autoreleasePoolPop(pool);

	[super dealloc];
}

- retain







>


>
>
>
>







129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
- (void)dealloc
{
	if (ignoreRelease)
		return;

	ignoreRelease = YES;

#ifdef OF_COMPILER_TLS
	if (first == pool)
		first = NULL;
#else
	if (of_tlskey_get(firstKey) == pool)
		assert(of_tlskey_set(firstKey, NULL));
#endif

	objc_autoreleasePoolPop(pool);

	[super dealloc];
}

- retain

Modified src/objfw-defs.h.in from [1faf553899] to [35b1efd8d0].

1
2
3

4
5
6
7
8
9
10
#undef OF_APPLE_RUNTIME
#undef OF_ATOMIC_OPS
#undef OF_BIG_ENDIAN

#undef OF_FLOAT_BIG_ENDIAN
#undef OF_HAVE_ASPRINTF
#undef OF_HAVE_BLOCKS
#undef OF_HAVE_FAST_ENUMERATION
#undef OF_HAVE_GCC_ATOMIC_OPS
#undef OF_HAVE_OPTIONAL_PROTOCOLS
#undef OF_HAVE_OSATOMIC



>







1
2
3
4
5
6
7
8
9
10
11
#undef OF_APPLE_RUNTIME
#undef OF_ATOMIC_OPS
#undef OF_BIG_ENDIAN
#undef OF_COMPILER_TLS
#undef OF_FLOAT_BIG_ENDIAN
#undef OF_HAVE_ASPRINTF
#undef OF_HAVE_BLOCKS
#undef OF_HAVE_FAST_ENUMERATION
#undef OF_HAVE_GCC_ATOMIC_OPS
#undef OF_HAVE_OPTIONAL_PROTOCOLS
#undef OF_HAVE_OSATOMIC

Modified src/runtime/autorelease.m from [b91ab77a61] to [790a0b73c2].

20
21
22
23
24
25
26



27
28

29
30
31











32
33
34
35
36
37
38
39
40
41




42
43
44
45
46
47
48
49




50
51
52
53
54
55

56




57
58
59
60
61






62
63
64







65
66
67
68
69
70
71
72
73
74







75
76
77
78
79
80





81
82
83
#include <stdlib.h>

#import "runtime.h"
#import "runtime-private.h"

#import "OFObject.h"




#import "macros.h"


static __thread id *objects = NULL;
static __thread id *top = NULL;
static __thread size_t size = 0;












id
objc_autorelease(id object)
{
	return [object autorelease];
}

void*
objc_autoreleasePoolPush()
{




	ptrdiff_t offset = top - objects;

	return (void*)offset;
}

void
objc_autoreleasePoolPop(void *offset)
{




	id *pool = objects + (ptrdiff_t)offset;
	id *iter;

	for (iter = pool; iter < top; iter++)
		[*iter release];


	top = pool;




}

id
_objc_rootAutorelease(id object)
{






	if (objects == NULL) {
		if ((objects = malloc(of_pagesize)) == NULL)
			ERROR("Out of memory for autorelease pools!")








		top = objects;
	}

	if ((uintptr_t)top >= (uintptr_t)objects + size) {
		ptrdiff_t diff = top - objects;

		size += of_pagesize;
		if ((objects = realloc(objects, size)) == NULL)
			ERROR("Out of memory for autorelease pools!")








		top = objects + diff;
	}

	*top = object;
	top++;






	return object;
}







>
>
>


>



>
>
>
>
>
>
>
>
>
>
>










>
>
>
>








>
>
>
>






>

>
>
>
>





>
>
>
>
>
>



>
>
>
>
>
>
>










>
>
>
>
>
>
>






>
>
>
>
>



20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
#include <stdlib.h>

#import "runtime.h"
#import "runtime-private.h"

#import "OFObject.h"

#ifndef OF_COMPILER_TLS
# import "threading.h"
#endif
#import "macros.h"

#ifdef OF_COMPILER_TLS
static __thread id *objects = NULL;
static __thread id *top = NULL;
static __thread size_t size = 0;
#else
static of_tlskey_t objectsKey, topKey, sizeKey;

static void __attribute__((constructor))
init(void)
{
	if (!of_tlskey_new(&objectsKey) || !of_tlskey_new(&sizeKey) ||
	    !of_tlskey_new(&topKey))
		ERROR("Unable to create TLS key for autorelease pools!")
}
#endif

id
objc_autorelease(id object)
{
	return [object autorelease];
}

void*
objc_autoreleasePoolPush()
{
#ifndef OF_COMPILER_TLS
	id *top = of_tlskey_get(topKey);
	id *objects = of_tlskey_get(objectsKey);
#endif
	ptrdiff_t offset = top - objects;

	return (void*)offset;
}

void
objc_autoreleasePoolPop(void *offset)
{
#ifndef OF_COMPILER_TLS
	id *top = of_tlskey_get(topKey);
	id *objects = of_tlskey_get(objectsKey);
#endif
	id *pool = objects + (ptrdiff_t)offset;
	id *iter;

	for (iter = pool; iter < top; iter++)
		[*iter release];

#ifdef OF_COMPILER_TLS
	top = pool;
#else
	if (!of_tlskey_set(topKey, pool))
		ERROR("Failed to set TLS key!")
#endif
}

id
_objc_rootAutorelease(id object)
{
#ifndef OF_COMPILER_TLS
	id *top = of_tlskey_get(topKey);
	id *objects = of_tlskey_get(objectsKey);
	size_t size = (size_t)(uintptr_t)of_tlskey_get(sizeKey);
#endif

	if (objects == NULL) {
		if ((objects = malloc(of_pagesize)) == NULL)
			ERROR("Out of memory for autorelease pools!")

#ifndef OF_COMPILER_TLS
		if (!of_tlskey_set(objectsKey, objects))
			ERROR("Failed to set TLS key!")
		if (!of_tlskey_set(sizeKey, (void*)(uintptr_t)of_pagesize))
			ERROR("Failed to set TLS key!")
#endif

		top = objects;
	}

	if ((uintptr_t)top >= (uintptr_t)objects + size) {
		ptrdiff_t diff = top - objects;

		size += of_pagesize;
		if ((objects = realloc(objects, size)) == NULL)
			ERROR("Out of memory for autorelease pools!")

#ifndef OF_COMPILER_TLS
		if (!of_tlskey_set(objectsKey, objects))
			ERROR("Failed to set TLS key!")
		if (!of_tlskey_set(sizeKey, (void*)(uintptr_t)size))
			ERROR("Failed to set TLS key!")
#endif

		top = objects + diff;
	}

	*top = object;
	top++;

#ifndef OF_COMPILER_TLS
	if (!of_tlskey_set(topKey, objects))
		ERROR("Failed to set TLS key!")
#endif

	return object;
}