Support two common cases, one being that the resulting message is
small enough to fit into a on-stack buffer.
The seconds being the common 'printf("%s", "Message")' scheme.

Unfortunately, iterating a va_list is destructive,
so it has to be copied before calling vprintf.
This will result in the function never becoming inlined,
thus the helper function was manually "inlined".

Signed-off-by: Norbert Lange <nolang...@gmail.com>
---
 src/common/tracer.h          |  2 +
 src/lib/lttng-ust/tracef.c   | 83 ++++++++++++++++++++++++---------
 src/lib/lttng-ust/tracelog.c | 90 ++++++++++++++++++++++++------------
 3 files changed, 122 insertions(+), 53 deletions(-)

diff --git a/src/common/tracer.h b/src/common/tracer.h
index 2affd6ab..8e18c9b5 100644
--- a/src/common/tracer.h
+++ b/src/common/tracer.h
@@ -26,6 +26,8 @@
 #define LTTNG_RFLAG_EXTENDED           RING_BUFFER_RFLAG_END
 #define LTTNG_RFLAG_END                        (LTTNG_RFLAG_EXTENDED << 1)
 
+#define LTTNG_TRACE_PRINTF_BUFSIZE     512
+
 /*
  * LTTng client type enumeration. Used by the consumer to map the
  * callbacks from its own address space.
diff --git a/src/lib/lttng-ust/tracef.c b/src/lib/lttng-ust/tracef.c
index c05c7811..21af5b9e 100644
--- a/src/lib/lttng-ust/tracef.c
+++ b/src/lib/lttng-ust/tracef.c
@@ -7,6 +7,7 @@
 #define _LGPL_SOURCE
 #include <stdio.h>
 #include "common/macros.h"
+#include "common/tracer.h"
 
 /* The tracepoint definition is public, but the provider definition is hidden. 
*/
 #define LTTNG_UST_TRACEPOINT_PROVIDER_HIDDEN_DEFINITION
@@ -15,30 +16,40 @@
 #define LTTNG_UST_TRACEPOINT_DEFINE
 #include "lttng-ust-tracef-provider.h"
 
-static inline
-void lttng_ust___vtracef(const char *fmt, va_list ap)
-       __attribute__((always_inline, format(printf, 1, 0)));
-static inline
-void lttng_ust___vtracef(const char *fmt, va_list ap)
-{
-       char *msg;
-       const int len = vasprintf(&msg, fmt, ap);
-
-       /* len does not include the final \0 */
-       if (len < 0)
-               goto end;
-       lttng_ust_tracepoint_cb_lttng_ust_tracef___event(msg, len,
-               LTTNG_UST_CALLER_IP());
-       free(msg);
-end:
-       return;
-}
-
 void lttng_ust__vtracef(const char *fmt, va_list ap)
        __attribute__((format(printf, 1, 0)));
 void lttng_ust__vtracef(const char *fmt, va_list ap)
 {
-       lttng_ust___vtracef(fmt, ap);
+       char local_buf[LTTNG_TRACE_PRINTF_BUFSIZE];
+       char *alloc_buff = NULL;
+       char *msg = local_buf;
+       size_t buflen = sizeof(local_buf);
+       int len = -1;
+
+       if (caa_unlikely(fmt[0] == '%' && fmt[1] == 's' && fmt[2] == '\0')) {
+               msg = va_arg(ap, char *);
+               len = strlen(msg);
+       } else
+               do {
+                       va_list ap2;
+
+                       if (caa_unlikely(len >= sizeof(local_buf))) {
+                               buflen = (size_t)(len) + 1U;
+                               alloc_buff = (char *)malloc(buflen);
+                               msg = alloc_buff;
+                               if (!alloc_buff)
+                                       return;
+                       }
+                       va_copy(ap2, ap);
+                       len = vsnprintf(msg, buflen, fmt, ap2);
+                       va_end(ap2);
+               } while (caa_unlikely(len >= sizeof(local_buf) && !alloc_buff));
+
+       /* len does not include the final \0 */
+       if (caa_likely(len >= 0))
+               lttng_ust_tracepoint_cb_lttng_ust_tracef___event(msg, len,
+                       LTTNG_UST_CALLER_IP());
+       free(alloc_buff);
 }
 
 void lttng_ust__tracef(const char *fmt, ...)
@@ -46,8 +57,34 @@ void lttng_ust__tracef(const char *fmt, ...)
 void lttng_ust__tracef(const char *fmt, ...)
 {
        va_list ap;
+       char local_buf[LTTNG_TRACE_PRINTF_BUFSIZE];
+       char *alloc_buff = NULL;
+       char *msg = local_buf;
+       size_t buflen = sizeof(local_buf);
+       int len = -1;
 
-       va_start(ap, fmt);
-       lttng_ust___vtracef(fmt, ap);
-       va_end(ap);
+       if (caa_unlikely(fmt[0] == '%' && fmt[1] == 's' && fmt[2] == '\0')) {
+               va_start(ap, fmt);
+               msg = va_arg(ap, char *);
+               va_end(ap);
+               len = strlen(msg);
+       } else
+               do {
+                       if (caa_unlikely(len >= sizeof(local_buf))) {
+                               buflen = (size_t)(len) + 1U;
+                               alloc_buff = (char *)malloc(buflen);
+                               msg = alloc_buff;
+                               if (!alloc_buff)
+                                       return;
+                       }
+                       va_start(ap, fmt);
+                       len = vsnprintf(msg, buflen, fmt, ap);
+                       va_end(ap);
+               } while (caa_unlikely(len >= sizeof(local_buf) && !alloc_buff));
+
+       /* len does not include the final \0 */
+       if (caa_likely(len >= 0))
+               lttng_ust_tracepoint_cb_lttng_ust_tracef___event(msg, len,
+                       LTTNG_UST_CALLER_IP());
+       free(alloc_buff);
 }
