ObjFW  Check-in [90637a4ecc]

Overview
Comment:Merge trunk into branch "amiga-library"
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | amiga-library
Files: files | file ages | folders
SHA3-256: 90637a4ecc80ba5aae4cf448a859321a3504c6b1e8fd10432640023dd04067b5
User & Date: js on 2020-12-20 21:36:30
Other Links: branch diff | manifest | tags
Context
2020-12-20
22:51
Make linklib compile for MorphOS check-in: 6dac4586ab user: js tags: amiga-library
21:36
Merge trunk into branch "amiga-library" check-in: 90637a4ecc user: js tags: amiga-library
21:29
runtime: Remove errno from Amiga library check-in: 8c90e88939 user: js tags: trunk
11:33
linklib: Show errors with requester check-in: da2d0e7c07 user: js tags: amiga-library
Changes

Modified configure.ac from [713816fa59] to [574361ab39].

769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818

819
820
821
822
823
824
825
826
827
828
829
830
831

832


833
834
835
836
837
838
839
769
770
771
772
773
774
775





























776
777
778
779
780
781
782
783
784
785
786
787


788
789
790
791
792
793
794
795
796
797
798
799
800
801
802

803
804
805
806
807
808
809
810
811







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-












-
-
+













+
-
+
+







AC_C_BIGENDIAN([
	AC_DEFINE(OF_BIG_ENDIAN, 1, [Whether we are big endian])
])
AS_IF([test x"$ac_cv_c_bigendian" = x"universal"], [
	AC_DEFINE(OF_UNIVERSAL, 1, [Whether we are building a universal binary])
])

AC_MSG_CHECKING(for SIZE_MAX)
AC_EGREP_CPP(egrep_cpp_yes, [
	#include <stdint.h>
	#include <limits.h>

	#ifdef SIZE_MAX
	egrep_cpp_yes
	#endif
], [
	AC_MSG_RESULT(yes)
], [
	AC_MSG_RESULT(no)
	AC_MSG_CHECKING(for SIZE_T_MAX)
	AC_EGREP_CPP(egrep_cpp_yes, [
		#include <stdint.h>
		#include <limits.h>

		#ifdef SIZE_T_MAX
		egrep_cpp_yes
		#endif
	], [
		AC_MSG_RESULT(yes)
		size_max="SIZE_T_MAX"
	], [
		AC_MSG_RESULT(no)
		size_max="(~(size_t)0)"
	])
	AC_DEFINE_UNQUOTED(SIZE_MAX, $size_max, [Maximum value for size_t])
])
AC_MSG_CHECKING(for SSIZE_MAX)
AC_EGREP_CPP(egrep_cpp_yes, [
	#include <stdint.h>
	#include <limits.h>

	#ifdef SSIZE_MAX
	egrep_cpp_yes
	#endif
], [
	AC_MSG_RESULT(yes)
], [
	AC_MSG_RESULT(no)
	AC_DEFINE(SSIZE_MAX, [((ssize_t)(SIZE_MAX / 2))],
		[Maximum value for ssize_t])
	AC_DEFINE(SSIZE_MAX, [(SIZE_MAX / 2)], [Maximum value for ssize_t])
])
AC_MSG_CHECKING(for UINTPTR_MAX)
AC_EGREP_CPP(egrep_cpp_yes, [
	#include <stdint.h>
	#include <limits.h>

	#ifdef UINTPTR_MAX
	egrep_cpp_yes
	#endif
], [
	AC_MSG_RESULT(yes)
], [
	AC_MSG_RESULT(no)
	AC_CHECK_SIZEOF(uintptr_t)
	AC_DEFINE(UINTPTR_MAX, [(~(uintptr_t)0)], [Maximum value for uintptr_t])
	AC_DEFINE(UINTPTR_MAX,
		[(SIZEOF_UINTPTR_T * CHAR_BIT)], [Maximum value for uintptr_t])
])

AC_CHECK_HEADER(inttypes.h,
	[AC_DEFINE(OF_HAVE_INTTYPES_H, 1, [Whether we have inttypes.h])])

AC_CHECK_HEADER(sys/types.h,
	[AC_DEFINE(OF_HAVE_SYS_TYPES_H, 1, [Whether we have sys/types.h])])
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
847
848
849
850
851
852
853































854
855
856
857
858
859
860







-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-







	fp_endianess="universal"
])
AC_MSG_RESULT($fp_endianess)
AS_IF([test x"$fp_endianess" = x"unknown"], [
	AC_MSG_ERROR(
		[Floating point implementation does not conform to IEEE 754!])])

AC_MSG_CHECKING(for INFINITY)
AC_COMPILE_IFELSE([
	AC_LANG_PROGRAM([
		#include <stdio.h>
		#include <math.h>
	], [
		printf("%f", INFINITY);
	])
], [
	AC_MSG_RESULT(yes)
], [
	AC_MSG_RESULT(no)

	AC_MSG_CHECKING(for __builtin_inf)
	AC_COMPILE_IFELSE([
		AC_LANG_PROGRAM([
			#include <stdio.h>
		], [
			printf("%f", __builtin_inf());
		])
	], [
		AC_MSG_RESULT(yes)
		AC_DEFINE(INFINITY, [(__builtin_inf())],
			[Workaround for missing INFINITY])
	], [
		AC_MSG_RESULT(no)

		AC_MSG_ERROR([Neither INFINITY or __builtin_inf was found!])
	])
])

case "$host_cpu" in
	arm* | earm*)
		AC_MSG_CHECKING(for VFP2 or above)
		AC_COMPILE_IFELSE([
			AC_LANG_PROGRAM([], [
				#if !defined(__arm64__) && \
				    !defined(__aarch64__) && \

Modified src/OFBlock.m from [d3c798f275] to [ada45ac629].

189
190
191
192
193
194
195
196

197
198

199
200
201
202
203
204
205
189
190
191
192
193
194
195

196
197

198
199
200
201
202
203
204
205







-
+

-
+








	if ([(id)block isMemberOfClass: (Class)&_NSConcreteMallocBlock]) {
#ifdef OF_HAVE_ATOMIC_OPS
		of_atomic_int_inc(&block->flags);
#else
		unsigned hash = SPINLOCK_HASH(block);

		OF_ENSURE(of_spinlock_lock(&blockSpinlocks[hash]));
		OF_ENSURE(of_spinlock_lock(&blockSpinlocks[hash]) == 0);
		block->flags++;
		OF_ENSURE(of_spinlock_unlock(&blockSpinlocks[hash]));
		OF_ENSURE(of_spinlock_unlock(&blockSpinlocks[hash]) == 0);
#endif
	}

	return block;
}

void
216
217
218
219
220
221
222
223

224
225

226
227
228
229
230
231
232
233
234

235
236
237
238
239
240
241
216
217
218
219
220
221
222

223
224

225
226
227
228
229
230
231
232
233

234
235
236
237
238
239
240
241







-
+

-
+








-
+







			block->descriptor->dispose_helper(block);

		free(block);
	}
#else
	unsigned hash = SPINLOCK_HASH(block);

	OF_ENSURE(of_spinlock_lock(&blockSpinlocks[hash]));
	OF_ENSURE(of_spinlock_lock(&blockSpinlocks[hash]) == 0);
	if ((--block->flags & OF_BLOCK_REFCOUNT_MASK) == 0) {
		OF_ENSURE(of_spinlock_unlock(&blockSpinlocks[hash]));
		OF_ENSURE(of_spinlock_unlock(&blockSpinlocks[hash]) == 0);

		if (block->flags & OF_BLOCK_HAS_COPY_DISPOSE)
			block->descriptor->dispose_helper(block);

		free(block);

		return;
	}
	OF_ENSURE(of_spinlock_unlock(&blockSpinlocks[hash]));
	OF_ENSURE(of_spinlock_unlock(&blockSpinlocks[hash]) == 0);
#endif
}

void
_Block_object_assign(void *dst_, const void *src_, const int flags_)
{
	int flags = flags_ & (OF_BLOCK_FIELD_IS_BLOCK |
281
282
283
284
285
286
287
288

289
290
291
292
293
294
295
296

297

298
299
300
301
302
303
304
305
306
307

308
309

310
311
312
313
314
315
316
281
282
283
284
285
286
287

288
289
290
291
292
293
294
295
296
297

298
299
300
301
302
303
304
305
306
307

308
309

310
311
312
313
314
315
316
317







-
+








+
-
+









-
+

-
+







				free(*dst);

				*dst = src->forwarding;
			}
#else
			unsigned hash = SPINLOCK_HASH(src);

			OF_ENSURE(of_spinlock_lock(&byrefSpinlocks[hash]));
			OF_ENSURE(of_spinlock_lock(&byrefSpinlocks[hash]) == 0);
			if (src->forwarding == src)
				src->forwarding = *dst;
			else {
				src->byref_dispose(*dst);
				free(*dst);

				*dst = src->forwarding;
			}
			OF_ENSURE(
			OF_ENSURE(of_spinlock_unlock(&byrefSpinlocks[hash]));
			    of_spinlock_unlock(&byrefSpinlocks[hash]) == 0);
#endif
		} else
			*dst = src;

#ifdef OF_HAVE_ATOMIC_OPS
		of_atomic_int_inc(&(*dst)->flags);
#else
		unsigned hash = SPINLOCK_HASH(*dst);

		OF_ENSURE(of_spinlock_lock(&byrefSpinlocks[hash]));
		OF_ENSURE(of_spinlock_lock(&byrefSpinlocks[hash]) == 0);
		(*dst)->flags++;
		OF_ENSURE(of_spinlock_unlock(&byrefSpinlocks[hash]));
		OF_ENSURE(of_spinlock_unlock(&byrefSpinlocks[hash]) == 0);
#endif
		break;
	}
}

void
_Block_object_dispose(const void *object_, const int flags_)
341
342
343
344
345
346
347
348

349

350

351
352
353
354
355
356
357

358
359
360
361
362
363
364
365
366
367
368
369


370
371
372
373
374
375
376
342
343
344
345
346
347
348

349
350
351

352
353
354
355
356
357
358

359
360
361
362
363
364
365
366
367
368
369


370
371
372
373
374
375
376
377
378







-
+

+
-
+






-
+










-
-
+
+







				object->byref_dispose(object);

			free(object);
		}
#else
		unsigned hash = SPINLOCK_HASH(object);

		OF_ENSURE(of_spinlock_lock(&byrefSpinlocks[hash]));
		OF_ENSURE(of_spinlock_lock(&byrefSpinlocks[hash]) == 0);
		if ((--object->flags & OF_BLOCK_REFCOUNT_MASK) == 0) {
			OF_ENSURE(
			OF_ENSURE(of_spinlock_unlock(&byrefSpinlocks[hash]));
			    of_spinlock_unlock(&byrefSpinlocks[hash]) == 0);

			if (object->flags & OF_BLOCK_HAS_COPY_DISPOSE)
				object->byref_dispose(object);

			free(object);
		}
		OF_ENSURE(of_spinlock_unlock(&byrefSpinlocks[hash]));
		OF_ENSURE(of_spinlock_unlock(&byrefSpinlocks[hash]) == 0);
#endif
		break;
	}
}

@implementation OFBlock
+ (void)load
{
#ifndef OF_HAVE_ATOMIC_OPS
	for (size_t i = 0; i < NUM_SPINLOCKS; i++)
		if (!of_spinlock_new(&blockSpinlocks[i]) ||
		    !of_spinlock_new(&byrefSpinlocks[i]))
		if (of_spinlock_new(&blockSpinlocks[i]) != 0 ||
		    of_spinlock_new(&byrefSpinlocks[i]) != 0)
			@throw [OFInitializationFailedException
			    exceptionWithClass: self];
#endif

#ifdef OF_APPLE_RUNTIME
	Class tmp;

Modified src/OFCondition.m from [24791db544] to [53f832df7b].

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
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







-
+













-
-
+
+
+
+











-
+
+
+


-
+





-
+
+
+
+


-
+





-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
-








-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
-







	return [[[self alloc] init] autorelease];
}

- (instancetype)init
{
	self = [super init];

	if (!of_condition_new(&_condition)) {
	if (of_condition_new(&_condition) != 0) {
		Class c = self.class;
		[self release];
		@throw [OFInitializationFailedException exceptionWithClass: c];
	}

	_conditionInitialized = true;

	return self;
}

- (void)dealloc
{
	if (_conditionInitialized) {
		if (!of_condition_free(&_condition)) {
			OF_ENSURE(errno == EBUSY);
		int error = of_condition_free(&_condition);

		if (error != 0) {
			OF_ENSURE(error == EBUSY);

			@throw [OFConditionStillWaitingException
			    exceptionWithCondition: self];
		}
	}

	[super dealloc];
}

- (void)wait
{
	if (!of_condition_wait(&_condition, &_mutex))
	int error = of_condition_wait(&_condition, &_mutex);

	if (error != 0)
		@throw [OFConditionWaitFailedException
		    exceptionWithCondition: self
				     errNo: errno];
				     errNo: error];
}

#ifdef OF_AMIGAOS
- (void)waitForConditionOrExecSignal: (ULONG *)signalMask
{
	if (!of_condition_wait_or_signal(&_condition, &_mutex, signalMask))
	int error = of_condition_wait_or_signal(&_condition, &_mutex,
	    signalMask);

	if (error != 0)
		@throw [OFConditionWaitFailedException
		    exceptionWithCondition: self
				     errNo: errno];
				     errNo: error];
}
#endif

- (bool)waitForTimeInterval: (of_time_interval_t)timeInterval
{
	if (!of_condition_timed_wait(&_condition, &_mutex, timeInterval)) {
		if (errno == ETIMEDOUT)
			return false;
		else
			@throw [OFConditionWaitFailedException
			    exceptionWithCondition: self
					     errNo: errno];
	int error = of_condition_timed_wait(&_condition, &_mutex, timeInterval);

	if (error == ETIMEDOUT)
		return false;

	if (error != 0)
		@throw [OFConditionWaitFailedException
		    exceptionWithCondition: self
				     errNo: error];
	}

	return true;
}

#ifdef OF_AMIGAOS
- (bool)waitForTimeInterval: (of_time_interval_t)timeInterval
	       orExecSignal: (ULONG *)signalMask
{
	if (!of_condition_timed_wait_or_signal(&_condition, &_mutex,
	    timeInterval, signalMask)) {
		if (errno == ETIMEDOUT)
			return false;
		else
			@throw [OFConditionWaitFailedException
			    exceptionWithCondition: self
					     errNo: errno];
	int error = of_condition_timed_wait_or_signal(&_condition, &_mutex,
	    timeInterval, signalMask);

	if (error == ETIMEDOUT)
		return false;

	if (error != 0)
		@throw [OFConditionWaitFailedException
		    exceptionWithCondition: self
				     errNo: error];
	}

	return true;
}
#endif

- (bool)waitUntilDate: (OFDate *)date
{
125
126
127
128
129
130
131
132



133
134
135

136
137
138
139
140



141
142
143

144
145
134
135
136
137
138
139
140

141
142
143
144
145

146
147
148
149
150

151
152
153
154
155

156
157
158







-
+
+
+


-
+




-
+
+
+


-
+


	return [self waitForTimeInterval: date.timeIntervalSinceNow
			    orExecSignal: signalMask];
}
#endif

- (void)signal
{
	if (!of_condition_signal(&_condition))
	int error = of_condition_signal(&_condition);

	if (error != 0)
		@throw [OFConditionSignalFailedException
		    exceptionWithCondition: self
				     errNo: errno];
				     errNo: error];
}

