ObjFW  Check-in [dfd52d5220]

Overview
Comment:of_mutex_t -> OFPlainMutex

Also rename of_rmutex_t -> OFPlainRecursiveMutex.

Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | new-naming-convention
Files: files | file ages | folders
SHA3-256: dfd52d5220f098541e8179aae0d7c4c5a3c41828572540de1b28d9e0422c5ba7
User & Date: js on 2021-04-17 16:24:13
Other Links: branch diff | manifest | tags
Context
2021-04-17
16:29
of_spinlock_t -> OFSpinlock check-in: fabf53041a user: js tags: new-naming-convention
16:24
of_mutex_t -> OFPlainMutex check-in: dfd52d5220 user: js tags: new-naming-convention
16:13
of_once_t -> OFOnceControl check-in: 26aa88fc9b user: js tags: new-naming-convention
Changes

Modified src/OFMutex.h from [e51e28c02b] to [5171988a3a].

23
24
25
26
27
28
29
30

31
32
33
34
35
36
37
23
24
25
26
27
28
29

30
31
32
33
34
35
36
37







-
+







/**
 * @class OFMutex OFMutex.h ObjFW/OFMutex.h
 *
 * @brief A class for creating mutual exclusions.
 */
@interface OFMutex: OFObject <OFLocking>
{
	of_mutex_t _mutex;
	OFPlainMutex _mutex;
	bool _initialized;
	OFString *_Nullable _name;
	OF_RESERVE_IVARS(OFMutex, 4)
}

/**
 * @brief Creates a new mutex.

Modified src/OFMutex.m from [8256799039] to [beea68f36f].

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







-
+













-
+















-
+








-
+














-
+







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

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

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

	_initialized = true;

	return self;
}

- (void)dealloc
{
	if (_initialized) {
		int error = of_mutex_free(&_mutex);
		int error = OFPlainMutexFree(&_mutex);

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

			@throw [OFStillLockedException exceptionWithLock: self];
		}
	}

	[_name release];

	[super dealloc];
}

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

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

- (bool)tryLock
{
	int error = of_mutex_trylock(&_mutex);
	int error = OFPlainMutexTryLock(&_mutex);

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

	return true;
}

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

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

- (OFString *)description

Modified src/OFRecursiveMutex.h from [d6ed860e64] to [7583593446].

25
26
27
28
29
30
31
32

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

32
33
34
35
36
37
38
39
40
41
42
43
44
45







-
+













 *
 * @brief A class for creating mutual exclusions which can be entered
 *	  recursively.
 */
OF_SUBCLASSING_RESTRICTED
@interface OFRecursiveMutex: OFObject <OFLocking>
{
	of_rmutex_t _rmutex;
	OFPlainRecursiveMutex _rmutex;
	bool _initialized;
	OFString *_Nullable _name;
}

/**
 * @brief Creates a new recursive mutex.
 *
 * @return A new autoreleased recursive mutex.
 */
+ (instancetype)mutex;
@end

OF_ASSUME_NONNULL_END

Modified src/OFRecursiveMutex.m from [14f9082e7e] to [f6b5e7fc87].

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







-
+













-
+















-
+








-
+














-
+







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

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

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

	_initialized = true;

	return self;
}

- (void)dealloc
{
	if (_initialized) {
		int error = of_rmutex_free(&_rmutex);
		int error = OFPlainRecursiveMutexFree(&_rmutex);

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

			@throw [OFStillLockedException exceptionWithLock: self];
		}
	}

	[_name release];

	[super dealloc];
}

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

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

- (bool)tryLock
{
	int error = of_rmutex_trylock(&_rmutex);
	int error = OFPlainRecursiveMutexTryLock(&_rmutex);

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

	return true;
}

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

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

- (OFString *)description

Modified src/condition.h from [0d9f4192a1] to [1ee99bce0d].

49
50
51
52
53
54
55
56

57
58

59
60
61

62
63

64
65
66
67
68
49
50
51
52
53
54
55

56
57

58
59
60

61
62

63
64
65
66
67
68







-
+

-
+


-
+

-
+






