xref: /aosp_15_r20/external/libtracefs/src/tracefs-marker.c (revision 287e80b3a36113050663245e7f2c00d274188f18)
1*287e80b3SSadaf Ebrahimi // SPDX-License-Identifier: LGPL-2.1
2*287e80b3SSadaf Ebrahimi /*
3*287e80b3SSadaf Ebrahimi  * Copyright (C) 2021, VMware, Tzvetomir Stoyanov <[email protected]>
4*287e80b3SSadaf Ebrahimi  *
5*287e80b3SSadaf Ebrahimi  */
6*287e80b3SSadaf Ebrahimi 
7*287e80b3SSadaf Ebrahimi #include <stdlib.h>
8*287e80b3SSadaf Ebrahimi #include <unistd.h>
9*287e80b3SSadaf Ebrahimi #include <stdio.h>
10*287e80b3SSadaf Ebrahimi #include <pthread.h>
11*287e80b3SSadaf Ebrahimi 
12*287e80b3SSadaf Ebrahimi #include "tracefs.h"
13*287e80b3SSadaf Ebrahimi #include "tracefs-local.h"
14*287e80b3SSadaf Ebrahimi 
15*287e80b3SSadaf Ebrahimi /* File descriptors for Top level trace markers */
16*287e80b3SSadaf Ebrahimi static int ftrace_marker_fd = -1;
17*287e80b3SSadaf Ebrahimi static int ftrace_marker_raw_fd = -1;
18*287e80b3SSadaf Ebrahimi 
get_marker_fd(struct tracefs_instance * instance,bool raw)19*287e80b3SSadaf Ebrahimi static inline int *get_marker_fd(struct tracefs_instance *instance, bool raw)
20*287e80b3SSadaf Ebrahimi {
21*287e80b3SSadaf Ebrahimi 	if (raw)
22*287e80b3SSadaf Ebrahimi 		return instance ? &instance->ftrace_marker_raw_fd : &ftrace_marker_raw_fd;
23*287e80b3SSadaf Ebrahimi 	return instance ? &instance->ftrace_marker_fd : &ftrace_marker_fd;
24*287e80b3SSadaf Ebrahimi }
25*287e80b3SSadaf Ebrahimi 
marker_init(struct tracefs_instance * instance,bool raw)26*287e80b3SSadaf Ebrahimi static int marker_init(struct tracefs_instance *instance, bool raw)
27*287e80b3SSadaf Ebrahimi {
28*287e80b3SSadaf Ebrahimi 	const char *file = raw ? "trace_marker_raw" : "trace_marker";
29*287e80b3SSadaf Ebrahimi 	pthread_mutex_t *lock = trace_get_lock(instance);
30*287e80b3SSadaf Ebrahimi 	int *fd = get_marker_fd(instance, raw);
31*287e80b3SSadaf Ebrahimi 	int ret;
32*287e80b3SSadaf Ebrahimi 
33*287e80b3SSadaf Ebrahimi 	if (*fd >= 0)
34*287e80b3SSadaf Ebrahimi 		return 0;
35*287e80b3SSadaf Ebrahimi 
36*287e80b3SSadaf Ebrahimi 	/*
37*287e80b3SSadaf Ebrahimi 	 * The mutex is only to hold the integrity of the file descriptor
38*287e80b3SSadaf Ebrahimi 	 * to prevent opening it more than once, or closing the same
39*287e80b3SSadaf Ebrahimi 	 * file descriptor more than once. It does not protect against
40*287e80b3SSadaf Ebrahimi 	 * one thread closing the file descriptor and another thread
41*287e80b3SSadaf Ebrahimi 	 * writing to it. That is up to the application to prevent
42*287e80b3SSadaf Ebrahimi 	 * from happening.
43*287e80b3SSadaf Ebrahimi 	 */
44*287e80b3SSadaf Ebrahimi 	pthread_mutex_lock(lock);
45*287e80b3SSadaf Ebrahimi 	/* The file could have been opened since we taken the lock */
46*287e80b3SSadaf Ebrahimi 	if (*fd < 0)
47*287e80b3SSadaf Ebrahimi 		*fd = tracefs_instance_file_open(instance, file, O_WRONLY | O_CLOEXEC);
48*287e80b3SSadaf Ebrahimi 
49*287e80b3SSadaf Ebrahimi 	ret = *fd < 0 ? -1 : 0;
50*287e80b3SSadaf Ebrahimi 	pthread_mutex_unlock(lock);
51*287e80b3SSadaf Ebrahimi 
52*287e80b3SSadaf Ebrahimi 	return ret;
53*287e80b3SSadaf Ebrahimi }
54*287e80b3SSadaf Ebrahimi 
marker_close(struct tracefs_instance * instance,bool raw)55*287e80b3SSadaf Ebrahimi static void marker_close(struct tracefs_instance *instance, bool raw)
56*287e80b3SSadaf Ebrahimi {
57*287e80b3SSadaf Ebrahimi 	pthread_mutex_t *lock = trace_get_lock(instance);
58*287e80b3SSadaf Ebrahimi 	int *fd = get_marker_fd(instance, raw);
59*287e80b3SSadaf Ebrahimi 
60*287e80b3SSadaf Ebrahimi 	pthread_mutex_lock(lock);
61*287e80b3SSadaf Ebrahimi 	if (*fd >= 0) {
62*287e80b3SSadaf Ebrahimi 		close(*fd);
63*287e80b3SSadaf Ebrahimi 		*fd = -1;
64*287e80b3SSadaf Ebrahimi 	}
65*287e80b3SSadaf Ebrahimi 	pthread_mutex_unlock(lock);
66*287e80b3SSadaf Ebrahimi }
67*287e80b3SSadaf Ebrahimi 
marker_write(struct tracefs_instance * instance,bool raw,void * data,int len)68*287e80b3SSadaf Ebrahimi static int marker_write(struct tracefs_instance *instance, bool raw, void *data, int len)
69*287e80b3SSadaf Ebrahimi {
70*287e80b3SSadaf Ebrahimi 	int *fd = get_marker_fd(instance, raw);
71*287e80b3SSadaf Ebrahimi 	int ret;
72*287e80b3SSadaf Ebrahimi 
73*287e80b3SSadaf Ebrahimi 	/*
74*287e80b3SSadaf Ebrahimi 	 * The lock does not need to be taken for writes. As a write
75*287e80b3SSadaf Ebrahimi 	 * does not modify the file descriptor. It's up to the application
76*287e80b3SSadaf Ebrahimi 	 * to prevent it from being closed if another thread is doing a write.
77*287e80b3SSadaf Ebrahimi 	 */
78*287e80b3SSadaf Ebrahimi 	if (!data || len < 1)
79*287e80b3SSadaf Ebrahimi 		return -1;
80*287e80b3SSadaf Ebrahimi 	if (*fd < 0) {
81*287e80b3SSadaf Ebrahimi 		ret = marker_init(instance, raw);
82*287e80b3SSadaf Ebrahimi 		if (ret < 0)
83*287e80b3SSadaf Ebrahimi 			return ret;
84*287e80b3SSadaf Ebrahimi 	}
85*287e80b3SSadaf Ebrahimi 
86*287e80b3SSadaf Ebrahimi 	ret = write(*fd, data, len);
87*287e80b3SSadaf Ebrahimi 
88*287e80b3SSadaf Ebrahimi 	return ret == len ? 0 : -1;
89*287e80b3SSadaf Ebrahimi }
90*287e80b3SSadaf Ebrahimi 
91*287e80b3SSadaf Ebrahimi /**
92*287e80b3SSadaf Ebrahimi  * tracefs_print_init - Open trace marker of selected instance for writing
93*287e80b3SSadaf Ebrahimi  * @instance: ftrace instance, can be NULL for top tracing instance.
94*287e80b3SSadaf Ebrahimi  *
95*287e80b3SSadaf Ebrahimi  * Returns 0 if the trace marker is opened successfully, or -1 in case of an error
96*287e80b3SSadaf Ebrahimi  */
tracefs_print_init(struct tracefs_instance * instance)97*287e80b3SSadaf Ebrahimi int tracefs_print_init(struct tracefs_instance *instance)
98*287e80b3SSadaf Ebrahimi {
99*287e80b3SSadaf Ebrahimi 	return marker_init(instance, false);
100*287e80b3SSadaf Ebrahimi }
101*287e80b3SSadaf Ebrahimi 
102*287e80b3SSadaf Ebrahimi /**
103*287e80b3SSadaf Ebrahimi  * tracefs_vprintf - Write a formatted string in the trace marker
104*287e80b3SSadaf Ebrahimi  * @instance: ftrace instance, can be NULL for top tracing instance.
105*287e80b3SSadaf Ebrahimi  * @fmt: pritnf formatted string
106*287e80b3SSadaf Ebrahimi  * @ap: list of arguments for the formatted string
107*287e80b3SSadaf Ebrahimi  *
108*287e80b3SSadaf Ebrahimi  * If the trace marker of the desired instance is not open already,
109*287e80b3SSadaf Ebrahimi  * this API will open it for writing. It will stay open until
110*287e80b3SSadaf Ebrahimi  * tracefs_print_close() is called.
111*287e80b3SSadaf Ebrahimi  *
112*287e80b3SSadaf Ebrahimi  * Returns 0 if the string is written correctly, or -1 in case of an error
113*287e80b3SSadaf Ebrahimi  */
tracefs_vprintf(struct tracefs_instance * instance,const char * fmt,va_list ap)114*287e80b3SSadaf Ebrahimi int tracefs_vprintf(struct tracefs_instance *instance, const char *fmt, va_list ap)
115*287e80b3SSadaf Ebrahimi {
116*287e80b3SSadaf Ebrahimi 	char *str = NULL;
117*287e80b3SSadaf Ebrahimi 	int ret;
118*287e80b3SSadaf Ebrahimi 
119*287e80b3SSadaf Ebrahimi 	ret = vasprintf(&str, fmt, ap);
120*287e80b3SSadaf Ebrahimi 	if (ret < 0)
121*287e80b3SSadaf Ebrahimi 		return ret;
122*287e80b3SSadaf Ebrahimi 	ret = marker_write(instance, false, str, strlen(str));
123*287e80b3SSadaf Ebrahimi 	free(str);
124*287e80b3SSadaf Ebrahimi 
125*287e80b3SSadaf Ebrahimi 	return ret;
126*287e80b3SSadaf Ebrahimi }
127*287e80b3SSadaf Ebrahimi 
128*287e80b3SSadaf Ebrahimi /**
129*287e80b3SSadaf Ebrahimi  * tracefs_printf - Write a formatted string in the trace marker
130*287e80b3SSadaf Ebrahimi  * @instance: ftrace instance, can be NULL for top tracing instance.
131*287e80b3SSadaf Ebrahimi  * @fmt: pritnf formatted string with variable arguments ...
132*287e80b3SSadaf Ebrahimi  *
133*287e80b3SSadaf Ebrahimi  * If the trace marker of the desired instance is not open already,
134*287e80b3SSadaf Ebrahimi  * this API will open it for writing. It will stay open until
135*287e80b3SSadaf Ebrahimi  * tracefs_print_close() is called.
136*287e80b3SSadaf Ebrahimi  *
137*287e80b3SSadaf Ebrahimi  * Returns 0 if the string is written correctly, or -1 in case of an error
138*287e80b3SSadaf Ebrahimi  */
tracefs_printf(struct tracefs_instance * instance,const char * fmt,...)139*287e80b3SSadaf Ebrahimi int tracefs_printf(struct tracefs_instance *instance, const char *fmt, ...)
140*287e80b3SSadaf Ebrahimi {
141*287e80b3SSadaf Ebrahimi 	va_list ap;
142*287e80b3SSadaf Ebrahimi 	int ret;
143*287e80b3SSadaf Ebrahimi 
144*287e80b3SSadaf Ebrahimi 	va_start(ap, fmt);
145*287e80b3SSadaf Ebrahimi 	ret = tracefs_vprintf(instance, fmt, ap);
146*287e80b3SSadaf Ebrahimi 	va_end(ap);
147*287e80b3SSadaf Ebrahimi 
148*287e80b3SSadaf Ebrahimi 	return ret;
149*287e80b3SSadaf Ebrahimi }
150*287e80b3SSadaf Ebrahimi 
151*287e80b3SSadaf Ebrahimi /**
152*287e80b3SSadaf Ebrahimi  * tracefs_print_close - Close trace marker of selected instance
153*287e80b3SSadaf Ebrahimi  * @instance: ftrace instance, can be NULL for top tracing instance.
154*287e80b3SSadaf Ebrahimi  *
155*287e80b3SSadaf Ebrahimi  * Closes the trace marker, previously opened with any of the other tracefs_print APIs
156*287e80b3SSadaf Ebrahimi  */
tracefs_print_close(struct tracefs_instance * instance)157*287e80b3SSadaf Ebrahimi void tracefs_print_close(struct tracefs_instance *instance)
158*287e80b3SSadaf Ebrahimi {
159*287e80b3SSadaf Ebrahimi 	marker_close(instance, false);
160*287e80b3SSadaf Ebrahimi }
161*287e80b3SSadaf Ebrahimi 
162*287e80b3SSadaf Ebrahimi /**
163*287e80b3SSadaf Ebrahimi  * tracefs_binary_init - Open raw trace marker of selected instance for writing
164*287e80b3SSadaf Ebrahimi  * @instance: ftrace instance, can be NULL for top tracing instance.
165*287e80b3SSadaf Ebrahimi  *
166*287e80b3SSadaf Ebrahimi  * Returns 0 if the raw trace marker is opened successfully, or -1 in case of an error
167*287e80b3SSadaf Ebrahimi  */
tracefs_binary_init(struct tracefs_instance * instance)168*287e80b3SSadaf Ebrahimi int tracefs_binary_init(struct tracefs_instance *instance)
169*287e80b3SSadaf Ebrahimi {
170*287e80b3SSadaf Ebrahimi 	return marker_init(instance, true);
171*287e80b3SSadaf Ebrahimi }
172*287e80b3SSadaf Ebrahimi 
173*287e80b3SSadaf Ebrahimi /**
174*287e80b3SSadaf Ebrahimi  * tracefs_binary_write - Write binary data in the raw trace marker
175*287e80b3SSadaf Ebrahimi  * @instance: ftrace instance, can be NULL for top tracing instance.
176*287e80b3SSadaf Ebrahimi  * @data: binary data, that is going to be written in the trace marker
177*287e80b3SSadaf Ebrahimi  * @len: length of the @data
178*287e80b3SSadaf Ebrahimi  *
179*287e80b3SSadaf Ebrahimi  * If the raw trace marker of the desired instance is not open already,
180*287e80b3SSadaf Ebrahimi  * this API will open it for writing. It will stay open until
181*287e80b3SSadaf Ebrahimi  * tracefs_binary_close() is called.
182*287e80b3SSadaf Ebrahimi  *
183*287e80b3SSadaf Ebrahimi  * Returns 0 if the data is written correctly, or -1 in case of an error
184*287e80b3SSadaf Ebrahimi  */
tracefs_binary_write(struct tracefs_instance * instance,void * data,int len)185*287e80b3SSadaf Ebrahimi int tracefs_binary_write(struct tracefs_instance *instance, void *data, int len)
186*287e80b3SSadaf Ebrahimi {
187*287e80b3SSadaf Ebrahimi 	return marker_write(instance, true, data, len);
188*287e80b3SSadaf Ebrahimi }
189*287e80b3SSadaf Ebrahimi 
190*287e80b3SSadaf Ebrahimi /**
191*287e80b3SSadaf Ebrahimi  * tracefs_binary_close - Close raw trace marker of selected instance
192*287e80b3SSadaf Ebrahimi  * @instance: ftrace instance, can be NULL for top tracing instance.
193*287e80b3SSadaf Ebrahimi  *
194*287e80b3SSadaf Ebrahimi  * Closes the raw trace marker, previously opened with any of the other tracefs_binary APIs
195*287e80b3SSadaf Ebrahimi  */
tracefs_binary_close(struct tracefs_instance * instance)196*287e80b3SSadaf Ebrahimi void tracefs_binary_close(struct tracefs_instance *instance)
197*287e80b3SSadaf Ebrahimi {
198*287e80b3SSadaf Ebrahimi 	marker_close(instance, true);
199*287e80b3SSadaf Ebrahimi }
200