- (void)broadcast
{
	if (!of_condition_broadcast(&_condition))
	int error = of_condition_broadcast(&_condition);

	if (error != 0)
		@throw [OFConditionBroadcastFailedException
		    exceptionWithCondition: self
				     errNo: errno];
				     errNo: error];
}
@end

Modified src/OFFileURLHandler.m from [9e0a7e3741] to [529682cb40].

714
715
716
717
718
719
720




721
722

723
724
725
726
727
728
729
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734







+
+
+
+


+







	modificationTime -= locale->loc_GMTOffset * 60.0;
	CloseLocale(locale);

	date.ds_Days = modificationTime / 86400;
	date.ds_Minute = ((LONG)modificationTime % 86400) / 60;
	date.ds_Tick = fmod(modificationTime, 60) * TICKS_PER_SECOND;

# ifdef OF_AMIGAOS4
	if (!SetDate([path cStringWithEncoding: [OFLocale encoding]],
	    &date) != 0) {
# else
	if (!SetFileDate([path cStringWithEncoding: [OFLocale encoding]],
	    &date) != 0) {
# endif
		setErrno();

		@throw [OFSetItemAttributesFailedException
		    exceptionWithURL: URL
			  attributes: attributes
		     failedAttribute: attributeKey
			       errNo: errno];

Modified src/OFMutex.m from [2c5bdb0793] to [4c3fd1c33e].

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
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







-
+













-
-
+
+
+
+












-
+
+
+

-
+




-
-
+
+
+
+



-
+







-
+
+
+

-
+










	return [[[self alloc] init] autorelease];
}

- (instancetype)init
{
	self = [super init];

	if (!of_mutex_new(&_mutex)) {
	if (of_mutex_new(&_mutex) != 0) {
		Class c = self.class;
		[self release];
		@throw [OFInitializationFailedException exceptionWithClass: c];
	}

	_initialized = true;

	return self;
}

- (void)dealloc
{
	if (_initialized) {
		if (!of_mutex_free(&_mutex)) {
			OF_ENSURE(errno == EBUSY);
		int error = of_mutex_free(&_mutex);

		if (error != 0) {
			OF_ENSURE(error == EBUSY);

			@throw [OFStillLockedException exceptionWithLock: self];
		}
	}

	[_name release];

	[super dealloc];
}

- (void)lock
{
	if (!of_mutex_lock(&_mutex))
	int error = of_mutex_lock(&_mutex);

	if (error != 0)
		@throw [OFLockFailedException exceptionWithLock: self
							  errNo: errno];
							  errNo: error];
}

- (bool)tryLock
{
	if (!of_mutex_trylock(&_mutex)) {
		if (errno == EBUSY)
	int error = of_mutex_trylock(&_mutex);

	if (error != 0) {
		if (error == EBUSY)
			return false;
		else
			@throw [OFLockFailedException exceptionWithLock: self
								  errNo: errno];
								  errNo: error];
	}

	return true;
}

- (void)unlock
{
	if (!of_mutex_unlock(&_mutex))
	int error = of_mutex_unlock(&_mutex);

	if (error != 0)
		@throw [OFUnlockFailedException exceptionWithLock: self
							    errNo: errno];
							    errNo: error];
}

- (OFString *)description
{
	if (_name == nil)
		return super.description;

	return [OFString stringWithFormat: @"<%@: %@>", self.className, _name];
}
@end

Modified src/OFObject.m from [7354b5ddd4] to [779114b0ef].

319
320
321
322
323
324
325
326
327


328
329
330
331
332
333
334
319
320
321
322
323
324
325


326
327
328
329
330
331
332
333
334







-
-
+
+







		allocFailedException.isa = [OFAllocFailedException class];
		@throw (id)&allocFailedException;
	}

	((struct pre_ivar *)instance)->retainCount = 1;

#if !defined(OF_HAVE_ATOMIC_OPS) && !defined(OF_AMIGAOS)
	if OF_UNLIKELY (!of_spinlock_new(
	    &((struct pre_ivar *)instance)->retainCountSpinlock)) {
	if OF_UNLIKELY (of_spinlock_new(
	    &((struct pre_ivar *)instance)->retainCountSpinlock) != 0) {
		free(instance);
		@throw [OFInitializationFailedException
		    exceptionWithClass: class];
	}
#endif

	instance = (OFObject *)(void *)((char *)instance + PRE_IVARS_ALIGN);
1129
1130
1131
1132
1133
1134
1135
1136

1137
1138

1139
1140
1141
1142
1143
1144
1145
1129
1130
1131
1132
1133
1134
1135

1136
1137

1138
1139
1140
1141
1142
1143
1144
1145







-
+

-
+







	Forbid();
# endif
	PRE_IVARS->retainCount++;
# ifndef OF_AMIGAOS_M68K
	Permit();
# endif
#else
	OF_ENSURE(of_spinlock_lock(&PRE_IVARS->retainCountSpinlock));
	OF_ENSURE(of_spinlock_lock(&PRE_IVARS->retainCountSpinlock) == 0);
	PRE_IVARS->retainCount++;
	OF_ENSURE(of_spinlock_unlock(&PRE_IVARS->retainCountSpinlock));
	OF_ENSURE(of_spinlock_unlock(&PRE_IVARS->retainCountSpinlock) == 0);
#endif

	return self;
}

- (unsigned int)retainCount
{
1165
1166
1167
1168
1169
1170
1171
1172

1173
1174

1175
1176
1177
1178
1179
1180
1181
1165
1166
1167
1168
1169
1170
1171

1172
1173

1174
1175
1176
1177
1178
1179
1180
1181







-
+

-
+







	Permit();

	if (retainCount == 0)
		[self dealloc];
#else
	int retainCount;

	OF_ENSURE(of_spinlock_lock(&PRE_IVARS->retainCountSpinlock));
	OF_ENSURE(of_spinlock_lock(&PRE_IVARS->retainCountSpinlock) == 0);
	retainCount = --PRE_IVARS->retainCount;
	OF_ENSURE(of_spinlock_unlock(&PRE_IVARS->retainCountSpinlock));
	OF_ENSURE(of_spinlock_unlock(&PRE_IVARS->retainCountSpinlock) == 0);

	if (retainCount == 0)
		[self dealloc];
#endif
}

- (instancetype)autorelease

Modified src/OFRecursiveMutex.m from [3739c89b37] to [e5da5416e7].

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
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







-
+













-
-
+
+
+
+












-
+
+
+

-
+




-
-
+
+
+
+



-
+







-
+
+
+

-
+










	return [[[self alloc] init] autorelease];
}

- (instancetype)init
{
	self = [super init];

	if (!of_rmutex_new(&_rmutex)) {
	if (of_rmutex_new(&_rmutex) != 0) {
		Class c = self.class;
		[self release];
		@throw [OFInitializationFailedException exceptionWithClass: c];
	}

	_initialized = true;

	return self;
}

- (void)dealloc
{
	if (_initialized) {
		if (!of_rmutex_free(&_rmutex)) {
			OF_ENSURE(errno == EBUSY);
		int error = of_rmutex_free(&_rmutex);

		if (error != 0) {
			OF_ENSURE(error == EBUSY);

			@throw [OFStillLockedException exceptionWithLock: self];
		}
	}

	[_name release];

	[super dealloc];
}

- (void)lock
{
	if (!of_rmutex_lock(&_rmutex))
	int error = of_rmutex_lock(&_rmutex);

	if (error != 0)
		@throw [OFLockFailedException exceptionWithLock: self
							  errNo: errno];
							  errNo: error];
}

- (bool)tryLock
{
	if (!of_rmutex_trylock(&_rmutex)) {
		if (errno == EBUSY)
	int error = of_rmutex_trylock(&_rmutex);

	if (error != 0) {
		if (error == EBUSY)
			return false;
		else
			@throw [OFLockFailedException exceptionWithLock: self
								  errNo: errno];
								  errNo: error];
	}

	return true;
}

- (void)unlock
{
	if (!of_rmutex_unlock(&_rmutex))
	int error = of_rmutex_unlock(&_rmutex);

	if (error != 0)
		@throw [OFUnlockFailedException exceptionWithLock: self
							    errNo: errno];
							    errNo: error];
}

- (OFString *)description
{
	if (_name == nil)
		return super.description;

	return [OFString stringWithFormat: @"<%@: %@>", self.className, _name];
}
@end

Modified src/OFSecureData.m from [7de8ab3a25] to [a977d1a98b].

119
120
121
122
123
124
125
126

127
128
129
130
131
132
133
134
135
136

137
138
139
140
141
142
143
119
120
121
122
123
124
125

126
127
128
129
130
131
132
133
134
135

136
137
138
139
140
141
142
143







-
+









-
+







			struct page **preallocatedPages =
			    of_tlskey_get(preallocatedPagesKey);
# endif

			numPreallocatedPages--;
# if !defined(OF_HAVE_COMPILER_TLS) && defined(OF_HAVE_THREADS)
			OF_ENSURE(of_tlskey_set(numPreallocatedPagesKey,
			    (void *)numPreallocatedPages));
			    (void *)numPreallocatedPages) == 0);
# endif

			page = preallocatedPages[numPreallocatedPages];

			if (numPreallocatedPages == 0) {
				free(preallocatedPages);
				preallocatedPages = NULL;
# if !defined(OF_HAVE_COMPILER_TLS) && defined(OF_HAVE_THREADS)
				OF_ENSURE(of_tlskey_set(preallocatedPagesKey,
				    preallocatedPages));
				    preallocatedPages) == 0);
# endif
			}

			return page;
		}
	}

169
170
171
172
173
174
175
176

177
178
179

180
181
182
183
184
185
186
169
170
171
172
173
174
175

176
177
178

179
180
181
182
183
184
185
186







-
+


-
+








# if defined(OF_HAVE_COMPILER_TLS) || !defined(OF_HAVE_THREADS)
	lastPage = page;

	if (firstPage == NULL)
		firstPage = page;
# else
	OF_ENSURE(of_tlskey_set(lastPageKey, page));
	OF_ENSURE(of_tlskey_set(lastPageKey, page) == 0);

	if (of_tlskey_get(firstPageKey) == NULL)
		OF_ENSURE(of_tlskey_set(firstPageKey, page));
		OF_ENSURE(of_tlskey_set(firstPageKey, page) == 0);
# endif

	return page;
}

static void
removePageIfEmpty(struct page *page)
205
206
207
208
209
210
211
212

213
214

215
216
217
218
219
220
221
205
206
207
208
209
210
211

212
213

214
215
216
217
218
219
220
221







-
+

-
+







# if defined(OF_HAVE_COMPILER_TLS) || !defined(OF_HAVE_THREADS)
	if (firstPage == page)
		firstPage = page->next;
	if (lastPage == page)
		lastPage = page->previous;
# else
	if (of_tlskey_get(firstPageKey) == page)
		OF_ENSURE(of_tlskey_set(firstPageKey, page->next));
		OF_ENSURE(of_tlskey_set(firstPageKey, page->next) == 0);
	if (of_tlskey_get(lastPageKey) == page)
		OF_ENSURE(of_tlskey_set(lastPageKey, page->previous));
		OF_ENSURE(of_tlskey_set(lastPageKey, page->previous) == 0);
# endif

	free(page);
}

static void *
allocateMemory(struct page *page, size_t bytes)
270
271
272
273
274
275
276

277
278
279



280
281
282
283
284
285
286
270
271
272
273
274
275
276
277



278
279
280
281
282
283
284
285
286
287







+
-
-
-
+
+
+







#if defined(HAVE_MMAP) && defined(HAVE_MLOCK) && defined(MAP_ANON) && \
    !defined(OF_HAVE_COMPILER_TLS) && defined(OF_HAVE_THREADS)
+ (void)initialize
{
	if (self != [OFSecureData class])
		return;

	if (of_tlskey_new(&firstPageKey) != 0 ||
	if (!of_tlskey_new(&firstPageKey) || !of_tlskey_new(&lastPageKey) ||
	    !of_tlskey_new(&preallocatedPagesKey) ||
	    !of_tlskey_new(&numPreallocatedPagesKey))
	    of_tlskey_new(&lastPageKey) != 0 ||
	    of_tlskey_new(&preallocatedPagesKey) != 0 ||
	    of_tlskey_new(&numPreallocatedPagesKey) != 0)
		@throw [OFInitializationFailedException
		    exceptionWithClass: self];
}
#endif

+ (void)preallocateUnswappableMemoryWithSize: (size_t)size
{
294
295
296
297
298
299
300
301

302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320


321
322
323
324
325
326
327
295
296
297
298
299
300
301

302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319


320
321
322
323
324
325
326
327
328







-
+

















-
-
+
+







	size_t i;

	if (preallocatedPages != NULL)
		@throw [OFInvalidArgumentException exception];

	preallocatedPages = of_alloc_zeroed(numPages, sizeof(struct page));
# if !defined(OF_HAVE_COMPILER_TLS) && defined(OF_HAVE_THREADS)
	of_tlskey_set(preallocatedPagesKey, preallocatedPages);
	OF_ENSURE(of_tlskey_set(preallocatedPagesKey, preallocatedPages) == 0);
# endif

	@try {
		for (i = 0; i < numPages; i++)
			preallocatedPages[i] = addPage(false);
	} @catch (id e) {
		for (size_t j = 0; j < i; j++)
			removePageIfEmpty(preallocatedPages[j]);

		free(preallocatedPages);
		preallocatedPages = NULL;

		@throw e;
	}

	numPreallocatedPages = numPages;
# if !defined(OF_HAVE_COMPILER_TLS) && defined(OF_HAVE_THREADS)
	of_tlskey_set(numPreallocatedPagesKey,
	    (void *)(uintptr_t)numPreallocatedPages);
	OF_ENSURE(of_tlskey_set(numPreallocatedPagesKey,
	    (void *)(uintptr_t)numPreallocatedPages) == 0);
# endif
#else
	@throw [OFNotImplementedException exceptionWithSelector: _cmd
							 object: self];
#endif
}

Modified src/OFString+JSONParsing.m from [57caefd874] to [87dbebe87e].

27
28
29
30
31
32
33




34
35
36
37
38
39
40
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44







+
+
+
+







#import "OFString+JSONParsing.h"
#import "OFArray.h"
#import "OFDictionary.h"
#import "OFNumber.h"
#import "OFNull.h"

#import "OFInvalidJSONException.h"

#ifndef INFINITY
# define INFINITY __builtin_inf()
#endif

int _OFString_JSONParsing_reference;

static id nextObject(const char **pointer, const char *stop, size_t *line,
    size_t depthLimit);

static void

Modified src/OFString.m from [8c96d0cf6e] to [77195aa3b1].

72
73
74
75
76
77
78




79
80
81
82
83
84
85
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89







+
+
+
+







# define strtod __strtod
#endif

#ifdef OF_AMIGAOS_M68K
/* libnix has strtod, but not strtof */
# define strtof strtod
#endif

#ifndef INFINITY
# define INFINITY __builtin_inf()
#endif

static struct {
	Class isa;
} placeholder;

#if defined(HAVE_STRTOF_L) || defined(HAVE_STRTOD_L)
static locale_t cLocale;

Modified src/OFThread.m from [fe4bfba4ee] to [7d209d5958].

99
100
101
102
103
104
105
106

107
108
109
110
111
112
113
99
100
101
102
103
104
105

106
107
108
109
110
111
112
113







-
+