#ifdef __cplusplus
extern "C" {
#endif
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_wait(of_condition_t *condition, OFPlainMutex *mutex);
extern int of_condition_timed_wait(of_condition_t *condition,
    of_mutex_t *mutex, OFTimeInterval timeout);
    OFPlainMutex *mutex, OFTimeInterval timeout);
#ifdef OF_AMIGAOS
extern int of_condition_wait_or_signal(of_condition_t *condition,
    of_mutex_t *mutex, ULONG *signalMask);
    OFPlainMutex *mutex, ULONG *signalMask);
extern int of_condition_timed_wait_or_signal(of_condition_t *condition,
    of_mutex_t *mutex, OFTimeInterval timeout, ULONG *signalMask);
    OFPlainMutex *mutex, OFTimeInterval timeout, ULONG *signalMask);
#endif
extern int of_condition_free(of_condition_t *condition);
#ifdef __cplusplus
}
#endif

Modified src/exceptions/OFException.m from [c381d0d5f6] to [7a4b36018b].

65
66
67
68
69
70
71
72

73
74
75
76

77
78
79
80
81

82
83
84
85
86
87
88
65
66
67
68
69
70
71

72
73
74
75

76
77
78
79
80

81
82
83
84
85
86
87
88







-
+



-
+




-
+







extern uintptr_t _Unwind_GetIP(struct _Unwind_Context *);
#else
extern int _Unwind_VRS_Get(struct _Unwind_Context *, int, uint32_t, int,
    void *);
#endif

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

OF_CONSTRUCTOR()
{
	OF_ENSURE(of_mutex_new(&mutex) == 0);
	OF_ENSURE(OFPlainMutexNew(&mutex) == 0);
}

OF_DESTRUCTOR()
{
	of_mutex_free(&mutex);
	OFPlainMutexFree(&mutex);
}
#endif

OFString *
of_strerror(int errNo)
{
	OFString *ret;
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
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







-
+









-
+







	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) != 0)
	if (OFPlainMutexLock(&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) != 0)
		if (OFPlainMutexUnlock(&mutex) != 0)
			@throw [OFUnlockFailedException exception];
	}
# endif
#endif

	return ret;
}

Modified src/mutex.h from [b00f51f16c] to [3c75ad2bae].

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







-
+


-
+


-
+









-
+








-
+



-
+

-
+





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







# error No mutexes available!
#endif

#import "macros.h"

#if defined(OF_HAVE_PTHREADS)
# include <pthread.h>
typedef pthread_mutex_t of_mutex_t;
typedef pthread_mutex_t OFPlainMutex;
#elif defined(OF_WINDOWS)
# include <windows.h>
typedef CRITICAL_SECTION of_mutex_t;
typedef CRITICAL_SECTION OFPlainMutex;
#elif defined(OF_AMIGAOS)
# include <exec/semaphores.h>
typedef struct SignalSemaphore of_mutex_t;
typedef struct SignalSemaphore OFPlainMutex;
#endif

#if defined(OF_HAVE_ATOMIC_OPS)
# import "atomic.h"
typedef volatile int of_spinlock_t;
# define OF_SPINCOUNT 10
#elif defined(OF_HAVE_PTHREAD_SPINLOCKS)
typedef pthread_spinlock_t of_spinlock_t;
#else
typedef of_mutex_t of_spinlock_t;
typedef OFPlainMutex of_spinlock_t;
#endif

#ifdef OF_HAVE_SCHED_YIELD
# include <sched.h>
#endif

#if defined(OF_HAVE_RECURSIVE_PTHREAD_MUTEXES) || defined(OF_WINDOWS) || \
    defined(OF_AMIGAOS)
# define of_rmutex_t of_mutex_t
# define OFPlainRecursiveMutex OFPlainMutex
#else
# import "tlskey.h"
typedef struct {
	of_mutex_t mutex;
	OFPlainMutex mutex;
	OFTLSKey count;
} of_rmutex_t;
} OFPlainRecursiveMutex;
#endif

