1 /*
2  * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.
8  *
9  * This code is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12  * version 2 for more details (a copy is included in the LICENSE file that
13  * accompanied this code).
14  *
15  * You should have received a copy of the GNU General Public License version
16  * 2 along with this work; if not, write to the Free Software Foundation,
17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18  *
19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20  * or visit www.oracle.com if you need additional information or have any
21  * questions.
22  */
23 
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <jvmti.h>
28 #include "agent_common.h"
29 
30 #include "nsk_tools.h"
31 #include "JVMTITools.h"
32 #include "jvmti_tools.h"
33 
34 extern "C" {
35 
36 #define STATUS_FAILED 2
37 #define PASSED 0
38 
39 #define MEM_SIZE 1024
40 
41 static jvmtiEnv *jvmti = NULL;
42 static jvmtiEventCallbacks callbacks;
43 static jvmtiCapabilities caps;
44 
45 static volatile jint result = PASSED;
46 static volatile int gcstart = 0;
47 unsigned char *mem;
48 
rawMonitorFunc(jvmtiEnv * jvmti_env,const char * msg)49 static void rawMonitorFunc(jvmtiEnv *jvmti_env, const char *msg) {
50     jrawMonitorID _lock;
51 
52     NSK_DISPLAY1("%s: creating a raw monitor ...\n",
53         msg);
54     if (!NSK_JVMTI_VERIFY(jvmti_env->CreateRawMonitor("_lock", &_lock))) {
55         result = STATUS_FAILED;
56         NSK_COMPLAIN1("TEST FAILED: %s: unable to create a raw monitor\n\n",
57             msg);
58         return;
59     }
60     NSK_DISPLAY1("CHECK PASSED: %s: raw monitor created\n",
61         msg);
62 
63     NSK_DISPLAY1("%s: entering the raw monitor ...\n",
64         msg);
65     if (!NSK_JVMTI_VERIFY(jvmti_env->RawMonitorEnter(_lock))) {
66         result = STATUS_FAILED;
67         NSK_COMPLAIN1("TEST FAILED: %s: unable to enter the raw monitor\n\n",
68             msg);
69         return;
70     }
71     else {
72         NSK_DISPLAY1("CHECK PASSED: %s: the raw monitor entered\n",
73             msg);
74 
75         NSK_DISPLAY1("%s: waiting the raw monitor ...\n",
76             msg);
77         if (!NSK_JVMTI_VERIFY(jvmti_env->RawMonitorWait(_lock, (jlong)10))) {
78             result = STATUS_FAILED;
79             NSK_COMPLAIN1("TEST FAILED: %s: unable to wait the raw monitor\n\n",
80                 msg);
81         }
82         NSK_DISPLAY1("CHECK PASSED: %s: the raw monitor waited\n",
83             msg);
84 
85 
86         NSK_DISPLAY1("%s: notifying a single thread waiting on the raw monitor ...\n",
87             msg);
88         if (!NSK_JVMTI_VERIFY(jvmti_env->RawMonitorNotify(_lock))) {
89             result = STATUS_FAILED;
90             NSK_COMPLAIN1("TEST FAILED: %s: unable to notify single thread\n\n",
91                 msg);
92         }
93         NSK_DISPLAY1("CHECK PASSED: %s: single thread notified\n",
94             msg);
95 
96 
97         NSK_DISPLAY1("%s: notifying all threads waiting on the raw monitor ...\n",
98             msg);
99         if (!NSK_JVMTI_VERIFY(jvmti_env->RawMonitorNotifyAll(_lock))) {
100             result = STATUS_FAILED;
101             NSK_COMPLAIN1("TEST FAILED: %s: unable to notify all threads\n\n",
102                 msg);
103         }
104         NSK_DISPLAY1("CHECK PASSED: %s: all threads notified\n",
105             msg);
106 
107 
108         NSK_DISPLAY1("%s: exiting the raw monitor ...\n",
109             msg);
110         if (!NSK_JVMTI_VERIFY(jvmti_env->RawMonitorExit(_lock))) {
111             result = STATUS_FAILED;
112             NSK_COMPLAIN1("TEST FAILED: %s: unable to exit the raw monitor\n\n",
113                 msg);
114         }
115         NSK_DISPLAY1("CHECK PASSED: %s: the raw monitor exited\n",
116             msg);
117     }
118 
119     NSK_DISPLAY1("%s: destroying the raw monitor ...\n",
120         msg);
121     if (!NSK_JVMTI_VERIFY(jvmti_env->DestroyRawMonitor(_lock))) {
122         result = STATUS_FAILED;
123         NSK_COMPLAIN1("TEST FAILED: %s: unable to destroy a raw monitor\n",
124             msg);
125         return;
126     }
127     NSK_DISPLAY1("CHECK PASSED: %s: the raw monitor destroyed\n",
128         msg);
129 }
130 
memoryFunc(jvmtiEnv * jvmti_env,const char * msg)131 static void memoryFunc(jvmtiEnv *jvmti_env, const char *msg) {
132     NSK_DISPLAY1("%s: allocating memory ...\n",
133         msg);
134     if (!NSK_JVMTI_VERIFY(jvmti_env->Allocate(MEM_SIZE, &mem))) {
135         result = STATUS_FAILED;
136         NSK_COMPLAIN1("TEST FAILED: %s: unable to allocate memory\n\n",
137             msg);
138         return;
139     }
140     else
141         NSK_DISPLAY1("CHECK PASSED: %s: memory has been allocated successfully\n",
142             msg);
143 
144     NSK_DISPLAY1("%s: deallocating memory ...\n",
145         msg);
146     if (!NSK_JVMTI_VERIFY(jvmti_env->Deallocate(mem))) {
147         result = STATUS_FAILED;
148         NSK_COMPLAIN1("TEST FAILED: %s: unable to deallocate memory\n\n",
149             msg);
150     }
151     else
152         NSK_DISPLAY1("CHECK PASSED: %s: memory has been deallocated successfully\n\n",
153             msg);
154 }
155 
156 /** callback functions **/
157 void JNICALL
GarbageCollectionStart(jvmtiEnv * jvmti_env)158 GarbageCollectionStart(jvmtiEnv *jvmti_env) {
159     gcstart++;
160     NSK_DISPLAY1(">>>> GarbageCollectionStart event #%d received\n",
161         gcstart);
162 
163     rawMonitorFunc(jvmti_env, "GarbageCollectionStart");
164 
165     memoryFunc(jvmti_env, "GarbageCollectionStart");
166 
167     NSK_DISPLAY0("<<<<\n\n");
168 }
169 
170 void JNICALL
VMDeath(jvmtiEnv * jvmti_env,JNIEnv * env)171 VMDeath(jvmtiEnv *jvmti_env, JNIEnv *env) {
172     NSK_DISPLAY0("VMDeath event received\n");
173 
174     if (result == STATUS_FAILED)
175         exit(95 + STATUS_FAILED);
176 }
177 
178 /************************/
179 
180 #ifdef STATIC_BUILD
Agent_OnLoad_gcstart002(JavaVM * jvm,char * options,void * reserved)181 JNIEXPORT jint JNICALL Agent_OnLoad_gcstart002(JavaVM *jvm, char *options, void *reserved) {
182     return Agent_Initialize(jvm, options, reserved);
183 }
Agent_OnAttach_gcstart002(JavaVM * jvm,char * options,void * reserved)184 JNIEXPORT jint JNICALL Agent_OnAttach_gcstart002(JavaVM *jvm, char *options, void *reserved) {
185     return Agent_Initialize(jvm, options, reserved);
186 }
JNI_OnLoad_gcstart002(JavaVM * jvm,char * options,void * reserved)187 JNIEXPORT jint JNI_OnLoad_gcstart002(JavaVM *jvm, char *options, void *reserved) {
188     return JNI_VERSION_1_8;
189 }
190 #endif
Agent_Initialize(JavaVM * jvm,char * options,void * reserved)191 jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) {
192     /* init framework and parse options */
193     if (!NSK_VERIFY(nsk_jvmti_parseOptions(options)))
194         return JNI_ERR;
195 
196     /* create JVMTI environment */
197     if (!NSK_VERIFY((jvmti =
198             nsk_jvmti_createJVMTIEnv(jvm, reserved)) != NULL))
199         return JNI_ERR;
200 
201     /* add capability to generate compiled method events */
202     memset(&caps, 0, sizeof(jvmtiCapabilities));
203     caps.can_generate_garbage_collection_events = 1;
204     if (!NSK_JVMTI_VERIFY(jvmti->AddCapabilities(&caps)))
205         return JNI_ERR;
206 
207     if (!NSK_JVMTI_VERIFY(jvmti->GetCapabilities(&caps)))
208         return JNI_ERR;
209 
210     if (!caps.can_generate_garbage_collection_events)
211         NSK_DISPLAY0("Warning: generation of garbage collection events is not implemented\n");
212 
213     /* set event callback */
214     NSK_DISPLAY0("setting event callbacks ...\n");
215     (void) memset(&callbacks, 0, sizeof(callbacks));
216     callbacks.VMDeath = &VMDeath;
217     callbacks.GarbageCollectionStart = &GarbageCollectionStart;
218     if (!NSK_JVMTI_VERIFY(jvmti->SetEventCallbacks(&callbacks, sizeof(callbacks))))
219         return JNI_ERR;
220 
221     NSK_DISPLAY0("setting event callbacks done\nenabling JVMTI events ...\n");
222     if (!NSK_JVMTI_VERIFY(jvmti->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_VM_DEATH, NULL)))
223         return JNI_ERR;
224     if (!NSK_JVMTI_VERIFY(jvmti->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_GARBAGE_COLLECTION_START, NULL)))
225         return JNI_ERR;
226     NSK_DISPLAY0("enabling the events done\n\n");
227 
228     return JNI_OK;
229 }
230 
231 }
232