#ifdef OF_HAVE_THREADS
static void
callMain(id object)
{
	OFThread *thread = (OFThread *)object;
	OFString *name;

	if (!of_tlskey_set(threadSelfKey, thread))
	if (of_tlskey_set(threadSelfKey, thread) != 0)
		@throw [OFInitializationFailedException
		    exceptionWithClass: thread.class];

#ifndef OF_OBJFW_RUNTIME
	thread->_pool = objc_autoreleasePoolPush();
#endif

162
163
164
165
166
167
168
169

170
171
172
173
174
175
176
162
163
164
165
166
167
168

169
170
171
172
173
174
175
176







-
+







# endif

+ (void)initialize
{
	if (self != [OFThread class])
		return;

	if (!of_tlskey_new(&threadSelfKey))
	if (of_tlskey_new(&threadSelfKey) != 0)
		@throw [OFInitializationFailedException
		    exceptionWithClass: self];
}

+ (instancetype)thread
{
	return [[[self alloc] init] autorelease];
346
347
348
349
350
351
352
353

354
355
356
357
358
359
360
361
362
363

364
365
366
367
368
369
370
346
347
348
349
350
351
352

353
354
355
356
357
358
359
360
361
362

363
364
365
366
367
368
369
370







-
+









-
+








+ (void)of_createMainThread
{
	mainThread = [[OFThread alloc] init];
	mainThread->_thread = of_thread_current();
	mainThread->_running = OF_THREAD_RUNNING;

	if (!of_tlskey_set(threadSelfKey, mainThread))
	if (of_tlskey_set(threadSelfKey, mainThread) != 0)
		@throw [OFInitializationFailedException
		    exceptionWithClass: self];
}

- (instancetype)init
{
	self = [super init];

	@try {
		if (!of_thread_attr_init(&_attr))
		if (of_thread_attr_init(&_attr) != 0)
			@throw [OFInitializationFailedException
			    exceptionWithClass: self.class];
	} @catch (id e) {
		[self release];
		@throw e;
	}

407
408
409
410
411
412
413


414
415
416
417
418
419
420
421
422
423
424
425
426
427
428


429
430
431
432
433

434
435
436
437
438


439
440
441
442
443
444

445
446

447
448
449
450
451
452
453
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428


429
430

431
432
433

434
435
436
437
438
439
440
441
442
443
444
445
446

447
448

449
450
451
452
453
454
455
456







+
+













-
-
+
+
-



-
+





+
+





-
+

-
+







	[_DNSResolver release];
	_DNSResolver = nil;
# endif
}

- (void)start
{
	int error;

	if (_running == OF_THREAD_RUNNING)
		@throw [OFThreadStillRunningException
		    exceptionWithThread: self];

	if (_running == OF_THREAD_WAITING_FOR_JOIN) {
		of_thread_detach(_thread);
		[_returnValue release];
	}

	[self retain];

	_running = OF_THREAD_RUNNING;

	if (!of_thread_new(&_thread,
	    [_name cStringWithEncoding: [OFLocale encoding]], callMain, self,
	if ((error = of_thread_new(&_thread, [_name cStringWithEncoding:
	    [OFLocale encoding]], callMain, self, &_attr)) != 0) {
	    &_attr)) {
		[self release];
		@throw [OFThreadStartFailedException
		    exceptionWithThread: self
				  errNo: errno];
				  errNo: error];
	}
}

- (id)join
{
	int error;

	if (_running == OF_THREAD_NOT_RUNNING)
		@throw [OFThreadJoinFailedException
		    exceptionWithThread: self
				  errNo: EINVAL];

	if (!of_thread_join(_thread))
	if ((error = of_thread_join(_thread)) != 0)
		@throw [OFThreadJoinFailedException exceptionWithThread: self
								  errNo: errno];
								  errNo: error];

	_running = OF_THREAD_NOT_RUNNING;

	return _returnValue;
}

- (id)copy

Modified src/condition.h from [ed39b78cbd] to [cbe5713cf5].

48
49
50
51
52
53
54
55
56
57
58
59





60
61
62

63
64

65
66
67

68
69
70
48
49
50
51
52
53
54





55
56
57
58
59
60
61

62
63

64
65
66

67
68
69
70







-
-
-
-
-
+
+
+
+
+


-
+

-
+


-
+



	} *waitingTasks;
} of_condition_t;
#endif