#ifdef __cplusplus
extern "C" {
#endif
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);
extern int OFPlainMutexNew(OFPlainMutex *mutex);
extern int OFPlainMutexLock(OFPlainMutex *mutex);
extern int OFPlainMutexTryLock(OFPlainMutex *mutex);
extern int OFPlainMutexUnlock(OFPlainMutex *mutex);
extern int OFPlainMutexFree(OFPlainMutex *mutex);
extern int OFPlainRecursiveMutexNew(OFPlainRecursiveMutex *rmutex);
extern int OFPlainRecursiveMutexLock(OFPlainRecursiveMutex *rmutex);
extern int OFPlainRecursiveMutexTryLock(OFPlainRecursiveMutex *rmutex);
extern int OFPlainRecursiveMutexUnlock(OFPlainRecursiveMutex *rmutex);
extern int OFPlainRecursiveMutexFree(OFPlainRecursiveMutex *rmutex);
#ifdef __cplusplus
}
#endif

/* Spinlocks are inlined for performance. */

static OF_INLINE void
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
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







-
+
















-
+




















-
+















-
+











-
+


{
#if defined(OF_HAVE_ATOMIC_OPS)
	*spinlock = 0;
	return 0;
#elif defined(OF_HAVE_PTHREAD_SPINLOCKS)
	return pthread_spin_init(spinlock, 0);
#else
	return of_mutex_new(spinlock);
	return OFPlainMutexNew(spinlock);
#endif
}

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 0;
	}

	return EBUSY;
#elif defined(OF_HAVE_PTHREAD_SPINLOCKS)
	return pthread_spin_trylock(spinlock);
#else
	return of_mutex_trylock(spinlock);
	return OFPlainMutexTryLock(spinlock);
#endif
}

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) == 0)
			return 0;

	while (of_spinlock_trylock(spinlock) == EBUSY)
		OFYieldThread();

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

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 ? 0 : EINVAL);
#elif defined(OF_HAVE_PTHREAD_SPINLOCKS)
	return pthread_spin_unlock(spinlock);
#else
	return of_mutex_unlock(spinlock);
	return OFPlainMutexUnlock(spinlock);
#endif
}

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

Modified src/platform/amiga/condition.m from [dc620431f9] to [cc3230123e].

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







-
+







-
+














-
+









-
+















-
+









-
-
+
+







		Permit();
	}

	return 0;
}

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

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

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

	if (waitingTask.sigBit == -1)
		return EAGAIN;

	Forbid();

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

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

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

	FreeSignal(waitingTask.sigBit);

	Permit();

	return error;
}

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

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

int
of_condition_timed_wait_or_signal(of_condition_t *condition, of_mutex_t *mutex,
    OFTimeInterval timeout, ULONG *signalMask)
