ns-3 Direct Code Execution
Home
Tutorials ▼
Docs ▼
Wiki
Manual
Develop ▼
API
Bugs
API
Main Page
Related Pages
Namespaces
Classes
Files
File List
File Members
All
Classes
Namespaces
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Friends
Macros
Pages
dce-pthread-mutex.cc
Go to the documentation of this file.
1
#include "
dce-pthread.h
"
2
#include "
utils.h
"
3
#include "
process.h
"
4
#include "
dce-manager.h
"
5
#include "ns3/assert.h"
6
#include "ns3/log.h"
7
#include <stdint.h>
8
#include <errno.h>
9
10
NS_LOG_COMPONENT_DEFINE
(
"PthreadMutex"
);
11
12
using namespace
ns3;
13
14
struct
PthreadMutexAttr
15
{
16
uint8_t
type
;
17
};
18
19
static
uint32_t
20
MutexToMid
(
const
pthread_mutex_t *mutex)
21
{
22
NS_ASSERT (
sizeof
(pthread_mutex_t) >= 4);
23
if
(mutex != 0)
24
{
25
const
uint32_t *pmid = (
const
uint32_t *)mutex;
26
return
*pmid;
27
}
28
return
0;
29
}
30
static
void
31
MidToMutex
(uint32_t mid, pthread_mutex_t *mutex)
32
{
33
uint32_t *pmid = (uint32_t *)mutex;
34
*pmid = mid;
35
}
36
37
static
void
38
PthreadMutexInitStatic
(pthread_mutex_t *mutex)
39
{
40
Thread
*current =
Current
();
41
NS_LOG_FUNCTION (mutex);
42
// This method initializes the mutex fully when it has been
43
// initialized with PTHREAD_MUTEX_INITIALIZER.
44
struct
Mutex
*mtx =
new
Mutex
();
45
switch
(mutex->__data.__kind)
46
{
47
case
PTHREAD_MUTEX_RECURSIVE:
48
NS_LOG_DEBUG (
"recursive"
);
49
mtx->
type
=
Mutex::RECURSIVE
;
50
break
;
51
default
:
52
NS_LOG_DEBUG (
"normal"
);
53
mtx->
type
=
Mutex::NORMAL
;
54
break
;
55
}
56
mtx->
mid
= current->
process
->
nextMid
;
57
current->
process
->
nextMid
++;
58
mtx->
count
= 0;
59
mtx->
waiting
.clear ();
60
mtx->
current
= 0;
61
current->
process
->
mutexes
.push_back (mtx);
62
MidToMutex
(mtx->
mid
, mutex);
63
}
64
65
static
struct
Mutex
*
66
SearchMutex
(pthread_mutex_t *mutex)
67
{
68
Thread
*current =
Current
();
69
if
(mutex == 0)
70
{
71
return
0;
72
}
73
if
(
MutexToMid
(mutex) == 0)
74
{
75
// this is a mutex initialized with PTHREAD_MUTEX_INITIALIZER
76
PthreadMutexInitStatic
(mutex);
77
}
78
uint32_t mid =
MutexToMid
(mutex);
79
for
(uint32_t i = 0; i < current->
process
->
mutexes
.size (); ++i)
80
{
81
struct
Mutex
*mtx = current->
process
->
mutexes
[i];
82
if
(mtx->
mid
== mid)
83
{
84
return
mtx;
85
}
86
}
87
return
0;
88
}
89
90
int
dce_pthread_mutex_init
(pthread_mutex_t *mutex,
91
const
pthread_mutexattr_t *attribute)
92
{
93
Thread
*current =
Current
();
94
NS_LOG_FUNCTION (current <<
UtilsGetNodeId
() << mutex << attribute);
95
NS_ASSERT (current != 0);
96
if
(mutex == 0)
97
{
98
return
EINVAL;
99
}
100
struct
PthreadMutexAttr
*attr = (
struct
PthreadMutexAttr
*)attribute;
101
if
(attr != 0
102
&& attr->
type
!= PTHREAD_MUTEX_RECURSIVE
103
&& attr->
type
!= PTHREAD_MUTEX_NORMAL)
104
{
105
return
EINVAL;
106
}
107
/* Note: there is no way to detect a second attempt to initialize
108
* a mutex because there is no way to detect the difference between
109
* a mutex initialized correctly and a mutex un-initialized but filled
110
* with random garbage which happens to look like correctly-initialized
111
* data. So, we don't even try to return EBUSY.
112
*/
113
struct
Mutex
*mtx =
new
Mutex
();
114
mtx->
mid
= current->
process
->
nextMid
;
115
current->
process
->
nextMid
++;
116
if
(attr == 0 || attr->
type
!= PTHREAD_MUTEX_RECURSIVE)
117
{
118
mtx->
type
=
Mutex::NORMAL
;
119
}
120
else
if
(attr != 0 || attr->
type
== PTHREAD_MUTEX_RECURSIVE)
121
{
122
mtx->
type
=
Mutex::RECURSIVE
;
123
}
124
else
125
{
126
NS_ASSERT (
false
);
127
}
128
mtx->
count
= 0;
129
mtx->
waiting
.clear ();
130
mtx->
current
= 0;
131
current->
process
->
mutexes
.push_back (mtx);
132
133
MidToMutex
(mtx->
mid
, mutex);
134
135
return
0;
136
}
137
int
dce_pthread_mutex_destroy
(pthread_mutex_t *mutex)
138
{
139
Thread
*current =
Current
();
140
NS_LOG_FUNCTION (current <<
UtilsGetNodeId
() << mutex);
141
NS_ASSERT (current != 0);
142
struct
Mutex
*mtx =
SearchMutex
(mutex);
143
if
(mtx == 0)
144
{
145
return
EINVAL;
146
}
147
if
(mtx->
current
!= 0 || !mtx->
waiting
.empty ())
148
{
149
/* Someone (potentially us) is holding this mutex
150
* or someone is waiting for this mutex.
151
*/
152
return
EBUSY;
153
}
154
// If no one is holding this mutex, its count should be zero.
155
NS_ASSERT (mtx->
count
== 0);
156
157
for
(std::vector<struct Mutex *>::iterator i = current->
process
->
mutexes
.begin ();
158
i != current->
process
->
mutexes
.end (); ++i)
159
{
160
if
(mtx == *i)
161
{
162
delete
mtx;
163
mtx = 0;
164
current->
process
->
mutexes
.erase (i);
165
break
;
166
}
167
}
168
NS_ASSERT (mtx == 0);
169
MidToMutex
(2, mutex);
170
171
return
0;
172
}
173
int
dce_pthread_mutex_lock
(pthread_mutex_t *mutex)
174
{
175
Thread
*current =
Current
();
176
NS_LOG_FUNCTION (current <<
UtilsGetNodeId
() << mutex);
177
NS_ASSERT (current != 0);
178
struct
Mutex
*mtx =
SearchMutex
(mutex);
179
if
(mtx == 0)
180
{
181
return
EINVAL;
182
}
183
if
(current == mtx->
current
)
184
{
185
if
(mtx->
type
==
Mutex::RECURSIVE
)
186
{
187
mtx->
count
++;
188
return
0;
189
}
190
else
if
(mtx->
type
==
Mutex::NORMAL
)
191
{
192
return
EDEADLK;
193
}
194
else
195
{
196
NS_ASSERT (
false
);
197
}
198
}
199
while
(mtx->
current
!= 0)
200
{
201
mtx->
waiting
.push_back (current);
202
current->
process
->
manager
->
Wait
();
203
mtx->
waiting
.remove (current);
204
}
205
NS_ASSERT (mtx->
current
== 0);
206
mtx->
current
= current;
207
mtx->
count
++;
208
209
return
0;
210
}
211
int
dce_pthread_mutex_trylock
(pthread_mutex_t *mutex)
212
{
213
Thread
*current =
Current
();
214
NS_LOG_FUNCTION (current <<
UtilsGetNodeId
() << mutex);
215
NS_ASSERT (current != 0);
216
struct
Mutex
*mtx =
SearchMutex
(mutex);
217
if
(mtx == 0)
218
{
219
return
EINVAL;
220
}
221
if
(mtx->
type
==
Mutex::RECURSIVE
)
222
{
223
if
(mtx->
current
== 0)
224
{
225
mtx->
current
= current;
226
mtx->
count
++;
227
return
0;
228
}
229
else
if
(mtx->
current
== current)
230
{
231
mtx->
count
++;
232
return
0;
233
}
234
else
235
{
236
return
EBUSY;
237
}
238
}
239
else
if
(mtx->
type
==
Mutex::NORMAL
)
240
{
241
if
(mtx->
current
== 0)
242
{
243
mtx->
count
++;
244
mtx->
current
= current;
245
return
0;
246
}
247
else
248
{
249
// even if mtx->current == current
250
// according to IEEE Std 1003.1, 2004
251
return
EBUSY;
252
}
253
}
254
else
255
{
256
NS_ASSERT (
false
);
257
}
258
// quiet compiler.
259
return
0;
260
}
261
int
dce_pthread_mutex_unlock
(pthread_mutex_t *mutex)
262
{
263
Thread
*current =
Current
();
264
NS_LOG_FUNCTION (current <<
UtilsGetNodeId
() << mutex);
265
NS_ASSERT (current != 0);
266
struct
Mutex
*mtx =
SearchMutex
(mutex);
267
if
(mtx == 0)
268
{
269
return
EINVAL;
270
}
271
if
(mtx->
current
== 0
272
|| mtx->
current
!= current)
273
{
274
return
EPERM;
275
}
276
mtx->
count
--;
277
if
(mtx->
count
== 0)
278
{
279
mtx->
current
= 0;
280
// Now, we tell the first waiting thread that
281
// it can potentially take the lock. Note that
282
// there are lots of different possible policies
283
// here. We could wake up everybody and let the
284
// process scheduler pick the highest priority
285
// thread, we could attempt to find a better candidate
286
// here locally to avoid waking up lots of threads only
287
// to bring them back to sleep after they wake up because
288
// they just realized that someone stole the lock from
289
// them, etc. What we do, instead, is implement the simplest
290
// "fair" policy by ensuring that every thread
291
// is woken up in FIFO order.
292
Thread
*waiting = mtx->
waiting
.front ();
293
if
(waiting != 0)
294
{
295
current->
process
->
manager
->
Wakeup
(waiting);
296
// give them a chance to run.
297
current->
process
->
manager
->
Yield
();
298
}
299
}
300
return
0;
301
}
302
int
dce_pthread_mutexattr_init
(pthread_mutexattr_t *attribute)
303
{
304
NS_LOG_FUNCTION (
Current
() <<
UtilsGetNodeId
() << attribute);
305
NS_ASSERT (
Current
() != 0);
306
if
(attribute == 0)
307
{
308
return
EINVAL;
309
}
310
NS_ASSERT (
sizeof
(
struct
PthreadMutexAttr
) <=
sizeof
(pthread_mutexattr_t));
311
struct
PthreadMutexAttr
*attr = (
struct
PthreadMutexAttr
*)attribute;
312
attr->
type
= PTHREAD_MUTEX_NORMAL;
313
return
0;
314
}
315
int
dce_pthread_mutexattr_destroy
(pthread_mutexattr_t *attribute)
316
{
317
NS_LOG_FUNCTION (
Current
() <<
UtilsGetNodeId
() << attribute);
318
NS_ASSERT (
Current
() != 0);
319
if
(attribute == 0)
320
{
321
return
EINVAL;
322
}
323
return
0;
324
}
325
int
dce_pthread_mutexattr_settype
(pthread_mutexattr_t *attribute,
int
kind)
326
{
327
NS_LOG_FUNCTION (
Current
() <<
UtilsGetNodeId
() << attribute << kind);
328
NS_ASSERT (
Current
() != 0);
329
if
(attribute == 0)
330
{
331
return
EINVAL;
332
}
333
struct
PthreadMutexAttr
*attr = (
struct
PthreadMutexAttr
*)attribute;
334
attr->
type
= kind;
335
return
0;
336
}
model
dce-pthread-mutex.cc
Generated on Fri Aug 30 2013 13:57:55 for ns-3-dce by
1.8.1.2