diff --git a/src/lib/lttng-ust/tracelog.c b/src/lib/lttng-ust/tracelog.c
index b28c6c78..6889869c 100644
--- a/src/lib/lttng-ust/tracelog.c
+++ b/src/lib/lttng-ust/tracelog.c
@@ -7,6 +7,7 @@
 #define _LGPL_SOURCE
 #include <stdio.h>
 #include "common/macros.h"
+#include "common/tracer.h"
 
 /* The tracepoint definition is public, but the provider definition is hidden. 
*/
 #define LTTNG_UST_TRACEPOINT_PROVIDER_HIDDEN_DEFINITION
@@ -31,44 +32,73 @@ extern void lttng_ust__tracelog_vprintf(tpcallback_t 
*callback,
        const struct lttng_ust__tracelog_sourceinfo *source, const char *fmt, 
va_list ap)
        __attribute__ ((format(printf, 3, 0)));
 
-static inline
-void lttng_ust___tracelog_vprintf(tpcallback_t *callback,
-       const struct lttng_ust__tracelog_sourceinfo *source,
-       const char *fmt, va_list ap)
-       __attribute__((always_inline, format(printf, 3, 0)));
-
-
-static inline
-void lttng_ust___tracelog_vprintf(tpcallback_t *callback,
-       const struct lttng_ust__tracelog_sourceinfo *source,
-       const char *fmt, va_list ap)
-{
-       char *msg;
-       const int len = vasprintf(&msg, fmt, ap);
-
-       /* len does not include the final \0 */
-       if (len >= 0)
-               goto end;
-       (*callback)(source->file, source->line, source->func, msg, len,
-               LTTNG_UST_CALLER_IP());
-       free(msg);
-end:
-       return;
-}
-
-
 void lttng_ust__tracelog_printf(tpcallback_t *callback,
        const struct lttng_ust__tracelog_sourceinfo *source, const char *fmt, 
...)
 {
        va_list ap;
+       char local_buf[LTTNG_TRACE_PRINTF_BUFSIZE];
+       char *alloc_buff = NULL;
+       char *msg = local_buf;
+       size_t buflen = sizeof(local_buf);
+       int len = -1;
+
+       if (caa_unlikely(fmt[0] == '%' && fmt[1] == 's' && fmt[2] == '\0')) {
+               va_start(ap, fmt);
+               msg = va_arg(ap, char *);
+               va_end(ap);
+               len = strlen(msg);
+       } else
+               do {
+                       if (caa_unlikely(len >= sizeof(local_buf))) {
+                               buflen = (size_t)(len) + 1U;
+                               alloc_buff = (char *)malloc(buflen);
+                               msg = alloc_buff;
+                               if (!alloc_buff)
+                                       return;
+                       }
+                       va_start(ap, fmt);
+                       len = vsnprintf(msg, buflen, fmt, ap);
+                       va_end(ap);
+               } while (caa_unlikely(len >= sizeof(local_buf) && !alloc_buff));
 
-       va_start(ap, fmt);
-       lttng_ust___tracelog_vprintf(callback, source, fmt, ap);
-       va_end(ap);
+       /* len does not include the final \0 */
+       if (caa_likely(len >= 0))
+               (*callback)(source->file, source->line, source->func, msg, len,
+                       LTTNG_UST_CALLER_IP());
+       free(alloc_buff);
 }
 
 void lttng_ust__tracelog_vprintf(tpcallback_t *callback,
        const struct lttng_ust__tracelog_sourceinfo *source, const char *fmt, 
va_list ap)
 {
-       lttng_ust___tracelog_vprintf(callback, source, fmt, ap);
+       char local_buf[LTTNG_TRACE_PRINTF_BUFSIZE];
+       char *alloc_buff = NULL;
+       char *msg = local_buf;
+       size_t buflen = sizeof(local_buf);
+       int len = -1;
+
+       if (caa_unlikely(fmt[0] == '%' && fmt[1] == 's' && fmt[2] == '\0')) {
+               msg = va_arg(ap, char *);
+               len = strlen(msg);
+       } else
+               do {
+                       va_list ap2;
+
+                       if (caa_unlikely(len >= sizeof(local_buf))) {
+                               buflen = (size_t)(len) + 1U;
+                               alloc_buff = (char *)malloc(buflen);
+                               msg = alloc_buff;
+                               if (!alloc_buff)
+                                       return;
+                       }
+                       va_copy(ap2, ap);
+                       len = vsnprintf(msg, buflen, fmt, ap2);
+                       va_end(ap2);
+               } while (caa_unlikely(len >= sizeof(local_buf) && !alloc_buff));
+
+       /* len does not include the final \0 */
+       if (caa_likely(len >= 0))
+               (*callback)(source->file, source->line, source->func, msg, len,
+                       LTTNG_UST_CALLER_IP());
+       free(alloc_buff);
 }
-- 
2.30.2

_______________________________________________
lttng-dev mailing list
lttng-dev@lists.lttng.org
https://lists.lttng.org/cgi-bin/mailman/listinfo/lttng-dev

Reply via email to