of_condition_timed_wait_or_signal(of_condition_t *condition,
    OFPlainMutex *mutex, OFTimeInterval timeout, ULONG *signalMask)
{
	struct of_condition_waiting_task waitingTask = {
		.task = FindTask(NULL),
		.sigBit = AllocSignal(-1)
	};
	struct MsgPort port = {
		.mp_Node = {
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
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







-
+












-
+







	    (struct IORequest *)&request, 0) != 0) {
		error = EAGAIN;
		goto fail;
	}

	Forbid();

	if ((error = of_mutex_unlock(mutex)) != 0) {
	if ((error = OFPlainMutexUnlock(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))
		error = of_mutex_lock(mutex);
		error = OFPlainMutexLock(mutex);
	else if (mask & (1ul << port.mp_SigBit))
		error = ETIMEDOUT;
	else
		/*
		 * This should not happen - it means something interrupted the
		 * Wait(), so the best we can do is return EINTR.
		 */

Modified src/platform/amiga/mutex.m from [e7b8301e49] to [e655c5c2cf].

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







-
+







-
+







-
+








-
+







-
+





-
+

-
+



-
+

-
+



-
+

-
+



-
+

-
+



-
+

-
+

#include <errno.h>

#import "mutex.h"

#include <proto/exec.h>

int
of_mutex_new(of_mutex_t *mutex)
OFPlainMutexNew(OFPlainMutex *mutex)
{
	InitSemaphore(mutex);

	return 0;
}

int
of_mutex_lock(of_mutex_t *mutex)
OFPlainMutexLock(OFPlainMutex *mutex)
{
	ObtainSemaphore(mutex);

	return 0;
}

int
of_mutex_trylock(of_mutex_t *mutex)
OFPlainMutexTryLock(OFPlainMutex *mutex)
{
	if (!AttemptSemaphore(mutex))
		return EBUSY;

	return 0;
}

int
of_mutex_unlock(of_mutex_t *mutex)
OFPlainMutexUnlock(OFPlainMutex *mutex)
{
	ReleaseSemaphore(mutex);

	return 0;
}

int
of_mutex_free(of_mutex_t *mutex)
OFPlainMutexFree(OFPlainMutex *mutex)
{
	return 0;
}

int
of_rmutex_new(of_rmutex_t *rmutex)
OFPlainRecursiveMutexNew(OFPlainRecursiveMutex *rmutex)
{
	return of_mutex_new(rmutex);
	return OFPlainMutexNew(rmutex);
}

int
of_rmutex_lock(of_rmutex_t *rmutex)
OFPlainRecursiveMutexLock(OFPlainRecursiveMutex *rmutex)
{
	return of_mutex_lock(rmutex);
	return OFPlainMutexLock(rmutex);
}

int
of_rmutex_trylock(of_rmutex_t *rmutex)
OFPlainRecursiveMutexTryLock(OFPlainRecursiveMutex *rmutex)
{
	return of_mutex_trylock(rmutex);
	return OFPlainMutexTryLock(rmutex);
}

int
of_rmutex_unlock(of_rmutex_t *rmutex)
OFPlainRecursiveMutexUnlock(OFPlainRecursiveMutex *rmutex)
{
	return of_mutex_unlock(rmutex);
	return OFPlainMutexUnlock(rmutex);
}

int
of_rmutex_free(of_rmutex_t *rmutex)
OFPlainRecursiveMutexFree(OFPlainRecursiveMutex *rmutex)
{
	return of_mutex_free(rmutex);
	return OFPlainMutexFree(rmutex);
}

Modified src/platform/posix/condition.m from [7ce4083f77] to [04e776f8bc].

32
33
34
35
36
37
38
39

40
41
42
43
44
45

46
47
48
49
50
51
52
32
33
34
35
36
37
38

39
40
41
42
43
44

45
46
47
48
49
50
51
52







-
+





-
+







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

int
of_condition_wait(of_condition_t *condition, of_mutex_t *mutex)
of_condition_wait(of_condition_t *condition, OFPlainMutex *mutex)
{
	return pthread_cond_wait(condition, mutex);
}

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

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

Modified src/platform/posix/mutex.m from [292d31cec6] to [c8763c1f31].

14
15
16
17
18
19
20
21

22
23
24
25
26
27

28
29
30
31
32
33

34
35
36
37
38
39

40
41
42
43
44
45

46
47
48
49
50
51
52

53
54
55
56
57
58
59
14
15
16
17
18
19
20

21
22
23
24
25
26

27
28
29
30
31
32

33
34
35
36
37
38

39
40
41
42
43
44

45
46
47
48
49
50
51

52
53
54
55
56
57
58
59







-
+





-
+





-
+





-
+





-
+






-
+







 */

#include "config.h"

#import "mutex.h"

int
of_mutex_new(of_mutex_t *mutex)
OFPlainMutexNew(OFPlainMutex *mutex)
{
	return pthread_mutex_init(mutex, NULL);
}

int
of_mutex_lock(of_mutex_t *mutex)
OFPlainMutexLock(OFPlainMutex *mutex)
{
	return pthread_mutex_lock(mutex);
}

int
of_mutex_trylock(of_mutex_t *mutex)
OFPlainMutexTryLock(OFPlainMutex *mutex)
{
	return pthread_mutex_trylock(mutex);
}

int
of_mutex_unlock(of_mutex_t *mutex)
OFPlainMutexUnlock(OFPlainMutex *mutex)
{
	return pthread_mutex_unlock(mutex);
}

int
of_mutex_free(of_mutex_t *mutex)
OFPlainMutexFree(OFPlainMutex *mutex)
{
	return pthread_mutex_destroy(mutex);
}

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

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

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







+
+
+
+
-
+
+
+

-
+



-
+

-
+



-
-
-
-
-
+
-
-

-
+



-
+



-
+









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












-
+



-
+







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















-
+






-
+



-
+








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

	return 0;
}

int
OFPlainRecursiveMutexLock(OFPlainRecursiveMutex *rmutex)
{
	return OFPlainMutexLock(rmutex);
}
of_rmutex_lock(of_rmutex_t *rmutex)

int
OFPlainRecursiveMutexTryLock(OFPlainRecursiveMutex *rmutex)
{
	return of_mutex_lock(rmutex);
	return OFPlainMutexTryLock(rmutex);
}

int
of_rmutex_trylock(of_rmutex_t *rmutex)
OFPlainRecursiveMutexUnlock(OFPlainRecursiveMutex *rmutex)
{
	return of_mutex_trylock(rmutex);
	return OFPlainMutexUnlock(rmutex);
}

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

OFPlainRecursiveMutexFree(OFPlainRecursiveMutex *rmutex)
int
of_rmutex_free(of_rmutex_t *rmutex)
{
	return of_mutex_free(rmutex);
	return OFPlainMutexFree(rmutex);
}
#else
int
of_rmutex_new(of_rmutex_t *rmutex)
OFPlainRecursiveMutexNew(OFPlainRecursiveMutex *rmutex)
{
	int error;

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

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

	return 0;
}

int
OFPlainRecursiveMutexLock(OFPlainRecursiveMutex *rmutex)
{
	uintptr_t count = (uintptr_t)OFTLSKeyGet(rmutex->count);
	int error;
of_rmutex_lock(of_rmutex_t *rmutex)

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

		return 0;
	}

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

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

	return 0;
}

int
OFPlainRecursiveMutexTryLock(OFPlainRecursiveMutex *rmutex)
{
	uintptr_t count = (uintptr_t)OFTLSKeyGet(rmutex->count);
	int error;

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

		return 0;
	}

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

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

	return 0;
}

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

