CACAO
threadlist.cpp
Go to the documentation of this file.
1 /* src/threads/threadlist.cpp - thread list maintenance
2 
3  Copyright (C) 1996-2013
4  CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
5 
6  This file is part of CACAO.
7 
8  This program is free software; you can redistribute it and/or
9  modify it under the terms of the GNU General Public License as
10  published by the Free Software Foundation; either version 2, or (at
11  your option) any later version.
12 
13  This program is distributed in the hope that it will be useful, but
14  WITHOUT ANY WARRANTY; without even the implied warranty of
15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  General Public License for more details.
17 
18  You should have received a copy of the GNU General Public License
19  along with this program; if not, write to the Free Software
20  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21  02110-1301, USA.
22 
23 */
24 
25 
26 #include "config.h"
27 
28 #include <stdint.h>
29 #include <algorithm>
30 #include <functional>
31 
32 #include "threads/mutex.hpp"
33 #include "threads/threadlist.hpp"
34 #include "threads/thread.hpp"
35 
36 #include "toolbox/list.hpp"
37 #include "toolbox/logging.hpp"
38 
39 #include "vm/jit/stacktrace.hpp"
40 
42 
43 /**
44  * Dumps info for all threads running in the VM. This function is
45  * called when SIGQUIT (<ctrl>-\) is sent to the VM.
46  */
48 {
49  // XXX we should stop the world here and remove explicit
50  // thread suspension from the loop below.
51  // Lock the thread lists.
53 
54  printf("Full thread dump CACAO "VERSION_FULL":\n");
55 
56  // Iterate over all started threads.
57  threadobject* self = THREADOBJECT;
58  for (List<threadobject*>::iterator it = _active_thread_list.begin(); it != _active_thread_list.end(); it++) {
59  threadobject* t = *it;
60 
61  // Ignore threads which are in state NEW.
62  if (t->state == THREAD_STATE_NEW)
63  continue;
64 
65  /* Suspend the thread (and ignore return value). */
66 
67  if (t != self)
69 
70  /* Print thread info. */
71 
72  printf("\n");
74  printf("\n");
75 
76  /* Print trace of thread. */
77 
79 
80  /* Resume the thread (and ignore return value). */
81 
82  if (t != self)
84  }
85 }
86 
87 
88 /**
89  * Fills the passed list with all currently active threads. Creating a copy
90  * of the thread list here, is the only way to ensure we do not end up in a
91  * dead-lock when iterating over the list.
92  *
93  * @param list list class to be filled
94  */
96 {
98 
99  // Use the assignment operator to create a copy of the thread list.
100  list = _active_thread_list;
101 }
102 
103 
104 /**
105  * Fills the passed list with all currently active threads which should be
106  * visible to Java. Creating a copy of the thread list here, is the only way
107  * to ensure we do not end up in a dead-lock when iterating over the list.
108  *
109  * @param list list class to be filled
110  */
112 {
114 
115  // Iterate over all active threads.
116  for (List<threadobject*>::iterator it = _active_thread_list.begin(); it != _active_thread_list.end(); it++) {
117  threadobject* t = *it;
118 
119  // We skip internal threads.
120  if (t->flags & THREAD_FLAG_INTERNAL)
121  continue;
122 
123  list.push_back(t);
124  }
125 }
126 
127 
128 /**
129  * Get the next free thread object.
130  *
131  * Gets the next free thread object and a thread index for it.
132  * The results are stored into the passed pointers.
133  *
134  * If no free thread is available `*thread' will contain NULL.
135  * `*index' will always, even if no free thread is available,
136  * contain a valid index you can use for a new thread.
137  */
140 
141  // Do we have free threads in the free-list?
142  if (_free_thread_list.empty() == false) {
143  // Yes, get the index and remove it from the free list.
144  threadobject* t = _free_thread_list.front();
145  _free_thread_list.pop_front();
146 
147  *thread = t;
148  *index = t->index;
149  } else {
150  *thread = NULL;
151  *index = ++_last_index;
152  }
153 }
154 
155 
156 /**
157  * Return the number of daemon threads visible to Java.
158  *
159  * NOTE: This function does a linear-search over the threads list,
160  * because it is only used by the management interface.
161  *
162  * @return number of daemon threads
163  */
165 {
166  int number = 0;
167 
168  // Lock the thread lists.
170 
171  // Iterate over all active threads.
172  for (List<threadobject*>::iterator it = _active_thread_list.begin(); it != _active_thread_list.end(); it++) {
173  threadobject* t = *it;
174 
175  // We skip internal threads.
176  if (t->flags & THREAD_FLAG_INTERNAL)
177  continue;
178 
179  if (thread_is_daemon(t))
180  number++;
181  }
182 
183  return number;
184 }
185 
186 
187 /**
188  * Return the number of non-daemon threads.
189  *
190  * NOTE: This function does a linear-search over the threads list,
191  * because it is only used for joining the threads.
192  *
193  * @return number of non daemon threads
194  */
196 {
198 
199  int nondaemons = 0;
200 
201  for (List<threadobject*>::iterator it = _active_thread_list.begin(); it != _active_thread_list.end(); it++) {
202  threadobject* t = *it;
203 
204  if (!thread_is_daemon(t))
205  nondaemons++;
206  }
207 
208  return nondaemons;
209 }
210 
211 // Comparator class.
212 class comparator : public std::binary_function<threadobject*, int32_t, bool> {
213 public:
214  bool operator() (const threadobject* t, const int32_t index) const {
215  return (t->index == index);
216  }
217 };
218 
219 /**
220  * Return the thread object with the given index.
221  *
222  * @return thread object
223  */
225 {
227 
228  List<threadobject*>::iterator it = find_if(_active_thread_list.begin(), _active_thread_list.end(), std::bind2nd(comparator(), index));
229 
230  // No thread found.
231  if (it == _active_thread_list.end()) {
232  return NULL;
233  }
234 
235  threadobject* t = *it;
236 
237  // The thread found is in state new.
238  if (t->state == THREAD_STATE_NEW) {
239  return NULL;
240  }
241 
242  return t;
243 }
244 
245 
246 /**
247  * Return the Java thread object from the given thread object.
248  *
249  * @return Java thread object
250  */
252 {
254 
255  for (List<threadobject*>::iterator it = _active_thread_list.begin(); it != _active_thread_list.end(); it++) {
256  threadobject* t = *it;
257 
258  bool equal;
259  LLNI_equals(t->object, h, equal);
260 
261  if (equal == true) {
262  return t;
263  }
264  }
265 
266  return NULL;
267 }
268 
270 {
272 
274  threads_impl_clear_heap_pointers(t); // allow it to be garbage collected
275 }
276 
277 /**
278  * Release the thread.
279  *
280  * @return free thread index
281  */
282 void ThreadList::release_thread(threadobject* t, bool needs_deactivate)
283 {
285 
286  if (needs_deactivate)
287  // Move thread from active thread list to free thread list.
289  else
290  assert(!t->is_in_active_list);
291 
292  _free_thread_list.push_back(t);
293 }
294 
295 
296 /*
297  * These are local overrides for various environment variables in Emacs.
298  * Please do not remove this and leave it at the end of the file, where
299  * Emacs will automagically detect them.
300  * ---------------------------------------------------------------------
301  * Local variables:
302  * mode: c++
303  * indent-tabs-mode: t
304  * c-basic-offset: 4
305  * tab-width: 4
306  * End:
307  * vim:noexpandtab:sw=4:ts=4:
308  */
std::size_t index
void dump_threads()
Dumps info for all threads running in the VM.
Definition: threadlist.cpp:47
#define LLNI_equals(obj1, obj2, result)
Definition: llni.hpp:70
bool threads_suspend_thread(threadobject *thread, SuspendReason reason)
Suspend the passed thread.
threadobject * get_thread_by_index(int32_t index)
Return the thread object with the given index.
Definition: threadlist.cpp:224
void get_active_java_threads(List< threadobject * > &list)
Fills the passed list with all currently active threads which should be visible to Java...
Definition: threadlist.cpp:111
typedef void(JNICALL *jvmtiEventSingleStep)(jvmtiEnv *jvmti_env
static bool thread_is_daemon(threadobject *t)
Definition: thread.hpp:285
int32_t get_number_of_daemon_java_threads()
Return the number of daemon threads visible to Java.
Definition: threadlist.cpp:164
Mutex _mutex
Definition: threadlist.hpp:42
List< threadobject * > _free_thread_list
Definition: threadlist.hpp:45
int32_t get_number_of_non_daemon_threads()
Return the number of non-daemon threads.
Definition: threadlist.cpp:195
static ThreadList * the_threadlist
Definition: threadlist.hpp:40
void release_thread(threadobject *t, bool needs_deactivate)
Release the thread.
Definition: threadlist.cpp:282
void remove_from_active_thread_list(threadobject *t)
Definition: threadlist.hpp:126
static Mutex lock
Definition: atomic.cpp:34
int32_t _last_index
Definition: threadlist.hpp:53
List implementation.
Definition: lock.hpp:35
void get_active_threads(List< threadobject * > &list)
Fills the passed list with all currently active threads.
Definition: threadlist.cpp:95
void deactivate_thread(threadobject *t)
Definition: threadlist.cpp:269
JNIEnv jthread thread
Definition: jvmti.h:207
bool operator()(const threadobject *t, const int32_t index) const
Definition: threadlist.cpp:214
ThreadState state
Definition: thread.hpp:97
void stacktrace_print_of_thread(threadobject *t)
Helper class used to implicitly acquire and release a mutex within a method scope.
Definition: mutex.hpp:42
void get_free_thread(threadobject **t, int32_t *index)
Get the next free thread object.
Definition: threadlist.cpp:138
void threads_impl_clear_heap_pointers(threadobject *t)
void thread_print_info(threadobject *t)
Definition: thread.cpp:650
java_object_t * object
Definition: thread.hpp:93
threadobject * get_thread_from_java_object(java_handle_t *h)
Return the Java thread object from the given thread object.
Definition: threadlist.cpp:251
bool is_in_active_list
Definition: thread.hpp:100
#define printf(...)
Definition: ssa2.cpp:40
#define THREADOBJECT
Definition: thread-none.hpp:47
List< threadobject * > _active_thread_list
Definition: threadlist.hpp:44
bool threads_resume_thread(threadobject *thread, SuspendReason reason)
Resumes execution of the passed thread.