2 //=============================================================================
4 * @file deadlock_detection_test.cpp
8 //=============================================================================
10 #include "ace/Token_Manager.h"
11 #include "ace/Remote_Tokens.h"
12 #include "ace/Thread.h"
13 #include "ace/Thread_Manager.h"
14 #include "ace/Get_Opt.h"
15 #include "ace/Token_Invariants.h"
17 #if defined (ACE_HAS_THREADS) && defined (ACE_HAS_THREADS_LIBRARY)
19 typedef ACE_Token_Invariant_Manager ACE_TOKEN_INVARIANTS
;
21 static ACE_Token_Proxy
*global_mutex
;
26 Two_Tokens (ACE_Thread_Manager
*tm
): thr_mgr_ (tm
) {}
27 ACE_Token_Proxy
*first_
;
28 ACE_Token_Proxy
*second_
;
29 ACE_Thread_Manager
*thr_mgr_
;
35 Four_Tokens (ACE_Thread_Manager
*tm
): thr_mgr_ (tm
) {}
36 ACE_Token_Proxy
*first1_
;
37 ACE_Token_Proxy
*first2_
;
38 ACE_Token_Proxy
*first3_
;
39 ACE_Token_Proxy
*second_
;
40 ACE_Thread_Manager
*thr_mgr_
;
43 static int ignore_deadlock
= 0;
44 static int remote_mutexes
= 0;
45 static const char *server_host
= ACE_DEFAULT_SERVER_HOST
;
46 static int server_port
= ACE_DEFAULT_SERVER_PORT
;
47 static int iterations
= 100;
48 static int rwlocks
= 0;
51 two_token_thread (void *vp
)
53 Two_Tokens
* tm
= (Two_Tokens
*) vp
;
55 for (int x
= 0; x
< iterations
; x
++)
57 if (tm
->first_
->acquire () == -1)
59 ACE_DEBUG ((LM_DEBUG
, "Deadlock detected\n"));
63 if (ACE_TOKEN_INVARIANTS::instance ()->acquired (tm
->first_
) == 0)
66 ACE_ERROR_RETURN ((LM_ERROR
, "violated invariant.\n"), 0);
69 if (tm
->second_
->acquire () == -1)
71 ACE_DEBUG ((LM_DEBUG
, "Deadlock Detected\n"));
75 if (ACE_TOKEN_INVARIANTS::instance ()->acquired (tm
->second_
) == 0)
78 ACE_ERROR_RETURN ((LM_ERROR
, "violated invariant.\n"), 0);
81 ACE_TOKEN_INVARIANTS::instance ()->releasing (tm
->second_
);
83 tm
->second_
->release ();
85 ACE_TOKEN_INVARIANTS::instance ()->releasing (tm
->first_
);
87 tm
->first_
->release ();
90 ACE_DEBUG ((LM_DEBUG
, "thread %t exiting\n"));
97 Four_Tokens
*ft
= (Four_Tokens
*) vp
;
98 int acquire_number
= 0;
100 for (int x
= 0; x
< iterations
; x
++)
102 // Cycle through each of the first three tokens.
103 ACE_Token_Proxy
*t
= 0;
104 switch (acquire_number
)
117 acquire_number
= (acquire_number
+ 1) % 3;
119 if (t
->acquire () == -1)
121 ACE_ASSERT (errno
== EDEADLK
);
122 ACE_DEBUG ((LM_DEBUG
, "Deadlock detected.\n"));
126 if (ACE_TOKEN_INVARIANTS::instance ()->acquired (t
) == 0)
129 ACE_ERROR_RETURN ((LM_ERROR
, "violated invariant.\n"), 0);
132 if (ft
->second_
->acquire () == -1)
134 ACE_ASSERT (errno
== EDEADLK
);
135 ACE_DEBUG ((LM_DEBUG
, "Deadlock Detected..\n"));
139 if (ACE_TOKEN_INVARIANTS::instance ()->acquired (ft
->second_
) == 0)
141 ft
->second_
->dump ();
142 ACE_ERROR_RETURN ((LM_ERROR
, "violated invariant.\n"), 0);
145 ACE_TOKEN_INVARIANTS::instance ()->releasing (ft
->second_
);
147 ft
->second_
->release ();
150 ACE_TOKEN_INVARIANTS::instance ()->releasing (t
);
155 ACE_DEBUG ((LM_DEBUG
, "thread %t exiting\n"));
160 parse_args (int argc
, ACE_TCHAR
*argv
[])
162 ACE_LOG_MSG
->open (argv
[0]);
164 ACE_Get_Opt
get_opt (argc
, argv
, ACE_TEXT("iuh:rp:n:"), 1);
166 for (int c
; (c
= get_opt ()) != -1; )
177 server_host
= get_opt
.opt_arg ();
181 server_port
= ACE_OS::atoi (get_opt
.opt_arg ());
185 iterations
= ACE_OS::atoi (get_opt
.opt_arg ());
189 ACE_ERROR_RETURN ((LM_ERROR
,
191 "[-r test readers/writer locks]\n"
192 "[-n <iterations>]\n"
193 "[-h <remote host>]\n"
194 "[-p <remote port>]\n"
195 "[-i ignore deadlock]\n%a", 1), -1);
205 ACE_Thread_Manager thr_mgr
;
207 Two_Tokens
one (&thr_mgr
);
208 Two_Tokens
two (&thr_mgr
);
210 if (remote_mutexes
== 0)
212 global_mutex
= new ACE_Local_Mutex ("global proxy", ignore_deadlock
, 1);
213 one
.first_
= new ACE_Local_Mutex ("local proxy", ignore_deadlock
, 1);
214 two
.second_
= new ACE_Local_Mutex ("local proxy", ignore_deadlock
, 1);
218 ACE_Remote_Mutex::set_server_address (ACE_INET_Addr (server_port
, server_host
));
219 global_mutex
= new ACE_Remote_Mutex ("global proxy", ignore_deadlock
, 1);
220 one
.first_
= new ACE_Remote_Mutex ("local proxy", ignore_deadlock
, 1);
221 two
.second_
= new ACE_Remote_Mutex ("local proxy", ignore_deadlock
, 1);
224 one
.second_
= global_mutex
;
225 two
.first_
= global_mutex
;
227 // Tell the token manager to be verbose when reporting deadlock.
228 ACE_Token_Manager::instance ()->debug (1);
230 if (thr_mgr
.spawn (ACE_THR_FUNC (two_token_thread
),
231 (void *) &one
, THR_BOUND
) == -1)
232 ACE_ERROR_RETURN ((LM_DEBUG
, "%p\n", "first spawn"), -1);
234 if (thr_mgr
.spawn (ACE_THR_FUNC (two_token_thread
),
235 (void *) &two
, THR_BOUND
) == -1)
236 ACE_ERROR_RETURN ((LM_DEBUG
, "%p\n", "second spawn"), -1);
238 // Wait for all threads to exit.
247 ACE_Thread_Manager thr_mgr
;
249 Two_Tokens
reader1 (&thr_mgr
);
250 Two_Tokens
reader2 (&thr_mgr
);
251 Two_Tokens
reader3 (&thr_mgr
);
252 Four_Tokens
writer (&thr_mgr
);
254 if (remote_mutexes
== 0)
256 reader1
.first_
= new ACE_Local_RLock ("reader first", ignore_deadlock
, 1);
257 reader1
.second_
= new ACE_Local_RLock ("writer first 1", ignore_deadlock
, 1);
258 reader2
.first_
= new ACE_Local_RLock ("reader first", ignore_deadlock
, 1);
259 reader2
.second_
= new ACE_Local_RLock ("writer first 2", ignore_deadlock
, 1);
260 reader3
.first_
= new ACE_Local_RLock ("reader first", ignore_deadlock
, 1);
261 reader3
.second_
= new ACE_Local_RLock ("writer first 3", ignore_deadlock
, 1);
263 writer
.first1_
= new ACE_Local_WLock ("writer first 1", ignore_deadlock
, 1);
264 writer
.first2_
= new ACE_Local_WLock ("writer first 2", ignore_deadlock
, 1);
265 writer
.first3_
= new ACE_Local_WLock ("writer first 3", ignore_deadlock
, 1);
266 writer
.second_
= new ACE_Local_WLock ("reader first", ignore_deadlock
, 1);
270 ACE_Remote_Mutex::set_server_address (ACE_INET_Addr (server_port
, server_host
));
272 reader1
.first_
= new ACE_Remote_RLock ("writer first 1", ignore_deadlock
, 1);
273 reader1
.second_
= new ACE_Remote_RLock ("reader first", ignore_deadlock
, 1);
274 reader2
.first_
= new ACE_Remote_RLock ("writer first 2", ignore_deadlock
, 1);
275 reader2
.second_
= new ACE_Remote_RLock ("reader first", ignore_deadlock
, 1);
276 reader3
.first_
= new ACE_Remote_RLock ("writer first 3", ignore_deadlock
, 1);
277 reader3
.second_
= new ACE_Remote_RLock ("reader first", ignore_deadlock
, 1);
279 writer
.first1_
= new ACE_Remote_WLock ("writer first 1", ignore_deadlock
, 1);
280 writer
.first2_
= new ACE_Remote_WLock ("writer first 2", ignore_deadlock
, 1);
281 writer
.first3_
= new ACE_Remote_WLock ("writer first 3", ignore_deadlock
, 1);
282 writer
.second_
= new ACE_Remote_WLock ("reader first", ignore_deadlock
, 1);
285 // Tell the token manager to be verbose when reporting deadlock.
286 ACE_Token_Manager::instance ()->debug (1);
288 if (thr_mgr
.spawn (ACE_THR_FUNC (two_token_thread
),
289 (void *) &reader1
, THR_BOUND
) == -1)
290 ACE_ERROR_RETURN ((LM_DEBUG
, "%p\n", "first spawn"), -1);
292 if (thr_mgr
.spawn (ACE_THR_FUNC (two_token_thread
),
293 (void *) &reader2
, THR_BOUND
) == -1)
294 ACE_ERROR_RETURN ((LM_DEBUG
, "%p\n", "first spawn"), -1);
296 if (thr_mgr
.spawn (ACE_THR_FUNC (two_token_thread
),
297 (void *) &reader3
, THR_BOUND
) == -1)
298 ACE_ERROR_RETURN ((LM_DEBUG
, "%p\n", "first spawn"), -1);
300 if (thr_mgr
.spawn (ACE_THR_FUNC (run_writer
),
301 (void *) &writer
, THR_BOUND
) == -1)
302 ACE_ERROR_RETURN ((LM_DEBUG
, "%p\n", "second spawn"), -1);
304 // Wait for all threads to exit.
311 ACE_TMAIN(int argc
, ACE_TCHAR
*argv
[])
313 if (parse_args (argc
, argv
) == -1)
321 ACE_DEBUG ((LM_DEBUG
, "test exiting.\n"));
326 ACE_TMAIN(int, ACE_TCHAR
*[])
328 ACE_ERROR_RETURN ((LM_ERROR
,
329 "threads not supported on this platform\n"), -1);
331 #endif /* ACE_HAS_THREADS */