#ifdef __cplusplus
extern "C" {
#endif
extern bool of_condition_new(of_condition_t *condition);
extern bool of_condition_signal(of_condition_t *condition);
extern bool of_condition_broadcast(of_condition_t *condition);
extern bool of_condition_wait(of_condition_t *condition, of_mutex_t *mutex);
extern bool of_condition_timed_wait(of_condition_t *condition,
extern int of_condition_new(of_condition_t *condition);
extern int of_condition_signal(of_condition_t *condition);
extern int of_condition_broadcast(of_condition_t *condition);
extern int of_condition_wait(of_condition_t *condition, of_mutex_t *mutex);
extern int of_condition_timed_wait(of_condition_t *condition,
    of_mutex_t *mutex, of_time_interval_t timeout);
#ifdef OF_AMIGAOS
extern bool of_condition_wait_or_signal(of_condition_t *condition,
extern int of_condition_wait_or_signal(of_condition_t *condition,
    of_mutex_t *mutex, ULONG *signalMask);
extern bool of_condition_timed_wait_or_signal(of_condition_t *condition,
extern int of_condition_timed_wait_or_signal(of_condition_t *condition,
    of_mutex_t *mutex, of_time_interval_t timeout, ULONG *signalMask);
#endif
extern bool of_condition_free(of_condition_t *condition);
extern int of_condition_free(of_condition_t *condition);
#ifdef __cplusplus
}
#endif

Modified src/exceptions/OFException.m from [bf7ff24437] to [aa89efc62e].

71
72
73
74
75
76
77
78

79
80
81
82
83
84
85
71
72
73
74
75
76
77

78
79
80
81
82
83
84
85







-
+







#endif

#if !defined(HAVE_STRERROR_R) && defined(OF_HAVE_THREADS)
static of_mutex_t mutex;

OF_CONSTRUCTOR()
{
	if (!of_mutex_new(&mutex))
	if (of_mutex_new(&mutex) != 0)
		@throw [OFInitializationFailedException exception];
}
#endif

OFString *
of_strerror(int errNo)
{
185
186
187
188
189
190
191
192

193
194
195
196
197
198
199
200
201
202

203
204
205
206
207
208
209
185
186
187
188
189
190
191

192
193
194
195
196
197
198
199
200
201

202
203
204
205
206
207
208
209







-
+









-
+







	if (strerror_r(errNo, buffer, 256) != 0)
		return @"Unknown error (strerror_r failed)";

	ret = [OFString stringWithCString: buffer
				 encoding: [OFLocale encoding]];
#else
# ifdef OF_HAVE_THREADS
	if (!of_mutex_lock(&mutex))
	if (of_mutex_lock(&mutex) != 0)
		@throw [OFLockFailedException exception];

	@try {
# endif
		ret = [OFString
		    stringWithCString: strerror(errNo)
			     encoding: [OFLocale encoding]];
# ifdef OF_HAVE_THREADS
	} @finally {
		if (!of_mutex_unlock(&mutex))
		if (of_mutex_unlock(&mutex) != 0)
			@throw [OFUnlockFailedException exception];
	}
# endif
#endif

	return ret;
}

Modified src/mutex.h from [cbacd2f77f] to [5c06ee482b].

12
13
14
15
16
17
18


19
20
21
22
23
24
25
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27







+
+







 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#include "objfw-defs.h"

#include <errno.h>

#include "platform.h"

#if !defined(OF_HAVE_THREADS) || \
    (!defined(OF_HAVE_PTHREADS) && !defined(OF_WINDOWS) && !defined(OF_AMIGAOS))
# error No mutexes available!
#endif
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
137

138
139

140
141
142
143
144
145

146
147
148
149
150
151
152
153

154
155

156
157
158
159
160
161

162
163
164
165

166
167

168
169
170
171
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
137
138

139
140

141
142
143
144
145
146

147
148
149
150
151
152
153
154

155
156

157
158
159
160
161
162

163
164
165
166

167
168

169
170
171
172
173







-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
















-
+




-
+

-
+





-
+





-
+


-
+

-
+





-
+






-
-
+
+

-
+


-
+

-
+





-
+







-
+

-
+





-
+



-
+

-
+




	of_tlskey_t count;
} of_rmutex_t;
#endif

#ifdef __cplusplus
extern "C" {
#endif
extern bool of_mutex_new(of_mutex_t *mutex);
extern bool of_mutex_lock(of_mutex_t *mutex);
extern bool of_mutex_trylock(of_mutex_t *mutex);
extern bool of_mutex_unlock(of_mutex_t *mutex);
extern bool of_mutex_free(of_mutex_t *mutex);
extern bool of_rmutex_new(of_rmutex_t *rmutex);
extern bool of_rmutex_lock(of_rmutex_t *rmutex);
extern bool of_rmutex_trylock(of_rmutex_t *rmutex);
extern bool of_rmutex_unlock(of_rmutex_t *rmutex);
extern bool of_rmutex_free(of_rmutex_t *rmutex);
extern int of_mutex_new(of_mutex_t *mutex);
extern int of_mutex_lock(of_mutex_t *mutex);
extern int of_mutex_trylock(of_mutex_t *mutex);
extern int of_mutex_unlock(of_mutex_t *mutex);
extern int of_mutex_free(of_mutex_t *mutex);
extern int of_rmutex_new(of_rmutex_t *rmutex);
extern int of_rmutex_lock(of_rmutex_t *rmutex);
extern int of_rmutex_trylock(of_rmutex_t *rmutex);
extern int of_rmutex_unlock(of_rmutex_t *rmutex);
extern int of_rmutex_free(of_rmutex_t *rmutex);
#ifdef __cplusplus
}
#endif

/* Spinlocks are inlined for performance. */

static OF_INLINE void
of_thread_yield(void)
{
#if defined(OF_HAVE_SCHED_YIELD)
	sched_yield();
#elif defined(OF_WINDOWS)
	Sleep(0);
#endif
}

static OF_INLINE bool
static OF_INLINE int
of_spinlock_new(of_spinlock_t *spinlock)
{
#if defined(OF_HAVE_ATOMIC_OPS)
	*spinlock = 0;
	return true;
	return 0;
#elif defined(OF_HAVE_PTHREAD_SPINLOCKS)
	return (pthread_spin_init(spinlock, 0) == 0);
	return pthread_spin_init(spinlock, 0);
#else
	return of_mutex_new(spinlock);
#endif
}

static OF_INLINE bool
static OF_INLINE int
of_spinlock_trylock(of_spinlock_t *spinlock)
{
#if defined(OF_HAVE_ATOMIC_OPS)
	if (of_atomic_int_cmpswap(spinlock, 0, 1)) {
		of_memory_barrier_acquire();
		return true;
		return 0;
	}

	return false;
	return EBUSY;
#elif defined(OF_HAVE_PTHREAD_SPINLOCKS)
	return (pthread_spin_trylock(spinlock) == 0);
	return pthread_spin_trylock(spinlock);
#else
	return of_mutex_trylock(spinlock);
#endif
}

static OF_INLINE bool
static OF_INLINE int
of_spinlock_lock(of_spinlock_t *spinlock)
{
#if defined(OF_HAVE_ATOMIC_OPS)
	size_t i;

	for (i = 0; i < OF_SPINCOUNT; i++)
		if (of_spinlock_trylock(spinlock))
			return true;
		if (of_spinlock_trylock(spinlock) == 0)
			return 0;

	while (!of_spinlock_trylock(spinlock))
	while (of_spinlock_trylock(spinlock) == EBUSY)
		of_thread_yield();

	return true;
	return 0;
#elif defined(OF_HAVE_PTHREAD_SPINLOCKS)
	return (pthread_spin_lock(spinlock) == 0);
	return pthread_spin_lock(spinlock);
#else
	return of_mutex_lock(spinlock);
#endif
}

static OF_INLINE bool
static OF_INLINE int
of_spinlock_unlock(of_spinlock_t *spinlock)
{
#if defined(OF_HAVE_ATOMIC_OPS)
	bool ret = of_atomic_int_cmpswap(spinlock, 1, 0);

	of_memory_barrier_release();

	return ret;
	return (ret ? 0 : EINVAL);
#elif defined(OF_HAVE_PTHREAD_SPINLOCKS)
	return (pthread_spin_unlock(spinlock) == 0);
	return pthread_spin_unlock(spinlock);
#else
	return of_mutex_unlock(spinlock);
#endif
}

static OF_INLINE bool
static OF_INLINE int
of_spinlock_free(of_spinlock_t *spinlock)
{
#if defined(OF_HAVE_ATOMIC_OPS)
	return true;
	return 0;
#elif defined(OF_HAVE_PTHREAD_SPINLOCKS)
	return (pthread_spin_destroy(spinlock) == 0);
	return pthread_spin_destroy(spinlock);
#else
	return of_mutex_free(spinlock);
#endif
}

Modified src/objfw-defs.h.in from [4530c4317b] to [cb58f5fac1].

1
2
3
4
5
6
7
8
9
10



1
2
3
4
5
6
7
-
-
-







#undef INFINITY
#undef LLONG_MAX
#undef LLONG_MIN
#undef OF_APPLE_RUNTIME
#undef OF_BIG_ENDIAN
#undef OF_FLOAT_BIG_ENDIAN
#undef OF_HAVE_ATOMIC_BUILTINS
#undef OF_HAVE_ATOMIC_OPS
#undef OF_HAVE_BUILTIN_BSWAP16
#undef OF_HAVE_BUILTIN_BSWAP32
44
45
46
47
48
49
50
51
52
53
54
41
42
43
44
45
46
47











-
-
-
-
#undef OF_HAVE___THREAD
#undef OF_NINTENDO_3DS
#undef OF_NINTENDO_DS
#undef OF_NO_SHARED
#undef OF_OBJFW_RUNTIME
#undef OF_UNIVERSAL
#undef OF_WII
#undef SIZE_MAX
#undef UINTPTR_MAX
#undef ULLONG_MAX
#undef __have_longlong64

Modified src/platform/amiga/condition.m from [022f3487c0] to [e63442b656].

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
137
138
139
140
141

142
143
144
145
146
147
148
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

137
138
139
140
141
142
143
144







-
+




-
+


-
+





-
+









-
+


-
+





-
+











-
+


-
+







-
+







-
+


-
+
-
-
+
-



-
+

-
+







-
-
+
+




-
-
+
-





-
+


-
+









-
+








#include <proto/exec.h>
#include <devices/timer.h>
#ifndef OF_AMIGAOS4
# include <clib/alib_protos.h>
#endif

bool
int
of_condition_new(of_condition_t *condition)
{
	condition->waitingTasks = NULL;

	return true;
	return 0;
}

bool
int
of_condition_signal(of_condition_t *condition)
{
	Forbid();
	@try {
		if (condition->waitingTasks == NULL)
			return true;
			return 0;

		Signal(condition->waitingTasks->task,
		    (1ul << condition->waitingTasks->sigBit));

		condition->waitingTasks = condition->waitingTasks->next;
	} @finally {
		Permit();
	}

	return true;
	return 0;
}

bool
int
of_condition_broadcast(of_condition_t *condition)
{
	Forbid();
	@try {
		if (condition->waitingTasks == NULL)
			return true;
			return 0;

		while (condition->waitingTasks != NULL) {
			Signal(condition->waitingTasks->task,
			    (1ul << condition->waitingTasks->sigBit));

			condition->waitingTasks = condition->waitingTasks->next;
		}
	} @finally {
		Permit();
	}

	return true;
	return 0;
}

bool
int
of_condition_wait(of_condition_t *condition, of_mutex_t *mutex)
{
	ULONG signalMask = 0;

	return of_condition_wait_or_signal(condition, mutex, &signalMask);
}

bool
int
of_condition_wait_or_signal(of_condition_t *condition, of_mutex_t *mutex,
    ULONG *signalMask)
{
	struct of_condition_waiting_task waitingTask = {
		.task = FindTask(NULL),
		.sigBit = AllocSignal(-1)
	};
	bool ret;
	int error = 0;
	ULONG mask;

	if (waitingTask.sigBit == -1) {
	if (waitingTask.sigBit == -1)
		errno = EAGAIN;
		return false;
		return EAGAIN;
	}

	Forbid();

	if (!of_mutex_unlock(mutex)) {
	if ((error = of_mutex_unlock(mutex)) != 0) {
		FreeSignal(waitingTask.sigBit);
		return false;
		return error;
	}

	waitingTask.next = condition->waitingTasks;
	condition->waitingTasks = &waitingTask;

	mask = Wait((1ul << waitingTask.sigBit) | *signalMask);
	if (mask & (1ul << waitingTask.sigBit) || (*signalMask &= mask))
		ret = of_mutex_lock(mutex);
	else {
		error = of_mutex_lock(mutex);
	else
		/*
		 * This should not happen - it means something interrupted the
		 * Wait(), so the best we can do is return EINTR.
		 */
		ret = false;
		errno = EINTR;
		error = EINTR;
	}

	FreeSignal(waitingTask.sigBit);

	Permit();

	return ret;
	return error;
}

bool
int
of_condition_timed_wait(of_condition_t *condition, of_mutex_t *mutex,
    of_time_interval_t timeout)
{
	ULONG signalMask = 0;

	return of_condition_timed_wait_or_signal(condition, mutex, timeout,
	    &signalMask);
}

bool
int
of_condition_timed_wait_or_signal(of_condition_t *condition, of_mutex_t *mutex,
    of_time_interval_t timeout, ULONG *signalMask)
{
	struct of_condition_waiting_task waitingTask = {
		.task = FindTask(NULL),
		.sigBit = AllocSignal(-1)
	};
178
179
180
181
182
183
184

185
186
187
188
189
190
191

192
193
194
195
196
197

198
199
200
201
202
203

204
205
206
207
208
209
210
211
212
213
214
215
216
217


218
219
220


221
222
223
224
225
226

227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250

251
252
253

254
255
256
257
258

259
260

261
262
263
264
265
266

267
174
175
176
177
178
179
180
181
182

183
184
185
186

187
188
189
190
191
192

193
194
195
196
197
198

199
200
201
202
203
204
205
206
207
208
209
210
211


212
213



214
215
216
217
218
219


220

221
222
223
224
225
226
227
228
229
230
231





232
233
234
235
236
237

238
239
240

241
242
243
244
245

246


247

248
249
250
251

252
253







+

-




-
+





-
+





-
+












-
-
+
+
-
-
-
+
+




-
-
+
-











-
-
-
-
-






-
+


-
+




-
+
-
-
+
-




-
+

#else
		.tr_time = {
			.tv_sec = (ULONG)timeout,
			.tv_micro = (timeout - request.tr_time.tv_sec) * 1000000
#endif
		}
	};
	int error = 0;
	ULONG mask;
	bool ret;

	NewList(&port.mp_MsgList);

	if (waitingTask.sigBit == -1 || port.mp_SigBit == -1) {
		errno = EAGAIN;
		error = EAGAIN;
		goto fail;
	}

	if (OpenDevice("timer.device", UNIT_MICROHZ,
	    (struct IORequest *)&request, 0) != 0) {
		errno = EAGAIN;
		error = EAGAIN;
		goto fail;
	}

	Forbid();

	if (!of_mutex_unlock(mutex)) {
	if ((error = of_mutex_unlock(mutex)) != 0) {
		Permit();
		goto fail;
	}

	waitingTask.next = condition->waitingTasks;
	condition->waitingTasks = &waitingTask;

	SendIO((struct IORequest *)&request);

	mask = Wait((1ul << waitingTask.sigBit) | (1ul << port.mp_SigBit) |
	    *signalMask);
	if (mask & (1ul << waitingTask.sigBit) || (*signalMask &= mask))
		ret = of_mutex_lock(mutex);
	else if (mask & (1ul << port.mp_SigBit)) {
		error = of_mutex_lock(mutex);
	else if (mask & (1ul << port.mp_SigBit))
		ret = false;
		errno = ETIMEDOUT;
	} else {
		error = ETIMEDOUT;
	else
		/*
		 * This should not happen - it means something interrupted the
		 * Wait(), so the best we can do is return EINTR.
		 */
		ret = false;
		errno = EINTR;
		error = EINTR;
	}

	condition->waitingTasks = waitingTask.next;

	if (!CheckIO((struct IORequest *)&request)) {
		AbortIO((struct IORequest *)&request);
		WaitIO((struct IORequest *)&request);
	}
	CloseDevice((struct IORequest *)&request);

	Permit();

	FreeSignal(waitingTask.sigBit);
	FreeSignal(port.mp_SigBit);

	return ret;

fail:
	if (waitingTask.sigBit != -1)
		FreeSignal(waitingTask.sigBit);
	if (port.mp_SigBit != -1)
		FreeSignal(port.mp_SigBit);

	return false;
	return error;
}

bool
int
of_condition_free(of_condition_t *condition)
{
	Forbid();
	@try {
		if (condition->waitingTasks != NULL) {
		if (condition->waitingTasks != NULL)
			errno = EBUSY;
			return false;
			return EBUSY;
		}
	} @finally {
		Permit();
	}

	return true;
	return 0;
}

Modified src/platform/amiga/mutex.m from [c8d24f47bf] to [53f62a4365].

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
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







-
+




-
+


-
+




-
+


-
+


-
+
-
-
-
+
+
-
-
+


-
+




-
+


-
+


-
+


-
+





-
+





-
+





-
+





-
+





#include <errno.h>

#import "mutex.h"

#include <proto/exec.h>

bool
int
of_mutex_new(of_mutex_t *mutex)
{
	InitSemaphore(mutex);

	return true;
	return 0;
}

bool
int
of_mutex_lock(of_mutex_t *mutex)
{
	ObtainSemaphore(mutex);

	return true;
	return 0;
}

bool
int
of_mutex_trylock(of_mutex_t *mutex)
{
	if (!AttemptSemaphore(mutex)) {
	if (!AttemptSemaphore(mutex))
		errno = EBUSY;
		return false;
	}
		return EBUSY;


	return true;
	return 0;
}

bool
int
of_mutex_unlock(of_mutex_t *mutex)
{
	ReleaseSemaphore(mutex);

	return true;
	return 0;
}

bool
int
of_mutex_free(of_mutex_t *mutex)
{
	return true;
	return 0;
}

bool
int
of_rmutex_new(of_rmutex_t *rmutex)
{
	return of_mutex_new(rmutex);
}

bool
int
of_rmutex_lock(of_rmutex_t *rmutex)
{
	return of_mutex_lock(rmutex);
}

bool
int
of_rmutex_trylock(of_rmutex_t *rmutex)
{
	return of_mutex_trylock(rmutex);
}

bool
int
of_rmutex_unlock(of_rmutex_t *rmutex)
{
	return of_mutex_unlock(rmutex);
}

bool
int
of_rmutex_free(of_rmutex_t *rmutex)
{
	return of_mutex_free(rmutex);
}

Modified src/platform/amiga/thread.m from [1416763f86] to [020e13328a].

32
33
34
35
36
37
38
39

40
41
42
43
44
45
46
47
48

49
50
51
52
53
54
55
32
33
34
35
36
37
38

39
40
41
42
43
44
45
46
47

48
49
50
51
52
53
54
55







-
+








-
+







#ifndef OF_MORPHOS
extern void of_tlskey_thread_exited(void);
#endif
static of_tlskey_t threadKey;

OF_CONSTRUCTOR()
{
	OF_ENSURE(of_tlskey_new(&threadKey));
	OF_ENSURE(of_tlskey_new(&threadKey) == 0);
}

static void
functionWrapper(void)
{
	bool detached = false;
	of_thread_t thread =
	    (of_thread_t)((struct Process *)FindTask(NULL))->pr_ExitData;
	OF_ENSURE(of_tlskey_set(threadKey, thread));
	OF_ENSURE(of_tlskey_set(threadKey, thread) == 0);

	thread->function(thread->object);

	ObtainSemaphore(&thread->semaphore);
	@try {
		thread->done = true;

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
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







-
+





-
+


-
+





-
+
-
-
+
-







		ReleaseSemaphore(&thread->semaphore);
	}

	if (detached)
		free(thread);
}

bool
int
of_thread_attr_init(of_thread_attr_t *attr)
{
	attr->priority = 0;
	attr->stackSize = 0;

	return true;
	return 0;
}

bool
int
of_thread_new(of_thread_t *thread, const char *name, void (*function)(id),
    id object, const of_thread_attr_t *attr)
{
	OFMutableData *tags = nil;

	if ((*thread = calloc(1, sizeof(**thread))) == NULL) {
	if ((*thread = calloc(1, sizeof(**thread))) == NULL)
		errno = ENOMEM;
		return false;
		return ENOMEM;
	}

	@try {
		(*thread)->function = function;
		(*thread)->object = object;
		InitSemaphore(&(*thread)->semaphore);

		tags = [[OFMutableData alloc]
120
121
122
123
124
125
126
127

128
129

130
131
132
133
134
135
136
137
118
119
120
121
122
123
124

125


126

127
128
129
130
131
132
133







-
+
-
-
+
-







		ADD_TAG(NP_Output, ((struct Process *)FindTask(NULL))->pr_COS)
		ADD_TAG(NP_Error, ((struct Process *)FindTask(NULL))->pr_CES)
		ADD_TAG(NP_CloseInput, FALSE)
		ADD_TAG(NP_CloseOutput, FALSE)
		ADD_TAG(NP_CloseError, FALSE)

		if (attr != NULL && attr->priority != 0) {
			if (attr->priority < 1 || attr->priority > 1) {
			if (attr->priority < 1 || attr->priority > 1)
				errno = EINVAL;
				return false;
				return EINVAL;
			}

			/*
			 * -1 should be -128 (lowest possible priority) while
			 * +1 should be +127 (highest possible priority).
			 */
			ADD_TAG(NP_Priority, (attr->priority > 0
			    ? attr->priority * 127 : attr->priority * 128))
145
146
147
148
149
150
151
152
153

154
155
156
157
158
159
160
161
162

163
164
165
166
167
168
169
170
171

172
173
174
175
176
177
178
179
180

181
182
183
184

185
186
187


188
189

190
191

192
193
194
195
196
197
198
199
200
201
202
203
204
205

206
207
208

209
210
211
212
213
214
215
216
217
218
219
220

221
222
223
224
225
226
141
142
143
144
145
146
147


148
149
150
151
152
153
154
155
156

157
158
159
160
161
162
163
164
165

166
167
168
169
170
171
172
173
174

175
176
177
178

179



180
181


182


183

184
185
186
187
188
189
190
191
192
193
194
195

196
197
198

199
200
201
202
203
204
205
206
207
208
209
210

211
212
213
214
215
216
217







-
-
+








-
+








-
+








-
+



-
+
-
-
-
+
+
-
-
+
-
-
+
-












-
+


-
+











-
+







		ADD_TAG(TAG_DONE, 0)
#undef ADD_TAG

		(*thread)->task = (struct Task *)CreateNewProc(tags.items);
		if ((*thread)->task == NULL) {
			free(*thread);
			errno = EAGAIN;
			return false;
			return EAGAIN;
		}
	} @catch (id e) {
		free(*thread);
		@throw e;
	} @finally {
		[tags release];
	}

	return true;
	return 0;
}

of_thread_t
of_thread_current(void)
{
	return of_tlskey_get(threadKey);
}

bool
int
of_thread_join(of_thread_t thread)
{
	ObtainSemaphore(&thread->semaphore);

	if (thread->done) {
		ReleaseSemaphore(&thread->semaphore);

		free(thread);
		return true;
		return 0;
	}

	@try {
		if (thread->detached || thread->joinTask != NULL) {
		if (thread->detached || thread->joinTask != NULL)
			errno = EINVAL;
			return false;
		}
			return EINVAL;


		if ((thread->joinSigBit = AllocSignal(-1)) == -1) {
		if ((thread->joinSigBit = AllocSignal(-1)) == -1)
			errno = EAGAIN;
			return false;
			return EAGAIN;
		}

		thread->joinTask = FindTask(NULL);
	} @finally {
		ReleaseSemaphore(&thread->semaphore);
	}

	Wait(1ul << thread->joinSigBit);
	FreeSignal(thread->joinSigBit);

	assert(thread->done);
	free(thread);

	return true;
	return 0;
}

bool
int
of_thread_detach(of_thread_t thread)
{
	ObtainSemaphore(&thread->semaphore);

	if (thread->done)
		free(thread);
	else
		thread->detached = true;

	ReleaseSemaphore(&thread->semaphore);

	return true;
	return 0;
}

void
of_thread_set_name(const char *name)
{
}

Modified src/platform/amiga/tlskey.m from [c1bdeb2ced] to [55fe5cc12c].

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
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155

156
157
158
159
160
161
162
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
137
138
139
140
141
142
143
144
145
146
147
148


149
150
151
152

153
154
155
156
157
158
159
160







-
+













-
+




















-
+


-
+




















-
+




















-
+













-
-




-
+







{
	if (!semaphoreInitialized) {
		InitSemaphore(&semaphore);
		semaphoreInitialized = true;
	}
}

bool
int
of_tlskey_new(of_tlskey_t *key)
{
	if (!semaphoreInitialized) {
		/*
		 * We might be called from another constructor, while ours has
		 * not run yet. This is safe, as the constructor is definitely
		 * run before a thread is spawned.
		 */
		InitSemaphore(&semaphore);
		semaphoreInitialized = true;
	}

	if ((*key = malloc(sizeof(**key))) == NULL)
		return false;
		return ENOMEM;

	(*key)->table = NULL;

	ObtainSemaphore(&semaphore);
	@try {
		(*key)->next = NULL;
		(*key)->previous = lastKey;

		if (lastKey != NULL)
			lastKey->next = *key;

		lastKey = *key;

		if (firstKey == NULL)
			firstKey = *key;
	} @finally {
		ReleaseSemaphore(&semaphore);
	}

	/* We create the hash table lazily. */
	return true;
	return 0;
}

bool
int
of_tlskey_free(of_tlskey_t key)
{
	ObtainSemaphore(&semaphore);
	@try {
		if (key->previous != NULL)
			key->previous->next = key->next;
		if (key->next != NULL)
			key->next->previous = key->previous;

		if (firstKey == key)
			firstKey = key->next;
		if (lastKey == key)
			lastKey = key->previous;

		objc_hashtable_free(key->table);
		free(key);
	} @finally {
		ReleaseSemaphore(&semaphore);
	}

	return true;
	return 0;
}

void *
of_tlskey_get(of_tlskey_t key)
{
	void *ret;

	ObtainSemaphore(&semaphore);
	@try {
		if (key->table == NULL)
			return NULL;

		ret = objc_hashtable_get(key->table, FindTask(NULL));
	} @finally {
		ReleaseSemaphore(&semaphore);
	}

	return ret;
}

bool
int
of_tlskey_set(of_tlskey_t key, void *ptr)
{
	ObtainSemaphore(&semaphore);
	@try {
		struct Task *task = FindTask(NULL);

		if (key->table == NULL)
			key->table = objc_hashtable_new(hashFunc, equalFunc, 2);

		if (ptr == NULL)
			objc_hashtable_delete(key->table, task);
		else
			objc_hashtable_set(key->table, task, ptr);
	} @catch (id e) {
		return false;
	} @finally {
		ReleaseSemaphore(&semaphore);
	}

	return true;
	return 0;
}

void
of_tlskey_thread_exited(void)
{
	ObtainSemaphore(&semaphore);
	@try {

Modified src/platform/morphos/tlskey.m from [b6a6f32a2b] to [ac011a1581].

15
16
17
18
19
20
21
22

23
24
25
26




27


28


29
30
31

32
15
16
17
18
19
20
21

22
23
24


25
26
27
28
29
30
31

32
33
34
35

36
37







-
+


-
-
+
+
+
+

+
+
-
+
+


-
+

 * file.
 */

#include "config.h"

#import "tlskey.h"

bool
int
of_tlskey_new(of_tlskey_t *key)
{
	return ((*key = TLSAllocA(NULL)) != TLS_INVALID_INDEX);
}
	*key = TLSAllocA(NULL);

	if (*key == TLS_INVALID_INDEX)
		return EAGAIN;

	return 0;
}
bool

int
of_tlskey_free(of_tlskey_t key)
{
	return TLSFree(key);
	return (TLSFree(key) ? 0 : EINVAL);
}

Modified src/platform/posix/condition.m from [59d3a90643] to [d7af2c3e9e].

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
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







-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+








-
+


-
+


-
+

 * file.
 */

#include "config.h"

#import "condition.h"

bool
int
of_condition_new(of_condition_t *condition)
{
	return (pthread_cond_init(condition, NULL) == 0);
	return pthread_cond_init(condition, NULL);
}

bool
int
of_condition_signal(of_condition_t *condition)
{
	return (pthread_cond_signal(condition) == 0);
	return pthread_cond_signal(condition);
}

bool
int
of_condition_broadcast(of_condition_t *condition)
{
	return (pthread_cond_broadcast(condition) == 0);
	return pthread_cond_broadcast(condition);
}

bool
int
of_condition_wait(of_condition_t *condition, of_mutex_t *mutex)
{
	return (pthread_cond_wait(condition, mutex) == 0);
	return pthread_cond_wait(condition, mutex);
}

bool
int
of_condition_timed_wait(of_condition_t *condition, of_mutex_t *mutex,
    of_time_interval_t timeout)
{
	struct timespec ts;

	ts.tv_sec = (time_t)timeout;
	ts.tv_nsec = (long)((timeout - ts.tv_sec) * 1000000000);

	return (pthread_cond_timedwait(condition, mutex, &ts) == 0);
	return pthread_cond_timedwait(condition, mutex, &ts);
}

bool
int
of_condition_free(of_condition_t *condition)
{
	return (pthread_cond_destroy(condition) == 0);
	return pthread_cond_destroy(condition);
}

Modified src/platform/posix/mutex.m from [608d6df3a8] to [9dc6dfa8c4].

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
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
137
138
139



140
141

142
143
144
145


146
147

148
149

150
151
152

153
154
155

156
157
158

159
160
161
162



163
164

165
166
167
168


169
170
171


172
173

174
175
176

177
178


179
180


181
182
183


184
185

186
187
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


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
137

138
139
140
141
142
143
144


145
146
147
148

149
150
151


152
153
154

155
156

157
158
159

160
161
162

163
164
165
166
167
168
169


170
171
172
173

174
175
176


177
178
179


180
181
182

183
184
185

186
187
188
189
190


191
192
193


194
195
196

197
198
199







-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+


-
+



-
+


+


-
-
+
+

-
-
+
+
+

-
-
+
+

-
-
+
+

-
+


-
+





-
+





-
+





-
+





-
+


+
+
-
-
+
+

-
-
+
+

-
+


-
+



+


-
-
+
+
+

-
+


-
-
+
+

-
+

-
+


-
+


-
+



+


-
-
+
+
+

-
+


-
-
+
+

-
+

-
+


-
+


-
+



+


-
-
+
+
+

-
+


-
-
+
+

-
-
+
+

-
+


-
+


+
+
-
-
+
+

-
-
+
+

-
+


 * file.
 */

#include "config.h"

#import "mutex.h"

bool
int
of_mutex_new(of_mutex_t *mutex)
{
	return (pthread_mutex_init(mutex, NULL) == 0);
	return pthread_mutex_init(mutex, NULL);
}

bool
int
of_mutex_lock(of_mutex_t *mutex)
{
	return (pthread_mutex_lock(mutex) == 0);
	return pthread_mutex_lock(mutex);
}

bool
int
of_mutex_trylock(of_mutex_t *mutex)
{
	return (pthread_mutex_trylock(mutex) == 0);
	return pthread_mutex_trylock(mutex);
}

bool
int
of_mutex_unlock(of_mutex_t *mutex)
{
	return (pthread_mutex_unlock(mutex) == 0);
	return pthread_mutex_unlock(mutex);
}

bool
int
of_mutex_free(of_mutex_t *mutex)
{
	return (pthread_mutex_destroy(mutex) == 0);
	return pthread_mutex_destroy(mutex);
}

#ifdef OF_HAVE_RECURSIVE_PTHREAD_MUTEXES
bool
int
of_rmutex_new(of_rmutex_t *rmutex)
{
	int error;
	pthread_mutexattr_t attr;

	if (pthread_mutexattr_init(&attr) != 0)
		return false;
	if ((error = pthread_mutexattr_init(&attr)) != 0)
		return error;

	if (pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE) != 0)
		return false;
	if ((error = pthread_mutexattr_settype(&attr,
	    PTHREAD_MUTEX_RECURSIVE)) != 0)
		return error;

	if (pthread_mutex_init(rmutex, &attr) != 0)
		return false;
	if ((error = pthread_mutex_init(rmutex, &attr)) != 0)
		return error;

	if (pthread_mutexattr_destroy(&attr) != 0)
		return false;
	if ((error = pthread_mutexattr_destroy(&attr)) != 0)
		return error;

	return true;
	return 0;
}

bool
int
of_rmutex_lock(of_rmutex_t *rmutex)
{
	return of_mutex_lock(rmutex);
}

bool
int
of_rmutex_trylock(of_rmutex_t *rmutex)
{
	return of_mutex_trylock(rmutex);
}

bool
int
of_rmutex_unlock(of_rmutex_t *rmutex)
{
	return of_mutex_unlock(rmutex);
}

bool
int
of_rmutex_free(of_rmutex_t *rmutex)
{
	return of_mutex_free(rmutex);
}
#else
bool
int
of_rmutex_new(of_rmutex_t *rmutex)
{
	int error;

	if (!of_mutex_new(&rmutex->mutex))
		return false;
	if ((error = of_mutex_new(&rmutex->mutex)) != 0)
		return error;

	if (!of_tlskey_new(&rmutex->count))
		return false;
	if ((error = of_tlskey_new(&rmutex->count)) != 0)
		return error;

	return true;
	return 0;
}

bool
int
of_rmutex_lock(of_rmutex_t *rmutex)
{
	uintptr_t count = (uintptr_t)of_tlskey_get(rmutex->count);
	int error;

	if (count > 0) {
		if (!of_tlskey_set(rmutex->count, (void *)(count + 1)))
			return false;
		if ((error = of_tlskey_set(rmutex->count,
		    (void *)(count + 1))) != 0)
			return error;

		return true;
		return 0;
	}

	if (!of_mutex_lock(&rmutex->mutex))
		return false;
	if ((error = of_mutex_lock(&rmutex->mutex)) != 0)
		return error;

	if (!of_tlskey_set(rmutex->count, (void *)1)) {
	if ((error = of_tlskey_set(rmutex->count, (void *)1)) != 0) {
		of_mutex_unlock(&rmutex->mutex);
		return false;
		return error;
	}

	return true;
	return 0;
}

bool
int
of_rmutex_trylock(of_rmutex_t *rmutex)
{
	uintptr_t count = (uintptr_t)of_tlskey_get(rmutex->count);
	int error;

	if (count > 0) {
		if (!of_tlskey_set(rmutex->count, (void *)(count + 1)))
			return false;
		if ((error = of_tlskey_set(rmutex->count,
		    (void *)(count + 1))) != 0)
			return error;

		return true;
		return 0;
	}

	if (!of_mutex_trylock(&rmutex->mutex))
		return false;
	if ((error = of_mutex_trylock(&rmutex->mutex)) != 0)
		return error;

	if (!of_tlskey_set(rmutex->count, (void *)1)) {
	if ((error = of_tlskey_set(rmutex->count, (void *)1)) != 0) {
		of_mutex_unlock(&rmutex->mutex);
		return false;
		return error;
	}

	return true;
	return 0;
}

bool
int
of_rmutex_unlock(of_rmutex_t *rmutex)
{
	uintptr_t count = (uintptr_t)of_tlskey_get(rmutex->count);
	int error;

	if (count > 1) {
		if (!of_tlskey_set(rmutex->count, (void *)(count - 1)))
			return false;
		if ((error = of_tlskey_set(rmutex->count,
		    (void *)(count - 1))) != 0)
			return error;

		return true;
		return 0;
	}

	if (!of_tlskey_set(rmutex->count, (void *)0))
		return false;
	if ((error = of_tlskey_set(rmutex->count, (void *)0)) != 0)
		return error;

	if (!of_mutex_unlock(&rmutex->mutex))
		return false;
	if ((error = of_mutex_unlock(&rmutex->mutex)) != 0)
		return error;

	return true;
	return 0;
}

bool
int
of_rmutex_free(of_rmutex_t *rmutex)
{
	int error;

	if (!of_mutex_free(&rmutex->mutex))
		return false;
	if ((error = of_mutex_free(&rmutex->mutex)) != 0)
		return error;

	if (!of_tlskey_free(rmutex->count))
		return false;
	if ((error = of_tlskey_free(rmutex->count)) != 0)
		return error;

	return true;
	return 0;
}
#endif

Modified src/platform/posix/thread.m from [cdd7c510a1] to [08a22e6008].

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
137
138
139
140
141
142
143
144
145
146



147
148
149
150
151



152
153
154
155

156
157

158
159
160
161
162
163
164

165
166
167
168
169
170

171
172
173

174
175
176
177
178

179
180
181

182
183
184

185
186
187
188
189
190
191
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
137
138
139


140
141
142
143
144



145
146
147
148
149
150

151


152

153
154
155
156
157

158

159
160
161
162

163
164
165

166
167
168
169
170

171
172
173

174
175
176

177
178
179
180
181
182
183
184







-
+


+


-
-
+
+

-
-
+
-
-
-
+
+
-
-
-
+
+
-
-
+


-
+



-
+


-
-
+
+







-
+
-
-
-
+
+
-

-
-
-
+
+
+










-
-
+
+
+


-
-
-
+
+
+



-
+
-
-
+
-





-
+
-




-
+


-
+




-
+


-
+


-
+








	ctx->function(ctx->object);

	pthread_cleanup_pop(1);
	return NULL;
}

bool
int
of_thread_attr_init(of_thread_attr_t *attr)
{
	int error;
	pthread_attr_t pattr;

	if (pthread_attr_init(&pattr) != 0)
		return false;
	if ((error = pthread_attr_init(&pattr)) != 0)
		return error;

	@try {
		attr->priority = 0;
	attr->priority = 0;

		if (pthread_attr_getstacksize(&pattr, &attr->stackSize) != 0)
			return false;
	error = pthread_attr_getstacksize(&pattr, &attr->stackSize);

	} @finally {
		pthread_attr_destroy(&pattr);
	}
	pthread_attr_destroy(&pattr);


	return true;
	return error;
}

bool
int
of_thread_new(of_thread_t *thread, const char *name, void (*function)(id),
    id object, const of_thread_attr_t *attr)
{
	bool ret;
	int error = 0;
	pthread_attr_t pattr;

	if (pthread_attr_init(&pattr) != 0)
		return false;
	if ((error = pthread_attr_init(&pattr)) != 0)
		return error;

	@try {
		struct thread_ctx *ctx;

		if (attr != NULL) {
			struct sched_param param;

			if (attr->priority < -1 || attr->priority > 1) {
			if (attr->priority < -1 || attr->priority > 1)
				errno = EINVAL;
				return false;
			}
				return EINVAL;


#ifdef HAVE_PTHREAD_ATTR_SETINHERITSCHED
			if (pthread_attr_setinheritsched(&pattr,
			    PTHREAD_EXPLICIT_SCHED) != 0)
				return false;
			if ((error = pthread_attr_setinheritsched(&pattr,
			    PTHREAD_EXPLICIT_SCHED)) != 0)
				return error;
#endif

			if (attr->priority < 0) {
				param.sched_priority = minPrio +
				    (1.0f + attr->priority) *
				    (normalPrio - minPrio);
			} else
				param.sched_priority = normalPrio +
				    attr->priority * (maxPrio - normalPrio);

			if (pthread_attr_setschedparam(&pattr, &param) != 0)
				return false;
			if ((error = pthread_attr_setschedparam(&pattr,
			    &param)) != 0)
				return error;

			if (attr->stackSize > 0) {
				if (pthread_attr_setstacksize(&pattr,
				    attr->stackSize) != 0)
					return false;
				if ((error = pthread_attr_setstacksize(&pattr,
				    attr->stackSize)) != 0)
					return error;
			}
		}

		if ((ctx = malloc(sizeof(*ctx))) == NULL) {
		if ((ctx = malloc(sizeof(*ctx))) == NULL)
			errno = ENOMEM;
			return false;
			return ENOMEM;
		}

		ctx->function = function;
		ctx->object = object;
		ctx->name = name;

		ret = (pthread_create(thread, &pattr,
		error = pthread_create(thread, &pattr, functionWrapper, ctx);
		    functionWrapper, ctx) == 0);
	} @finally {
		pthread_attr_destroy(&pattr);
	}

	return ret;
	return error;
}

bool
int
of_thread_join(of_thread_t thread)
{
	void *ret;

	return (pthread_join(thread, &ret) == 0);
	return pthread_join(thread, &ret);
}

bool
int
of_thread_detach(of_thread_t thread)
{
	return (pthread_detach(thread) == 0);
	return pthread_detach(thread);
}

void
of_thread_set_name(const char *name)
{
#if defined(OF_HAIKU)
	rename_thread(find_thread(NULL), name);

Modified src/platform/posix/tlskey.m from [01a5f7adde] to [b21f6b68b0].

15
16
17
18
19
20
21
22

23
24
25

26
27
28

29
30
31

32
15
16
17
18
19
20
21

22
23
24

25
26
27

28
29
30

31
32







-
+


-
+


-
+


-
+

 * file.
 */

#include "config.h"

#import "tlskey.h"

bool
int
of_tlskey_new(of_tlskey_t *key)
{
	return (pthread_key_create(key, NULL) == 0);
	return pthread_key_create(key, NULL);
}

bool
int
of_tlskey_free(of_tlskey_t key)
{
	return (pthread_key_delete(key) == 0);
	return pthread_key_delete(key);
}

Modified src/platform/windows/condition.m from [848a636ef0] to [bcc658da38].

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

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
137
138

139
140
141


142
143

144
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
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
137







-
+




-
+
-
-
-
+
+
-
-
+


-
+





-
-
+





-
+


-
+








-
-
+






-
+


-
+


+


-
-
+
+











-
-
+








-
+



+


-
-
+
+









-
-
+



-
-
+








-
+


-
+
-
-
-
+
+
-
-
+


#include <errno.h>

#import "condition.h"

#include <windows.h>

bool
int
of_condition_new(of_condition_t *condition)
{
	condition->count = 0;

	if ((condition->event = CreateEvent(NULL, FALSE, 0, NULL)) == NULL) {
	if ((condition->event = CreateEvent(NULL, FALSE, 0, NULL)) == NULL)
		errno = EAGAIN;
		return false;
	}
		return EAGAIN;


	return true;
	return 0;
}

bool
int
of_condition_signal(of_condition_t *condition)
{
	if (!SetEvent(condition->event)) {
		switch (GetLastError()) {
		case ERROR_INVALID_HANDLE:
			errno = EINVAL;
			return false;
			return EINVAL;
		default:
			OF_ENSURE(0);
		}
	}

	return true;
	return 0;
}

bool
int
of_condition_broadcast(of_condition_t *condition)
{
	int count = condition->count;

	for (int i = 0; i < count; i++) {
		if (!SetEvent(condition->event)) {
			switch (GetLastError()) {
			case ERROR_INVALID_HANDLE:
				errno = EINVAL;
				return false;
				return EINVAL;
			default:
				OF_ENSURE(0);
			}
		}
	}

	return true;
	return 0;
}

bool
int
of_condition_wait(of_condition_t *condition, of_mutex_t *mutex)
{
	int error;
	DWORD status;

	if (!of_mutex_unlock(mutex))
		return false;
	if ((error = of_mutex_unlock(mutex)) != 0)
		return error;

	of_atomic_int_inc(&condition->count);
	status = WaitForSingleObject(condition->event, INFINITE);
	of_atomic_int_dec(&condition->count);

	switch (status) {
	case WAIT_OBJECT_0:
		return of_mutex_lock(mutex);
	case WAIT_FAILED:
		switch (GetLastError()) {
		case ERROR_INVALID_HANDLE:
			errno = EINVAL;
			return false;
			return EINVAL;
		default:
			OF_ENSURE(0);
		}
	default:
		OF_ENSURE(0);
	}
}

bool
int
of_condition_timed_wait(of_condition_t *condition, of_mutex_t *mutex,
    of_time_interval_t timeout)
{
	int error;
	DWORD status;

	if (!of_mutex_unlock(mutex))
		return false;
	if ((error = of_mutex_unlock(mutex)) != 0)
		return error;

	of_atomic_int_inc(&condition->count);
	status = WaitForSingleObject(condition->event, timeout * 1000);
	of_atomic_int_dec(&condition->count);

	switch (status) {
	case WAIT_OBJECT_0:
		return of_mutex_lock(mutex);
	case WAIT_TIMEOUT:
		errno = ETIMEDOUT;
		return false;
		return ETIMEDOUT;
	case WAIT_FAILED:
		switch (GetLastError()) {
		case ERROR_INVALID_HANDLE:
			errno = EINVAL;
			return false;
			return EINVAL;
		default:
			OF_ENSURE(0);
		}
	default:
		OF_ENSURE(0);
	}
}

bool
int
of_condition_free(of_condition_t *condition)
{
	if (condition->count != 0) {
	if (condition->count != 0)
		errno = EBUSY;
		return false;
	}
		return EBUSY;


	return CloseHandle(condition->event);
	return (CloseHandle(condition->event) ? 0 : EINVAL);
}

Modified src/platform/windows/mutex.m from [c67aeb237e] to [872d7f229b].

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
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







-
+




-
+


-
+




-
+


-
+


-
+
-
-
-
+
+
-
-
+


-
+




-
+


-
+




-
+


-
+





-
+





-
+





-
+





-
+





#include <errno.h>

#import "mutex.h"

#include <windows.h>

bool
int
of_mutex_new(of_mutex_t *mutex)
{
	InitializeCriticalSection(mutex);

	return true;
	return 0;
}

bool
int
of_mutex_lock(of_mutex_t *mutex)
{
	EnterCriticalSection(mutex);

	return true;
	return 0;
}

bool
int
of_mutex_trylock(of_mutex_t *mutex)
{
	if (!TryEnterCriticalSection(mutex)) {
	if (!TryEnterCriticalSection(mutex))
		errno = EBUSY;
		return false;
	}
		return EBUSY;


	return true;
	return 0;
}

bool
int
of_mutex_unlock(of_mutex_t *mutex)
{
	LeaveCriticalSection(mutex);

	return true;
	return 0;
}

bool
int
of_mutex_free(of_mutex_t *mutex)
{
	DeleteCriticalSection(mutex);

	return true;
	return 0;
}

bool
int
of_rmutex_new(of_rmutex_t *rmutex)
{
	return of_mutex_new(rmutex);
}

bool
int
of_rmutex_lock(of_rmutex_t *rmutex)
{
	return of_mutex_lock(rmutex);
}

bool
int
of_rmutex_trylock(of_rmutex_t *rmutex)
{
	return of_mutex_trylock(rmutex);
}

bool
int
of_rmutex_unlock(of_rmutex_t *rmutex)
{
	return of_mutex_unlock(rmutex);
}

bool
int
of_rmutex_free(of_rmutex_t *rmutex)
{
	return of_mutex_free(rmutex);
}

Modified src/platform/windows/thread.m from [d3d9eb9ec8] to [ea501b1747].

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
137
138
139
140
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







-
+





-
+


-
+








-
+
-
-
+
-











-
+
-
-
+
-








-
+



-
+


-
+






-
-
+





-
+


-
+





-
+



-
-
+








-
+




-
+






functionWrapper(struct thread_context *context)
{
	context->function(context->object);

	free(context);
}

bool
int
of_thread_attr_init(of_thread_attr_t *attr)
{
	attr->priority = 0;
	attr->stackSize = 0;

	return true;
	return 0;
}

bool
int
of_thread_new(of_thread_t *thread, const char *name, void (*function)(id),
    id object, const of_thread_attr_t *attr)
{
	DWORD priority = THREAD_PRIORITY_NORMAL;
	struct thread_context *context;
	DWORD threadID;

	if (attr != NULL && attr->priority != 0) {
		if (attr->priority < -1 || attr->priority > 1) {
		if (attr->priority < -1 || attr->priority > 1)
			errno = EINVAL;
			return false;
			return EINVAL;
		}

		if (attr->priority < 0)
			priority = THREAD_PRIORITY_LOWEST +
			    (1.0 + attr->priority) *
			    (THREAD_PRIORITY_NORMAL - THREAD_PRIORITY_LOWEST);
		else
			priority = THREAD_PRIORITY_NORMAL +
			    attr->priority *
			    (THREAD_PRIORITY_HIGHEST - THREAD_PRIORITY_NORMAL);
	}

	if ((context = malloc(sizeof(*context))) == NULL) {
	if ((context = malloc(sizeof(*context))) == NULL)
		errno = ENOMEM;
		return false;
		return ENOMEM;
	}

	context->function = function;
	context->object = object;

	*thread = CreateThread(NULL, (attr != NULL ? attr->stackSize : 0),
	    (LPTHREAD_START_ROUTINE)functionWrapper, context, 0, &threadID);

	if (thread == NULL) {
		int errNo;
		int error;

		switch (GetLastError()) {
		case ERROR_NOT_ENOUGH_MEMORY:
			errNo = ENOMEM;
			error = ENOMEM;
			break;
		case ERROR_ACCESS_DENIED:
			errNo = EACCES;
			error = EACCES;
			break;
		default:
			OF_ENSURE(0);
		}

		free(context);
		errno = errNo;
		return false;
		return error;
	}

	if (attr != NULL && attr->priority != 0)
		OF_ENSURE(!SetThreadPriority(*thread, priority));

	return true;
	return 0;
}

bool
int
of_thread_join(of_thread_t thread)
{
	switch (WaitForSingleObject(thread, INFINITE)) {
	case WAIT_OBJECT_0:
		CloseHandle(thread);
		return true;
		return 0;
	case WAIT_FAILED:
		switch (GetLastError()) {
		case ERROR_INVALID_HANDLE:
			errno = EINVAL;
			return false;
			return EINVAL;
		default:
			OF_ENSURE(0);
		}
	default:
		OF_ENSURE(0);
	}
}

bool
int
of_thread_detach(of_thread_t thread)
{
	CloseHandle(thread);

	return true;
	return 0;
}

void
of_thread_set_name(const char *name)
{
}

Modified src/platform/windows/tlskey.m from [c8aecc8bc3] to [a76af40888].

15
16
17
18
19
20
21
22

23
24
25
26




27


28


29
30
31

32
15
16
17
18
19
20
21

22
23
24


25
26
27
28
29
30
31

32
33
34
35

36
37







-
+


-
-
+
+
+
+

+
+
-
+
+


-
+

 * file.
 */

#include "config.h"

#import "tlskey.h"

bool
int
of_tlskey_new(of_tlskey_t *key)
{
	return ((*key = TlsAlloc()) != TLS_OUT_OF_INDEXES);
}
	*key = TlsAlloc();

	if (*key == TLS_OUT_OF_INDEXES)
		return EAGAIN;

	return 0;
}
bool

int
of_tlskey_free(of_tlskey_t key)
{
	return TlsFree(key);
	return (TlsFree(key) ? 0 : EINVAL);
}

Modified src/runtime/amiga-library.h from [1e7c65ebe4] to [65524391cb].

56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
56
57
58
59
60
61
62

63
64
65
66
67
68
69
70
71
72







-










	    void *_Nonnull);
	void *(*_Nonnull __deregister_frame_info)(const void *_Nonnull);
# endif
# ifdef OF_MORPHOS
	void (*_Nonnull __register_frame)(void *_Nonnull);
	void (*_Nonnull __deregister_frame)(void *_Nonnull);
# endif
	int *_Nonnull (*_Nonnull get_errno)(void);
# ifdef OF_AMIGAOS_M68K
	int (*_Nonnull vsnprintf)(char *restrict _Nonnull str, size_t size,
	    const char *_Nonnull restrict fmt, va_list args);
# endif
	int (*_Nonnull atexit)(void (*_Nonnull)(void));
	void (*_Nonnull exit)(int);
};

extern bool objc_init(unsigned int, struct objc_libc *_Nonnull,
    FILE *_Nonnull *_Nonnull);

Modified src/runtime/amiga-library.m from [4cd36fe799] to [174921abc5].

573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
573
574
575
576
577
578
579






580
581
582
583
584
585
586







-
-
-
-
-
-







void
_Unwind_Resume(void *ex)
{
	libc._Unwind_Resume(ex);
}
#endif

int *
objc_get_errno(void)
{
	return libc.get_errno();
}

#ifdef OF_AMIGAOS_M68K
int
snprintf(char *restrict str, size_t size, const char *restrict fmt, ...)
{
	va_list args;
	int ret;

Modified src/runtime/arc.m from [4544515edf] to [0378415cdf].

47
48
49
50
51
52
53
54

55
56
57
58
59
60
61
47
48
49
50
51
52
53

54
55
56
57
58
59
60
61







-
+







}

OF_CONSTRUCTOR()
{
	hashtable = objc_hashtable_new(hash, equal, 2);

#ifdef OF_HAVE_THREADS
	if (!of_spinlock_new(&spinlock))
	if (of_spinlock_new(&spinlock) != 0)
		OBJC_ERROR("Failed to create spinlock!");
#endif
}

id
objc_retain(id object)
{
118
119
120
121
122
123
124
125

126
127
128
129
130
131
132
118
119
120
121
122
123
124

125
126
127
128
129
130
131
132







-
+








id
objc_storeWeak(id *object, id value)
{
	struct weak_ref *old;

#ifdef OF_HAVE_THREADS
	if (!of_spinlock_lock(&spinlock))
	if (of_spinlock_lock(&spinlock) != 0)
		OBJC_ERROR("Failed to lock spinlock!");
#endif

	if (*object != nil &&
	    (old = objc_hashtable_get(hashtable, *object)) != NULL) {
		for (size_t i = 0; i < old->count; i++) {
			if (old->locations[i] == object) {
175
176
177
178
179
180
181
182

183
184
185
186
187
188
189
190
191
192
193
194
195
196

197
198
199
200
201
202
203
204
205

206
207
208
209
210
211
212
175
176
177
178
179
180
181

182
183
184
185
186
187
188
189
190
191
192
193
194
195

196
197
198
199
200
201
202
203
204

205
206
207
208
209
210
211
212







-
+













-
+








-
+







		ref->locations[ref->count++] = object;
	} else
		value = nil;

	*object = value;

#ifdef OF_HAVE_THREADS
	if (!of_spinlock_unlock(&spinlock))
	if (of_spinlock_unlock(&spinlock) != 0)
		OBJC_ERROR("Failed to unlock spinlock!");
#endif

	return value;
}

id
objc_loadWeakRetained(id *object)
{
	id value = nil;
	struct weak_ref *ref;

#ifdef OF_HAVE_THREADS
	if (!of_spinlock_lock(&spinlock))
	if (of_spinlock_lock(&spinlock) != 0)
		OBJC_ERROR("Failed to lock spinlock!");
#endif

	if (*object != nil &&
	    (ref = objc_hashtable_get(hashtable, *object)) != NULL)
		value = *object;

#ifdef OF_HAVE_THREADS
	if (!of_spinlock_unlock(&spinlock))
	if (of_spinlock_unlock(&spinlock) != 0)
		OBJC_ERROR("Failed to unlock spinlock!");
#endif

	if (class_respondsToSelector(object_getClass(value),
	    @selector(retainWeakReference)) && [value retainWeakReference])
		return value;

240
241
242
243
244
245
246
247

248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265

266
267
268
269
270
271
272
273
274
275
276

277
278
279
280
281
282
283
284
285
286
287
288
289
290

291
292
293
240
241
242
243
244
245
246

247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264

265
266
267
268
269
270
271
272
273
274
275

276
277
278
279
280
281
282
283
284
285
286
287
288
289

290
291
292
293







-
+

















-
+










-
+













-
+




void
objc_moveWeak(id *dest, id *src)
{
	struct weak_ref *ref;

#ifdef OF_HAVE_THREADS
	if (!of_spinlock_lock(&spinlock))
	if (of_spinlock_lock(&spinlock) != 0)
		OBJC_ERROR("Failed to lock spinlock!");
#endif

	if (*src != nil &&
	    (ref = objc_hashtable_get(hashtable, *src)) != NULL) {
		for (size_t i = 0; i < ref->count; i++) {
			if (ref->locations[i] == src) {
				ref->locations[i] = dest;
				break;
			}
		}
	}

	*dest = *src;
	*src = nil;

#ifdef OF_HAVE_THREADS
	if (!of_spinlock_unlock(&spinlock))
	if (of_spinlock_unlock(&spinlock) != 0)
		OBJC_ERROR("Failed to unlock spinlock!");
#endif
}

void
objc_zero_weak_references(id value)
{
	struct weak_ref *ref;

#ifdef OF_HAVE_THREADS
	if (!of_spinlock_lock(&spinlock))
	if (of_spinlock_lock(&spinlock) != 0)
		OBJC_ERROR("Failed to lock spinlock!");
#endif

	if ((ref = objc_hashtable_get(hashtable, value)) != NULL) {
		for (size_t i = 0; i < ref->count; i++)
			*ref->locations[i] = nil;

		objc_hashtable_delete(hashtable, value);
		free(ref->locations);
		free(ref);
	}

#ifdef OF_HAVE_THREADS
	if (!of_spinlock_unlock(&spinlock))
	if (of_spinlock_unlock(&spinlock) != 0)
		OBJC_ERROR("Failed to unlock spinlock!");
#endif
}

Modified src/runtime/autorelease.m from [e5ceb906d0] to [0e5c7aa48b].

49
50
51
52
53
54
55
56
57
58



59
60
61
62
63
64
65
49
50
51
52
53
54
55



56
57
58
59
60
61
62
63
64
65







-
-
-
+
+
+







static uintptr_t count = 0;
static uintptr_t size = 0;
#endif

#if !defined(OF_HAVE_COMPILER_TLS) && defined(OF_HAVE_THREADS)
OF_CONSTRUCTOR()
{
	OF_ENSURE(of_tlskey_new(&objectsKey));
	OF_ENSURE(of_tlskey_new(&countKey));
	OF_ENSURE(of_tlskey_new(&sizeKey));
	OF_ENSURE(of_tlskey_new(&objectsKey) == 0);
	OF_ENSURE(of_tlskey_new(&countKey) == 0);
	OF_ENSURE(of_tlskey_new(&sizeKey) == 0);
}
#endif

void *
objc_autoreleasePoolPush()
{
#if !defined(OF_HAVE_COMPILER_TLS) && defined(OF_HAVE_THREADS)
96
97
98
99
100
101
102
103
104


105
106
107
108
109

110
111
112
113
114
115
116
96
97
98
99
100
101
102


103
104
105
106
107
108

109
110
111
112
113
114
115
116







-
-
+
+




-
+








	if (freeMem) {
		free(objects);
		objects = NULL;
#if defined(OF_HAVE_COMPILER_TLS) || !defined(OF_HAVE_THREADS)
		size = 0;
#else
		OF_ENSURE(of_tlskey_set(objectsKey, objects));
		OF_ENSURE(of_tlskey_set(sizeKey, (void *)0));
		OF_ENSURE(of_tlskey_set(objectsKey, objects) == 0);
		OF_ENSURE(of_tlskey_set(sizeKey, (void *)0) == 0);
#endif
	}

#if !defined(OF_HAVE_COMPILER_TLS) && defined(OF_HAVE_THREADS)
	OF_ENSURE(of_tlskey_set(countKey, (void *)count));
	OF_ENSURE(of_tlskey_set(countKey, (void *)count) == 0);
#endif
}

id
_objc_rootAutorelease(id object)
{
#if !defined(OF_HAVE_COMPILER_TLS) && defined(OF_HAVE_THREADS)
125
126
127
128
129
130
131
132
133


134
135
136
137
138
139
140

141
142
143
144
125
126
127
128
129
130
131


132
133
134
135
136
137
138
139

140
141
142
143
144







-
-
+
+






-
+




		else
			size *= 2;

		OF_ENSURE((objects =
		    realloc(objects, size * sizeof(id))) != NULL);

#if !defined(OF_HAVE_COMPILER_TLS) && defined(OF_HAVE_THREADS)
		OF_ENSURE(of_tlskey_set(objectsKey, objects));
		OF_ENSURE(of_tlskey_set(sizeKey, (void *)size));
		OF_ENSURE(of_tlskey_set(objectsKey, objects) == 0);
		OF_ENSURE(of_tlskey_set(sizeKey, (void *)size) == 0);
#endif
	}

	objects[count++] = object;

#if !defined(OF_HAVE_COMPILER_TLS) && defined(OF_HAVE_THREADS)
	OF_ENSURE(of_tlskey_set(countKey, (void *)count));
	OF_ENSURE(of_tlskey_set(countKey, (void *)count) == 0);
#endif

	return object;
}

Modified src/runtime/exception.m from [3255d28641] to [50eac6751c].

244
245
246
247
248
249
250
251

252
253
254
255
256
257
258
244
245
246
247
248
249
250

251
252
253
254
255
256
257
258







-
+







static objc_uncaught_exception_handler_t uncaughtExceptionHandler;
static struct objc_exception emergencyExceptions[NUM_EMERGENCY_EXCEPTIONS];
#ifdef OF_HAVE_THREADS
static of_spinlock_t emergencyExceptionsSpinlock;

OF_CONSTRUCTOR()
{
	if (!of_spinlock_new(&emergencyExceptionsSpinlock))
	if (of_spinlock_new(&emergencyExceptionsSpinlock) != 0)
		OBJC_ERROR("Cannot create spinlock!");
}
#endif

static uint64_t
readULEB128(const uint8_t **ptr)
{
703
704
705
706
707
708
709
710

711
712
713
714
715
716
717

718
719
720
721
722
723
724
725
726
727
728
729
730

731
732
733
734
735
736
737
738
739
740
741
742
743
744
745

746
747
748
749
750
751
752
703
704
705
706
707
708
709

710
711
712
713
714
715
716

717
718
719
720
721
722
723
724
725
726
727
728
729

730
731
732
733
734
735
736
737
738
739
740
741
742
743
744

745
746
747
748
749
750
751
752







-
+






-
+












-
+














-
+







}

static void
emergencyExceptionCleanup(_Unwind_Reason_Code reason,
    struct _Unwind_Exception *ex)
{
#ifdef OF_HAVE_THREADS
	if (!of_spinlock_lock(&emergencyExceptionsSpinlock))
	if (of_spinlock_lock(&emergencyExceptionsSpinlock) != 0)
		OBJC_ERROR("Cannot lock spinlock!");
#endif

	ex->class = 0;

#ifdef OF_HAVE_THREADS
	if (!of_spinlock_unlock(&emergencyExceptionsSpinlock))
	if (of_spinlock_unlock(&emergencyExceptionsSpinlock) != 0)
		OBJC_ERROR("Cannot unlock spinlock!");
#endif
}

void
objc_exception_throw(id object)
{
	struct objc_exception *e = calloc(1, sizeof(*e));
	bool emergency = false;

	if (e == NULL) {
#ifdef OF_HAVE_THREADS
		if (!of_spinlock_lock(&emergencyExceptionsSpinlock))
		if (of_spinlock_lock(&emergencyExceptionsSpinlock) != 0)
			OBJC_ERROR("Cannot lock spinlock!");
#endif

		for (uint_fast8_t i = 0; i < NUM_EMERGENCY_EXCEPTIONS; i++) {
			if (emergencyExceptions[i].exception.class == 0) {
				e = &emergencyExceptions[i];
				e->exception.class = GNUCOBJC_EXCEPTION_CLASS;
				emergency = true;

				break;
			}
		}

#ifdef OF_HAVE_THREADS
		if (!of_spinlock_unlock(&emergencyExceptionsSpinlock))
		if (of_spinlock_unlock(&emergencyExceptionsSpinlock) != 0)
			OBJC_ERROR("Cannot lock spinlock!");
#endif
	}

	if (e == NULL)
		OBJC_ERROR("Not enough memory to allocate exception!");

Modified src/runtime/linklib/linklib.m from [05384cb064] to [8918300072].

25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
25
26
27
28
29
30
31

32
33
34
35
36
37
38







-







#include <proto/exec.h>
#include <proto/intuition.h>

struct ObjFWRTBase;

#import "inline.h"

#include <errno.h>
#include <stdio.h>
#include <stdlib.h>

#if defined(OF_AMIGAOS_M68K)
# include <stabs.h>
# define SYM(name) __asm__("_" name)
#elif defined(OF_MORPHOS)
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
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







-
-
-
+
+
+










-
-
-
-
-
-







{
	struct Library *IntuitionBase = OpenLibrary("intuition.library", 0);

	if (IntuitionBase != NULL) {
		struct EasyStruct easy = {
			.es_StructSize = sizeof(easy),
			.es_Flags = 0,
			.es_Title = (UBYTE *)NULL,
			.es_TextFormat = (UBYTE *)string,
			(UBYTE *)"OK"
			.es_Title = (void *)NULL,
			.es_TextFormat = (void *)string,
			(void *)"OK"
		};

		EasyRequest(NULL, &easy, NULL, arg);

		CloseLibrary(IntuitionBase);
	}

	exit(EXIT_FAILURE);
}

static int *
get_errno(void)
{
	return &errno;
}

static void __attribute__((__used__))
ctor(void)
{
	static bool initialized = false;
	struct objc_libc libc = {
		.malloc = malloc,
		.calloc = calloc,
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
126
127
128
129
130
131
132

133
134
135
136
137
138
139







-







		.__register_frame_info = __register_frame_info,
		.__deregister_frame_info = __deregister_frame_info,
#endif
#ifdef OF_MORPHOS
		.__register_frame = __register_frame,
		.__deregister_frame = __deregister_frame,
#endif
		.get_errno = get_errno,
#ifdef OF_AMIGAOS_M68K
		.vsnprintf = vsnprintf,
#endif
		.atexit = atexit,
		.exit = exit,
	};

Modified src/runtime/misc.m from [aa8c7fb972] to [2faf8bad32].

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
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







+











+

+







 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#include "config.h"

#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>

#include "ObjFWRT.h"
#include "private.h"

#ifdef OF_AMIGAOS
# define USE_INLINE_STDARG
# include <proto/exec.h>
# include <clib/debug_protos.h>
# define __NOLIBBASE__
# define Class IntuitionClass
# include <proto/intuition.h>
# undef Class
# undef __NOLIBBASE__
#endif

static objc_enumeration_mutation_handler_t enumerationMutationHandler = NULL;

void
objc_enumerationMutation(id object)
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
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







+
+
+
+











+

+

-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-

-
+

+
-
-
+
+
+
+








-
+

-
+









#ifdef OF_AMIGAOS
# define BUF_LEN 256
	char title[BUF_LEN];
	char message[BUF_LEN];
	int status;
	va_list args;
	struct Library *IntuitionBase;
# ifdef OF_AMIGAOS4
	struct IntuitionIFace *IIntuition;
# endif
	struct EasyStruct easy;

	status = snprintf(title, BUF_LEN, "ObjFWRT @ %s:%u", file, line);
	if (status <= 0 || status >= BUF_LEN)
		title[0] = '\0';

	va_start(args, format);
	status = vsnprintf(message, BUF_LEN, format, args);
	if (status <= 0 || status >= BUF_LEN)
		message[0] = '\0';
	va_end(args);

# ifndef OF_AMIGAOS4
	kprintf("[%s] %s\n", title, message);
# endif

	IntuitionBase = OpenLibrary("intuition.library", 0);
	if (IntuitionBase != NULL) {
		struct EasyStruct easy = {
			.es_StructSize = sizeof(easy),
			.es_Flags = 0,
			.es_Title = (UBYTE *)title,
			.es_TextFormat = (UBYTE *)"%s",
			(UBYTE *)"OK"
	if ((IntuitionBase = OpenLibrary("intuition.library", 0)) == NULL)
		exit(EXIT_FAILURE);

# ifdef OF_AMIGAOS4
	if ((IIntuition = (struct IntuitionIFace *)GetInterface(IntuitionBase,
	    "main", 1, NULL)) == NULL)
		exit(EXIT_FAILURE);
# endif

	easy.es_StructSize = sizeof(easy);
	easy.es_Flags = 0;
	easy.es_Title = (void *)title;
	easy.es_TextFormat = (void *)"%s";
	easy.es_GadgetFormat = (void *)"OK";
		};

		EasyRequest(NULL, &easy, NULL, (ULONG)message);
	EasyRequest(NULL, &easy, NULL, (ULONG)message);

# ifdef OF_AMIGAOS4
		CloseLibrary(IntuitionBase);
	}
	DropInterface((struct Interface *)IIntuition);
# endif

	CloseLibrary(IntuitionBase);

	exit(EXIT_FAILURE);
# undef BUF_LEN
#else
	va_list args;

	va_start(args, format);

	vfprintf(stderr, "[ObjFWRT @ %s:%u] ", file, line);
	fprintf(stderr, "[ObjFWRT @ %s:%u] ", file, line);
	vfprintf(stderr, format, args);
	vfprintf(stderr, "\n");
	fprintf(stderr, "\n");
	fflush(stderr);

	va_end(args);

	abort();
#endif

	OF_UNREACHABLE
}

Modified src/runtime/private.h from [91ae810d9d] to [cd3ba36b2b].

212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
212
213
214
215
216
217
218






219
220
221
222
223
224
225







-
-
-
-
-
-







		} *_Nonnull buckets[256];
#else
		IMP _Nullable buckets[256];
#endif
	} *_Nonnull buckets[256];
};

#ifdef OBJC_COMPILING_AMIGA_LIBRARY
# undef errno
extern int *_Nonnull objc_get_errno(void);
# define errno (*objc_get_errno())
#endif

extern void objc_register_all_categories(struct objc_symtab *_Nonnull);
extern struct objc_category *_Nullable *_Nullable
    objc_categories_for_class(Class _Nonnull);
extern void objc_unregister_all_categories(void);
extern void objc_initialize_class(Class _Nonnull);
extern void objc_update_dtable(Class _Nonnull);
extern void objc_register_all_classes(struct objc_symtab *_Nonnull);
287
288
289
290
291
292
293
294
295


296
297
298
299
300
301
302
281
282
283
284
285
286
287


288
289
290
291
292
293
294
295
296







-
-
+
+







	uint8_t i = idx >> 8;
	uint8_t j = idx;

	return dtable->buckets[i]->buckets[j];
#endif
}

extern void OF_NO_RETURN_FUNC objc_error(const char *file, unsigned int line,
    const char *format, ...);
extern void OF_NO_RETURN_FUNC objc_error(const char *_Nonnull file,
    unsigned int line, const char *_Nonnull format, ...);
#define OBJC_ERROR(...) objc_error(__FILE__, __LINE__, __VA_ARGS__)

#if defined(OF_ELF)
# if defined(OF_X86_64) || defined(OF_X86) || defined(OF_POWERPC) || \
    defined(OF_ARM64) || defined(OF_ARM) || \
    defined(OF_MIPS64_N64) || defined(OF_MIPS) || \
    defined(OF_SPARC64) || defined(OF_SPARC)

Modified src/runtime/property.m from [6195775ed5] to [ead25184a1].

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
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







-
+












-
+



-
+


















-
+


















-
+







static of_spinlock_t spinlocks[NUM_SPINLOCKS];
#endif

#ifdef OF_HAVE_THREADS
OF_CONSTRUCTOR()
{
	for (size_t i = 0; i < NUM_SPINLOCKS; i++)
		if (!of_spinlock_new(&spinlocks[i]))
		if (of_spinlock_new(&spinlocks[i]) != 0)
			OBJC_ERROR("Failed to initialize spinlocks!");
}
#endif

id
objc_getProperty(id self, SEL _cmd, ptrdiff_t offset, bool atomic)
{
	if (atomic) {
		id *ptr = (id *)(void *)((char *)self + offset);
#ifdef OF_HAVE_THREADS
		unsigned hash = SPINLOCK_HASH(ptr);

		OF_ENSURE(of_spinlock_lock(&spinlocks[hash]));
		OF_ENSURE(of_spinlock_lock(&spinlocks[hash]) == 0);
		@try {
			return [[*ptr retain] autorelease];
		} @finally {
			OF_ENSURE(of_spinlock_unlock(&spinlocks[hash]));
			OF_ENSURE(of_spinlock_unlock(&spinlocks[hash]) == 0);
		}
#else
		return [[*ptr retain] autorelease];
#endif
	}

	return *(id *)(void *)((char *)self + offset);
}

void
objc_setProperty(id self, SEL _cmd, ptrdiff_t offset, id value, bool atomic,
    signed char copy)
{
	if (atomic) {
		id *ptr = (id *)(void *)((char *)self + offset);
#ifdef OF_HAVE_THREADS
		unsigned hash = SPINLOCK_HASH(ptr);

		OF_ENSURE(of_spinlock_lock(&spinlocks[hash]));
		OF_ENSURE(of_spinlock_lock(&spinlocks[hash]) == 0);
		@try {
#endif
			id old = *ptr;

			switch (copy) {
			case 0:
				*ptr = [value retain];
				break;
			case 2:
				*ptr = [value mutableCopy];
				break;
			default:
				*ptr = [value copy];
			}

			[old release];
#ifdef OF_HAVE_THREADS
		} @finally {
			OF_ENSURE(of_spinlock_unlock(&spinlocks[hash]));
			OF_ENSURE(of_spinlock_unlock(&spinlocks[hash]) == 0);
		}
#endif

		return;
	}

	id *ptr = (id *)(void *)((char *)self + offset);
117
118
119
120
121
122
123
124

125
126
127
128

129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145

146
147
148
149

150
151
152
153
154
155
156
117
118
119
120
121
122
123

124
125
126
127

128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144

145
146
147
148

149
150
151
152
153
154
155
156







-
+



-
+
















-
+



-
+







objc_getPropertyStruct(void *dest, const void *src, ptrdiff_t size, bool atomic,
    bool strong)
{
	if (atomic) {
#ifdef OF_HAVE_THREADS
		unsigned hash = SPINLOCK_HASH(src);

		OF_ENSURE(of_spinlock_lock(&spinlocks[hash]));
		OF_ENSURE(of_spinlock_lock(&spinlocks[hash]) == 0);
#endif
		memcpy(dest, src, size);
#ifdef OF_HAVE_THREADS
		OF_ENSURE(of_spinlock_unlock(&spinlocks[hash]));
		OF_ENSURE(of_spinlock_unlock(&spinlocks[hash]) == 0);
#endif

		return;
	}

	memcpy(dest, src, size);
}

void
objc_setPropertyStruct(void *dest, const void *src, ptrdiff_t size, bool atomic,
    bool strong)
{
	if (atomic) {
#ifdef OF_HAVE_THREADS
		unsigned hash = SPINLOCK_HASH(src);

		OF_ENSURE(of_spinlock_lock(&spinlocks[hash]));
		OF_ENSURE(of_spinlock_lock(&spinlocks[hash]) == 0);
#endif
		memcpy(dest, src, size);
#ifdef OF_HAVE_THREADS
		OF_ENSURE(of_spinlock_unlock(&spinlocks[hash]));
		OF_ENSURE(of_spinlock_unlock(&spinlocks[hash]) == 0);
#endif

		return;
	}

	memcpy(dest, src, size);
}

Modified src/runtime/synchronized.m from [106c451b62] to [8b8ee09700].

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
137
138
139
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
137
138
139







-
+













-
+









-
+


-
+









-
+








-
+


-
+















-
+








-
+



-
+










-
+










	struct lock_s *next;
} *locks = NULL;

static of_mutex_t mutex;

OF_CONSTRUCTOR()
{
	if (!of_mutex_new(&mutex))
	if (of_mutex_new(&mutex) != 0)
		OBJC_ERROR("Failed to create mutex!");
}
#endif

int
objc_sync_enter(id object)
{
	if (object == nil)
		return 0;

#ifdef OF_HAVE_THREADS
	struct lock_s *lock;

	if (!of_mutex_lock(&mutex))
	if (of_mutex_lock(&mutex) != 0)
		OBJC_ERROR("Failed to lock mutex!");

	/* Look if we already have a lock */
	for (lock = locks; lock != NULL; lock = lock->next) {
		if (lock->object != object)
			continue;

		lock->count++;

		if (!of_mutex_unlock(&mutex))
		if (of_mutex_unlock(&mutex) != 0)
			OBJC_ERROR("Failed to unlock mutex!");

		if (!of_rmutex_lock(&lock->rmutex))
		if (of_rmutex_lock(&lock->rmutex) != 0)
			OBJC_ERROR("Failed to lock mutex!");

		return 0;
	}

	/* Create a new lock */
	if ((lock = malloc(sizeof(*lock))) == NULL)
		OBJC_ERROR("Failed to allocate memory for mutex!");

	if (!of_rmutex_new(&lock->rmutex))
	if (of_rmutex_new(&lock->rmutex) != 0)
		OBJC_ERROR("Failed to create mutex!");

	lock->object = object;
	lock->count = 1;
	lock->next = locks;

	locks = lock;

	if (!of_mutex_unlock(&mutex))
	if (of_mutex_unlock(&mutex) != 0)
		OBJC_ERROR("Failed to unlock mutex!");

	if (!of_rmutex_lock(&lock->rmutex))
	if (of_rmutex_lock(&lock->rmutex) != 0)
		OBJC_ERROR("Failed to lock mutex!");
#endif

	return 0;
}

int
objc_sync_exit(id object)
{
	if (object == nil)
		return 0;

#ifdef OF_HAVE_THREADS
	struct lock_s *lock, *last = NULL;

	if (!of_mutex_lock(&mutex))
	if (of_mutex_lock(&mutex) != 0)
		OBJC_ERROR("Failed to lock mutex!");

	for (lock = locks; lock != NULL; lock = lock->next) {
		if (lock->object != object) {
			last = lock;
			continue;
		}

		if (!of_rmutex_unlock(&lock->rmutex))
		if (of_rmutex_unlock(&lock->rmutex) != 0)
			OBJC_ERROR("Failed to unlock mutex!");

		if (--lock->count == 0) {
			if (!of_rmutex_free(&lock->rmutex))
			if (of_rmutex_free(&lock->rmutex) != 0)
				OBJC_ERROR("Failed to destroy mutex!");

			if (last != NULL)
				last->next = lock->next;
			if (locks == lock)
				locks = lock->next;

			free(lock);
		}

		if (!of_mutex_unlock(&mutex))
		if (of_mutex_unlock(&mutex) != 0)
			OBJC_ERROR("Failed to unlock mutex!");

		return 0;
	}

	OBJC_ERROR("objc_sync_exit() was called for an object not locked!");
#else
	return 0;
#endif
}

Modified src/runtime/threading.m from [e792c643b3] to [4a1cc07735].

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
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







-
+









-
+






-
+


#import "once.h"

static of_rmutex_t globalMutex;

static void
init(void)
{
	if (!of_rmutex_new(&globalMutex))
	if (of_rmutex_new(&globalMutex) != 0)
		OBJC_ERROR("Failed to create global mutex!");
}

void
objc_global_mutex_lock(void)
{
	static of_once_t once_control = OF_ONCE_INIT;
	of_once(&once_control, init);

	if (!of_rmutex_lock(&globalMutex))
	if (of_rmutex_lock(&globalMutex) != 0)
		OBJC_ERROR("Failed to lock global mutex!");
}

void
objc_global_mutex_unlock(void)
{
	if (!of_rmutex_unlock(&globalMutex))
	if (of_rmutex_unlock(&globalMutex) != 0)
		OBJC_ERROR("Failed to unlock global mutex!");
}

Modified src/socket.m from [d03343d8fd] to [7f38594dbe].

75
76
77
78
79
80
81
82

83
84
85
86

87
88
89
90
91
92
93
75
76
77
78
79
80
81

82
83
84
85

86
87
88
89
90
91
92
93







-
+



-
+







#  endif
# endif
#endif

#if defined(OF_HAVE_THREADS) && defined(OF_AMIGAOS) && !defined(OF_MORPHOS)
OF_CONSTRUCTOR()
{
	if (!of_tlskey_new(&of_socket_base_key))
	if (of_tlskey_new(&of_socket_base_key) != 0)
		@throw [OFInitializationFailedException exception];

# ifdef OF_AMIGAOS4
	if (!of_tlskey_new(&of_socket_interface_key))
	if (of_tlskey_new(&of_socket_interface_key) != 0)
		@throw [OFInitializationFailedException exception];
# endif
}
#endif

#if !defined(OF_AMIGAOS) || defined(OF_MORPHOS) || !defined(OF_HAVE_THREADS)
static void
121
122
123
124
125
126
127
128

129
130
131
132

133
134
135
136
137
138
139
121
122
123
124
125
126
127

128
129
130
131

132
133
134
135
136
137
138
139







-
+



-
+







	if (socInit(ctx, 0x100000) != 0)
		return;

	atexit((void (*)(void))socExit);
# endif

# if defined(OF_HAVE_THREADS) && (!defined(OF_AMIGAOS) || defined(OF_MORPHOS))
	if (!of_mutex_new(&mutex))
	if (of_mutex_new(&mutex) != 0)
		return;

#  ifdef OF_WII
	if (!of_spinlock_new(&spinlock))
	if (of_spinlock_new(&spinlock) != 0)
		return;
#  endif
# endif

	initSuccessful = true;
}

179
180
181
182
183
184
185
186

187
188
189
190
191
192
193
194
195

196
197
198
199
200
201
202
179
180
181
182
183
184
185

186
187
188
189
190
191
192
193
194

195
196
197
198
199
200
201
202







-
+








-
+







	if ((socketInterface = (struct SocketIFace *)
	    GetInterface(socketBase, "main", 1, NULL)) == NULL) {
		CloseLibrary(socketBase);
		return false;
	}
# endif

	if (!of_tlskey_set(of_socket_base_key, socketBase)) {
	if (of_tlskey_set(of_socket_base_key, socketBase) != 0) {
		CloseLibrary(socketBase);
# ifdef OF_AMIGAOS4
		DropInterface((struct Interface *)socketInterface);
# endif
		return false;
	}

# ifdef OF_AMIGAOS4
	if (!of_tlskey_set(of_socket_interface_key, socketInterface)) {
	if (of_tlskey_set(of_socket_interface_key, socketInterface) != 0) {
		CloseLibrary(socketBase);
		DropInterface((struct Interface *)socketInterface);
		return false;
	}
# endif

	return true;
325
326
327
328
329
330
331
332

333
334
335
336
337
338
339
340

341
342
343
344
345
346
347
325
326
327
328
329
330
331

332
333
334
335
336
337
338
339

340
341
342
343
344
345
346
347







-
+







-
+







int
of_getsockname(of_socket_t sock, struct sockaddr *restrict addr,
    socklen_t *restrict addrLen)
{
	int ret;

# if defined(OF_HAVE_THREADS) && (!defined(OF_AMIGAOS) || defined(OF_MORPHOS))
	if (!of_mutex_lock(&mutex))
	if (of_mutex_lock(&mutex) != 0)
		@throw [OFLockFailedException exception];

# endif

	ret = getsockname(sock, addr, addrLen);

# if defined(OF_HAVE_THREADS) && (!defined(OF_AMIGAOS) || defined(OF_MORPHOS))
	if (!of_mutex_unlock(&mutex))
	if (of_mutex_unlock(&mutex) != 0)
		@throw [OFUnlockFailedException exception];
# endif

	return ret;
}
#endif

Modified src/thread.h from [bf84b7cea6] to [821c6c8243].

61
62
63
64
65
66
67
68
69


70
71
72
73


74
75
76
61
62
63
64
65
66
67


68
69
70
71


72
73
74
75
76







-
-
+
+


-
-
+
+



# define of_thread_is_current(t) (t->thread == FindTask(NULL))
extern of_thread_t of_thread_current(void);
#endif

#ifdef __cplusplus
extern "C" {
#endif
extern bool of_thread_attr_init(of_thread_attr_t *attr);
extern bool of_thread_new(of_thread_t *thread, const char *name,
extern int of_thread_attr_init(of_thread_attr_t *attr);
extern int of_thread_new(of_thread_t *thread, const char *name,
    void (*function)(id), id object, const of_thread_attr_t *attr);
extern void of_thread_set_name(const char *name);
extern bool of_thread_join(of_thread_t thread);
extern bool of_thread_detach(of_thread_t thread);
extern int of_thread_join(of_thread_t thread);
extern int of_thread_detach(of_thread_t thread);
#ifdef __cplusplus
}
#endif

Modified src/tlskey.h from [19e6f1fad4] to [bf467b6736].

12
13
14
15
16
17
18


19
20
21
22
23
24
25
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27







+
+







 * Alternatively, it may be distributed under the terms of the GNU General
 * Public License, either version 2 or 3, which can be found in the file
 * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this
 * file.
 */

#include "objfw-defs.h"

#include <errno.h>

#include "platform.h"

#if !defined(OF_HAVE_THREADS) || \
    (!defined(OF_HAVE_PTHREADS) && !defined(OF_WINDOWS) && !defined(OF_AMIGAOS))
# error No thread-local storage available!
#endif
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
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







-
-
+
+













-
+


-
+








-
+


-
+








-
+


-
+







-
+




	struct of_tlskey *next, *previous;
} *of_tlskey_t;
#endif

#ifdef __cplusplus
extern "C" {
#endif
extern bool of_tlskey_new(of_tlskey_t *key);
extern bool of_tlskey_free(of_tlskey_t key);
extern int of_tlskey_new(of_tlskey_t *key);
extern int of_tlskey_free(of_tlskey_t key);
#ifdef __cplusplus
}
#endif

/* TLS keys are inlined for performance. */

#if defined(OF_HAVE_PTHREADS)
static OF_INLINE void *
of_tlskey_get(of_tlskey_t key)
{
	return pthread_getspecific(key);
}

static OF_INLINE bool
static OF_INLINE int
of_tlskey_set(of_tlskey_t key, void *ptr)
{
	return (pthread_setspecific(key, ptr) == 0);
	return pthread_setspecific(key, ptr);
}
#elif defined(OF_WINDOWS)
static OF_INLINE void *
of_tlskey_get(of_tlskey_t key)
{
	return TlsGetValue(key);
}

static OF_INLINE bool
static OF_INLINE int
of_tlskey_set(of_tlskey_t key, void *ptr)
{
	return TlsSetValue(key, ptr);
	return (TlsSetValue(key, ptr) ? 0 : EINVAL);
}
#elif defined(OF_MORPHOS)
static OF_INLINE void *
of_tlskey_get(of_tlskey_t key)
{
	return (void *)TLSGetValue(key);
}

static OF_INLINE bool
static OF_INLINE int
of_tlskey_set(of_tlskey_t key, void *ptr)
{
	return TLSSetValue(key, (APTR)ptr);
	return (TLSSetValue(key, (APTR)ptr) ? 0 : EINVAL);
}
#elif defined(OF_AMIGAOS)
/* Those are too big too inline. */
# ifdef __cplusplus
extern "C" {
# endif
extern void *of_tlskey_get(of_tlskey_t key);
extern bool of_tlskey_set(of_tlskey_t key, void *ptr);
extern int of_tlskey_set(of_tlskey_t key, void *ptr);
# ifdef __cplusplus
}
# endif
#endif

Modified tests/OFStringTests.m from [1ca0b0e0e8] to [bb912e724d].

22
23
24
25
26
27
28




29
30
31
32
33
34
35
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39







+
+
+
+







#include <math.h>

#import "TestsAppDelegate.h"

#import "OFString.h"
#import "OFMutableUTF8String.h"
#import "OFUTF8String.h"

#ifndef INFINITY
# define INFINITY __builtin_inf()
#endif

static OFString *module = nil;
static OFString *whitespace[] = {
	@" \r \t\n\t \tasd  \t \t\t\r\n",
	@" \t\t  \t\t  \t \t"
};
static of_unichar_t ucstr[] = {