/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <stdlib.h>
#include <stddef.h>
#include <limits.h>
#include <strings.h>
#include <pthread.h>
#include <dtrace_jni.h>
/*
* dtj_jnitab.c defines the JNI table of classes, methods, and fields belonging
* to the Java DTrace API. Another JNI table defining classes from the JDK is
* defined in dtj_util.c. Utility functions specific to the Java DTrace API are
* also defined here, while general utilities are defined in dtj_util.c.
*/
static boolean_t dtj_check_request_pool(void);
static boolean_t dtj_check_program_pool(void);
static boolean_t dtj_check_aggval_pool(void);
/* LocalConsumer */
/* DTraceException */
/* InterfaceAttributes */
/* ProbeDescription */
/* ProbeInfo */
/* Probe */
/* Program */
/* Program.File */
/* ProgramInfo */
/* Flow */
/* ProbeData */
/* Drop */
/* Error */
/* ProcessState */
/* Aggregate */
/* AggregateSpec */
/* Tuple */
/* AggregationRecord */
/* SumValue */
/* CountValue */
/* AvgValue */
/* MinValue */
/* MaxValue */
/* StddevValue */
/* KernelStackRecord */
/* UserStackRecord */
/* Distribution */
/* LogDistribution */
/* LinearDistribution */
/* KernelSymbolRecord */
/* UserSymbolRecord */
/* ScalarRecord */
static dtj_status_t
{
/*
* If you change this table, increment DTRACE_JNI_VERSION in
* dtrace_jni.c.
*/
/* LocalConsumer */
{ JCLASS, &g_caller_jc,
"org/opensolaris/os/dtrace/LocalConsumer" },
"(Lorg/opensolaris/os/dtrace/ProbeData;)V" },
"(Lorg/opensolaris/os/dtrace/Drop;)V" },
"(Lorg/opensolaris/os/dtrace/Error;)V" },
"(Lorg/opensolaris/os/dtrace/ProcessState;)V" },
/* DTraceException */
/* InterfaceAttributes */
/* ProbeDescription */
{ JCLASS, &g_probedesc_jc,
/* ProbeInfo */
{ JCLASS, &g_probeinfo_jc,
"org/opensolaris/os/dtrace/ProbeInfo" },
")V" },
/* Probe */
"Lorg/opensolaris/os/dtrace/ProbeInfo;)V" },
/* Program */
{ JCLASS, &g_program_jc,
"org/opensolaris/os/dtrace/Program" },
"Lorg/opensolaris/os/dtrace/ProgramInfo;" },
/* Program.File */
{ JCLASS, &g_programfile_jc,
"org/opensolaris/os/dtrace/Program$File" },
/* ProgramInfo */
{ JCLASS, &g_proginfo_jc,
"org/opensolaris/os/dtrace/ProgramInfo" },
"I)V" },
/* Flow */
/* ProbeData */
{ JCLASS, &g_pdata_jc,
"org/opensolaris/os/dtrace/ProbeData" },
"Lorg/opensolaris/os/dtrace/Flow;I)V" },
"(Lorg/opensolaris/os/dtrace/Record;)V" },
"(Lorg/opensolaris/os/dtrace/Record;)V" },
"invalidatePrintaRecord", "()V" },
"Lorg/opensolaris/os/dtrace/AggregationRecord;)V" },
"addPrintaFormattedString",
"(Lorg/opensolaris/os/dtrace/Tuple;"
"(II)V" },
/* Drop */
/* Error */
"(Lorg/opensolaris/os/dtrace/ProbeDescription;IIII"
/* ProcessState */
{ JCLASS, &g_process_jc,
"org/opensolaris/os/dtrace/ProcessState" },
/* Aggregate */
"Lorg/opensolaris/os/dtrace/AggregationRecord;)V" },
/* AggregateSpec */
{ JCLASS, &g_aggspec_jc,
"org/opensolaris/os/dtrace/AggregateSpec" },
/* Tuple */
"(Lorg/opensolaris/os/dtrace/ValueRecord;)V" },
"Lorg/opensolaris/os/dtrace/Tuple;" },
/* AggregationRecord */
{ JCLASS, &g_aggrec_jc,
"(Lorg/opensolaris/os/dtrace/Tuple;"
"Lorg/opensolaris/os/dtrace/AggregationValue;)V" },
"()Lorg/opensolaris/os/dtrace/Tuple;" },
/* SumValue */
{ JCLASS, &g_aggsum_jc,
"org/opensolaris/os/dtrace/SumValue" },
/* CountValue */
{ JCLASS, &g_aggcount_jc,
"org/opensolaris/os/dtrace/CountValue" },
/* AvgValue */
{ JCLASS, &g_aggavg_jc,
"org/opensolaris/os/dtrace/AvgValue" },
/* MinValue */
{ JCLASS, &g_aggmin_jc,
"org/opensolaris/os/dtrace/MinValue" },
/* MaxValue */
{ JCLASS, &g_aggmax_jc,
"org/opensolaris/os/dtrace/MaxValue" },
/* StddevValue */
{ JCLASS, &g_aggstddev_jc,
"org/opensolaris/os/dtrace/StddevValue" },
"(JJLjava/math/BigInteger;)V" },
/* KernelStackRecord */
{ JCLASS, &g_stack_jc,
"[Lorg/opensolaris/os/dtrace/StackFrame;" },
"([Lorg/opensolaris/os/dtrace/StackFrame;)V" },
/* UserStackRecord */
{ JCLASS, &g_ustack_jc,
"([Lorg/opensolaris/os/dtrace/StackFrame;)V" },
/* Distribution */
{ JCLASS, &g_adist_jc,
"org/opensolaris/os/dtrace/Distribution" },
/* LogDistribution */
/* LinearDistribution */
{ JCLASS, &g_ldist_jc,
/* KernelSymbolRecord */
{ JCLASS, &g_symbol_jc,
/* UserSymbolRecord */
{ JCLASS, &g_usymbol_jc,
/* ScalarRecord */
{ JCLASS, &g_scalar_jc,
"org/opensolaris/os/dtrace/ScalarRecord" },
{ DTJ_TYPE_END }
};
}
{
/* Java Error pending */
return (DTJ_ERR);
}
return (dtj_table_load(jenv));
}
static boolean_t
dtj_check_request_pool(void)
{
if (!g_request_pool) {
sizeof (dtj_request_t),
(g_dtj_util_debug ? UU_LIST_POOL_DEBUG : 0));
if (!g_request_pool) {
return (B_FALSE);
}
}
return (B_TRUE);
}
{
dtj_request_t *r;
if (!dtj_check_request_pool()) {
"Failed to allocate request pool");
return (NULL);
}
r = uu_zalloc(sizeof (dtj_request_t));
if (r) {
r->dtjr_args = dtj_string_list_create();
if (r->dtjr_args) {
const char *arg;
int i, len;
switch (type) {
case DTJ_REQUEST_OPTION:
len = 2;
break;
default:
len = 0;
}
for (i = 0; i < len; ++i) {
"Failed to add request arg");
uu_list_node_fini(r, &r->dtjr_node,
dtj_request_destroy(r, NULL);
r = NULL;
}
}
} else {
"Failed to allocate request arglist");
dtj_request_destroy(r, NULL);
r = NULL;
}
} else {
"Failed to allocate request");
}
return (r);
}
static boolean_t
dtj_check_program_pool(void)
{
if (!g_program_pool) {
sizeof (dtj_program_t),
(g_dtj_util_debug ? UU_LIST_POOL_DEBUG : 0));
if (!g_program_pool) {
return (B_FALSE);
}
}
return (B_TRUE);
}
{
dtj_program_t *p;
if (!dtj_check_program_pool()) {
"Failed to allocate program pool");
return (NULL);
}
p = uu_zalloc(sizeof (dtj_program_t));
if (p) {
char *program_name;
if (program_name) {
p->dtjp_name = program_name;
p->dtjp_enabled = B_FALSE;
} else {
"Failed to allocate program name");
dtj_program_destroy(p, NULL);
p = NULL;
}
} else {
"Failed to allocate program");
}
return (p);
}
static boolean_t
dtj_check_aggval_pool(void)
{
if (!g_aggval_pool) {
sizeof (dtj_aggval_t),
(g_dtj_util_debug ? UU_LIST_POOL_DEBUG : 0));
if (!g_aggval_pool) {
return (B_FALSE);
}
}
return (B_TRUE);
}
{
dtj_aggval_t *e;
if (!dtj_check_aggval_pool()) {
"Failed to allocate aggval entry pool");
return (NULL);
}
e = uu_zalloc(sizeof (dtj_aggval_t));
if (e) {
char *a_name;
e->dtja_value = aggval;
if (a_name) {
e->dtja_aggname = a_name;
} else {
"Failed to allocate aggregation name");
/* caller responsible for input java reference */
e->dtja_value = NULL;
dtj_aggval_destroy(e, jenv);
e = NULL;
}
e->dtja_aggid = aggid;
} else {
"Failed to allocate aggval entry");
}
return (e);
}
{
if (!dtj_check_aggval_pool()) {
"Failed to allocate aggval pool");
return (DTJ_ERR);
}
(g_dtj_util_debug ? UU_LIST_DEBUG : 0));
if (!jc->dtjj_aggval_list) {
"Failed to allocate aggval list");
return (DTJ_ERR);
}
/* Does not throw exceptions */
return (DTJ_OK);
}
void
{
if (jc) {
if (jc->dtjj_probedata) {
}
if (jc->dtjj_printa_buffer) {
}
if (jc->dtjj_aggregate) {
}
if (jc->dtjj_tuple) {
}
if (jc->dtjj_aggval_list) {
}
/*
* aggregate_spec records an input argument to a native JNI
* function (a reference we did not create), so we are not
* responsible for it.
*/
/*
* probelist records an in-out argument to a native JNI function
* (a reference we did not create), so we are not responsible
* for it.
*/
if (jc->dtjj_exception) {
}
}
}
{
dtj_consumer_t *c;
if (!dtj_check_request_pool()) {
"Failed to allocate request pool");
return (NULL);
}
if (!dtj_check_program_pool()) {
"Failed to allocate program pool");
return (NULL);
}
c = uu_zalloc(sizeof (dtj_consumer_t));
if (c) {
(g_dtj_util_debug ? UU_LIST_DEBUG : 0));
if (!c->dtjc_request_list) {
"Failed to allocate consumer request list");
return (NULL);
}
(g_dtj_util_debug ? UU_LIST_DEBUG : 0));
if (!c->dtjc_program_list) {
"Failed to allocate consumer program list");
return (NULL);
}
c->dtjc_probedata_rec_i = 0;
c->dtjc_aggid = -1;
c->dtjc_expected = -1;
c->dtjc_state = DTJ_CONSUMER_INIT;
} else {
"Failed to allocate consumer");
}
return (c);
}
void
/* ARGSUSED */
{
if (v) {
dtj_request_t *r = v;
bzero(v, sizeof (dtj_request_t));
uu_free(v);
}
}
void
/* ARGSUSED */
{
if (v) {
dtj_program_t *p = v;
if (p->dtjp_name) {
}
bzero(v, sizeof (dtj_program_t));
uu_free(v);
}
}
void
{
if (v) {
dtj_aggval_t *a = v;
if (a->dtja_value && arg) {
}
if (a->dtja_aggname) {
free((void *)a->dtja_aggname);
}
bzero(v, sizeof (dtj_aggval_t));
uu_free(v);
}
}
/*
* Frees per-consumer state. Assumes that the DTrace handle has been closed
* already.
*/
void
{
if (c) {
NULL);
(void) pthread_mutex_destroy(&c->dtjc_request_list_lock);
NULL);
/*
* Cannot dtrace_proc_release the c->process_list proc
* elements here, because we need the dtrace handle for that.
* By the time this destructor is called, the dtrace handle is
* already closed. The proc elements are released in
* dtrace_jni.c _close().
*/
if (c->dtjc_process_list) {
}
bzero(c, sizeof (dtj_consumer_t));
uu_free(c);
}
}
void
{
if (!message) {
return; /* java exception pending */
}
if (exception) {
}
}