OFPlainRecursiveMutexUnlock(OFPlainRecursiveMutex *rmutex)
	if (count > 0) {
		if ((error = OFTLSKeySet(rmutex->count,
		    (void *)(count + 1))) != 0)
			return error;

		return 0;
	}

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

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

	return 0;
}

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

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

		return 0;
	}

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

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

	return 0;
}

int
of_rmutex_free(of_rmutex_t *rmutex)
OFPlainRecursiveMutexFree(OFPlainRecursiveMutex *rmutex)
{
	int error;

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

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

	return 0;
}
#endif

Modified src/platform/windows/condition.m from [595cdc3d8b] to [33e65b6da7].

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







-
+




-
+








-
+













-
+





-
+








-
+







		}
	}

	return 0;
}

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

	if ((error = of_mutex_unlock(mutex)) != 0)
	if ((error = OFPlainMutexUnlock(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);
		return OFPlainMutexLock(mutex);
	case WAIT_FAILED:
		switch (GetLastError()) {
		case ERROR_INVALID_HANDLE:
			return EINVAL;
		default:
			OF_ENSURE(0);
		}
	default:
		OF_ENSURE(0);
	}
}

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

	if ((error = of_mutex_unlock(mutex)) != 0)
	if ((error = OFPlainMutexUnlock(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);
		return OFPlainMutexLock(mutex);
	case WAIT_TIMEOUT:
		return ETIMEDOUT;
	case WAIT_FAILED:
		switch (GetLastError()) {
		case ERROR_INVALID_HANDLE:
			return EINVAL;
		default:

Modified src/platform/windows/mutex.m from [ed38f771ab] to [32f709f554].

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







-
+







-
+







-
+








-
+







-
+







-
+

-
+



-
+

-
+



-
+

-
+



-
+

-
+



-
+

-
+

#include <errno.h>

#import "mutex.h"

#include <windows.h>

int
of_mutex_new(of_mutex_t *mutex)
OFPlainMutexNew(OFPlainMutex *mutex)
{
	InitializeCriticalSection(mutex);

	return 0;
}

int
of_mutex_lock(of_mutex_t *mutex)
OFPlainMutexLock(OFPlainMutex *mutex)
{
	EnterCriticalSection(mutex);

	return 0;
}

int
of_mutex_trylock(of_mutex_t *mutex)
OFPlainMutexTryLock(OFPlainMutex *mutex)
{
	if (!TryEnterCriticalSection(mutex))
		return EBUSY;

	return 0;
}

int
of_mutex_unlock(of_mutex_t *mutex)
OFPlainMutexUnlock(OFPlainMutex *mutex)
{
	LeaveCriticalSection(mutex);

	return 0;
}

int
of_mutex_free(of_mutex_t *mutex)
OFPlainMutexFree(OFPlainMutex *mutex)
{
	DeleteCriticalSection(mutex);

	return 0;
}

int
of_rmutex_new(of_rmutex_t *rmutex)
OFPlainRecursiveMutexNew(OFPlainRecursiveMutex *rmutex)
{
	return of_mutex_new(rmutex);
	return OFPlainMutexNew(rmutex);
}

int
of_rmutex_lock(of_rmutex_t *rmutex)
OFPlainRecursiveMutexLock(OFPlainRecursiveMutex *rmutex)
{
	return of_mutex_lock(rmutex);
	return OFPlainMutexLock(rmutex);
}

int
of_rmutex_trylock(of_rmutex_t *rmutex)
OFPlainRecursiveMutexTryLock(OFPlainRecursiveMutex *rmutex)
{
	return of_mutex_trylock(rmutex);
	return OFPlainMutexTryLock(rmutex);
}

int
of_rmutex_unlock(of_rmutex_t *rmutex)
OFPlainRecursiveMutexUnlock(OFPlainRecursiveMutex *rmutex)
{
	return of_mutex_unlock(rmutex);
	return OFPlainMutexUnlock(rmutex);
}

int
of_rmutex_free(of_rmutex_t *rmutex)
OFPlainRecursiveMutexFree(OFPlainRecursiveMutex *rmutex)
{
	return of_mutex_free(rmutex);
	return OFPlainMutexFree(rmutex);
}

Modified src/runtime/synchronized.m from [fe8bbba7b5] to [0034717236].

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







-
-
-
-
-
+
+
+
+
+


-
+



-
+











-
+

-
+









-
+


-
+









-
+








-
+


-
+













-
+

-
+








-
+



-
+










-
+











#import "ObjFWRT.h"
#import "private.h"

#ifdef OF_HAVE_THREADS
# import "mutex.h"

static struct lock_s {
	id	      object;
	int	      count;
	of_rmutex_t   rmutex;
	struct lock_s *next;
static struct lock {
	id object;
	int count;
	OFPlainRecursiveMutex rmutex;
	struct lock *next;
} *locks = NULL;

static of_mutex_t mutex;
static OFPlainMutex mutex;

OF_CONSTRUCTOR()
{
	if (of_mutex_new(&mutex) != 0)
	if (OFPlainMutexNew(&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;
	struct lock *lock;

	if (of_mutex_lock(&mutex) != 0)
	if (OFPlainMutexLock(&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) != 0)
		if (OFPlainMutexUnlock(&mutex) != 0)
			OBJC_ERROR("Failed to unlock mutex!");

		if (of_rmutex_lock(&lock->rmutex) != 0)
		if (OFPlainRecursiveMutexLock(&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) != 0)
	if (OFPlainRecursiveMutexNew(&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) != 0)
	if (OFPlainMutexUnlock(&mutex) != 0)
		OBJC_ERROR("Failed to unlock mutex!");

	if (of_rmutex_lock(&lock->rmutex) != 0)
	if (OFPlainRecursiveMutexLock(&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;
	struct lock *lock, *last = NULL;

	if (of_mutex_lock(&mutex) != 0)
	if (OFPlainMutexLock(&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) != 0)
		if (OFPlainRecursiveMutexUnlock(&lock->rmutex) != 0)
			OBJC_ERROR("Failed to unlock mutex!");

		if (--lock->count == 0) {
			if (of_rmutex_free(&lock->rmutex) != 0)
			if (OFPlainRecursiveMutexFree(&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) != 0)
		if (OFPlainMutexUnlock(&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 [50e87d61c7] to [04a725fac0].

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







-
+




-
+









-
+






-
+


#include <stdlib.h>

#import "ObjFWRT.h"
#import "private.h"
#import "mutex.h"
#import "once.h"

static of_rmutex_t globalMutex;
static OFPlainRecursiveMutex globalMutex;

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

void
objc_global_mutex_lock(void)
{
	static OFOnceControl onceControl = OFOnceControlInitValue;
	OFOnce(&onceControl, init);

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

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