Changes to attempt to silence bcc64x
[ACE_TAO.git] / ACE / netsvcs / clients / Tokens / deadlock / deadlock_detection_test.cpp
blob4818fb99785c79faa720dc5fb83a7a7311b7ebda
2 //=============================================================================
3 /**
4 * @file deadlock_detection_test.cpp
6 * @author Tim Harrison
7 */
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;
23 struct Two_Tokens
25 public:
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_;
32 struct Four_Tokens
34 public:
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;
50 static void *
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"));
60 continue;
63 if (ACE_TOKEN_INVARIANTS::instance ()->acquired (tm->first_) == 0)
65 tm->first_->dump ();
66 ACE_ERROR_RETURN ((LM_ERROR, "violated invariant.\n"), 0);
69 if (tm->second_->acquire () == -1)
71 ACE_DEBUG ((LM_DEBUG, "Deadlock Detected\n"));
72 goto G1;
75 if (ACE_TOKEN_INVARIANTS::instance ()->acquired (tm->second_) == 0)
77 tm->second_->dump ();
78 ACE_ERROR_RETURN ((LM_ERROR, "violated invariant.\n"), 0);
81 ACE_TOKEN_INVARIANTS::instance ()->releasing (tm->second_);
83 tm->second_->release ();
84 G1:
85 ACE_TOKEN_INVARIANTS::instance ()->releasing (tm->first_);
87 tm->first_->release ();
90 ACE_DEBUG ((LM_DEBUG, "thread %t exiting\n"));
91 return 0;
94 static void *
95 run_writer (void *vp)
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)
106 case 0:
107 t = ft->first1_;
108 break;
109 case 1:
110 t = ft->first2_;
111 break;
112 case 2:
113 t = ft->first3_;
114 break;
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"));
123 continue;
126 if (ACE_TOKEN_INVARIANTS::instance ()->acquired (t) == 0)
128 t->dump ();
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"));
136 goto G1;
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);
152 t->release ();
155 ACE_DEBUG ((LM_DEBUG, "thread %t exiting\n"));
156 return 0;
159 static int
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; )
168 switch (c)
170 case 'r':
171 rwlocks = 1;
172 break;
173 case 'i':
174 ignore_deadlock = 1;
175 break;
176 case 'h':
177 server_host = get_opt.opt_arg ();
178 remote_mutexes = 1;
179 break;
180 case 'p':
181 server_port = ACE_OS::atoi (get_opt.opt_arg ());
182 remote_mutexes = 1;
183 break;
184 case 'n':
185 iterations = ACE_OS::atoi (get_opt.opt_arg ());
186 break;
187 case 'u':
188 default:
189 ACE_ERROR_RETURN ((LM_ERROR,
190 "%n:\n"
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);
199 return 0;
203 mutex_test ()
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);
216 else
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.
239 thr_mgr.wait ();
241 return 0;
244 static int
245 rwlock_test ()
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);
268 else
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.
305 thr_mgr.wait ();
307 return 0;
311 ACE_TMAIN(int argc, ACE_TCHAR *argv[])
313 if (parse_args (argc, argv) == -1)
314 return -1;
316 if (rwlocks)
317 rwlock_test ();
318 else
319 mutex_test ();
321 ACE_DEBUG ((LM_DEBUG, "test exiting.\n"));
322 return 0;
324 #else
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 */