1 // SPDX-License-Identifier: LGPL-2.1
2 /*
3 * Copyright (C) 2023 Google LLC, Steven Rostedt <rostedt@goodmis.org>
4 */
5 #include <stdlib.h>
6 #include <ctype.h>
7 #include "tracefs.h"
8 #include "tracefs-local.h"
9
convert_ts(char * value)10 static long long convert_ts(char *value)
11 {
12 long long ts;
13 char *saveptr;
14 char *secs;
15 char *usecs;
16
17 secs = strtok_r(value, ".", &saveptr);
18 if (!secs)
19 return -1LL;
20
21 ts = strtoll(secs, NULL, 0);
22
23 usecs = strtok_r(NULL, ".", &saveptr);
24 if (!usecs)
25 return ts;
26
27 /* Could be in nanoseconds */
28 if (strlen(usecs) > 6)
29 ts *= 1000000000LL;
30 else
31 ts *= 1000000LL;
32
33 ts += strtoull(usecs, NULL, 0);
34
35 return ts;
36 }
37
38 struct tracefs_buffer_stat *
tracefs_instance_get_stat(struct tracefs_instance * instance,int cpu)39 tracefs_instance_get_stat(struct tracefs_instance *instance, int cpu)
40 {
41 struct tracefs_buffer_stat *tstat;
42 char *saveptr;
43 char *value;
44 char *field;
45 char *path;
46 char *line;
47 char *next;
48 char *buf;
49 int len;
50 int ret;
51
52 ret = asprintf(&path, "per_cpu/cpu%d/stats", cpu);
53 if (ret < 0)
54 return NULL;
55
56 buf = tracefs_instance_file_read(instance, path, &len);
57 free(path);
58
59 if (!buf)
60 return NULL;
61
62 tstat = malloc(sizeof(*tstat));
63 if (!tstat) {
64 free(buf);
65 return NULL;
66 }
67
68 /* Set everything to -1 */
69 memset(tstat, -1, sizeof(*tstat));
70
71 next = buf;
72 while ((line = strtok_r(next, "\n", &saveptr))) {
73 char *save2;
74
75 next = NULL;
76
77 field = strtok_r(line, ":", &save2);
78 if (!field)
79 break;
80
81 value = strtok_r(NULL, ":", &save2);
82 if (!value)
83 break;
84
85 while (isspace(*value))
86 value++;
87
88 if (strcmp(field, "entries") == 0) {
89 tstat->entries = strtoull(value, NULL, 0);
90
91 } else if (strcmp(field, "overrun") == 0) {
92 tstat->overrun = strtoull(value, NULL, 0);
93
94 } else if (strcmp(field, "commit overrun") == 0) {
95 tstat->commit_overrun = strtoull(value, NULL, 0);
96
97 } else if (strcmp(field, "bytes") == 0) {
98 tstat->bytes = strtoull(value, NULL, 0);
99
100 } else if (strcmp(field, "oldest event ts") == 0) {
101 tstat->oldest_ts = convert_ts(value);
102
103 } else if (strcmp(field, "now ts") == 0) {
104 tstat->now_ts = convert_ts(value);
105
106 } else if (strcmp(field, "dropped events") == 0) {
107 tstat->dropped_events = strtoull(value, NULL, 0);
108
109 } else if (strcmp(field, "read events") == 0) {
110 tstat->read_events = strtoull(value, NULL, 0);
111 }
112 }
113 free(buf);
114
115 return tstat;
116 }
117
tracefs_instance_put_stat(struct tracefs_buffer_stat * tstat)118 void tracefs_instance_put_stat(struct tracefs_buffer_stat *tstat)
119 {
120 free(tstat);
121 }
122
tracefs_buffer_stat_entries(struct tracefs_buffer_stat * tstat)123 ssize_t tracefs_buffer_stat_entries(struct tracefs_buffer_stat *tstat)
124 {
125 return tstat->entries;
126 }
127
tracefs_buffer_stat_overrun(struct tracefs_buffer_stat * tstat)128 ssize_t tracefs_buffer_stat_overrun(struct tracefs_buffer_stat *tstat)
129 {
130 return tstat->overrun;
131 }
132
tracefs_buffer_stat_commit_overrun(struct tracefs_buffer_stat * tstat)133 ssize_t tracefs_buffer_stat_commit_overrun(struct tracefs_buffer_stat *tstat)
134 {
135 return tstat->commit_overrun;
136 }
137
tracefs_buffer_stat_bytes(struct tracefs_buffer_stat * tstat)138 ssize_t tracefs_buffer_stat_bytes(struct tracefs_buffer_stat *tstat)
139 {
140 return tstat->bytes;
141 }
142
tracefs_buffer_stat_event_timestamp(struct tracefs_buffer_stat * tstat)143 long long tracefs_buffer_stat_event_timestamp(struct tracefs_buffer_stat *tstat)
144 {
145 return tstat->oldest_ts;
146 }
147
tracefs_buffer_stat_timestamp(struct tracefs_buffer_stat * tstat)148 long long tracefs_buffer_stat_timestamp(struct tracefs_buffer_stat *tstat)
149 {
150 return tstat->now_ts;
151 }
152
tracefs_buffer_stat_dropped_events(struct tracefs_buffer_stat * tstat)153 ssize_t tracefs_buffer_stat_dropped_events(struct tracefs_buffer_stat *tstat)
154 {
155 return tstat->dropped_events;
156 }
157
tracefs_buffer_stat_read_events(struct tracefs_buffer_stat * tstat)158 ssize_t tracefs_buffer_stat_read_events(struct tracefs_buffer_stat *tstat)
159 {
160 return tstat->read_events;
161 }
162
163