2 * SPDX-License-Identifier: LGPL-2.1-only
4 * Copyright (C) 2016 EfficiOS Inc.
5 * Copyright (C) 2016 Alexandre Montplaisir <alexmonthy@efficios.com>
6 * Copyright (C) 2016 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
9 #include "org_lttng_ust_agent_context_LttngContextApi.h"
13 #include <lttng/ust-events.h>
14 #include <lttng/ringbuffer-context.h>
15 #include <ust-context-provider.h>
17 #include "ust-helper.h"
18 #include "lttng_ust_context.h"
20 enum lttng_ust_jni_type
{
32 struct lttng_ust_jni_ctx_entry
{
33 int32_t context_name_offset
;
34 char type
; /* enum lttng_ust_jni_type */
43 int32_t _string_offset
;
45 } __attribute__((packed
));
47 /* TLS passing context info from JNI to callbacks. */
48 __thread
struct lttng_ust_jni_tls lttng_ust_context_info_tls
;
50 static const char *get_ctx_string_at_offset(int32_t offset
)
52 signed char *ctx_strings_array
= lttng_ust_context_info_tls
.ctx_strings
;
54 if (offset
< 0 || offset
>= lttng_ust_context_info_tls
.ctx_strings_len
) {
57 return (const char *) (ctx_strings_array
+ offset
);
60 static struct lttng_ust_jni_ctx_entry
*lookup_ctx_by_name(const char *ctx_name
)
62 struct lttng_ust_jni_ctx_entry
*ctx_entries_array
= lttng_ust_context_info_tls
.ctx_entries
;
63 int i
, len
= lttng_ust_context_info_tls
.ctx_entries_len
/ sizeof(struct lttng_ust_jni_ctx_entry
);
65 for (i
= 0; i
< len
; i
++) {
66 int32_t offset
= ctx_entries_array
[i
].context_name_offset
;
67 const char *string
= get_ctx_string_at_offset(offset
);
69 if (string
&& strcmp(string
, ctx_name
) == 0) {
70 return &ctx_entries_array
[i
];
76 static size_t get_size_cb(struct lttng_ust_ctx_field
*field
, size_t offset
)
78 struct lttng_ust_jni_ctx_entry
*jctx
;
80 const char *ctx_name
= field
->event_field
->name
;
81 enum lttng_ust_jni_type jni_type
;
84 size
+= lttng_ust_lib_ring_buffer_align(offset
, lttng_ust_rb_alignof(char));
85 size
+= sizeof(char); /* tag */
86 jctx
= lookup_ctx_by_name(ctx_name
);
88 jni_type
= JNI_TYPE_NULL
;
90 jni_type
= jctx
->type
;
95 case JNI_TYPE_INTEGER
:
96 size
+= lttng_ust_lib_ring_buffer_align(offset
, lttng_ust_rb_alignof(int32_t));
97 size
+= sizeof(int32_t); /* variant */
100 size
+= lttng_ust_lib_ring_buffer_align(offset
, lttng_ust_rb_alignof(int64_t));
101 size
+= sizeof(int64_t); /* variant */
103 case JNI_TYPE_DOUBLE
:
104 size
+= lttng_ust_lib_ring_buffer_align(offset
, lttng_ust_rb_alignof(double));
105 size
+= sizeof(double); /* variant */
108 size
+= lttng_ust_lib_ring_buffer_align(offset
, lttng_ust_rb_alignof(float));
109 size
+= sizeof(float); /* variant */
112 size
+= lttng_ust_lib_ring_buffer_align(offset
, lttng_ust_rb_alignof(int16_t));
113 size
+= sizeof(int16_t); /* variant */
115 case JNI_TYPE_BYTE
: /* Fall-through. */
116 case JNI_TYPE_BOOLEAN
:
117 size
+= lttng_ust_lib_ring_buffer_align(offset
, lttng_ust_rb_alignof(char));
118 size
+= sizeof(char); /* variant */
120 case JNI_TYPE_STRING
:
122 /* The value is an offset, the string is in the "strings" array */
123 int32_t string_offset
= jctx
->value
._string_offset
;
124 const char *string
= get_ctx_string_at_offset(string_offset
);
127 size
+= strlen(string
) + 1;
138 static void record_cb(struct lttng_ust_ctx_field
*field
,
139 struct lttng_ust_lib_ring_buffer_ctx
*ctx
,
140 struct lttng_ust_channel_buffer
*lttng_chan_buf
)
142 struct lttng_ust_jni_ctx_entry
*jctx
;
143 const char *ctx_name
= field
->event_field
->name
;
144 enum lttng_ust_jni_type jni_type
;
147 jctx
= lookup_ctx_by_name(ctx_name
);
149 jni_type
= JNI_TYPE_NULL
;
151 jni_type
= jctx
->type
;
156 sel_char
= LTTNG_UST_DYNAMIC_TYPE_NONE
;
157 lttng_ust_lib_ring_buffer_align_ctx(ctx
, lttng_ust_rb_alignof(char));
158 lttng_chan_buf
->ops
->event_write(ctx
, &sel_char
, sizeof(sel_char
));
160 case JNI_TYPE_INTEGER
:
162 int32_t v
= jctx
->value
._integer
;
164 sel_char
= LTTNG_UST_DYNAMIC_TYPE_S32
;
165 lttng_ust_lib_ring_buffer_align_ctx(ctx
, lttng_ust_rb_alignof(char));
166 lttng_chan_buf
->ops
->event_write(ctx
, &sel_char
, sizeof(sel_char
));
167 lttng_ust_lib_ring_buffer_align_ctx(ctx
, lttng_ust_rb_alignof(v
));
168 lttng_chan_buf
->ops
->event_write(ctx
, &v
, sizeof(v
));
173 int64_t v
= jctx
->value
._long
;
175 sel_char
= LTTNG_UST_DYNAMIC_TYPE_S64
;
176 lttng_ust_lib_ring_buffer_align_ctx(ctx
, lttng_ust_rb_alignof(char));
177 lttng_chan_buf
->ops
->event_write(ctx
, &sel_char
, sizeof(sel_char
));
178 lttng_ust_lib_ring_buffer_align_ctx(ctx
, lttng_ust_rb_alignof(v
));
179 lttng_chan_buf
->ops
->event_write(ctx
, &v
, sizeof(v
));
182 case JNI_TYPE_DOUBLE
:
184 double v
= jctx
->value
._double
;
186 sel_char
= LTTNG_UST_DYNAMIC_TYPE_DOUBLE
;
187 lttng_ust_lib_ring_buffer_align_ctx(ctx
, lttng_ust_rb_alignof(char));
188 lttng_chan_buf
->ops
->event_write(ctx
, &sel_char
, sizeof(sel_char
));
189 lttng_ust_lib_ring_buffer_align_ctx(ctx
, lttng_ust_rb_alignof(v
));
190 lttng_chan_buf
->ops
->event_write(ctx
, &v
, sizeof(v
));
195 float v
= jctx
->value
._float
;
197 sel_char
= LTTNG_UST_DYNAMIC_TYPE_FLOAT
;
198 lttng_ust_lib_ring_buffer_align_ctx(ctx
, lttng_ust_rb_alignof(char));
199 lttng_chan_buf
->ops
->event_write(ctx
, &sel_char
, sizeof(sel_char
));
200 lttng_ust_lib_ring_buffer_align_ctx(ctx
, lttng_ust_rb_alignof(v
));
201 lttng_chan_buf
->ops
->event_write(ctx
, &v
, sizeof(v
));
206 int16_t v
= jctx
->value
._short
;
208 sel_char
= LTTNG_UST_DYNAMIC_TYPE_S16
;
209 lttng_ust_lib_ring_buffer_align_ctx(ctx
, lttng_ust_rb_alignof(char));
210 lttng_chan_buf
->ops
->event_write(ctx
, &sel_char
, sizeof(sel_char
));
211 lttng_ust_lib_ring_buffer_align_ctx(ctx
, lttng_ust_rb_alignof(v
));
212 lttng_chan_buf
->ops
->event_write(ctx
, &v
, sizeof(v
));
217 char v
= jctx
->value
._byte
;
219 sel_char
= LTTNG_UST_DYNAMIC_TYPE_S8
;
220 lttng_ust_lib_ring_buffer_align_ctx(ctx
, lttng_ust_rb_alignof(char));
221 lttng_chan_buf
->ops
->event_write(ctx
, &sel_char
, sizeof(sel_char
));
222 lttng_ust_lib_ring_buffer_align_ctx(ctx
, lttng_ust_rb_alignof(v
));
223 lttng_chan_buf
->ops
->event_write(ctx
, &v
, sizeof(v
));
226 case JNI_TYPE_BOOLEAN
:
228 char v
= jctx
->value
._boolean
;
230 sel_char
= LTTNG_UST_DYNAMIC_TYPE_S8
;
231 lttng_ust_lib_ring_buffer_align_ctx(ctx
, lttng_ust_rb_alignof(char));
232 lttng_chan_buf
->ops
->event_write(ctx
, &sel_char
, sizeof(sel_char
));
233 lttng_ust_lib_ring_buffer_align_ctx(ctx
, lttng_ust_rb_alignof(v
));
234 lttng_chan_buf
->ops
->event_write(ctx
, &v
, sizeof(v
));
237 case JNI_TYPE_STRING
:
239 int32_t offset
= jctx
->value
._string_offset
;
240 const char *str
= get_ctx_string_at_offset(offset
);
243 sel_char
= LTTNG_UST_DYNAMIC_TYPE_STRING
;
245 sel_char
= LTTNG_UST_DYNAMIC_TYPE_NONE
;
247 lttng_ust_lib_ring_buffer_align_ctx(ctx
, lttng_ust_rb_alignof(char));
248 lttng_chan_buf
->ops
->event_write(ctx
, &sel_char
, sizeof(sel_char
));
250 lttng_chan_buf
->ops
->event_write(ctx
, str
, strlen(str
) + 1);
259 static void get_value_cb(struct lttng_ust_ctx_field
*field
,
260 struct lttng_ust_ctx_value
*value
)
262 struct lttng_ust_jni_ctx_entry
*jctx
;
263 const char *ctx_name
= field
->event_field
->name
;
264 enum lttng_ust_jni_type jni_type
;
266 jctx
= lookup_ctx_by_name(ctx_name
);
268 jni_type
= JNI_TYPE_NULL
;
270 jni_type
= jctx
->type
;
275 value
->sel
= LTTNG_UST_DYNAMIC_TYPE_NONE
;
277 case JNI_TYPE_INTEGER
:
278 value
->sel
= LTTNG_UST_DYNAMIC_TYPE_S64
;
279 value
->u
.s64
= (int64_t) jctx
->value
._integer
;
282 value
->sel
= LTTNG_UST_DYNAMIC_TYPE_S64
;
283 value
->u
.s64
= jctx
->value
._long
;
285 case JNI_TYPE_DOUBLE
:
286 value
->sel
= LTTNG_UST_DYNAMIC_TYPE_DOUBLE
;
287 value
->u
.d
= jctx
->value
._double
;
290 value
->sel
= LTTNG_UST_DYNAMIC_TYPE_DOUBLE
;
291 value
->u
.d
= (double) jctx
->value
._float
;
294 value
->sel
= LTTNG_UST_DYNAMIC_TYPE_S64
;
295 value
->u
.s64
= (int64_t) jctx
->value
._short
;
298 value
->sel
= LTTNG_UST_DYNAMIC_TYPE_S64
;
299 value
->u
.s64
= (int64_t) jctx
->value
._byte
;
301 case JNI_TYPE_BOOLEAN
:
302 value
->sel
= LTTNG_UST_DYNAMIC_TYPE_S64
;
303 value
->u
.s64
= (int64_t) jctx
->value
._boolean
;
305 case JNI_TYPE_STRING
:
307 int32_t offset
= jctx
->value
._string_offset
;
308 const char *str
= get_ctx_string_at_offset(offset
);
311 value
->sel
= LTTNG_UST_DYNAMIC_TYPE_STRING
;
314 value
->sel
= LTTNG_UST_DYNAMIC_TYPE_NONE
;
324 * Register a context provider to UST.
326 * Called from the Java side when an application registers a context retriever,
327 * so we create and register a corresponding provider on the C side.
329 JNIEXPORT jlong JNICALL
Java_org_lttng_ust_agent_context_LttngContextApi_registerProvider(JNIEnv
*env
,
331 jstring provider_name
)
334 const char *provider_name_jstr
;
335 char *provider_name_cstr
;
336 struct lttng_ust_context_provider
*provider
;
338 * Note: a "jlong" is 8 bytes on all architectures, whereas a
343 provider_name_jstr
= (*env
)->GetStringUTFChars(env
, provider_name
, &iscopy
);
344 if (!provider_name_jstr
) {
347 /* Keep our own copy of the string so UST can use it. */
348 provider_name_cstr
= strdup(provider_name_jstr
);
349 (*env
)->ReleaseStringUTFChars(env
, provider_name
, provider_name_jstr
);
350 if (!provider_name_cstr
) {
353 provider
= zmalloc(sizeof(*provider
));
357 provider
->struct_size
= sizeof(*provider
);
358 provider
->name
= provider_name_cstr
;
359 provider
->get_size
= get_size_cb
;
360 provider
->record
= record_cb
;
361 provider
->get_value
= get_value_cb
;
363 if (lttng_ust_context_provider_register(provider
)) {
367 provider_ref
= (jlong
) (long) provider
;
370 /* Error handling. */
374 free(provider_name_cstr
);
381 * Unregister a previously-registered context provider.
383 * Called from the Java side when an application unregisters a context retriever,
384 * so we unregister and delete the corresponding provider on the C side.
386 JNIEXPORT
void JNICALL
Java_org_lttng_ust_agent_context_LttngContextApi_unregisterProvider(JNIEnv
*env
,
390 struct lttng_ust_context_provider
*provider
=
391 (struct lttng_ust_context_provider
*) (unsigned long) provider_ref
;
397 lttng_ust_context_provider_unregister(provider
);
399 free(provider
->name
);