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 
  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     }
  70     else {
  71         NSK_DISPLAY1("CHECK PASSED: %s: the raw monitor entered\n",
  72             msg);
  73 
  74         NSK_DISPLAY1("%s: waiting the raw monitor ...\n",
  75             msg);
  76         if (!NSK_JVMTI_VERIFY(jvmti_env->RawMonitorWait(_lock, (jlong)10))) {
  77             result = STATUS_FAILED;
  78             NSK_COMPLAIN1("TEST FAILED: %s: unable to wait the raw monitor\n\n",
  79                 msg);
  80         }
  81         NSK_DISPLAY1("CHECK PASSED: %s: the raw monitor waited\n",
  82             msg);
  83 
  84 
  85         NSK_DISPLAY1("%s: notifying a single thread waiting on the raw monitor ...\n",
  86             msg);
  87         if (!NSK_JVMTI_VERIFY(jvmti_env->RawMonitorNotify(_lock))) {
  88             result = STATUS_FAILED;
  89             NSK_COMPLAIN1("TEST FAILED: %s: unable to notify single thread\n\n",
  90                 msg);
  91         }
  92         NSK_DISPLAY1("CHECK PASSED: %s: single thread notified\n",
  93             msg);
  94 
  95 
  96         NSK_DISPLAY1("%s: notifying all threads waiting on the raw monitor ...\n",
  97             msg);
  98         if (!NSK_JVMTI_VERIFY(jvmti_env->RawMonitorNotifyAll(_lock))) {
  99             result = STATUS_FAILED;
 100             NSK_COMPLAIN1("TEST FAILED: %s: unable to notify all threads\n\n",
 101                 msg);
 102         }
 103         NSK_DISPLAY1("CHECK PASSED: %s: all threads notified\n",
 104             msg);
 105 
 106 
 107         NSK_DISPLAY1("%s: exiting the raw monitor ...\n",
 108             msg);
 109         if (!NSK_JVMTI_VERIFY(jvmti_env->RawMonitorExit(_lock))) {
 110             result = STATUS_FAILED;
 111             NSK_COMPLAIN1("TEST FAILED: %s: unable to exit the raw monitor\n\n",
 112                 msg);
 113         }
 114         NSK_DISPLAY1("CHECK PASSED: %s: the raw monitor exited\n",
 115             msg);
 116     }
 117 
 118     NSK_DISPLAY1("%s: destroying the raw monitor ...\n",
 119         msg);
 120     if (!NSK_JVMTI_VERIFY(jvmti_env->DestroyRawMonitor(_lock))) {
 121         result = STATUS_FAILED;
 122         NSK_COMPLAIN1("TEST FAILED: %s: unable to destroy a raw monitor\n",
 123             msg);
 124         return;
 125     }
 126     NSK_DISPLAY1("CHECK PASSED: %s: the raw monitor destroyed\n",
 127         msg);
 128 }
 129 
 130 static void memoryFunc(jvmtiEnv *jvmti_env, const char *msg) {
 131     NSK_DISPLAY1("%s: allocating memory ...\n",
 132         msg);
 133     if (!NSK_JVMTI_VERIFY(jvmti_env->Allocate(MEM_SIZE, &mem))) {
 134         result = STATUS_FAILED;
 135         NSK_COMPLAIN1("TEST FAILED: %s: unable to allocate memory\n\n",
 136             msg);
 137         return;
 138     }
 139     else
 140         NSK_DISPLAY1("CHECK PASSED: %s: memory has been allocated successfully\n",
 141             msg);
 142 
 143     NSK_DISPLAY1("%s: deallocating memory ...\n",
 144         msg);
 145     if (!NSK_JVMTI_VERIFY(jvmti_env->Deallocate(mem))) {
 146         result = STATUS_FAILED;
 147         NSK_COMPLAIN1("TEST FAILED: %s: unable to deallocate memory\n\n",
 148             msg);
 149     }
 150     else
 151         NSK_DISPLAY1("CHECK PASSED: %s: memory has been deallocated successfully\n\n",
 152             msg);
 153 }
 154 
 155 /** callback functions **/
 156 void JNICALL
 157 GarbageCollectionFinish(jvmtiEnv *jvmti_env) {
 158     gcstart++;
 159     NSK_DISPLAY1(">>>> GarbageCollectionFinish event #%d received\n",
 160         gcstart);
 161 
 162     rawMonitorFunc(jvmti_env, "GarbageCollectionFinish");
 163 
 164     memoryFunc(jvmti_env, "GarbageCollectionFinish");
 165 
 166     NSK_DISPLAY0("<<<<\n\n");
 167 }
 168 
 169 void JNICALL
 170 VMDeath(jvmtiEnv *jvmti_env, JNIEnv *env) {
 171     NSK_DISPLAY0("VMDeath event received\n");
 172 
 173     if (result == STATUS_FAILED)
 174         exit(95 + STATUS_FAILED);
 175 }
 176 
 177 /************************/
 178 
 179 #ifdef STATIC_BUILD
 180 JNIEXPORT jint JNICALL Agent_OnLoad_gcfinish001(JavaVM *jvm, char *options, void *reserved) {
 181     return Agent_Initialize(jvm, options, reserved);
 182 }
 183 JNIEXPORT jint JNICALL Agent_OnAttach_gcfinish001(JavaVM *jvm, char *options, void *reserved) {
 184     return Agent_Initialize(jvm, options, reserved);
 185 }
 186 JNIEXPORT jint JNI_OnLoad_gcfinish001(JavaVM *jvm, char *options, void *reserved) {
 187     return JNI_VERSION_1_8;
 188 }
 189 #endif
 190 jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) {
 191     /* init framework and parse options */
 192     if (!NSK_VERIFY(nsk_jvmti_parseOptions(options)))
 193         return JNI_ERR;
 194 
 195     /* create JVMTI environment */
 196     if (!NSK_VERIFY((jvmti =
 197             nsk_jvmti_createJVMTIEnv(jvm, reserved)) != NULL))
 198         return JNI_ERR;
 199 
 200     /* add capability to generate compiled method events */
 201     memset(&caps, 0, sizeof(jvmtiCapabilities));
 202     caps.can_generate_garbage_collection_events = 1;
 203     if (!NSK_JVMTI_VERIFY(jvmti->AddCapabilities(&caps)))
 204         return JNI_ERR;
 205 
 206     if (!NSK_JVMTI_VERIFY(jvmti->GetCapabilities(&caps)))
 207         return JNI_ERR;
 208 
 209     if (!caps.can_generate_garbage_collection_events)
 210         NSK_DISPLAY0("Warning: generation of garbage collection events is not implemented\n");
 211 
 212     /* set event callback */
 213     NSK_DISPLAY0("setting event callbacks ...\n");
 214     (void) memset(&callbacks, 0, sizeof(callbacks));
 215     callbacks.VMDeath = &VMDeath;
 216     callbacks.GarbageCollectionFinish = &GarbageCollectionFinish;
 217     if (!NSK_JVMTI_VERIFY(jvmti->SetEventCallbacks(&callbacks, sizeof(callbacks))))
 218         return JNI_ERR;
 219 
 220     NSK_DISPLAY0("setting event callbacks done\nenabling JVMTI events ...\n");
 221     if (!NSK_JVMTI_VERIFY(jvmti->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_VM_DEATH, NULL)))
 222         return JNI_ERR;
 223     if (!NSK_JVMTI_VERIFY(jvmti->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_GARBAGE_COLLECTION_FINISH, NULL)))
 224         return JNI_ERR;
 225     NSK_DISPLAY0("enabling the events done\n\n");
 226 
 227     return JNI_OK;
 228 }
 229 
 230 }