Path: blob/master/runtime/jcl/common/jcltrace.c
6000 views
/*******************************************************************************1* Copyright (c) 1998, 2019 IBM Corp. and others2*3* This program and the accompanying materials are made available under4* the terms of the Eclipse Public License 2.0 which accompanies this5* distribution and is available at https://www.eclipse.org/legal/epl-2.0/6* or the Apache License, Version 2.0 which accompanies this distribution and7* is available at https://www.apache.org/licenses/LICENSE-2.0.8*9* This Source Code may also be made available under the following10* Secondary Licenses when the conditions for such availability set11* forth in the Eclipse Public License, v. 2.0 are satisfied: GNU12* General Public License, version 2 with the GNU Classpath13* Exception [1] and GNU General Public License, version 2 with the14* OpenJDK Assembly Exception [2].15*16* [1] https://www.gnu.org/software/classpath/license.html17* [2] http://openjdk.java.net/legal/assembly-exception.html18*19* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception20*******************************************************************************/2122#include <stdlib.h>23#include <string.h>24#include <ctype.h>25#include <assert.h>2627#include "jclprots.h"28#include "jclglob.h"29#include "j9protos.h"3031#define UT_TRACE_VERSION 732#define MAX_APPLICATION_NAME_CHARS 256 /*ibm@94275*/3334/* ibm@94077 starts */35#define TRACEDOTCGLOBAL(x) JCL_CACHE_GET(env, traceGlobals).x3637/* Argument type codes. These are combined to build a word describing the38* expected argument for a particular trace point.39*/4041#define JWORD 0x0142#define JDOUBLEWORD 0x0243#define JFLOATPOINT 0x0444#define JCHAR 0x0845#define JSTRING 0x1046#define JOBJECT 0x2047/*Pointers can be passed in as objects or double words*/48#define JPOINTER (JOBJECT | JDOUBLEWORD)4950static I_32 CompareAndSwap32(volatile U_32 *target, U_32 old, U_32 new32);5152static I_32 CompareAndSwapPtr(volatile UDATA *target, UDATA old, UDATA newptr);5354/**55* Thread-safe array list used for mapping handles to module info structures56*/57struct ArrayList {58UDATA slabSize;59void ** header;60};6162/*Data type function prototypes*/63/**64* Allocates new array list65*66* @param slabSize Size of each array slab67* @return Pointer to a new array list or NULL if there was a problem68*/69static struct ArrayList *allocArrayList(JNIEnv *const env, const UDATA slabSize);7071/**72* Inserts an element into the array list73*74* @param list Array list to insert into75* @param index Location to put value76* @param value Value to insert77* @return 0 on success, non-zero on failure78*79*/80static IDATA arrayListPut(JNIEnv *const env, const struct ArrayList *const list, const UDATA index, void *const value);8182/**83* Gets an element from the array list84*85* @param list Array list to get from86* @param index Location to get87* @return Value at that position or NULL if that position is not filled88*/89static void *arrayListGet(JNIEnv *const env, const struct ArrayList *const list, const UDATA index);9091/* Deep frees a modInfo structure */92static void freeModInfo(JNIEnv *const env, UtModuleInfo *toFree);9394/*Size of the slabs used to build array lists*/95#define SLAB_SIZE 109697#define ERROR_MESSAGE_BUFFER_LENGTH 2569899/* Macros for building argument descriptors (magic values describing a sequence of arguments) for the application trace methods.100* This has been done as macros rather than as a function so the work can be done at compile time.101*/102#define ARGUMENT_DESCRIPTOR() 0103#define ARGUMENT_DESCRIPTOR_1(x) x104#define ARGUMENT_DESCRIPTOR_2(x, y) ((x << 8) | y)105#define ARGUMENT_DESCRIPTOR_3(x, y, z) ((x << 16) | (y << 8) | z)106107static void108throwNewThrowable(JNIEnv *const env, const char *const exceptionClassName, const char *const message)109{110jclass exceptionClass = (*env)->FindClass(env, exceptionClassName);111112if (NULL == exceptionClass) {113return;114}115116(*env)->ThrowNew(env, exceptionClass, message);117}118119static void120throwIllegalArgumentException(JNIEnv *const env, const char *const message)121{122throwNewThrowable(env, "java/lang/IllegalArgumentException", message);123}124125static void126throwRuntimeException(JNIEnv *const env, const char *const message)127{128throwNewThrowable(env, "java/lang/RuntimeException", message);129}130131/* Terminates the trace structures. Must not be called while it's still possible for an application to call register */132void133terminateTrace(JNIEnv *env)134{135int lastIndex = 0;136void **slab = NULL;137138PORT_ACCESS_FROM_ENV(env);139140if ((NULL == TRACEDOTCGLOBAL(utIntf)) || (NULL == TRACEDOTCGLOBAL(utIntf)->server)) {141/* nothing to be done without the interfaces, so bail */142return;143}144145/* null the app trace handle count so that any attempts to trace will fail and save the tail index146* to iterate with147*/148do {149lastIndex = TRACEDOTCGLOBAL(numberOfAppTraceApplications);150} while (! CompareAndSwap32(&TRACEDOTCGLOBAL(numberOfAppTraceApplications), lastIndex, 0));151152/* free the modInfo and argument structures */153for (;lastIndex > 0; lastIndex--) {154UtModuleInfo *modInfo = (UtModuleInfo *)arrayListGet(env, TRACEDOTCGLOBAL(modInfoList), lastIndex);155UDATA **callPatternsArray = (UDATA **)arrayListGet(env, TRACEDOTCGLOBAL(argumentStructureList), lastIndex);156157assert((NULL != modInfo) && (NULL != callPatternsArray));158159freeModInfo(env, modInfo);160j9mem_free_memory(callPatternsArray);161}162163/* free the modInfo list */164slab = TRACEDOTCGLOBAL(modInfoList)->header;165while (NULL != slab) {166void **nextSlab = slab[TRACEDOTCGLOBAL(modInfoList)->slabSize];167j9mem_free_memory(slab);168slab = nextSlab;169}170j9mem_free_memory(TRACEDOTCGLOBAL(modInfoList));171172/* free the argument structures list */173slab = TRACEDOTCGLOBAL(argumentStructureList)->header;174while (NULL != slab) {175void **nextSlab = slab[TRACEDOTCGLOBAL(argumentStructureList)->slabSize];176j9mem_free_memory(slab);177slab = nextSlab;178}179j9mem_free_memory(TRACEDOTCGLOBAL(argumentStructureList));180}181182/**************************************************************************183* name - Java_com_ibm_jvm_Trace_initTrace184* description - Obtain system properties and initialize trace for JAVA.DLL185* parameters - JNIEnv, this186* returns - none187*************************************************************************/188void JNICALL189Java_com_ibm_jvm_Trace_initTraceImpl(JNIEnv *env, jobject this)190{191int rc = 0;192JavaVM *vm = NULL;193194TRACEDOTCGLOBAL(rasIntf) = NULL;195TRACEDOTCGLOBAL(utIntf) = NULL;196TRACEDOTCGLOBAL(numberOfAppTraceApplications) = 0;197198rc = (*env)->GetJavaVM(env, &vm);199if (JNI_OK == rc) {200/* Get RAS interface (Might not be available if trace not loaded) */201if ((JNI_OK == (*vm)->GetEnv(vm, (void **)&TRACEDOTCGLOBAL(rasIntf), JVMRAS_VERSION_1_3)) &&202(JNI_OK == (*vm)->GetEnv(vm, (void **)&TRACEDOTCGLOBAL(utIntf), UTE_VERSION_1_1))) {203TRACEDOTCGLOBAL(modInfoList) = allocArrayList(env, SLAB_SIZE);204TRACEDOTCGLOBAL(argumentStructureList) = allocArrayList(env, SLAB_SIZE);205206if ((NULL == TRACEDOTCGLOBAL(modInfoList)) || (NULL == TRACEDOTCGLOBAL(argumentStructureList))) {207/*Exception will have been thrown*/208TRACEDOTCGLOBAL(utIntf) = NULL;209TRACEDOTCGLOBAL(rasIntf) = NULL;210}211} else {212TRACEDOTCGLOBAL(utIntf) = NULL;213TRACEDOTCGLOBAL(rasIntf) = NULL;214/* No option but to return silently */215return;216}217}218return;219}220221/*222* Extracts UTF chars from string object and checks length against MAX_APPLICATION_NAME_CHARS223*224* @param *env [in] JNI environment225* @param name [in] String object226* @param **applicationName [out] Pointer to pointer that will be assigned with GetStringUTFChars227*/228static UDATA229processAndCheckNameString(JNIEnv *env, jobject name, const char **applicationName) {230*applicationName = (*env)->GetStringUTFChars(env, name, NULL);231232if (NULL == *applicationName) {233return 1;234}235236/* Check the application name does not exceed MAX_APPLICATION_NAME_CHARS */237if (strlen(*applicationName) > MAX_APPLICATION_NAME_CHARS) {238char messageBuffer[ERROR_MESSAGE_BUFFER_LENGTH + 1];239PORT_ACCESS_FROM_ENV(env);240241memset(messageBuffer, 0, sizeof(messageBuffer));242j9str_printf(PORTLIB, messageBuffer, ERROR_MESSAGE_BUFFER_LENGTH, "Application name is too long. Maximum length %d characters, supplied string was %d characters.\n", MAX_APPLICATION_NAME_CHARS, strlen(*applicationName));243throwIllegalArgumentException(env, messageBuffer);244return 2;245}246247return 0;248}249250/*251* A strcpy that won't copy beyond the end pointer252*253* @param **p [inout] Pointer to buffer to write out in254* @param *from [in] Buffer to copy from (must be NULL terminated255* @param end [in] Pointer to end of buffer *p256*/257static void258guardedStrcpy(char **p, const char *const from, const char *const end)259{260const char *fromCursor = from;261262while ((*p < end) && (0 != ((**p) = *fromCursor))) {263(*p)++;264fromCursor++;265}266}267268/*269* Formats a human readable version of a call pattern (as created by buildCallPattern).270*271* @param p [in] Pointer to buffer to hold the call pattern272* @param end [in] Pointer to end of buffer (we will not write past it)273* @param pattern [in] The pattern to format274*/275static void276formatCallPattern(char *p, char *const end, const UDATA pattern)277{278IDATA args = 0;279IDATA shift = 3 * 8;280281for (; shift >= 0; shift -= 8) {282UDATA thisPattern = (pattern >> shift) & 0xFF;283const char *humanReadablePattern = "unknown";284285switch (thisPattern) {286case (0) :287continue;288case (JWORD) :289humanReadablePattern = "word(byte/short/int)";290break;291case (JDOUBLEWORD) :292humanReadablePattern = "doubleword(long)";293break;294case (JOBJECT) :295humanReadablePattern = "object";296break;297case (JPOINTER) :298humanReadablePattern = "pointer(object/doubleword)";299break;300case (JFLOATPOINT) :301humanReadablePattern = "float/double";302break;303case (JCHAR) :304humanReadablePattern = "char";305break;306case (JSTRING) :307humanReadablePattern = "string";308break;309default:310/*Should be impossible*/311assert(0);312break;313}314315if (end <= p) {316/* no space left */317break;318}319320if (args != 0) {321/* a comma separator from the previous pattern */322*p = ',';323p++;324}325326guardedStrcpy(&p, humanReadablePattern, end);327args += 1;328}329330/* nul-terminate the string */331*p = '\0';332}333334/**335* State type for printf parsing (see buildCallPattern).336*/337enum PatternParseState { FINDING_PERCENT, SKIPPING_PRECISION, READING_MODIFIER, READING_TYPE };338339/*340* Reads a printf-style template (of up to 4 placeholders) and stores a value341* representing the argument sequence to *result.342*343* @param templateString [in] printf template string344* @param result [out] Pointer to output word345*/346static void347buildCallPattern(const char *const templateString, UDATA *const result)348{349int longModifierCount = 0;350const char *p = templateString;351enum PatternParseState state = FINDING_PERCENT;352353*result = 0;354355while (0 != *p) {356switch (state) {357case FINDING_PERCENT:358if ('%' == *p) {359longModifierCount = 0;360state = SKIPPING_PRECISION;361}362break;363case SKIPPING_PRECISION:364/*In this state we skip any 0-9 or .*/365if ('l' == *p) {366/*Reparse this letter in the READING_MODIFIER state*/367state = READING_MODIFIER;368continue;369} else if (('.' != *p) && !isdigit(*p)) {370state = READING_TYPE;371continue;372}373break;374case READING_MODIFIER:375if ('l' == *p) {376longModifierCount++;377} else {378state = READING_TYPE;379continue;380}381break;382case READING_TYPE:383{384unsigned char typeCode = 0;385switch (tolower(*p)) {386case 'c':387typeCode = JCHAR;388break;389case 'd':390case 'x':391case 'i':392case 'u':393if (longModifierCount > 1) {394typeCode = JDOUBLEWORD;395} else {396typeCode = JWORD;397}398break;399case 'p':400typeCode = JPOINTER;401break;402case 's':403typeCode = JSTRING;404break;405case 'f':406case 'g':407case 'e':408typeCode = JFLOATPOINT;409break;410default:411/*Unknown placeholder. Ignored by printf*/412break;413}414415if (0 != typeCode) {416*result = (*result << 8) | typeCode;417}418419state = FINDING_PERCENT;420break;421}422default:423/*This should be impossible*/424assert(0);425break;426}427428p++;429}430}431432/*433* Checks whether a character is a valid type character (one of ENTRY, EXIT, EVENT, EXCEPTION, EXIT_EXCEPTION)434*/435static BOOLEAN436isValidTypeChar(char character)437{438return ('0' == character)439|| ('1' == character)440|| ('2' == character)441|| ('3' == character)442|| ('4' == character)443|| ('5' == character);444}445446/**447* Processes the template strings provided to registerApplication()448*449* @param *env [in] JNI environment450* @param templates [in] Array containing templates451* @param formatStringsArray [out] Pointer to array of strings. Assigned by this method and populated with the UTF version of templates452* @param callPatternsArray [out] Pointer to array of UDATA. Assigned by this method and populated with the call patterns for the templates.453* @param tracePointCount [out] Pointer to UDATA to be set to number of trace points (size of templates array)454*/455static UDATA456extractAndProcessFormatStrings(JNIEnv *env, jarray templates, char ***const formatStringsArray, UDATA **const callPatternsArray, UDATA *const tracePointCount)457{458UDATA i = 0;459UDATA rc = 0;460J9InternalVMFunctions *vmFuncs = ((J9VMThread *)env)->javaVM->internalVMFunctions;461462PORT_ACCESS_FROM_ENV(env);463464*tracePointCount = (*env)->GetArrayLength(env, templates);465466if (NULL != (*env)->ExceptionOccurred(env)) {467return 1;468}469470/*Allocate the two arrays. The formatStringsArray is passed to the trace engine which expects an extra NULL field at the end*/471*formatStringsArray = (char **)j9mem_allocate_memory(sizeof(char *) * (*tracePointCount + 1), J9MEM_CATEGORY_VM_JCL);472473if (NULL == *formatStringsArray) {474vmFuncs->throwNativeOOMError(env, 0, 0);475rc = 2;476goto fail;477}478479memset(*formatStringsArray, 0, sizeof(char *) * (*tracePointCount + 1));480481*callPatternsArray = (UDATA *) j9mem_allocate_memory(sizeof(UDATA) * *tracePointCount, J9MEM_CATEGORY_VM_JCL);482483if (NULL == *callPatternsArray) {484vmFuncs->throwNativeOOMError(env, 0, 0);485rc = 2;486goto fail;487}488489memset(*callPatternsArray, 0, sizeof(UDATA) * *tracePointCount);490491for (i = 0; i < *tracePointCount; i++) {492jobject thisString = (*env)->GetObjectArrayElement(env, templates, (jsize)i);493const char *jniStringCharacters = NULL;494495if (NULL != (*env)->ExceptionOccurred(env)) {496rc = 3;497goto fail;498}499500if (NULL == thisString) {501throwIllegalArgumentException(env, "Null string passed as trace template");502rc = 4;503goto fail;504}505506jniStringCharacters = (*env)->GetStringUTFChars(env, thisString, NULL);507508if (NULL == jniStringCharacters) {509rc = 5;510goto fail;511}512513if (!isValidTypeChar(jniStringCharacters[0])) {514char messageBuffer[ERROR_MESSAGE_BUFFER_LENGTH + 1];515516memset(messageBuffer, 0, sizeof(messageBuffer));517j9str_printf(PORTLIB, messageBuffer, ERROR_MESSAGE_BUFFER_LENGTH, "Error: template %d does not have a valid trace prefix. Trace templates should start with one of Trace.EVENT, Trace.EXIT, Trace.ENTRY, Trace.EXCEPTION or Trace.EXCEPTION_EXIT", i);518throwIllegalArgumentException(env, messageBuffer);519}520521/*Dupe the string into the array*/522(*formatStringsArray)[i] = (char *)j9mem_allocate_memory(strlen(jniStringCharacters) + 1, J9MEM_CATEGORY_VM_JCL);523524if (NULL == (*formatStringsArray)[i]) {525vmFuncs->throwNativeOOMError(env, 0, 0);526(*env)->ReleaseStringUTFChars(env, thisString, jniStringCharacters);527rc = 6;528goto fail;529}530531strcpy((*formatStringsArray)[i], jniStringCharacters);532533buildCallPattern((*formatStringsArray)[i], &((*callPatternsArray)[i]));534535(*env)->ReleaseStringUTFChars(env, thisString, jniStringCharacters);536(*env)->DeleteLocalRef(env, thisString);537}538539return 0;540541fail:542543if (NULL != *formatStringsArray) {544for (i = 0; i < *tracePointCount; i++) {545char *formatString = (*formatStringsArray)[i];546547if (NULL != formatString) {548j9mem_free_memory(formatString);549}550}551552j9mem_free_memory(*formatStringsArray);553}554555if (NULL != *callPatternsArray) {556j9mem_free_memory(*callPatternsArray);557}558559return rc;560}561562/*563* Frees a modinfo structure.564*/565static void566freeModInfo(JNIEnv *const env, UtModuleInfo *toFree)567{568PORT_ACCESS_FROM_ENV(env);569570if (NULL == toFree) {571return;572}573574if (NULL != toFree->name) {575j9mem_free_memory(toFree->name);576}577578if (NULL != toFree->active) {579j9mem_free_memory(toFree->active);580}581582if (NULL != toFree->traceVersionInfo) {583j9mem_free_memory(toFree->traceVersionInfo);584}585586if (NULL != toFree->levels) {587j9mem_free_memory(toFree->levels);588}589590j9mem_free_memory(toFree);591}592593/**594* Builds and populates the UtModuleInfo structure to register with the trace engine.595*596* @param env [in] JNI environment597* @param japplicationName [in] UTF version of application name, from GetStringUTFChars598* @param tracePointCount [in] Number of trace points599* @return Populated UTModuleInfo structure or NULL if there was a problem.600*/601static UtModuleInfo *602buildModInfo(JNIEnv *const env, const char *const applicationName, const UDATA tracePointCount)603{604UtModuleInfo *toReturn = NULL;605UDATA arraySize = sizeof(unsigned char) * tracePointCount;606J9InternalVMFunctions *vmFuncs = ((J9VMThread *)env)->javaVM->internalVMFunctions;607608PORT_ACCESS_FROM_ENV(env);609610toReturn = (UtModuleInfo*) j9mem_allocate_memory( sizeof(UtModuleInfo), J9MEM_CATEGORY_VM_JCL);611if (NULL == toReturn) {612goto error;613}614615memset(toReturn, 0, sizeof(UtModuleInfo));616617/*Duplicate the application name*/618toReturn->namelength = (I_32)strlen(applicationName);619toReturn->name = j9mem_allocate_memory( toReturn->namelength + 1, J9MEM_CATEGORY_VM_JCL);620if (NULL == toReturn->name) {621vmFuncs->throwNativeOOMError(env, 0, 0);622goto error;623}624strcpy(toReturn->name, applicationName);625626toReturn->count = (I_32)tracePointCount;627628toReturn->moduleId = UT_APPLICATION_TRACE_MODULE;629630toReturn->active = (unsigned char *)j9mem_allocate_memory( arraySize, J9MEM_CATEGORY_VM_JCL);631if (NULL == toReturn->active) {632vmFuncs->throwNativeOOMError(env, 0, 0);633goto error;634}635636memset(toReturn->active, 0, arraySize);637638toReturn->traceVersionInfo = (UtTraceVersionInfo *)j9mem_allocate_memory( sizeof(UtTraceVersionInfo), J9MEM_CATEGORY_VM_JCL);639if (NULL == toReturn->traceVersionInfo) {640vmFuncs->throwNativeOOMError(env, 0, 0);641goto error;642}643644toReturn->traceVersionInfo->traceVersion = UT_TRACE_VERSION;645646toReturn->levels = (unsigned char *)j9mem_allocate_memory( arraySize, J9MEM_CATEGORY_VM_JCL);647if (NULL == toReturn->levels) {648vmFuncs->throwNativeOOMError(env, 0, 0);649goto error;650}651memset(toReturn->levels, 3, arraySize);652653return toReturn;654655error:656657if (NULL != toReturn) {658freeModInfo(env, toReturn);659}660661return NULL;662}663664/**************************************************************************665* name - Java_com_ibm_jvm_Trace_registerApplication666* description - Set trace options667* parameters - JNIEnv, this, trace configuration command668* returns - return code669*************************************************************************/670int JNICALL671Java_com_ibm_jvm_Trace_registerApplicationImpl(JNIEnv *env, jobject this, jobject name, jarray templates)672{673const char *applicationName = NULL;674char **formatStringsArray = NULL;675UDATA *callPatternsArray = NULL;676UDATA tracePointCount = 0;677int toReturn = JNI_ERR;678int err = 0;679int index = 0;680int tempIndex = 0;681UtModuleInfo *modInfo = NULL;682683PORT_ACCESS_FROM_ENV(env);684685/* If we don't have the trace engine, we have to exit. Pass back a valid handle so686* application trace becomes a silent no-op.687*/688if (NULL == TRACEDOTCGLOBAL(utIntf)) {689toReturn = 0;690goto error;691}692693err = (int)processAndCheckNameString(env, name, &applicationName);694695if (0 != err) {696/*An exception will have been thrown - we just need to free resources and return*/697toReturn = JNI_ERR;698goto error;699}700701err = (int)extractAndProcessFormatStrings(env, templates, &formatStringsArray, &callPatternsArray, &tracePointCount);702703if (0 != err) {704/*Exception will have been thrown*/705toReturn = JNI_ERR;706goto error;707}708709modInfo = buildModInfo(env, applicationName, tracePointCount);710711if (NULL == modInfo) {712toReturn = JNI_ERR;713goto error;714}715716/*Register the application with the trace engine*/717err = TRACEDOTCGLOBAL(utIntf)->server->AddComponent(modInfo, (const char **)formatStringsArray);718719if (0 != err) {720char messageBuffer[ERROR_MESSAGE_BUFFER_LENGTH + 1];721722memset(messageBuffer, 0, sizeof(messageBuffer));723j9str_printf(PORTLIB, messageBuffer, ERROR_MESSAGE_BUFFER_LENGTH, "Failed to register application with trace engine: %d", err);724throwRuntimeException(env, messageBuffer);725toReturn = JNI_ERR;726goto error;727}728729/*Get an index and store the modinfo and callPatternsArray to use later*/730do {731tempIndex = TRACEDOTCGLOBAL(numberOfAppTraceApplications);732index = tempIndex + 1;733} while (! CompareAndSwap32(&TRACEDOTCGLOBAL(numberOfAppTraceApplications), tempIndex, index));734735toReturn = index;736737err = (int)arrayListPut(env, TRACEDOTCGLOBAL(modInfoList), index, (void*)modInfo);738739if (0 != err) {740/*Exception will have been thrown*/741toReturn = JNI_ERR;742goto error;743}744745err = (int)arrayListPut(env, TRACEDOTCGLOBAL(argumentStructureList), index, (void*)callPatternsArray);746747if (0 != err) {748/*Exception will have been thrown*/749toReturn = JNI_ERR;750goto error;751}752753error:754755if (0 != err) {756if (NULL != formatStringsArray) {757UDATA i = 0;758759for (i = 0; i < tracePointCount; i++) {760if (NULL != formatStringsArray[i]) {761j9mem_free_memory(formatStringsArray[i]);762}763}764765j9mem_free_memory(formatStringsArray);766}767768if (NULL != callPatternsArray) {769j9mem_free_memory(callPatternsArray);770}771772if (NULL != modInfo) {773freeModInfo(env, modInfo);774}775}776777778if (NULL != applicationName) {779(*env)->ReleaseStringUTFChars(env, name, applicationName);780}781782return toReturn;783}784785/**786* Counts the number of arguments in a callPattern787* @param pattern [in] Call pattern788* @return Number of arguments789*/790static UDATA791countArguments(const UDATA pattern)792{793return (((pattern >> (3 * 8)) & 0xFF) != 0) ? 4794: (((pattern >> (2 * 8)) & 0xFF) != 0) ? 3795: (((pattern >> (1 * 8)) & 0xFF) != 0) ? 2796: (((pattern >> (0 * 8)) & 0xFF) != 0) ? 1797: 0;798}799800/**801* Trace method that all other com.ibm.jvm.Trace.trace() methods call through.802*803* @param env JNI environment804* @param handle Application trace handle (returned from registerApplication)805* @param traceId Id of trace point to trace806* @param methodSignature the signature of the method that supplied the arguments807*808* Trace arguments are passed by varargs809*/810static void811trace(JNIEnv *const env, const jint handle, const jint traceId, const UDATA methodSignature, ...)812{813UtModuleInfo *modInfo = NULL;814UDATA *callPatternsArray = NULL;815va_list args;816UDATA numberOfArgumentsExpected = 0;817UDATA numberOfArgumentsSupplied = 0;818819/*If trace is disabled, bail out*/820if (NULL == TRACEDOTCGLOBAL(utIntf)) {821return;822}823824/*Is the handle valid?*/825if (handle <= 0 || (U_32)handle > TRACEDOTCGLOBAL(numberOfAppTraceApplications)) {826throwIllegalArgumentException(env, "Invalid application trace handle. Check return code from registerApplication().");827return;828}829830modInfo = (UtModuleInfo *) arrayListGet(env, TRACEDOTCGLOBAL(modInfoList), handle);831assert(NULL != modInfo);832833callPatternsArray = (UDATA *) arrayListGet(env, TRACEDOTCGLOBAL(argumentStructureList), handle);834assert(NULL != callPatternsArray);835836/*Is the trace id in the right range?*/837if (traceId < 0 || traceId >= modInfo->count) {838char messageBuffer[ERROR_MESSAGE_BUFFER_LENGTH + 1];839PORT_ACCESS_FROM_ENV(env);840841memset(messageBuffer, 0, sizeof(messageBuffer));842j9str_printf(PORTLIB, messageBuffer, ERROR_MESSAGE_BUFFER_LENGTH, "Specified tracepoint: %d outside of valid range 0<=x<%d\n", traceId, modInfo->count);843throwIllegalArgumentException(env, messageBuffer);844return;845}846847/*Do we have the expected number of arguments?*/848numberOfArgumentsExpected = countArguments(callPatternsArray[traceId]);849numberOfArgumentsSupplied = countArguments(methodSignature);850851if (numberOfArgumentsExpected != numberOfArgumentsSupplied) {852char messageBuffer[ERROR_MESSAGE_BUFFER_LENGTH + 1];853PORT_ACCESS_FROM_ENV(env);854855memset(messageBuffer, 0, sizeof(messageBuffer));856j9str_printf(PORTLIB, messageBuffer, ERROR_MESSAGE_BUFFER_LENGTH, "Wrong number of arguments passed to tracepoint %s.%d expected %d received %d.", modInfo->name, traceId, numberOfArgumentsExpected, numberOfArgumentsSupplied);857throwIllegalArgumentException(env, messageBuffer);858return;859}860861/*Do the arguments match the trace point?*/862if ((methodSignature & callPatternsArray[traceId]) != methodSignature) {863char messageBuffer[ERROR_MESSAGE_BUFFER_LENGTH + 1];864char *p = NULL;865char *const end = messageBuffer + ERROR_MESSAGE_BUFFER_LENGTH;866PORT_ACCESS_FROM_ENV(env);867868memset(messageBuffer, 0, sizeof(messageBuffer));869j9str_printf(PORTLIB, messageBuffer, ERROR_MESSAGE_BUFFER_LENGTH, "Invalid arguments passed to tracepoint %s.%d. Tracepoint expects: ", modInfo->name, traceId);870871p = messageBuffer + strlen(messageBuffer);872formatCallPattern(p, end, callPatternsArray[traceId]);873874strncat(messageBuffer, " received: ", ERROR_MESSAGE_BUFFER_LENGTH - strlen(messageBuffer));875876p = messageBuffer + strlen(messageBuffer);877formatCallPattern(p, end, methodSignature);878879strncat(messageBuffer, ".", ERROR_MESSAGE_BUFFER_LENGTH - strlen(messageBuffer));880881throwIllegalArgumentException(env, messageBuffer);882return;883}884885va_start(args, methodSignature);886887TRACEDOTCGLOBAL(utIntf)->server->TraceVNoThread(modInfo, (traceId << 8) | modInfo->active[traceId], "", args);888889va_end(args);890}891892/**************************************************************************893* name - Java_com_ibm_jvm_Trace_traceImpl894* description - Make tracepoint895* parameters - JNIEnv, this, handle, tracepoint id, optional trace data896* returns - Nothing897*************************************************************************/898void JNICALL899Java_com_ibm_jvm_Trace_traceImpl__II(JNIEnv *env, jclass this, jint handle, jint traceId)900{901trace(env, handle, traceId, ARGUMENT_DESCRIPTOR());902}903904void JNICALL905Java_com_ibm_jvm_Trace_traceImpl__IILjava_lang_String_2(JNIEnv *env,906jclass this, jint handle, jint traceId, jstring s1)907{908const char *utfS1 = (*env)->GetStringUTFChars(env, s1, NULL);909910if (NULL == utfS1) {911return;912}913914trace(env, handle, traceId, ARGUMENT_DESCRIPTOR_1(JSTRING), utfS1);915916(*env)->ReleaseStringUTFChars(env, s1, utfS1);917}918919void JNICALL920Java_com_ibm_jvm_Trace_traceImpl__IILjava_lang_String_2Ljava_lang_String_2(JNIEnv *env,921jclass this, jint handle, jint traceId, jstring s1, jstring s2)922{923const char *utfS1 = (*env)->GetStringUTFChars(env, s1, NULL);924const char *utfS2 = NULL;925926if (NULL == utfS1) {927goto end;928}929930utfS2 = (*env)->GetStringUTFChars(env, s2, NULL);931932if (NULL == utfS2) {933goto end;934}935936trace(env, handle, traceId, ARGUMENT_DESCRIPTOR_2(JSTRING, JSTRING), utfS1, utfS2);937938end:939if (NULL != utfS1) {940(*env)->ReleaseStringUTFChars(env, s1, utfS1);941}942943if (NULL != utfS2) {944(*env)->ReleaseStringUTFChars(env, s2, utfS2);945}946}947948void JNICALL949Java_com_ibm_jvm_Trace_traceImpl__IILjava_lang_String_2Ljava_lang_String_2Ljava_lang_String_2(JNIEnv *env,950jclass this, jint handle, jint traceId, jstring s1, jstring s2, jstring s3)951{952const char *utfS1 = (*env)->GetStringUTFChars(env, s1, NULL);953const char *utfS2 = NULL;954const char *utfS3 = NULL;955956if (NULL == utfS1) {957goto end;958}959960utfS2 = (*env)->GetStringUTFChars(env, s2, NULL);961962if (NULL == utfS2) {963goto end;964}965966utfS3 = (*env)->GetStringUTFChars(env, s3, NULL);967968if (NULL == utfS3) {969goto end;970}971972trace(env, handle, traceId, ARGUMENT_DESCRIPTOR_3(JSTRING, JSTRING, JSTRING), utfS1, utfS2, utfS3);973974end:975if (NULL != utfS1) {976(*env)->ReleaseStringUTFChars(env, s1, utfS1);977}978979if (NULL != utfS2) {980(*env)->ReleaseStringUTFChars(env, s2, utfS2);981}982983if (NULL != utfS3) {984(*env)->ReleaseStringUTFChars(env, s3, utfS3);985}986}987988void JNICALL989Java_com_ibm_jvm_Trace_traceImpl__IILjava_lang_String_2Ljava_lang_Object_2(JNIEnv *env,990jclass this, jint handle, jint traceId, jstring s1, jobject o1)991{992const char *utfS1 = (*env)->GetStringUTFChars(env, s1, NULL);993994if (NULL == utfS1) {995return;996}997998trace(env, handle, traceId, ARGUMENT_DESCRIPTOR_2(JSTRING, JOBJECT), utfS1, o1);9991000(*env)->ReleaseStringUTFChars(env, s1, utfS1);1001}10021003void JNICALL1004Java_com_ibm_jvm_Trace_traceImpl__IILjava_lang_Object_2Ljava_lang_String_2(JNIEnv *env,1005jclass this, jint handle, jint traceId, jobject o1, jstring s1)1006{1007const char *utfS1 = (*env)->GetStringUTFChars(env, s1, NULL);10081009if (NULL == utfS1) {1010return;1011}10121013trace(env, handle, traceId, ARGUMENT_DESCRIPTOR_2(JOBJECT, JSTRING), o1, utfS1);10141015(*env)->ReleaseStringUTFChars(env, s1, utfS1);1016}10171018void JNICALL1019Java_com_ibm_jvm_Trace_traceImpl__IILjava_lang_String_2I(JNIEnv *env,1020jclass this, jint handle, jint traceId, jstring s1, jint i1)1021{1022const char *utfS1 = (*env)->GetStringUTFChars(env, s1, NULL);10231024if (NULL == utfS1) {1025return;1026}10271028trace(env, handle, traceId, ARGUMENT_DESCRIPTOR_2(JSTRING, JWORD), utfS1, i1);10291030(*env)->ReleaseStringUTFChars(env, s1, utfS1);1031}10321033void JNICALL1034Java_com_ibm_jvm_Trace_traceImpl__IIILjava_lang_String_2(JNIEnv *env,1035jclass this, jint handle, jint traceId, jint i1, jstring s1)1036{1037const char *utfS1 = (*env)->GetStringUTFChars(env, s1, NULL);10381039if (NULL == utfS1) {1040return;1041}10421043trace(env, handle, traceId, ARGUMENT_DESCRIPTOR_2(JWORD, JSTRING), i1, utfS1);10441045(*env)->ReleaseStringUTFChars(env, s1, utfS1);1046}10471048void JNICALL1049Java_com_ibm_jvm_Trace_traceImpl__IILjava_lang_String_2J(JNIEnv *env,1050jclass this, jint handle, jint traceId, jstring s1, jlong l1)1051{1052const char *utfS1 = (*env)->GetStringUTFChars(env, s1, NULL);10531054if (NULL == utfS1) {1055return;1056}10571058trace(env, handle, traceId, ARGUMENT_DESCRIPTOR_2(JSTRING, JDOUBLEWORD), utfS1, l1);10591060(*env)->ReleaseStringUTFChars(env, s1, utfS1);1061}1062void JNICALL1063Java_com_ibm_jvm_Trace_traceImpl__IIJLjava_lang_String_2(JNIEnv *env,1064jclass this, jint handle, jint traceId, jlong l1, jstring s1)1065{1066const char *utfS1 = (*env)->GetStringUTFChars(env, s1, NULL);10671068if (NULL == utfS1) {1069return;1070}10711072trace(env, handle, traceId, ARGUMENT_DESCRIPTOR_2(JDOUBLEWORD, JSTRING), l1, utfS1);10731074(*env)->ReleaseStringUTFChars(env, s1, utfS1);1075}1076void JNICALL1077Java_com_ibm_jvm_Trace_traceImpl__IILjava_lang_String_2B(JNIEnv *env,1078jclass this, jint handle, jint traceId, jstring s1, jbyte b1)1079{1080const char *utfS1 = (*env)->GetStringUTFChars(env, s1, NULL);10811082if (NULL == utfS1) {1083return;1084}10851086trace(env, handle, traceId, ARGUMENT_DESCRIPTOR_2(JSTRING, JWORD), utfS1, b1);10871088(*env)->ReleaseStringUTFChars(env, s1, utfS1);1089}10901091void JNICALL1092Java_com_ibm_jvm_Trace_traceImpl__IIBLjava_lang_String_2(JNIEnv *env,1093jclass this, jint handle, jint traceId, jbyte b1, jstring s1)1094{1095const char *utfS1 = (*env)->GetStringUTFChars(env, s1, NULL);10961097if (NULL == utfS1) {1098return;1099}11001101trace(env, handle, traceId, ARGUMENT_DESCRIPTOR_2(JWORD, JSTRING), b1, utfS1);11021103(*env)->ReleaseStringUTFChars(env, s1, utfS1);1104}11051106void JNICALL1107Java_com_ibm_jvm_Trace_traceImpl__IILjava_lang_String_2C(JNIEnv *env,1108jclass this, jint handle, jint traceId, jstring s1, jchar c1)1109{1110const char *utfS1 = (*env)->GetStringUTFChars(env, s1, NULL);11111112if (NULL == utfS1) {1113return;1114}11151116trace(env, handle, traceId, ARGUMENT_DESCRIPTOR_2(JSTRING, JCHAR), utfS1, c1);11171118(*env)->ReleaseStringUTFChars(env, s1, utfS1);1119}11201121void JNICALL1122Java_com_ibm_jvm_Trace_traceImpl__IICLjava_lang_String_2(JNIEnv *env,1123jclass this, jint handle, jint traceId, jchar c1, jstring s1)1124{1125const char *utfS1 = (*env)->GetStringUTFChars(env, s1, NULL);11261127if (NULL == utfS1) {1128return;1129}11301131trace(env, handle, traceId, ARGUMENT_DESCRIPTOR_2(JCHAR, JSTRING), c1, utfS1);11321133(*env)->ReleaseStringUTFChars(env, s1, utfS1);1134}11351136void JNICALL1137Java_com_ibm_jvm_Trace_traceImpl__IILjava_lang_String_2F(JNIEnv *env,1138jclass this, jint handle, jint traceId, jstring s1, jfloat f1)1139{1140const char *utfS1 = (*env)->GetStringUTFChars(env, s1, NULL);11411142if (NULL == utfS1) {1143return;1144}11451146trace(env, handle, traceId, ARGUMENT_DESCRIPTOR_2(JSTRING, JFLOATPOINT), utfS1, f1);11471148(*env)->ReleaseStringUTFChars(env, s1, utfS1);1149}11501151void JNICALL1152Java_com_ibm_jvm_Trace_traceImpl__IIFLjava_lang_String_2(JNIEnv *env,1153jclass this, jint handle, jint traceId, jfloat f1, jstring s1)1154{1155const char *utfS1 = (*env)->GetStringUTFChars(env, s1, NULL);11561157if (NULL == utfS1) {1158return;1159}11601161trace(env, handle, traceId, ARGUMENT_DESCRIPTOR_2(JFLOATPOINT, JSTRING), f1, utfS1);11621163(*env)->ReleaseStringUTFChars(env, s1, utfS1);1164}11651166void JNICALL1167Java_com_ibm_jvm_Trace_traceImpl__IILjava_lang_String_2D(JNIEnv *env,1168jclass this, jint handle, jint traceId, jstring s1, jdouble d1)1169{1170const char *utfS1 = (*env)->GetStringUTFChars(env, s1, NULL);11711172if (NULL == utfS1) {1173return;1174}11751176trace(env, handle, traceId, ARGUMENT_DESCRIPTOR_2(JSTRING, JFLOATPOINT), utfS1, d1);11771178(*env)->ReleaseStringUTFChars(env, s1, utfS1);1179}11801181void JNICALL1182Java_com_ibm_jvm_Trace_traceImpl__IIDLjava_lang_String_2(JNIEnv *env,1183jclass this, jint handle, jint traceId, jdouble d1, jstring s1)1184{1185const char *utfS1 = (*env)->GetStringUTFChars(env, s1, NULL);11861187if (NULL == utfS1) {1188return;1189}11901191trace(env, handle, traceId, ARGUMENT_DESCRIPTOR_2(JFLOATPOINT, JSTRING), d1, utfS1);11921193(*env)->ReleaseStringUTFChars(env, s1, utfS1);1194}11951196void JNICALL1197Java_com_ibm_jvm_Trace_traceImpl__IILjava_lang_Object_2(JNIEnv *env,1198jclass this, jint handle, jint traceId, jobject o1)1199{1200trace(env, handle, traceId, ARGUMENT_DESCRIPTOR_1(JOBJECT), o1);1201}12021203void JNICALL1204Java_com_ibm_jvm_Trace_traceImpl__IILjava_lang_Object_2Ljava_lang_Object_2(JNIEnv *env,1205jclass this, jint handle, jint traceId, jobject o1, jobject o2)1206{1207trace(env, handle, traceId, ARGUMENT_DESCRIPTOR_2(JOBJECT, JOBJECT), o1, o2);1208}12091210void JNICALL1211Java_com_ibm_jvm_Trace_traceImpl__III(JNIEnv *env,1212jclass this, jint handle, jint traceId, jint i1)1213{1214trace(env, handle, traceId, ARGUMENT_DESCRIPTOR_1(JWORD), i1);1215}12161217void JNICALL1218Java_com_ibm_jvm_Trace_traceImpl__IIII(JNIEnv *env,1219jclass this, jint handle, jint traceId, jint i1 , jint i2)1220{1221trace(env, handle, traceId, ARGUMENT_DESCRIPTOR_2(JWORD, JWORD), i1, i2);1222}12231224void JNICALL1225Java_com_ibm_jvm_Trace_traceImpl__IIIII(JNIEnv *env,1226jclass this, jint handle, jint traceId, jint i1, jint i2, jint i3)1227{1228trace(env, handle, traceId, ARGUMENT_DESCRIPTOR_3(JWORD, JWORD, JWORD), i1, i2, i3);1229}12301231void JNICALL1232Java_com_ibm_jvm_Trace_traceImpl__IIJ(JNIEnv *env,1233jclass this, jint handle, jint traceId, jlong l1)1234{1235trace(env, handle, traceId, ARGUMENT_DESCRIPTOR_1(JDOUBLEWORD), l1);1236}12371238void JNICALL1239Java_com_ibm_jvm_Trace_traceImpl__IIJJ(JNIEnv *env,1240jclass this, jint handle, jint traceId, jlong l1, jlong l2)1241{1242trace(env, handle, traceId, ARGUMENT_DESCRIPTOR_2(JDOUBLEWORD, JDOUBLEWORD), l1, l2);1243}12441245void JNICALL1246Java_com_ibm_jvm_Trace_traceImpl__IIJJJ(JNIEnv *env,1247jclass this, jint handle, jint traceId, jlong l1, jlong l2, jlong l3)1248{1249trace(env, handle, traceId, ARGUMENT_DESCRIPTOR_3(JDOUBLEWORD, JDOUBLEWORD, JDOUBLEWORD), l1, l2, l3);1250}12511252void JNICALL1253Java_com_ibm_jvm_Trace_traceImpl__IIB(JNIEnv *env,1254jclass this, jint handle, jint traceId, jbyte b1)1255{1256trace(env, handle, traceId, ARGUMENT_DESCRIPTOR_1(JWORD), b1);1257}12581259void JNICALL1260Java_com_ibm_jvm_Trace_traceImpl__IIBB(JNIEnv *env,1261jclass this, jint handle, jint traceId, jbyte b1, jbyte b2)1262{1263trace(env, handle, traceId, ARGUMENT_DESCRIPTOR_2(JWORD, JWORD), b1, b2);1264}12651266void JNICALL1267Java_com_ibm_jvm_Trace_traceImpl__IIBBB(JNIEnv *env,1268jclass this, jint handle, jint traceId, jbyte b1, jbyte b2, jbyte b3)1269{1270trace(env, handle, traceId, ARGUMENT_DESCRIPTOR_3(JWORD, JWORD, JWORD), b1, b2, b3);1271}12721273void JNICALL1274Java_com_ibm_jvm_Trace_traceImpl__IIC(JNIEnv *env,1275jclass this, jint handle, jint traceId, jchar c1)1276{1277trace(env, handle, traceId, ARGUMENT_DESCRIPTOR_1(JCHAR), c1);1278}12791280void JNICALL1281Java_com_ibm_jvm_Trace_traceImpl__IICC(JNIEnv *env,1282jclass this, jint handle, jint traceId, jchar c1, jchar c2)1283{1284trace(env, handle, traceId, ARGUMENT_DESCRIPTOR_2(JCHAR, JCHAR), c1, c2);1285}12861287void JNICALL1288Java_com_ibm_jvm_Trace_traceImpl__IICCC(JNIEnv *env,1289jclass this, jint handle, jint traceId, jchar c1, jchar c2, jchar c3)1290{1291trace(env, handle, traceId, ARGUMENT_DESCRIPTOR_3(JCHAR, JCHAR, JCHAR), c1, c2, c3);1292}12931294void JNICALL1295Java_com_ibm_jvm_Trace_traceImpl__IIF(JNIEnv *env,1296jclass this, jint handle, jint traceId, jfloat f1)1297{1298trace(env, handle, traceId, ARGUMENT_DESCRIPTOR_1(JFLOATPOINT), f1);1299}13001301void JNICALL1302Java_com_ibm_jvm_Trace_traceImpl__IIFF(JNIEnv *env,1303jclass this, jint handle, jint traceId, jfloat f1, jfloat f2)1304{1305trace(env, handle, traceId, ARGUMENT_DESCRIPTOR_2(JFLOATPOINT, JFLOATPOINT), f1, f2);1306}13071308void JNICALL1309Java_com_ibm_jvm_Trace_traceImpl__IIFFF(JNIEnv *env,1310jclass this, jint handle, jint traceId, jfloat f1, jfloat f2, jfloat f3)1311{1312trace(env, handle, traceId, ARGUMENT_DESCRIPTOR_3(JFLOATPOINT, JFLOATPOINT, JFLOATPOINT), f1, f2, f3);1313}13141315void JNICALL1316Java_com_ibm_jvm_Trace_traceImpl__IID(JNIEnv *env,1317jclass this, jint handle, jint traceId, jdouble d1)1318{1319trace(env, handle, traceId, ARGUMENT_DESCRIPTOR_1(JFLOATPOINT), d1);1320}13211322void JNICALL1323Java_com_ibm_jvm_Trace_traceImpl__IIDD(JNIEnv *env,1324jclass this, jint handle, jint traceId, jdouble d1, jdouble d2)1325{1326trace(env, handle, traceId, ARGUMENT_DESCRIPTOR_2(JFLOATPOINT, JFLOATPOINT), d1, d2);1327}13281329void JNICALL1330Java_com_ibm_jvm_Trace_traceImpl__IIDDD(JNIEnv *env,1331jclass this, jint handle, jint traceId, jdouble d1, jdouble d2, jdouble d3)1332{1333trace(env, handle, traceId, ARGUMENT_DESCRIPTOR_3(JFLOATPOINT, JFLOATPOINT, JFLOATPOINT), d1, d2, d3);1334}13351336void JNICALL1337Java_com_ibm_jvm_Trace_traceImpl__IILjava_lang_String_2Ljava_lang_Object_2Ljava_lang_String_2(JNIEnv *env,1338jclass this, jint handle, jint traceId, jstring s1, jobject o1, jstring s2)1339{1340const char *utfS1 = (*env)->GetStringUTFChars(env, s1, NULL);1341const char *utfS2 = NULL;13421343if (NULL == utfS1) {1344goto end;1345}13461347utfS2 = (*env)->GetStringUTFChars(env, s2, NULL);13481349if (NULL == utfS2) {1350goto end;1351}13521353trace(env, handle, traceId, ARGUMENT_DESCRIPTOR_3(JSTRING, JOBJECT, JSTRING), utfS1, o1, utfS2);13541355end:1356if (NULL != utfS1) {1357(*env)->ReleaseStringUTFChars(env, s1, utfS1);1358}13591360if (NULL != utfS2) {1361(*env)->ReleaseStringUTFChars(env, s2, utfS2);1362}1363}13641365void JNICALL1366Java_com_ibm_jvm_Trace_traceImpl__IILjava_lang_Object_2Ljava_lang_String_2Ljava_lang_Object_2(JNIEnv *env,1367jclass this, jint handle, jint traceId, jobject o1, jstring s1, jobject o2)1368{1369const char *utfS1 = (*env)->GetStringUTFChars(env, s1, NULL);13701371if (NULL == utfS1) {1372return;1373}13741375trace(env, handle, traceId, ARGUMENT_DESCRIPTOR_3(JOBJECT, JSTRING, JOBJECT), o1, utfS1, o2);13761377(*env)->ReleaseStringUTFChars(env, s1, utfS1);1378}13791380void JNICALL1381Java_com_ibm_jvm_Trace_traceImpl__IILjava_lang_String_2ILjava_lang_String_2(JNIEnv *env,1382jclass this, jint handle, jint traceId, jstring s1, jint i1, jstring s2)1383{1384const char *utfS1 = (*env)->GetStringUTFChars(env, s1, NULL);1385const char *utfS2 = NULL;13861387if (NULL == utfS1) {1388goto end;1389}13901391utfS2 = (*env)->GetStringUTFChars(env, s2, NULL);13921393if (NULL == utfS2) {1394goto end;1395}13961397trace(env, handle, traceId, ARGUMENT_DESCRIPTOR_3(JSTRING, JWORD, JSTRING), utfS1, i1, utfS2);13981399end:1400if (NULL != utfS1) {1401(*env)->ReleaseStringUTFChars(env, s1, utfS1);1402}14031404if (NULL != utfS2) {1405(*env)->ReleaseStringUTFChars(env, s2, utfS2);1406}1407}14081409void JNICALL1410Java_com_ibm_jvm_Trace_traceImpl__IIILjava_lang_String_2I(JNIEnv *env,1411jclass this, jint handle, jint traceId, jint i1, jstring s1, jint i2)1412{1413const char *utfS1 = (*env)->GetStringUTFChars(env, s1, NULL);14141415if (NULL == utfS1) {1416return;1417}14181419trace(env, handle, traceId, ARGUMENT_DESCRIPTOR_3(JWORD, JSTRING, JWORD), i1, utfS1, i2);14201421(*env)->ReleaseStringUTFChars(env, s1, utfS1);1422}14231424void JNICALL1425Java_com_ibm_jvm_Trace_traceImpl__IILjava_lang_String_2JLjava_lang_String_2(JNIEnv *env,1426jclass this, jint handle, jint traceId, jstring s1, jlong l1, jstring s2)1427{1428const char *utfS1 = (*env)->GetStringUTFChars(env, s1, NULL);1429const char *utfS2 = NULL;14301431if (NULL == utfS1) {1432goto end;1433}14341435utfS2 = (*env)->GetStringUTFChars(env, s2, NULL);14361437if (NULL == utfS2) {1438goto end;1439}14401441trace(env, handle, traceId, ARGUMENT_DESCRIPTOR_3(JSTRING, JDOUBLEWORD, JSTRING), utfS1, l1, utfS2);14421443end:1444if (NULL != utfS1) {1445(*env)->ReleaseStringUTFChars(env, s1, utfS1);1446}14471448if (NULL != utfS2) {1449(*env)->ReleaseStringUTFChars(env, s2, utfS2);1450}1451}14521453void JNICALL1454Java_com_ibm_jvm_Trace_traceImpl__IIJLjava_lang_String_2J(JNIEnv *env,1455jclass this, jint handle, jint traceId, jlong l1, jstring s1, jlong l2)1456{1457const char *utfS1 = (*env)->GetStringUTFChars(env, s1, NULL);14581459if (NULL == utfS1) {1460return;1461}14621463trace(env, handle, traceId, ARGUMENT_DESCRIPTOR_3(JDOUBLEWORD, JSTRING, JDOUBLEWORD), l1, utfS1, l2);14641465(*env)->ReleaseStringUTFChars(env, s1, utfS1);1466}14671468void JNICALL1469Java_com_ibm_jvm_Trace_traceImpl__IILjava_lang_String_2BLjava_lang_String_2(JNIEnv *env,1470jclass this, jint handle, jint traceId, jstring s1, jbyte b1, jstring s2)1471{1472const char *utfS1 = (*env)->GetStringUTFChars(env, s1, NULL);1473const char *utfS2 = NULL;14741475if (NULL == utfS1) {1476goto end;1477}14781479utfS2 = (*env)->GetStringUTFChars(env, s2, NULL);14801481if (NULL == utfS2) {1482goto end;1483}14841485trace(env, handle, traceId, ARGUMENT_DESCRIPTOR_3(JSTRING, JWORD, JSTRING), utfS1, b1, utfS2);14861487end:1488if (NULL != utfS1) {1489(*env)->ReleaseStringUTFChars(env, s1, utfS1);1490}14911492if (NULL != utfS2) {1493(*env)->ReleaseStringUTFChars(env, s2, utfS2);1494}1495}14961497void JNICALL1498Java_com_ibm_jvm_Trace_traceImpl__IIBLjava_lang_String_2B(JNIEnv *env,1499jclass this, jint handle, jint traceId, jbyte b1, jstring s1, jbyte b2)1500{1501const char *utfS1 = (*env)->GetStringUTFChars(env, s1, NULL);15021503if (NULL == utfS1) {1504return;1505}15061507trace(env, handle, traceId, ARGUMENT_DESCRIPTOR_3(JWORD, JSTRING, JWORD), b1, utfS1, b2);15081509(*env)->ReleaseStringUTFChars(env, s1, utfS1);1510}15111512void JNICALL1513Java_com_ibm_jvm_Trace_traceImpl__IILjava_lang_String_2CLjava_lang_String_2(JNIEnv *env,1514jclass this, jint handle, jint traceId, jstring s1, jchar c1, jstring s2)1515{1516const char *utfS1 = (*env)->GetStringUTFChars(env, s1, NULL);1517const char *utfS2 = NULL;15181519if (NULL == utfS1) {1520goto end;1521}15221523utfS2 = (*env)->GetStringUTFChars(env, s2, NULL);15241525if (NULL == utfS2) {1526goto end;1527}15281529trace(env, handle, traceId, ARGUMENT_DESCRIPTOR_3(JSTRING, JCHAR, JSTRING), utfS1, c1, utfS2);15301531end:1532if (NULL != utfS1) {1533(*env)->ReleaseStringUTFChars(env, s1, utfS1);1534}15351536if (NULL != utfS2) {1537(*env)->ReleaseStringUTFChars(env, s2, utfS2);1538}1539}15401541void JNICALL1542Java_com_ibm_jvm_Trace_traceImpl__IICLjava_lang_String_2C(JNIEnv *env,1543jclass this, jint handle, jint traceId, jchar c1, jstring s1, jchar c2)1544{1545const char *utfS1 = (*env)->GetStringUTFChars(env, s1, NULL);15461547if (NULL == utfS1) {1548return;1549}15501551trace(env, handle, traceId, ARGUMENT_DESCRIPTOR_3(JCHAR, JSTRING, JCHAR), c1, utfS1, c2);15521553(*env)->ReleaseStringUTFChars(env, s1, utfS1);1554}15551556void JNICALL1557Java_com_ibm_jvm_Trace_traceImpl__IILjava_lang_String_2FLjava_lang_String_2(JNIEnv *env,1558jclass this, jint handle, jint traceId, jstring s1, jfloat f1, jstring s2)1559{1560const char *utfS1 = (*env)->GetStringUTFChars(env, s1, NULL);1561const char *utfS2 = NULL;15621563if (NULL == utfS1) {1564goto end;1565}15661567utfS2 = (*env)->GetStringUTFChars(env, s2, NULL);15681569if (NULL == utfS2) {1570goto end;1571}15721573trace(env, handle, traceId, ARGUMENT_DESCRIPTOR_3(JSTRING, JFLOATPOINT, JSTRING), utfS1, f1, utfS2);15741575end:1576if (NULL != utfS1) {1577(*env)->ReleaseStringUTFChars(env, s1, utfS1);1578}15791580if (NULL != utfS2) {1581(*env)->ReleaseStringUTFChars(env, s2, utfS2);1582}1583}15841585void JNICALL1586Java_com_ibm_jvm_Trace_traceImpl__IIFLjava_lang_String_2F(JNIEnv *env,1587jclass this, jint handle, jint traceId, jfloat f1, jstring s1, jfloat f2)1588{1589const char *utfS1 = (*env)->GetStringUTFChars(env, s1, NULL);15901591if (NULL == utfS1) {1592return;1593}15941595trace(env, handle, traceId, ARGUMENT_DESCRIPTOR_3(JFLOATPOINT, JSTRING, JFLOATPOINT), f1, utfS1, f2);15961597(*env)->ReleaseStringUTFChars(env, s1, utfS1);1598}15991600void JNICALL1601Java_com_ibm_jvm_Trace_traceImpl__IILjava_lang_String_2DLjava_lang_String_2(JNIEnv *env,1602jclass this, jint handle, jint traceId, jstring s1, jdouble d1, jstring s2)1603{1604const char *utfS1 = (*env)->GetStringUTFChars(env, s1, NULL);1605const char *utfS2 = NULL;16061607if (NULL == utfS1) {1608goto end;1609}16101611utfS2 = (*env)->GetStringUTFChars(env, s2, NULL);16121613if (NULL == utfS2) {1614goto end;1615}16161617trace(env, handle, traceId, ARGUMENT_DESCRIPTOR_3(JSTRING, JFLOATPOINT, JSTRING), utfS1, d1, utfS2);16181619end:1620if (NULL != utfS1) {1621(*env)->ReleaseStringUTFChars(env, s1, utfS1);1622}16231624if (NULL != utfS2) {1625(*env)->ReleaseStringUTFChars(env, s2, utfS2);1626}1627}16281629void JNICALL1630Java_com_ibm_jvm_Trace_traceImpl__IIDLjava_lang_String_2D(JNIEnv *env,1631jclass this, jint handle, jint traceId, jdouble d1, jstring s1, jdouble d2)1632{1633const char *utfS1 = (*env)->GetStringUTFChars(env, s1, NULL);16341635if (NULL == utfS1) {1636return;1637}16381639trace(env, handle, traceId, ARGUMENT_DESCRIPTOR_3(JFLOATPOINT, JSTRING, JFLOATPOINT), d1, utfS1, d2);16401641(*env)->ReleaseStringUTFChars(env, s1, utfS1);1642}16431644/**************************************************************************1645* name - Java_com_ibm_jvm_Trace_set1646* description - Set trace options1647* parameters - JNIEnv, this, trace configuration command1648* returns - return code1649*************************************************************************/1650int JNICALL1651Java_com_ibm_jvm_Trace_setImpl(JNIEnv *env, jobject this, jstring jcmd)1652{1653const char *cmd = NULL;1654int ret = JNI_ERR;16551656/*1657* Check that interface is available1658*/1659if (NULL == TRACEDOTCGLOBAL(rasIntf)) {1660return ret;1661}16621663if (NULL == jcmd) {1664return JNI_EINVAL;1665}16661667cmd = (*env)->GetStringUTFChars(env, jcmd, JNI_FALSE);16681669if (NULL != cmd) {1670ret = TRACEDOTCGLOBAL(rasIntf)->TraceSet(env, cmd);16711672(*env)->ReleaseStringUTFChars(env, jcmd, cmd);1673}16741675return ret;1676}16771678/**************************************************************************1679* name - Java_com_ibm_jvm_Trace_snap1680* description - Snap internal trace buffers1681* parameters - JNIEnv, this.1682* returns - none1683*************************************************************************/1684void JNICALL1685Java_com_ibm_jvm_Trace_snapImpl(JNIEnv *env, jobject this)1686{1687/*1688* Check that interface is available1689*/1690if (NULL == TRACEDOTCGLOBAL(rasIntf)) {1691return;1692}16931694TRACEDOTCGLOBAL(rasIntf)->TraceSnap(env, NULL);1695}16961697/**************************************************************************1698* name - Java_com_ibm_jvm_Trace_suspend1699* description - Suspend tracing activity1700* parameters - JNIEnv, this.1701* returns - none1702*************************************************************************/1703void JNICALL1704Java_com_ibm_jvm_Trace_suspendImpl(JNIEnv *env, jobject this)1705{1706/*1707* Check that interface is available1708*/1709if (NULL == TRACEDOTCGLOBAL(rasIntf)) {1710return;1711}17121713TRACEDOTCGLOBAL(rasIntf)->TraceSuspend(env);1714}17151716/**************************************************************************1717* name - Java_com_ibm_jvm_Trace_resume1718* description - Resume tracing activity1719* parameters - JNIEnv, this.1720* returns - none1721*************************************************************************/1722void JNICALL1723Java_com_ibm_jvm_Trace_resumeImpl(JNIEnv *env, jobject this)1724{1725/*1726* Check that interface is available1727*/1728if (NULL == TRACEDOTCGLOBAL(rasIntf)) {1729return;1730}17311732TRACEDOTCGLOBAL(rasIntf)->TraceResume(env);1733}17341735/**************************************************************************1736* name - Java_com_ibm_jvm_Trace_suspendThis1737* description - Suspend tracing activity for this thread1738* parameters - JNIEnv, this.1739* returns - none1740*1741*************************************************************************/1742void JNICALL1743Java_com_ibm_jvm_Trace_suspendThisImpl(JNIEnv *env, jobject this)1744{1745/*1746* Check that interface is available1747*/1748if (NULL == TRACEDOTCGLOBAL(rasIntf)) {1749return;1750}17511752TRACEDOTCGLOBAL(rasIntf)->TraceSuspendThis(env);1753}17541755/**************************************************************************1756* name - Java_com_ibm_jvm_Trace_resumeThis1757* description - resume tracing activity for this thread1758* parameters - JNIEnv, this.1759* returns - none1760*1761*************************************************************************/1762void JNICALL1763Java_com_ibm_jvm_Trace_resumeThisImpl(JNIEnv *env, jobject this)1764{1765/*1766* Check that interface is available1767*/1768if (NULL == TRACEDOTCGLOBAL(rasIntf)) {1769return;1770}17711772TRACEDOTCGLOBAL(rasIntf)->TraceResumeThis(env);1773}17741775/**************************************************************************1776* name - Java_com_ibm_jvm_Trace_getMicros1777* description - Return the microsecond clock time1778* parameters - JNIEnv, this.1779* returns - A long containing the microsecond time1780* initial version for 6.0 - a better version might return the actual time1781* in microseconds.1782*************************************************************************/1783jlong JNICALL1784Java_com_ibm_jvm_Trace_getMicros(JNIEnv *env, jobject this)1785{1786PORT_ACCESS_FROM_ENV(env);1787/* Use j9time_hires_delta instead of deprecated j9time_usec_clock */1788return (jlong)j9time_hires_delta(0, j9time_hires_clock(), J9PORT_TIME_DELTA_IN_MICROSECONDS);1789}17901791/*Array list code*/17921793static struct ArrayList *1794allocArrayList(JNIEnv *const env, const UDATA slabSize)1795{1796PORT_ACCESS_FROM_ENV(env);17971798struct ArrayList *toReturn = j9mem_allocate_memory(sizeof(struct ArrayList), J9MEM_CATEGORY_VM_JCL);17991800if (NULL == toReturn) {1801/*Malloc failure*/1802((J9VMThread *)env)->javaVM->internalVMFunctions->throwNativeOOMError(env, 0, 0);1803return NULL;1804}18051806toReturn->slabSize = slabSize;1807toReturn->header = NULL;18081809return toReturn;1810}18111812static void **1813arrayListAllocateSlab(JNIEnv *const env, const struct ArrayList *const list)1814{1815PORT_ACCESS_FROM_ENV(env);18161817/*We allocate an extra slot in the slab for the pointer to the next slab*/1818UDATA allocSize = sizeof(void *) * (list->slabSize + 1);1819void **toReturn = j9mem_allocate_memory(allocSize, J9MEM_CATEGORY_VM_JCL);18201821if (NULL == toReturn) {1822((J9VMThread *)env)->javaVM->internalVMFunctions->throwNativeOOMError(env, 0, 0);1823return NULL;1824}18251826memset(toReturn, 0, allocSize);18271828return toReturn;1829}18301831static void **1832arrayListGetSlab(JNIEnv *const env, const struct ArrayList *const list, const UDATA index, const BOOLEAN allocate)1833{1834const int targetSlabNumber = (const int)(index / list->slabSize);1835int currentSlabNumber = 0;1836void **currentSlab;1837PORT_ACCESS_FROM_ENV(env);18381839/*The first time this is called the list header slab won't have been created.*/1840if (NULL == list->header) {1841void **newSlab = arrayListAllocateSlab(env, list);18421843if (NULL == newSlab) {1844/*Malloc failed*/1845return NULL;1846}18471848if (! CompareAndSwapPtr((UDATA*)&(list->header), (UDATA)NULL, (UDATA)newSlab)) {1849/*Header is no longer NULL - someone else did the allocation. Free our newSlab and keep going*/1850j9mem_free_memory(newSlab);1851}1852}18531854currentSlab = list->header;18551856while (currentSlabNumber < targetSlabNumber) {1857/*The last element in the array is the pointer to the next slab*/1858if (currentSlab[list->slabSize]) {1859currentSlab = (void**)currentSlab[list->slabSize];1860currentSlabNumber++;1861} else {1862/*We've hit the end of the chain. At this point we can either allocate the space we need or give up*/1863if (allocate) {1864void **newSlab = arrayListAllocateSlab(env, list);18651866if (NULL == newSlab) {1867/*Malloc failed*/1868return NULL;1869}18701871/*Atomically swap in the new slab*/1872if (CompareAndSwapPtr((UDATA*)&(currentSlab[list->slabSize]), (UDATA)NULL, (UDATA)newSlab)) {1873currentSlab = newSlab;1874currentSlabNumber++;1875} else {1876/* The compare and swap didn't work - which means another thread must have already allocated and assigned1877* the slab. Free the memory this thread allocated and go round the loop again to re-evaluate the current slab.1878*/1879j9mem_free_memory(newSlab);1880continue;1881}1882} else {1883/*We don't want to allocate the space for the slot, so we just return*/1884return NULL;1885}1886}1887}18881889return currentSlab;1890}18911892static IDATA1893arrayListPut(JNIEnv *const env, const struct ArrayList *const list, const UDATA index, void *const value)1894{1895void **const slab = arrayListGetSlab(env, list, index, TRUE);1896void *oldValue;1897const UDATA slabIndex = index % list->slabSize;18981899if (NULL == slab) {1900return 1;1901}19021903do {1904oldValue = slab[slabIndex];1905} while (!CompareAndSwapPtr((UDATA*)&(slab[slabIndex]), (UDATA)oldValue, (UDATA)value));19061907return 0;1908}19091910static void *1911arrayListGet(JNIEnv *const env, const struct ArrayList *const list, const UDATA index)1912{1913void **const slab = arrayListGetSlab(env, list, index, FALSE);1914UDATA slabIndex = index % list->slabSize;19151916if (NULL == slab) {1917return NULL;1918}19191920return slab[slabIndex];1921}19221923static I_321924CompareAndSwap32(volatile U_32 *target, U_32 old, U_32 new32)1925{1926return ( compareAndSwapU32((U_32*)target, old, new32) == old ) ? TRUE : FALSE;1927}19281929static I_321930CompareAndSwapPtr(volatile UDATA *target, UDATA old, UDATA newptr)1931{1932return ( compareAndSwapUDATA((UDATA*)target, old, newptr) == old ) ? TRUE : FALSE;1933}19341935/*END OF FILE*/193619371938