Move nr_callbacks to event state
[libside.git] / include / side / trace.h
CommitLineData
67337c4a
MD
1// SPDX-License-Identifier: MIT
2/*
3 * Copyright 2022 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
4 */
5
6#ifndef _SIDE_TRACE_H
7#define _SIDE_TRACE_H
8
9#include <stdint.h>
10#include <inttypes.h>
11#include <stdlib.h>
12#include <stdio.h>
13#include <math.h>
25ea4c79 14#include <stdbool.h>
441235e7 15#include <stddef.h>
67337c4a
MD
16#include <side/macros.h>
17#include <side/endian.h>
18
19/*
551d8244 20 * SIDE stands for "Software Instrumentation Dynamically Enabled"
67337c4a 21 *
2e197497 22 * This is an instrumentation ABI for Linux user-space, which exposes an
67337c4a
MD
23 * instrumentation type system and facilities allowing a kernel or
24 * user-space tracer to consume user-space instrumentation.
25 *
35e4f870
MD
26 * The extensibility scheme for the SIDE ABI for event state is as
27 * follows:
67337c4a 28 *
b2a84b9f
MD
29 * * If the semantic of the "struct side_event_state_N" fields change,
30 * the SIDE_EVENT_STATE_ABI_VERSION should be increased. The
31 * "struct side_event_state_N" is not extensible and must have its
32 * ABI version increased whenever it is changed. Note that increasing
33 * the version of SIDE_EVENT_DESCRIPTION_ABI_VERSION is not necessary
34 * when changing the layout of "struct side_event_state_N".
67337c4a
MD
35 */
36
b2a84b9f 37#define SIDE_EVENT_STATE_ABI_VERSION 0
67337c4a 38
b8dfb348
MD
39#include <side/abi/event-description.h>
40#include <side/abi/type-argument.h>
57553dfd 41#include <side/instrumentation-c-api.h>
67337c4a
MD
42
43enum side_error {
44 SIDE_ERROR_OK = 0,
45 SIDE_ERROR_INVAL = 1,
46 SIDE_ERROR_EXIST = 2,
47 SIDE_ERROR_NOMEM = 3,
48 SIDE_ERROR_NOENT = 4,
49 SIDE_ERROR_EXITING = 5,
50};
51
0d747f98
MD
52/*
53 * This structure is _not_ packed to allow atomic operations on its
b2a84b9f
MD
54 * fields. Changes to this structure must bump the "Event state ABI
55 * version" and tracers _must_ learn how to deal with this ABI,
56 * otherwise they should reject the event.
0d747f98 57 */
b2a84b9f 58
0d747f98 59struct side_event_state {
b2a84b9f
MD
60 uint32_t version; /* Event state ABI version. */
61};
62
63struct side_event_state_0 {
64 struct side_event_state p; /* Required first field. */
3cac1780 65 uint32_t nr_callbacks;
692ffa8b 66 uintptr_t enabled;
7269a8a3
MD
67 const struct side_callback *callbacks;
68 struct side_event_description *desc;
0d747f98
MD
69};
70
67337c4a
MD
71#ifdef __cplusplus
72extern "C" {
73#endif
74
2e197497
MD
75struct side_callback {
76 union {
77 void (*call)(const struct side_event_description *desc,
78 const struct side_arg_vec *side_arg_vec,
79 void *priv);
80 void (*call_variadic)(const struct side_event_description *desc,
81 const struct side_arg_vec *side_arg_vec,
82 const struct side_arg_dynamic_struct *var_struct,
83 void *priv);
84 } SIDE_PACKED u;
85 void *priv;
86} SIDE_PACKED;
87
67337c4a
MD
88extern const struct side_callback side_empty_callback;
89
0d747f98 90void side_call(const struct side_event_state *state,
67337c4a 91 const struct side_arg_vec *side_arg_vec);
0d747f98 92void side_call_variadic(const struct side_event_state *state,
67337c4a
MD
93 const struct side_arg_vec *side_arg_vec,
94 const struct side_arg_dynamic_struct *var_struct);
95
96struct side_events_register_handle *side_events_register(struct side_event_description **events,
97 uint32_t nr_events);
98void side_events_unregister(struct side_events_register_handle *handle);
99
100/*
101 * Userspace tracer registration API. This allows userspace tracers to
102 * register event notification callbacks to be notified of the currently
103 * registered instrumentation, and to register their callbacks to
104 * specific events.
105 */
106typedef void (*side_tracer_callback_func)(const struct side_event_description *desc,
107 const struct side_arg_vec *side_arg_vec,
108 void *priv);
109typedef void (*side_tracer_callback_variadic_func)(const struct side_event_description *desc,
110 const struct side_arg_vec *side_arg_vec,
111 const struct side_arg_dynamic_struct *var_struct,
112 void *priv);
113
114int side_tracer_callback_register(struct side_event_description *desc,
115 side_tracer_callback_func call,
116 void *priv);
117int side_tracer_callback_variadic_register(struct side_event_description *desc,
118 side_tracer_callback_variadic_func call_variadic,
119 void *priv);
120int side_tracer_callback_unregister(struct side_event_description *desc,
121 side_tracer_callback_func call,
122 void *priv);
123int side_tracer_callback_variadic_unregister(struct side_event_description *desc,
124 side_tracer_callback_variadic_func call_variadic,
125 void *priv);
126
127enum side_tracer_notification {
128 SIDE_TRACER_NOTIFICATION_INSERT_EVENTS,
129 SIDE_TRACER_NOTIFICATION_REMOVE_EVENTS,
130};
131
132/* Callback is invoked with side library internal lock held. */
133struct side_tracer_handle *side_tracer_event_notification_register(
134 void (*cb)(enum side_tracer_notification notif,
135 struct side_event_description **events, uint32_t nr_events, void *priv),
136 void *priv);
137void side_tracer_event_notification_unregister(struct side_tracer_handle *handle);
138
139/*
140 * Explicit hooks to initialize/finalize the side instrumentation
141 * library. Those are also library constructor/destructor.
142 */
143void side_init(void) __attribute__((constructor));
144void side_exit(void) __attribute__((destructor));
145
146/*
147 * The following constructors/destructors perform automatic registration
148 * of the declared side events. Those may have to be called explicitly
149 * in a statically linked library.
150 */
151
152/*
153 * These weak symbols, the constructor, and destructor take care of
154 * registering only _one_ instance of the side instrumentation per
155 * shared-ojbect (or for the whole main program).
156 */
157extern struct side_event_description * __start_side_event_description_ptr[]
158 __attribute__((weak, visibility("hidden")));
159extern struct side_event_description * __stop_side_event_description_ptr[]
160 __attribute__((weak, visibility("hidden")));
161int side_event_description_ptr_registered
162 __attribute__((weak, visibility("hidden")));
163struct side_events_register_handle *side_events_handle
164 __attribute__((weak, visibility("hidden")));
165
166static void
167side_event_description_ptr_init(void)
168 __attribute__((no_instrument_function))
169 __attribute__((constructor));
170static void
171side_event_description_ptr_init(void)
172{
173 if (side_event_description_ptr_registered++)
174 return;
175 side_events_handle = side_events_register(__start_side_event_description_ptr,
176 __stop_side_event_description_ptr - __start_side_event_description_ptr);
177}
178
179static void
180side_event_description_ptr_exit(void)
181 __attribute__((no_instrument_function))
182 __attribute__((destructor));
183static void
184side_event_description_ptr_exit(void)
185{
186 if (--side_event_description_ptr_registered)
187 return;
188 side_events_unregister(side_events_handle);
189 side_events_handle = NULL;
190}
191
192#ifdef __cplusplus
193}
194#endif
195
196#endif /* _SIDE_TRACE_H */
This page took 0.044161 seconds and 4 git commands to generate.