annotate src/share/vm/services/attachListener.cpp @ 1721:413ad0331a0c

6977924: Changes for 6975078 produce build error with certain gcc versions Summary: The changes introduced for 6975078 assign badHeapOopVal to the _allocation field in the ResourceObj class. In 32 bit linux builds with certain versions of gcc this assignment will be flagged as an error while compiling allocation.cpp. In 32 bit builds the constant value badHeapOopVal (which is cast to an intptr_t) is negative. The _allocation field is typed as an unsigned intptr_t and gcc catches this as an error. Reviewed-by: jcoomes, ysr, phh
author johnc
date Wed, 18 Aug 2010 10:59:06 -0700
parents c18cbe5936b8
children f95d63e2154a
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
a61af66fc99e Initial load
duke
parents:
diff changeset
1 /*
1552
c18cbe5936b8 6941466: Oracle rebranding changes for Hotspot repositories
trims
parents: 1142
diff changeset
2 * Copyright (c) 2005, 2007, Oracle and/or its affiliates. All rights reserved.
0
a61af66fc99e Initial load
duke
parents:
diff changeset
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
a61af66fc99e Initial load
duke
parents:
diff changeset
4 *
a61af66fc99e Initial load
duke
parents:
diff changeset
5 * This code is free software; you can redistribute it and/or modify it
a61af66fc99e Initial load
duke
parents:
diff changeset
6 * under the terms of the GNU General Public License version 2 only, as
a61af66fc99e Initial load
duke
parents:
diff changeset
7 * published by the Free Software Foundation.
a61af66fc99e Initial load
duke
parents:
diff changeset
8 *
a61af66fc99e Initial load
duke
parents:
diff changeset
9 * This code is distributed in the hope that it will be useful, but WITHOUT
a61af66fc99e Initial load
duke
parents:
diff changeset
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
a61af66fc99e Initial load
duke
parents:
diff changeset
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
a61af66fc99e Initial load
duke
parents:
diff changeset
12 * version 2 for more details (a copy is included in the LICENSE file that
a61af66fc99e Initial load
duke
parents:
diff changeset
13 * accompanied this code).
a61af66fc99e Initial load
duke
parents:
diff changeset
14 *
a61af66fc99e Initial load
duke
parents:
diff changeset
15 * You should have received a copy of the GNU General Public License version
a61af66fc99e Initial load
duke
parents:
diff changeset
16 * 2 along with this work; if not, write to the Free Software Foundation,
a61af66fc99e Initial load
duke
parents:
diff changeset
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
a61af66fc99e Initial load
duke
parents:
diff changeset
18 *
1552
c18cbe5936b8 6941466: Oracle rebranding changes for Hotspot repositories
trims
parents: 1142
diff changeset
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
c18cbe5936b8 6941466: Oracle rebranding changes for Hotspot repositories
trims
parents: 1142
diff changeset
20 * or visit www.oracle.com if you need additional information or have any
c18cbe5936b8 6941466: Oracle rebranding changes for Hotspot repositories
trims
parents: 1142
diff changeset
21 * questions.
0
a61af66fc99e Initial load
duke
parents:
diff changeset
22 *
a61af66fc99e Initial load
duke
parents:
diff changeset
23 */
a61af66fc99e Initial load
duke
parents:
diff changeset
24
a61af66fc99e Initial load
duke
parents:
diff changeset
25 # include "incls/_precompiled.incl"
a61af66fc99e Initial load
duke
parents:
diff changeset
26 # include "incls/_attachListener.cpp.incl"
a61af66fc99e Initial load
duke
parents:
diff changeset
27
a61af66fc99e Initial load
duke
parents:
diff changeset
28 volatile bool AttachListener::_initialized;
a61af66fc99e Initial load
duke
parents:
diff changeset
29
a61af66fc99e Initial load
duke
parents:
diff changeset
30 // Implementation of "properties" command.
a61af66fc99e Initial load
duke
parents:
diff changeset
31 //
a61af66fc99e Initial load
duke
parents:
diff changeset
32 // Invokes sun.misc.VMSupport.serializePropertiesToByteArray to serialize
a61af66fc99e Initial load
duke
parents:
diff changeset
33 // the system properties into a byte array.
a61af66fc99e Initial load
duke
parents:
diff changeset
34
a61af66fc99e Initial load
duke
parents:
diff changeset
35 static klassOop load_and_initialize_klass(symbolHandle sh, TRAPS) {
a61af66fc99e Initial load
duke
parents:
diff changeset
36 klassOop k = SystemDictionary::resolve_or_fail(sh, true, CHECK_NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
37 instanceKlassHandle ik (THREAD, k);
a61af66fc99e Initial load
duke
parents:
diff changeset
38 if (ik->should_be_initialized()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
39 ik->initialize(CHECK_NULL);
a61af66fc99e Initial load
duke
parents:
diff changeset
40 }
a61af66fc99e Initial load
duke
parents:
diff changeset
41 return ik();
a61af66fc99e Initial load
duke
parents:
diff changeset
42 }
a61af66fc99e Initial load
duke
parents:
diff changeset
43
a61af66fc99e Initial load
duke
parents:
diff changeset
44 static jint get_properties(AttachOperation* op, outputStream* out, symbolHandle serializePropertiesMethod) {
a61af66fc99e Initial load
duke
parents:
diff changeset
45 Thread* THREAD = Thread::current();
a61af66fc99e Initial load
duke
parents:
diff changeset
46 HandleMark hm;
a61af66fc99e Initial load
duke
parents:
diff changeset
47
a61af66fc99e Initial load
duke
parents:
diff changeset
48 // load sun.misc.VMSupport
a61af66fc99e Initial load
duke
parents:
diff changeset
49 symbolHandle klass = vmSymbolHandles::sun_misc_VMSupport();
a61af66fc99e Initial load
duke
parents:
diff changeset
50 klassOop k = load_and_initialize_klass(klass, THREAD);
a61af66fc99e Initial load
duke
parents:
diff changeset
51 if (HAS_PENDING_EXCEPTION) {
a61af66fc99e Initial load
duke
parents:
diff changeset
52 java_lang_Throwable::print(PENDING_EXCEPTION, out);
a61af66fc99e Initial load
duke
parents:
diff changeset
53 CLEAR_PENDING_EXCEPTION;
a61af66fc99e Initial load
duke
parents:
diff changeset
54 return JNI_ERR;
a61af66fc99e Initial load
duke
parents:
diff changeset
55 }
a61af66fc99e Initial load
duke
parents:
diff changeset
56 instanceKlassHandle ik(THREAD, k);
a61af66fc99e Initial load
duke
parents:
diff changeset
57
a61af66fc99e Initial load
duke
parents:
diff changeset
58 // invoke the serializePropertiesToByteArray method
a61af66fc99e Initial load
duke
parents:
diff changeset
59 JavaValue result(T_OBJECT);
a61af66fc99e Initial load
duke
parents:
diff changeset
60 JavaCallArguments args;
a61af66fc99e Initial load
duke
parents:
diff changeset
61
a61af66fc99e Initial load
duke
parents:
diff changeset
62
a61af66fc99e Initial load
duke
parents:
diff changeset
63 symbolHandle signature = vmSymbolHandles::serializePropertiesToByteArray_signature();
a61af66fc99e Initial load
duke
parents:
diff changeset
64 JavaCalls::call_static(&result,
a61af66fc99e Initial load
duke
parents:
diff changeset
65 ik,
a61af66fc99e Initial load
duke
parents:
diff changeset
66 serializePropertiesMethod,
a61af66fc99e Initial load
duke
parents:
diff changeset
67 signature,
a61af66fc99e Initial load
duke
parents:
diff changeset
68 &args,
a61af66fc99e Initial load
duke
parents:
diff changeset
69 THREAD);
a61af66fc99e Initial load
duke
parents:
diff changeset
70 if (HAS_PENDING_EXCEPTION) {
a61af66fc99e Initial load
duke
parents:
diff changeset
71 java_lang_Throwable::print(PENDING_EXCEPTION, out);
a61af66fc99e Initial load
duke
parents:
diff changeset
72 CLEAR_PENDING_EXCEPTION;
a61af66fc99e Initial load
duke
parents:
diff changeset
73 return JNI_ERR;
a61af66fc99e Initial load
duke
parents:
diff changeset
74 }
a61af66fc99e Initial load
duke
parents:
diff changeset
75
a61af66fc99e Initial load
duke
parents:
diff changeset
76 // The result should be a [B
a61af66fc99e Initial load
duke
parents:
diff changeset
77 oop res = (oop)result.get_jobject();
a61af66fc99e Initial load
duke
parents:
diff changeset
78 assert(res->is_typeArray(), "just checking");
a61af66fc99e Initial load
duke
parents:
diff changeset
79 assert(typeArrayKlass::cast(res->klass())->element_type() == T_BYTE, "just checking");
a61af66fc99e Initial load
duke
parents:
diff changeset
80
a61af66fc99e Initial load
duke
parents:
diff changeset
81 // copy the bytes to the output stream
a61af66fc99e Initial load
duke
parents:
diff changeset
82 typeArrayOop ba = typeArrayOop(res);
a61af66fc99e Initial load
duke
parents:
diff changeset
83 jbyte* addr = typeArrayOop(res)->byte_at_addr(0);
a61af66fc99e Initial load
duke
parents:
diff changeset
84 out->print_raw((const char*)addr, ba->length());
a61af66fc99e Initial load
duke
parents:
diff changeset
85
a61af66fc99e Initial load
duke
parents:
diff changeset
86 return JNI_OK;
a61af66fc99e Initial load
duke
parents:
diff changeset
87 }
a61af66fc99e Initial load
duke
parents:
diff changeset
88
a61af66fc99e Initial load
duke
parents:
diff changeset
89 // Implementation of "properties" command.
a61af66fc99e Initial load
duke
parents:
diff changeset
90 static jint get_system_properties(AttachOperation* op, outputStream* out) {
a61af66fc99e Initial load
duke
parents:
diff changeset
91 return get_properties(op, out, vmSymbolHandles::serializePropertiesToByteArray_name());
a61af66fc99e Initial load
duke
parents:
diff changeset
92 }
a61af66fc99e Initial load
duke
parents:
diff changeset
93
a61af66fc99e Initial load
duke
parents:
diff changeset
94 // Implementation of "agent_properties" command.
a61af66fc99e Initial load
duke
parents:
diff changeset
95 static jint get_agent_properties(AttachOperation* op, outputStream* out) {
a61af66fc99e Initial load
duke
parents:
diff changeset
96 return get_properties(op, out, vmSymbolHandles::serializeAgentPropertiesToByteArray_name());
a61af66fc99e Initial load
duke
parents:
diff changeset
97 }
a61af66fc99e Initial load
duke
parents:
diff changeset
98
a61af66fc99e Initial load
duke
parents:
diff changeset
99 // Implementation of "datadump" command.
a61af66fc99e Initial load
duke
parents:
diff changeset
100 //
a61af66fc99e Initial load
duke
parents:
diff changeset
101 // Raises a SIGBREAK signal so that VM dump threads, does deadlock detection,
a61af66fc99e Initial load
duke
parents:
diff changeset
102 // etc. In theory this command should only post a DataDumpRequest to any
a61af66fc99e Initial load
duke
parents:
diff changeset
103 // JVMTI environment that has enabled this event. However it's useful to
a61af66fc99e Initial load
duke
parents:
diff changeset
104 // trigger the SIGBREAK handler.
a61af66fc99e Initial load
duke
parents:
diff changeset
105
a61af66fc99e Initial load
duke
parents:
diff changeset
106 static jint data_dump(AttachOperation* op, outputStream* out) {
a61af66fc99e Initial load
duke
parents:
diff changeset
107 if (!ReduceSignalUsage) {
a61af66fc99e Initial load
duke
parents:
diff changeset
108 AttachListener::pd_data_dump();
a61af66fc99e Initial load
duke
parents:
diff changeset
109 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
110 if (JvmtiExport::should_post_data_dump()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
111 JvmtiExport::post_data_dump();
a61af66fc99e Initial load
duke
parents:
diff changeset
112 }
a61af66fc99e Initial load
duke
parents:
diff changeset
113 }
a61af66fc99e Initial load
duke
parents:
diff changeset
114 return JNI_OK;
a61af66fc99e Initial load
duke
parents:
diff changeset
115 }
a61af66fc99e Initial load
duke
parents:
diff changeset
116
a61af66fc99e Initial load
duke
parents:
diff changeset
117 // Implementation of "threaddump" command - essentially a remote ctrl-break
a61af66fc99e Initial load
duke
parents:
diff changeset
118 //
a61af66fc99e Initial load
duke
parents:
diff changeset
119 static jint thread_dump(AttachOperation* op, outputStream* out) {
a61af66fc99e Initial load
duke
parents:
diff changeset
120 bool print_concurrent_locks = false;
a61af66fc99e Initial load
duke
parents:
diff changeset
121 if (op->arg(0) != NULL && strcmp(op->arg(0), "-l") == 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
122 print_concurrent_locks = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
123 }
a61af66fc99e Initial load
duke
parents:
diff changeset
124
a61af66fc99e Initial load
duke
parents:
diff changeset
125 // thread stacks
a61af66fc99e Initial load
duke
parents:
diff changeset
126 VM_PrintThreads op1(out, print_concurrent_locks);
a61af66fc99e Initial load
duke
parents:
diff changeset
127 VMThread::execute(&op1);
a61af66fc99e Initial load
duke
parents:
diff changeset
128
a61af66fc99e Initial load
duke
parents:
diff changeset
129 // JNI global handles
a61af66fc99e Initial load
duke
parents:
diff changeset
130 VM_PrintJNI op2(out);
a61af66fc99e Initial load
duke
parents:
diff changeset
131 VMThread::execute(&op2);
a61af66fc99e Initial load
duke
parents:
diff changeset
132
a61af66fc99e Initial load
duke
parents:
diff changeset
133 // Deadlock detection
a61af66fc99e Initial load
duke
parents:
diff changeset
134 VM_FindDeadlocks op3(out);
a61af66fc99e Initial load
duke
parents:
diff changeset
135 VMThread::execute(&op3);
a61af66fc99e Initial load
duke
parents:
diff changeset
136
a61af66fc99e Initial load
duke
parents:
diff changeset
137 return JNI_OK;
a61af66fc99e Initial load
duke
parents:
diff changeset
138 }
a61af66fc99e Initial load
duke
parents:
diff changeset
139
a61af66fc99e Initial load
duke
parents:
diff changeset
140 #ifndef SERVICES_KERNEL // Heap dumping not supported
a61af66fc99e Initial load
duke
parents:
diff changeset
141 // Implementation of "dumpheap" command.
a61af66fc99e Initial load
duke
parents:
diff changeset
142 //
a61af66fc99e Initial load
duke
parents:
diff changeset
143 // Input arguments :-
a61af66fc99e Initial load
duke
parents:
diff changeset
144 // arg0: Name of the dump file
a61af66fc99e Initial load
duke
parents:
diff changeset
145 // arg1: "-live" or "-all"
a61af66fc99e Initial load
duke
parents:
diff changeset
146 jint dump_heap(AttachOperation* op, outputStream* out) {
a61af66fc99e Initial load
duke
parents:
diff changeset
147 const char* path = op->arg(0);
a61af66fc99e Initial load
duke
parents:
diff changeset
148 if (path == NULL || path[0] == '\0') {
a61af66fc99e Initial load
duke
parents:
diff changeset
149 out->print_cr("No dump file specified");
a61af66fc99e Initial load
duke
parents:
diff changeset
150 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
151 bool live_objects_only = true; // default is true to retain the behavior before this change is made
a61af66fc99e Initial load
duke
parents:
diff changeset
152 const char* arg1 = op->arg(1);
a61af66fc99e Initial load
duke
parents:
diff changeset
153 if (arg1 != NULL && (strlen(arg1) > 0)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
154 if (strcmp(arg1, "-all") != 0 && strcmp(arg1, "-live") != 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
155 out->print_cr("Invalid argument to dumpheap operation: %s", arg1);
a61af66fc99e Initial load
duke
parents:
diff changeset
156 return JNI_ERR;
a61af66fc99e Initial load
duke
parents:
diff changeset
157 }
a61af66fc99e Initial load
duke
parents:
diff changeset
158 live_objects_only = strcmp(arg1, "-live") == 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
159 }
a61af66fc99e Initial load
duke
parents:
diff changeset
160
a61af66fc99e Initial load
duke
parents:
diff changeset
161 // Request a full GC before heap dump if live_objects_only = true
a61af66fc99e Initial load
duke
parents:
diff changeset
162 // This helps reduces the amount of unreachable objects in the dump
a61af66fc99e Initial load
duke
parents:
diff changeset
163 // and makes it easier to browse.
a61af66fc99e Initial load
duke
parents:
diff changeset
164 HeapDumper dumper(live_objects_only /* request GC */);
a61af66fc99e Initial load
duke
parents:
diff changeset
165 int res = dumper.dump(op->arg(0));
a61af66fc99e Initial load
duke
parents:
diff changeset
166 if (res == 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
167 out->print_cr("Heap dump file created");
a61af66fc99e Initial load
duke
parents:
diff changeset
168 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
169 // heap dump failed
a61af66fc99e Initial load
duke
parents:
diff changeset
170 ResourceMark rm;
a61af66fc99e Initial load
duke
parents:
diff changeset
171 char* error = dumper.error_as_C_string();
a61af66fc99e Initial load
duke
parents:
diff changeset
172 if (error == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
173 out->print_cr("Dump failed - reason unknown");
a61af66fc99e Initial load
duke
parents:
diff changeset
174 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
175 out->print_cr("%s", error);
a61af66fc99e Initial load
duke
parents:
diff changeset
176 }
a61af66fc99e Initial load
duke
parents:
diff changeset
177 }
a61af66fc99e Initial load
duke
parents:
diff changeset
178 }
a61af66fc99e Initial load
duke
parents:
diff changeset
179 return JNI_OK;
a61af66fc99e Initial load
duke
parents:
diff changeset
180 }
a61af66fc99e Initial load
duke
parents:
diff changeset
181 #endif // SERVICES_KERNEL
a61af66fc99e Initial load
duke
parents:
diff changeset
182
a61af66fc99e Initial load
duke
parents:
diff changeset
183 // Implementation of "inspectheap" command
a61af66fc99e Initial load
duke
parents:
diff changeset
184 //
a61af66fc99e Initial load
duke
parents:
diff changeset
185 // Input arguments :-
a61af66fc99e Initial load
duke
parents:
diff changeset
186 // arg0: "-live" or "-all"
a61af66fc99e Initial load
duke
parents:
diff changeset
187 static jint heap_inspection(AttachOperation* op, outputStream* out) {
a61af66fc99e Initial load
duke
parents:
diff changeset
188 bool live_objects_only = true; // default is true to retain the behavior before this change is made
a61af66fc99e Initial load
duke
parents:
diff changeset
189 const char* arg0 = op->arg(0);
a61af66fc99e Initial load
duke
parents:
diff changeset
190 if (arg0 != NULL && (strlen(arg0) > 0)) {
a61af66fc99e Initial load
duke
parents:
diff changeset
191 if (strcmp(arg0, "-all") != 0 && strcmp(arg0, "-live") != 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
192 out->print_cr("Invalid argument to inspectheap operation: %s", arg0);
a61af66fc99e Initial load
duke
parents:
diff changeset
193 return JNI_ERR;
a61af66fc99e Initial load
duke
parents:
diff changeset
194 }
a61af66fc99e Initial load
duke
parents:
diff changeset
195 live_objects_only = strcmp(arg0, "-live") == 0;
a61af66fc99e Initial load
duke
parents:
diff changeset
196 }
615
c6c601a0f2d6 6797870: Add -XX:+{HeapDump,PrintClassHistogram}{Before,After}FullGC
ysr
parents: 0
diff changeset
197 VM_GC_HeapInspection heapop(out, live_objects_only /* request full gc */, true /* need_prologue */);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
198 VMThread::execute(&heapop);
a61af66fc99e Initial load
duke
parents:
diff changeset
199 return JNI_OK;
a61af66fc99e Initial load
duke
parents:
diff changeset
200 }
a61af66fc99e Initial load
duke
parents:
diff changeset
201
a61af66fc99e Initial load
duke
parents:
diff changeset
202 // set a boolean global flag using value from AttachOperation
a61af66fc99e Initial load
duke
parents:
diff changeset
203 static jint set_bool_flag(const char* name, AttachOperation* op, outputStream* out) {
a61af66fc99e Initial load
duke
parents:
diff changeset
204 bool value = true;
a61af66fc99e Initial load
duke
parents:
diff changeset
205 const char* arg1;
a61af66fc99e Initial load
duke
parents:
diff changeset
206 if ((arg1 = op->arg(1)) != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
207 int tmp;
a61af66fc99e Initial load
duke
parents:
diff changeset
208 int n = sscanf(arg1, "%d", &tmp);
a61af66fc99e Initial load
duke
parents:
diff changeset
209 if (n != 1) {
1067
ba7ea42fc66e 6898160: Need serviceability support for new vm argument type 'uint64_t'
phh
parents: 615
diff changeset
210 out->print_cr("flag value must be a boolean (1 or 0)");
0
a61af66fc99e Initial load
duke
parents:
diff changeset
211 return JNI_ERR;
a61af66fc99e Initial load
duke
parents:
diff changeset
212 }
a61af66fc99e Initial load
duke
parents:
diff changeset
213 value = (tmp != 0);
a61af66fc99e Initial load
duke
parents:
diff changeset
214 }
a61af66fc99e Initial load
duke
parents:
diff changeset
215 bool res = CommandLineFlags::boolAtPut((char*)name, &value, ATTACH_ON_DEMAND);
a61af66fc99e Initial load
duke
parents:
diff changeset
216 if (! res) {
a61af66fc99e Initial load
duke
parents:
diff changeset
217 out->print_cr("setting flag %s failed", name);
a61af66fc99e Initial load
duke
parents:
diff changeset
218 }
a61af66fc99e Initial load
duke
parents:
diff changeset
219 return res? JNI_OK : JNI_ERR;
a61af66fc99e Initial load
duke
parents:
diff changeset
220 }
a61af66fc99e Initial load
duke
parents:
diff changeset
221
a61af66fc99e Initial load
duke
parents:
diff changeset
222 // set a intx global flag using value from AttachOperation
a61af66fc99e Initial load
duke
parents:
diff changeset
223 static jint set_intx_flag(const char* name, AttachOperation* op, outputStream* out) {
a61af66fc99e Initial load
duke
parents:
diff changeset
224 intx value;
a61af66fc99e Initial load
duke
parents:
diff changeset
225 const char* arg1;
a61af66fc99e Initial load
duke
parents:
diff changeset
226 if ((arg1 = op->arg(1)) != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
227 int n = sscanf(arg1, INTX_FORMAT, &value);
a61af66fc99e Initial load
duke
parents:
diff changeset
228 if (n != 1) {
1067
ba7ea42fc66e 6898160: Need serviceability support for new vm argument type 'uint64_t'
phh
parents: 615
diff changeset
229 out->print_cr("flag value must be an integer");
0
a61af66fc99e Initial load
duke
parents:
diff changeset
230 return JNI_ERR;
a61af66fc99e Initial load
duke
parents:
diff changeset
231 }
a61af66fc99e Initial load
duke
parents:
diff changeset
232 }
1067
ba7ea42fc66e 6898160: Need serviceability support for new vm argument type 'uint64_t'
phh
parents: 615
diff changeset
233 bool res = CommandLineFlags::intxAtPut((char*)name, &value, ATTACH_ON_DEMAND);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
234 if (! res) {
a61af66fc99e Initial load
duke
parents:
diff changeset
235 out->print_cr("setting flag %s failed", name);
a61af66fc99e Initial load
duke
parents:
diff changeset
236 }
a61af66fc99e Initial load
duke
parents:
diff changeset
237
a61af66fc99e Initial load
duke
parents:
diff changeset
238 return res? JNI_OK : JNI_ERR;
a61af66fc99e Initial load
duke
parents:
diff changeset
239 }
a61af66fc99e Initial load
duke
parents:
diff changeset
240
a61af66fc99e Initial load
duke
parents:
diff changeset
241 // set a uintx global flag using value from AttachOperation
a61af66fc99e Initial load
duke
parents:
diff changeset
242 static jint set_uintx_flag(const char* name, AttachOperation* op, outputStream* out) {
a61af66fc99e Initial load
duke
parents:
diff changeset
243 uintx value;
a61af66fc99e Initial load
duke
parents:
diff changeset
244 const char* arg1;
a61af66fc99e Initial load
duke
parents:
diff changeset
245 if ((arg1 = op->arg(1)) != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
246 int n = sscanf(arg1, UINTX_FORMAT, &value);
a61af66fc99e Initial load
duke
parents:
diff changeset
247 if (n != 1) {
1067
ba7ea42fc66e 6898160: Need serviceability support for new vm argument type 'uint64_t'
phh
parents: 615
diff changeset
248 out->print_cr("flag value must be an unsigned integer");
0
a61af66fc99e Initial load
duke
parents:
diff changeset
249 return JNI_ERR;
a61af66fc99e Initial load
duke
parents:
diff changeset
250 }
a61af66fc99e Initial load
duke
parents:
diff changeset
251 }
1067
ba7ea42fc66e 6898160: Need serviceability support for new vm argument type 'uint64_t'
phh
parents: 615
diff changeset
252 bool res = CommandLineFlags::uintxAtPut((char*)name, &value, ATTACH_ON_DEMAND);
ba7ea42fc66e 6898160: Need serviceability support for new vm argument type 'uint64_t'
phh
parents: 615
diff changeset
253 if (! res) {
ba7ea42fc66e 6898160: Need serviceability support for new vm argument type 'uint64_t'
phh
parents: 615
diff changeset
254 out->print_cr("setting flag %s failed", name);
ba7ea42fc66e 6898160: Need serviceability support for new vm argument type 'uint64_t'
phh
parents: 615
diff changeset
255 }
ba7ea42fc66e 6898160: Need serviceability support for new vm argument type 'uint64_t'
phh
parents: 615
diff changeset
256
ba7ea42fc66e 6898160: Need serviceability support for new vm argument type 'uint64_t'
phh
parents: 615
diff changeset
257 return res? JNI_OK : JNI_ERR;
ba7ea42fc66e 6898160: Need serviceability support for new vm argument type 'uint64_t'
phh
parents: 615
diff changeset
258 }
ba7ea42fc66e 6898160: Need serviceability support for new vm argument type 'uint64_t'
phh
parents: 615
diff changeset
259
ba7ea42fc66e 6898160: Need serviceability support for new vm argument type 'uint64_t'
phh
parents: 615
diff changeset
260 // set a uint64_t global flag using value from AttachOperation
ba7ea42fc66e 6898160: Need serviceability support for new vm argument type 'uint64_t'
phh
parents: 615
diff changeset
261 static jint set_uint64_t_flag(const char* name, AttachOperation* op, outputStream* out) {
ba7ea42fc66e 6898160: Need serviceability support for new vm argument type 'uint64_t'
phh
parents: 615
diff changeset
262 uint64_t value;
ba7ea42fc66e 6898160: Need serviceability support for new vm argument type 'uint64_t'
phh
parents: 615
diff changeset
263 const char* arg1;
ba7ea42fc66e 6898160: Need serviceability support for new vm argument type 'uint64_t'
phh
parents: 615
diff changeset
264 if ((arg1 = op->arg(1)) != NULL) {
ba7ea42fc66e 6898160: Need serviceability support for new vm argument type 'uint64_t'
phh
parents: 615
diff changeset
265 int n = sscanf(arg1, UINT64_FORMAT, &value);
ba7ea42fc66e 6898160: Need serviceability support for new vm argument type 'uint64_t'
phh
parents: 615
diff changeset
266 if (n != 1) {
ba7ea42fc66e 6898160: Need serviceability support for new vm argument type 'uint64_t'
phh
parents: 615
diff changeset
267 out->print_cr("flag value must be an unsigned 64-bit integer");
ba7ea42fc66e 6898160: Need serviceability support for new vm argument type 'uint64_t'
phh
parents: 615
diff changeset
268 return JNI_ERR;
ba7ea42fc66e 6898160: Need serviceability support for new vm argument type 'uint64_t'
phh
parents: 615
diff changeset
269 }
ba7ea42fc66e 6898160: Need serviceability support for new vm argument type 'uint64_t'
phh
parents: 615
diff changeset
270 }
ba7ea42fc66e 6898160: Need serviceability support for new vm argument type 'uint64_t'
phh
parents: 615
diff changeset
271 bool res = CommandLineFlags::uint64_tAtPut((char*)name, &value, ATTACH_ON_DEMAND);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
272 if (! res) {
a61af66fc99e Initial load
duke
parents:
diff changeset
273 out->print_cr("setting flag %s failed", name);
a61af66fc99e Initial load
duke
parents:
diff changeset
274 }
a61af66fc99e Initial load
duke
parents:
diff changeset
275
a61af66fc99e Initial load
duke
parents:
diff changeset
276 return res? JNI_OK : JNI_ERR;
a61af66fc99e Initial load
duke
parents:
diff changeset
277 }
a61af66fc99e Initial load
duke
parents:
diff changeset
278
a61af66fc99e Initial load
duke
parents:
diff changeset
279 // set a string global flag using value from AttachOperation
a61af66fc99e Initial load
duke
parents:
diff changeset
280 static jint set_ccstr_flag(const char* name, AttachOperation* op, outputStream* out) {
a61af66fc99e Initial load
duke
parents:
diff changeset
281 const char* value;
a61af66fc99e Initial load
duke
parents:
diff changeset
282 if ((value = op->arg(1)) == NULL) {
1067
ba7ea42fc66e 6898160: Need serviceability support for new vm argument type 'uint64_t'
phh
parents: 615
diff changeset
283 out->print_cr("flag value must be a string");
0
a61af66fc99e Initial load
duke
parents:
diff changeset
284 return JNI_ERR;
a61af66fc99e Initial load
duke
parents:
diff changeset
285 }
1067
ba7ea42fc66e 6898160: Need serviceability support for new vm argument type 'uint64_t'
phh
parents: 615
diff changeset
286 bool res = CommandLineFlags::ccstrAtPut((char*)name, &value, ATTACH_ON_DEMAND);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
287 if (res) {
a61af66fc99e Initial load
duke
parents:
diff changeset
288 FREE_C_HEAP_ARRAY(char, value);
a61af66fc99e Initial load
duke
parents:
diff changeset
289 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
290 out->print_cr("setting flag %s failed", name);
a61af66fc99e Initial load
duke
parents:
diff changeset
291 }
a61af66fc99e Initial load
duke
parents:
diff changeset
292
a61af66fc99e Initial load
duke
parents:
diff changeset
293 return res? JNI_OK : JNI_ERR;
a61af66fc99e Initial load
duke
parents:
diff changeset
294 }
a61af66fc99e Initial load
duke
parents:
diff changeset
295
a61af66fc99e Initial load
duke
parents:
diff changeset
296 // Implementation of "setflag" command
a61af66fc99e Initial load
duke
parents:
diff changeset
297 static jint set_flag(AttachOperation* op, outputStream* out) {
a61af66fc99e Initial load
duke
parents:
diff changeset
298
a61af66fc99e Initial load
duke
parents:
diff changeset
299 const char* name = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
300 if ((name = op->arg(0)) == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
301 out->print_cr("flag name is missing");
a61af66fc99e Initial load
duke
parents:
diff changeset
302 return JNI_ERR;
a61af66fc99e Initial load
duke
parents:
diff changeset
303 }
a61af66fc99e Initial load
duke
parents:
diff changeset
304
a61af66fc99e Initial load
duke
parents:
diff changeset
305 Flag* f = Flag::find_flag((char*)name, strlen(name));
a61af66fc99e Initial load
duke
parents:
diff changeset
306 if (f && f->is_external() && f->is_writeable()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
307 if (f->is_bool()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
308 return set_bool_flag(name, op, out);
a61af66fc99e Initial load
duke
parents:
diff changeset
309 } else if (f->is_intx()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
310 return set_intx_flag(name, op, out);
a61af66fc99e Initial load
duke
parents:
diff changeset
311 } else if (f->is_uintx()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
312 return set_uintx_flag(name, op, out);
1067
ba7ea42fc66e 6898160: Need serviceability support for new vm argument type 'uint64_t'
phh
parents: 615
diff changeset
313 } else if (f->is_uint64_t()) {
ba7ea42fc66e 6898160: Need serviceability support for new vm argument type 'uint64_t'
phh
parents: 615
diff changeset
314 return set_uint64_t_flag(name, op, out);
0
a61af66fc99e Initial load
duke
parents:
diff changeset
315 } else if (f->is_ccstr()) {
a61af66fc99e Initial load
duke
parents:
diff changeset
316 return set_ccstr_flag(name, op, out);
a61af66fc99e Initial load
duke
parents:
diff changeset
317 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
318 ShouldNotReachHere();
a61af66fc99e Initial load
duke
parents:
diff changeset
319 return JNI_ERR;
a61af66fc99e Initial load
duke
parents:
diff changeset
320 }
a61af66fc99e Initial load
duke
parents:
diff changeset
321 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
322 return AttachListener::pd_set_flag(op, out);
a61af66fc99e Initial load
duke
parents:
diff changeset
323 }
a61af66fc99e Initial load
duke
parents:
diff changeset
324 }
a61af66fc99e Initial load
duke
parents:
diff changeset
325
a61af66fc99e Initial load
duke
parents:
diff changeset
326 // Implementation of "printflag" command
a61af66fc99e Initial load
duke
parents:
diff changeset
327 static jint print_flag(AttachOperation* op, outputStream* out) {
a61af66fc99e Initial load
duke
parents:
diff changeset
328 const char* name = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
329 if ((name = op->arg(0)) == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
330 out->print_cr("flag name is missing");
a61af66fc99e Initial load
duke
parents:
diff changeset
331 return JNI_ERR;
a61af66fc99e Initial load
duke
parents:
diff changeset
332 }
a61af66fc99e Initial load
duke
parents:
diff changeset
333 Flag* f = Flag::find_flag((char*)name, strlen(name));
a61af66fc99e Initial load
duke
parents:
diff changeset
334 if (f) {
a61af66fc99e Initial load
duke
parents:
diff changeset
335 f->print_as_flag(out);
a61af66fc99e Initial load
duke
parents:
diff changeset
336 out->print_cr("");
a61af66fc99e Initial load
duke
parents:
diff changeset
337 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
338 out->print_cr("no such flag '%s'", name);
a61af66fc99e Initial load
duke
parents:
diff changeset
339 }
a61af66fc99e Initial load
duke
parents:
diff changeset
340 return JNI_OK;
a61af66fc99e Initial load
duke
parents:
diff changeset
341 }
a61af66fc99e Initial load
duke
parents:
diff changeset
342
a61af66fc99e Initial load
duke
parents:
diff changeset
343 // Table to map operation names to functions.
a61af66fc99e Initial load
duke
parents:
diff changeset
344
a61af66fc99e Initial load
duke
parents:
diff changeset
345 // names must be of length <= AttachOperation::name_length_max
a61af66fc99e Initial load
duke
parents:
diff changeset
346 static AttachOperationFunctionInfo funcs[] = {
a61af66fc99e Initial load
duke
parents:
diff changeset
347 { "agentProperties", get_agent_properties },
a61af66fc99e Initial load
duke
parents:
diff changeset
348 { "datadump", data_dump },
a61af66fc99e Initial load
duke
parents:
diff changeset
349 #ifndef SERVICES_KERNEL
a61af66fc99e Initial load
duke
parents:
diff changeset
350 { "dumpheap", dump_heap },
a61af66fc99e Initial load
duke
parents:
diff changeset
351 #endif // SERVICES_KERNEL
a61af66fc99e Initial load
duke
parents:
diff changeset
352 { "load", JvmtiExport::load_agent_library },
a61af66fc99e Initial load
duke
parents:
diff changeset
353 { "properties", get_system_properties },
a61af66fc99e Initial load
duke
parents:
diff changeset
354 { "threaddump", thread_dump },
a61af66fc99e Initial load
duke
parents:
diff changeset
355 { "inspectheap", heap_inspection },
a61af66fc99e Initial load
duke
parents:
diff changeset
356 { "setflag", set_flag },
a61af66fc99e Initial load
duke
parents:
diff changeset
357 { "printflag", print_flag },
a61af66fc99e Initial load
duke
parents:
diff changeset
358 { NULL, NULL }
a61af66fc99e Initial load
duke
parents:
diff changeset
359 };
a61af66fc99e Initial load
duke
parents:
diff changeset
360
a61af66fc99e Initial load
duke
parents:
diff changeset
361
a61af66fc99e Initial load
duke
parents:
diff changeset
362
a61af66fc99e Initial load
duke
parents:
diff changeset
363 // The Attach Listener threads services a queue. It dequeues an operation
a61af66fc99e Initial load
duke
parents:
diff changeset
364 // from the queue, examines the operation name (command), and dispatches
a61af66fc99e Initial load
duke
parents:
diff changeset
365 // to the corresponding function to perform the operation.
a61af66fc99e Initial load
duke
parents:
diff changeset
366
a61af66fc99e Initial load
duke
parents:
diff changeset
367 static void attach_listener_thread_entry(JavaThread* thread, TRAPS) {
a61af66fc99e Initial load
duke
parents:
diff changeset
368 os::set_priority(thread, NearMaxPriority);
a61af66fc99e Initial load
duke
parents:
diff changeset
369
a61af66fc99e Initial load
duke
parents:
diff changeset
370 if (AttachListener::pd_init() != 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
371 return;
a61af66fc99e Initial load
duke
parents:
diff changeset
372 }
a61af66fc99e Initial load
duke
parents:
diff changeset
373 AttachListener::set_initialized();
a61af66fc99e Initial load
duke
parents:
diff changeset
374
a61af66fc99e Initial load
duke
parents:
diff changeset
375 for (;;) {
a61af66fc99e Initial load
duke
parents:
diff changeset
376 AttachOperation* op = AttachListener::dequeue();
a61af66fc99e Initial load
duke
parents:
diff changeset
377 if (op == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
378 return; // dequeue failed or shutdown
a61af66fc99e Initial load
duke
parents:
diff changeset
379 }
a61af66fc99e Initial load
duke
parents:
diff changeset
380
a61af66fc99e Initial load
duke
parents:
diff changeset
381 ResourceMark rm;
a61af66fc99e Initial load
duke
parents:
diff changeset
382 bufferedStream st;
a61af66fc99e Initial load
duke
parents:
diff changeset
383 jint res = JNI_OK;
a61af66fc99e Initial load
duke
parents:
diff changeset
384
a61af66fc99e Initial load
duke
parents:
diff changeset
385 // handle special detachall operation
a61af66fc99e Initial load
duke
parents:
diff changeset
386 if (strcmp(op->name(), AttachOperation::detachall_operation_name()) == 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
387 AttachListener::detachall();
a61af66fc99e Initial load
duke
parents:
diff changeset
388 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
389 // find the function to dispatch too
a61af66fc99e Initial load
duke
parents:
diff changeset
390 AttachOperationFunctionInfo* info = NULL;
a61af66fc99e Initial load
duke
parents:
diff changeset
391 for (int i=0; funcs[i].name != NULL; i++) {
a61af66fc99e Initial load
duke
parents:
diff changeset
392 const char* name = funcs[i].name;
a61af66fc99e Initial load
duke
parents:
diff changeset
393 assert(strlen(name) <= AttachOperation::name_length_max, "operation <= name_length_max");
a61af66fc99e Initial load
duke
parents:
diff changeset
394 if (strcmp(op->name(), name) == 0) {
a61af66fc99e Initial load
duke
parents:
diff changeset
395 info = &(funcs[i]);
a61af66fc99e Initial load
duke
parents:
diff changeset
396 break;
a61af66fc99e Initial load
duke
parents:
diff changeset
397 }
a61af66fc99e Initial load
duke
parents:
diff changeset
398 }
a61af66fc99e Initial load
duke
parents:
diff changeset
399
a61af66fc99e Initial load
duke
parents:
diff changeset
400 // check for platform dependent attach operation
a61af66fc99e Initial load
duke
parents:
diff changeset
401 if (info == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
402 info = AttachListener::pd_find_operation(op->name());
a61af66fc99e Initial load
duke
parents:
diff changeset
403 }
a61af66fc99e Initial load
duke
parents:
diff changeset
404
a61af66fc99e Initial load
duke
parents:
diff changeset
405 if (info != NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
406 // dispatch to the function that implements this operation
a61af66fc99e Initial load
duke
parents:
diff changeset
407 res = (info->func)(op, &st);
a61af66fc99e Initial load
duke
parents:
diff changeset
408 } else {
a61af66fc99e Initial load
duke
parents:
diff changeset
409 st.print("Operation %s not recognized!", op->name());
a61af66fc99e Initial load
duke
parents:
diff changeset
410 res = JNI_ERR;
a61af66fc99e Initial load
duke
parents:
diff changeset
411 }
a61af66fc99e Initial load
duke
parents:
diff changeset
412 }
a61af66fc99e Initial load
duke
parents:
diff changeset
413
a61af66fc99e Initial load
duke
parents:
diff changeset
414 // operation complete - send result and output to client
a61af66fc99e Initial load
duke
parents:
diff changeset
415 op->complete(res, &st);
a61af66fc99e Initial load
duke
parents:
diff changeset
416 }
a61af66fc99e Initial load
duke
parents:
diff changeset
417 }
a61af66fc99e Initial load
duke
parents:
diff changeset
418
a61af66fc99e Initial load
duke
parents:
diff changeset
419 // Starts the Attach Listener thread
a61af66fc99e Initial load
duke
parents:
diff changeset
420 void AttachListener::init() {
a61af66fc99e Initial load
duke
parents:
diff changeset
421 EXCEPTION_MARK;
a61af66fc99e Initial load
duke
parents:
diff changeset
422 klassOop k = SystemDictionary::resolve_or_fail(vmSymbolHandles::java_lang_Thread(), true, CHECK);
a61af66fc99e Initial load
duke
parents:
diff changeset
423 instanceKlassHandle klass (THREAD, k);
a61af66fc99e Initial load
duke
parents:
diff changeset
424 instanceHandle thread_oop = klass->allocate_instance_handle(CHECK);
a61af66fc99e Initial load
duke
parents:
diff changeset
425
a61af66fc99e Initial load
duke
parents:
diff changeset
426 const char thread_name[] = "Attach Listener";
a61af66fc99e Initial load
duke
parents:
diff changeset
427 Handle string = java_lang_String::create_from_str(thread_name, CHECK);
a61af66fc99e Initial load
duke
parents:
diff changeset
428
a61af66fc99e Initial load
duke
parents:
diff changeset
429 // Initialize thread_oop to put it into the system threadGroup
a61af66fc99e Initial load
duke
parents:
diff changeset
430 Handle thread_group (THREAD, Universe::system_thread_group());
a61af66fc99e Initial load
duke
parents:
diff changeset
431 JavaValue result(T_VOID);
a61af66fc99e Initial load
duke
parents:
diff changeset
432 JavaCalls::call_special(&result, thread_oop,
a61af66fc99e Initial load
duke
parents:
diff changeset
433 klass,
a61af66fc99e Initial load
duke
parents:
diff changeset
434 vmSymbolHandles::object_initializer_name(),
a61af66fc99e Initial load
duke
parents:
diff changeset
435 vmSymbolHandles::threadgroup_string_void_signature(),
a61af66fc99e Initial load
duke
parents:
diff changeset
436 thread_group,
a61af66fc99e Initial load
duke
parents:
diff changeset
437 string,
a61af66fc99e Initial load
duke
parents:
diff changeset
438 CHECK);
a61af66fc99e Initial load
duke
parents:
diff changeset
439
1142
4ce7240d622c 6914300: ciEnv should export all well known classes
never
parents: 1067
diff changeset
440 KlassHandle group(THREAD, SystemDictionary::ThreadGroup_klass());
0
a61af66fc99e Initial load
duke
parents:
diff changeset
441 JavaCalls::call_special(&result,
a61af66fc99e Initial load
duke
parents:
diff changeset
442 thread_group,
a61af66fc99e Initial load
duke
parents:
diff changeset
443 group,
a61af66fc99e Initial load
duke
parents:
diff changeset
444 vmSymbolHandles::add_method_name(),
a61af66fc99e Initial load
duke
parents:
diff changeset
445 vmSymbolHandles::thread_void_signature(),
a61af66fc99e Initial load
duke
parents:
diff changeset
446 thread_oop, // ARG 1
a61af66fc99e Initial load
duke
parents:
diff changeset
447 CHECK);
a61af66fc99e Initial load
duke
parents:
diff changeset
448
a61af66fc99e Initial load
duke
parents:
diff changeset
449 { MutexLocker mu(Threads_lock);
a61af66fc99e Initial load
duke
parents:
diff changeset
450 JavaThread* listener_thread = new JavaThread(&attach_listener_thread_entry);
a61af66fc99e Initial load
duke
parents:
diff changeset
451
a61af66fc99e Initial load
duke
parents:
diff changeset
452 // Check that thread and osthread were created
a61af66fc99e Initial load
duke
parents:
diff changeset
453 if (listener_thread == NULL || listener_thread->osthread() == NULL) {
a61af66fc99e Initial load
duke
parents:
diff changeset
454 vm_exit_during_initialization("java.lang.OutOfMemoryError",
a61af66fc99e Initial load
duke
parents:
diff changeset
455 "unable to create new native thread");
a61af66fc99e Initial load
duke
parents:
diff changeset
456 }
a61af66fc99e Initial load
duke
parents:
diff changeset
457
a61af66fc99e Initial load
duke
parents:
diff changeset
458 java_lang_Thread::set_thread(thread_oop(), listener_thread);
a61af66fc99e Initial load
duke
parents:
diff changeset
459 java_lang_Thread::set_daemon(thread_oop());
a61af66fc99e Initial load
duke
parents:
diff changeset
460
a61af66fc99e Initial load
duke
parents:
diff changeset
461 listener_thread->set_threadObj(thread_oop());
a61af66fc99e Initial load
duke
parents:
diff changeset
462 Threads::add(listener_thread);
a61af66fc99e Initial load
duke
parents:
diff changeset
463 Thread::start(listener_thread);
a61af66fc99e Initial load
duke
parents:
diff changeset
464 }
a61af66fc99e Initial load
duke
parents:
diff changeset
465 }
a61af66fc99e Initial load
duke
parents:
diff changeset
466
a61af66fc99e Initial load
duke
parents:
diff changeset
467 // Performs clean-up tasks on platforms where we can detect that the last
a61af66fc99e Initial load
duke
parents:
diff changeset
468 // client has detached
a61af66fc99e Initial load
duke
parents:
diff changeset
469 void AttachListener::detachall() {
a61af66fc99e Initial load
duke
parents:
diff changeset
470 // call the platform dependent clean-up
a61af66fc99e Initial load
duke
parents:
diff changeset
471 pd_detachall();
a61af66fc99e Initial load
duke
parents:
diff changeset
472 }