Commit | Line | Data |
---|---|---|
ebabbf58 MD |
1 | /* SPDX-License-Identifier: (GPL-2.0-only or LGPL-2.1-only) |
2 | * | |
3 | * lttng-counter-client-percpu-64-modular.c | |
4 | * | |
5 | * LTTng lib counter client. Per-cpu 64-bit counters in modular | |
6 | * arithmetic. | |
7 | * | |
8 | * Copyright (C) 2020 Mathieu Desnoyers <mathieu.desnoyers@efficios.com> | |
9 | */ | |
10 | ||
8cd08025 | 11 | #include "common/counter-clients/clients.h" |
cdff92e0 | 12 | #include "common/counter/counter-api.h" |
8cd08025 MJ |
13 | #include "common/counter/counter.h" |
14 | #include "common/events.h" | |
15 | #include "common/tracer.h" | |
ebabbf58 MD |
16 | |
17 | static const struct lib_counter_config client_config = { | |
18 | .alloc = COUNTER_ALLOC_PER_CPU, | |
19 | .sync = COUNTER_SYNC_PER_CPU, | |
20 | .arithmetic = COUNTER_ARITHMETIC_MODULAR, | |
21 | .counter_size = COUNTER_SIZE_64_BIT, | |
22 | }; | |
23 | ||
b187bcd5 | 24 | static struct lttng_ust_channel_counter *counter_create(size_t nr_dimensions, |
ebabbf58 MD |
25 | const struct lttng_counter_dimension *dimensions, |
26 | int64_t global_sum_step, | |
27 | int global_counter_fd, | |
28 | int nr_counter_cpu_fds, | |
29 | const int *counter_cpu_fds, | |
30 | bool is_daemon) | |
31 | { | |
32 | size_t max_nr_elem[LTTNG_COUNTER_DIMENSION_MAX], i; | |
b187bcd5 MD |
33 | struct lttng_ust_channel_counter *lttng_chan_counter; |
34 | struct lib_counter *counter; | |
ebabbf58 MD |
35 | |
36 | if (nr_dimensions > LTTNG_COUNTER_DIMENSION_MAX) | |
37 | return NULL; | |
38 | for (i = 0; i < nr_dimensions; i++) { | |
39 | if (dimensions[i].has_underflow || dimensions[i].has_overflow) | |
40 | return NULL; | |
41 | max_nr_elem[i] = dimensions[i].size; | |
42 | } | |
b187bcd5 MD |
43 | lttng_chan_counter = lttng_ust_alloc_channel_counter(); |
44 | if (!lttng_chan_counter) | |
45 | return NULL; | |
46 | counter = lttng_counter_create(&client_config, nr_dimensions, max_nr_elem, | |
ebabbf58 MD |
47 | global_sum_step, global_counter_fd, nr_counter_cpu_fds, |
48 | counter_cpu_fds, is_daemon); | |
b187bcd5 MD |
49 | if (!counter) |
50 | goto error; | |
51 | lttng_chan_counter->priv->counter = counter; | |
24f7193c MD |
52 | for (i = 0; i < nr_dimensions; i++) |
53 | lttng_chan_counter->priv->dimension_key_types[i] = dimensions[i].key_type; | |
b187bcd5 MD |
54 | return lttng_chan_counter; |
55 | ||
56 | error: | |
57 | lttng_ust_free_channel_common(lttng_chan_counter->parent); | |
58 | return NULL; | |
59 | } | |
60 | ||
61 | static void counter_destroy(struct lttng_ust_channel_counter *counter) | |
62 | { | |
63 | lttng_counter_destroy(counter->priv->counter); | |
64 | lttng_ust_free_channel_common(counter->parent); | |
ebabbf58 MD |
65 | } |
66 | ||
b187bcd5 MD |
67 | static int counter_add(struct lttng_ust_channel_counter *counter, |
68 | const size_t *dimension_indexes, int64_t v) | |
ebabbf58 | 69 | { |
b187bcd5 | 70 | return lttng_counter_add(&client_config, counter->priv->counter, dimension_indexes, v); |
ebabbf58 MD |
71 | } |
72 | ||
24f7193c MD |
73 | static int counter_hit(struct lttng_ust_event_counter *event_counter, |
74 | const char *stack_data __attribute__((unused)), | |
75 | struct lttng_ust_probe_ctx *probe_ctx __attribute__((unused)), | |
76 | struct lttng_ust_event_counter_ctx *event_counter_ctx __attribute__((unused))) | |
ebabbf58 | 77 | { |
b187bcd5 | 78 | struct lttng_ust_channel_counter *counter = event_counter->chan; |
b187bcd5 | 79 | |
24f7193c MD |
80 | switch (event_counter->priv->action) { |
81 | case LTTNG_EVENT_COUNTER_ACTION_INCREMENT: | |
82 | { | |
83 | size_t index = event_counter->priv->parent.id; | |
84 | return counter_add(counter, &index, 1); | |
85 | } | |
86 | default: | |
87 | return -ENOSYS; | |
88 | } | |
ebabbf58 MD |
89 | } |
90 | ||
b187bcd5 | 91 | static int counter_read(struct lttng_ust_channel_counter *counter, const size_t *dimension_indexes, int cpu, |
ebabbf58 MD |
92 | int64_t *value, bool *overflow, bool *underflow) |
93 | { | |
b187bcd5 | 94 | return lttng_counter_read(&client_config, counter->priv->counter, dimension_indexes, cpu, value, |
ebabbf58 MD |
95 | overflow, underflow); |
96 | } | |
97 | ||
b187bcd5 | 98 | static int counter_aggregate(struct lttng_ust_channel_counter *counter, const size_t *dimension_indexes, |
ebabbf58 MD |
99 | int64_t *value, bool *overflow, bool *underflow) |
100 | { | |
b187bcd5 | 101 | return lttng_counter_aggregate(&client_config, counter->priv->counter, dimension_indexes, value, |
ebabbf58 MD |
102 | overflow, underflow); |
103 | } | |
104 | ||
b187bcd5 | 105 | static int counter_clear(struct lttng_ust_channel_counter *counter, const size_t *dimension_indexes) |
ebabbf58 | 106 | { |
b187bcd5 | 107 | return lttng_counter_clear(&client_config, counter->priv->counter, dimension_indexes); |
ebabbf58 MD |
108 | } |
109 | ||
110 | static struct lttng_counter_transport lttng_counter_transport = { | |
111 | .name = "counter-per-cpu-64-modular", | |
112 | .ops = { | |
b187bcd5 MD |
113 | .struct_size = sizeof(struct lttng_ust_channel_counter_ops), |
114 | .priv = LTTNG_UST_COMPOUND_LITERAL(struct lttng_ust_channel_counter_ops_private, { | |
115 | .pub = <tng_counter_transport.ops, | |
116 | .counter_create = counter_create, | |
117 | .counter_destroy = counter_destroy, | |
118 | .counter_add = counter_add, | |
119 | .counter_read = counter_read, | |
120 | .counter_aggregate = counter_aggregate, | |
121 | .counter_clear = counter_clear, | |
122 | }), | |
24f7193c | 123 | .counter_hit = counter_hit, |
ebabbf58 MD |
124 | }, |
125 | .client_config = &client_config, | |
126 | }; | |
127 | ||
128 | void lttng_counter_client_percpu_64_modular_init(void) | |
129 | { | |
130 | lttng_counter_transport_register(<tng_counter_transport); | |
131 | } | |
132 | ||
133 | void lttng_counter_client_percpu_64_modular_exit(void) | |
134 | { | |
135 | lttng_counter_transport_unregister(<tng_counter_transport); | |
136 | } |