ObjFW  Diff

Differences From Artifact [cbacd2f77f]:

To Artifact [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
}