summaryrefslogtreecommitdiffstats
path: root/runtime/print.c
diff options
context:
space:
mode:
authorhunt <hunt>2006-09-18 16:44:19 +0000
committerhunt <hunt>2006-09-18 16:44:19 +0000
commitddcd4a1d43f7b3bc6edb5c431d4fd29bc72fa471 (patch)
treed67048aa0034d2a83100af4cbcfb5f0fe75acde0 /runtime/print.c
parente92bf44b99785ad743d8657038e7c7b8fd05c5ba (diff)
downloadsystemtap-steved-ddcd4a1d43f7b3bc6edb5c431d4fd29bc72fa471.tar.gz
systemtap-steved-ddcd4a1d43f7b3bc6edb5c431d4fd29bc72fa471.tar.xz
systemtap-steved-ddcd4a1d43f7b3bc6edb5c431d4fd29bc72fa471.zip
2006-09-18 Martin Hunt <hunt@redhat.com>
* print.c (_stp_print_flush): Rewrite so one version works for relayfs or procfs. Use proper per-cpu functions. (_stp_reserve_bytes): New function. Reserve bytes in the output buffer. (_stp_print_binary): New function. Write a variable number of 64-bit values directly into the output buffer. * string.c (_stp_sprintf): Rewrite using new per-cpu buffers. (_stp_vsprintf): Ditto. (_stp_string_cat_cstr): Ditto. (_stp_string_cat_char): Ditto. * runtime.h: Set defaults for MAXTRYLOCK and TRYLOCKDELAY to make runtime tests in bench2 happy.
Diffstat (limited to 'runtime/print.c')
-rw-r--r--runtime/print.c138
1 files changed, 86 insertions, 52 deletions
diff --git a/runtime/print.c b/runtime/print.c
index f01e27e9..65b2d37f 100644
--- a/runtime/print.c
+++ b/runtime/print.c
@@ -33,85 +33,119 @@
* @{
*/
-static int _stp_pbuf_len[NR_CPUS];
+#ifdef STP_RELAYFS
+#define STP_TIMESTAMP_SIZE (sizeof(uint32_t))
+#else
+#define STP_TIMESTAMP_SIZE 0
+#endif /* STP_RELAYFS */
-#ifndef STP_RELAYFS
-#define STP_PRINT_BUF_START 0
-/** Size of buffer, not including terminating NULL */
+#define STP_PRINT_BUF_START (STP_TIMESTAMP_SIZE)
#ifndef STP_PRINT_BUF_LEN
-#define STP_PRINT_BUF_LEN 8191
+#define STP_PRINT_BUF_LEN 8192
#endif
-static char _stp_pbuf[NR_CPUS][STP_PRINT_BUF_LEN + 1];
+typedef struct __stp_pbuf {
+ uint32_t len; /* bytes used in the buffer */
+ char timestamp[STP_TIMESTAMP_SIZE];
+ char buf[STP_PRINT_BUF_LEN];
+} _stp_pbuf;
+
+DEFINE_PER_CPU(_stp_pbuf, Stp_pbuf);
+
+/** Send the print buffer to the transport now.
+ * Output accumulates in the print buffer until it
+ * is filled, or this is called. This MUST be called before returning
+ * from a probe or accumulated output in the print buffer will be lost.
+ *
+ * @note Preemption must be disabled to use this.
+ */
void _stp_print_flush (void)
{
- int cpu = smp_processor_id();
- char *buf = &_stp_pbuf[cpu][0];
- int len = _stp_pbuf_len[cpu];
- int ret;
+ _stp_pbuf *pb = &__get_cpu_var(Stp_pbuf);
- if (len == 0)
+ /* check to see if there is anything in the buffer */
+ if (pb->len == 0)
return;
- ret =_stp_transport_write(buf, len);
- if (unlikely(ret < 0)) {
-#if 0
- if (!atomic_read(&_stp_transport_failures))
- _stp_warn("Transport failure - try using a larger buffer size\n");
-#endif
- atomic_inc (&_stp_transport_failures);
- }
+#ifdef STP_RELAYFS_MERGE
+ /* In merge-mode, stpd expects relayfs data to start with a 4-byte length */
+ /* followed by a 4-byte sequence number. In non-merge mode, anything goes. */
- _stp_pbuf_len[cpu] = 0;
- *buf = 0;
-}
+ *((uint32_t *)pb->timestamp) = _stp_seq_inc();
-#else /* STP_RELAYFS */
+ if (unlikely(_stp_transport_write(pb, pb->len+4+STP_TIMESTAMP_SIZE) < 0))
+ atomic_inc (&_stp_transport_failures);
+#else
+ if (unlikely(_stp_transport_write(pb->buf, pb->len) < 0))
+ atomic_inc (&_stp_transport_failures);
+#endif
-/* size of timestamp, in bytes, including space */
-#define STP_TIMESTAMP_SIZE (sizeof(int))
-#define STP_PRINT_BUF_START (STP_TIMESTAMP_SIZE)
+ pb->len = 0;
+}
-/** Size of buffer, not including terminating NULL */
-#ifndef STP_PRINT_BUF_LEN
-#define STP_PRINT_BUF_LEN (8192 - STP_TIMESTAMP_SIZE - 1)
+#ifndef STP_MAXBINARYARGS
+#define STP_MAXBINARYARGS 127
#endif
-static char _stp_pbuf[NR_CPUS][STP_PRINT_BUF_LEN + STP_PRINT_BUF_START + 1];
-/** Send the print buffer to the transport now.
- * Output accumulates in the print buffer until it
- * is filled, or this is called. This MUST be called before returning
- * from a probe or accumulated output in the print buffer will be lost.
+/** Reserves space in the output buffer for direct I/O.
*/
-void _stp_print_flush (void)
+#if defined STP_RELAYFS && !defined STP_RELAYFS_MERGE
+static void * _stp_reserve_bytes (int numbytes)
+{
+ if (unlikely(numbytes == 0))
+ return NULL;
+ _stp_print_flush();
+ return relay_reserve(_stp_chan, numbytes);
+}
+#else
+static void * _stp_reserve_bytes (int numbytes)
{
- int cpu = smp_processor_id();
- char *buf = &_stp_pbuf[cpu][0];
- char *ptr = buf + STP_PRINT_BUF_START;
- int ret;
+ _stp_pbuf *pb = &__get_cpu_var(Stp_pbuf);
+ int size = STP_PRINT_BUF_LEN - pb->len;
+ void * ret;
- if (_stp_pbuf_len[cpu] == 0)
- return;
+ if (unlikely(numbytes == 0 || numbytes > STP_PRINT_BUF_LEN))
+ return NULL;
- *((int *)buf) = _stp_seq_inc();
- ret = _stp_transport_write(buf, _stp_pbuf_len[cpu] + STP_TIMESTAMP_SIZE + 1);
- if (unlikely(ret < 0)) {
-#if 0
- if (!atomic_read(&_stp_transport_failures))
- _stp_warn("Transport failure - try using a larger buffer size\n");
-#endif
- atomic_inc (&_stp_transport_failures);
- }
+ if (numbytes > size)
+ _stp_print_flush();
- _stp_pbuf_len[cpu] = 0;
- *ptr = 0;
+ ret = pb->buf + pb->len;
+ pb->len += numbytes;
+ return ret;
}
#endif /* STP_RELAYFS */
+/** Write 64-bit args directly into the output stream.
+ * This function takes a variable number of 64-bit arguments
+ * and writes them directly into the output stream. Marginally faster
+ * than doing the same in _stp_vsnprintf().
+ * @sa _stp_vsnprintf()
+ */
+static void _stp_print_binary (int num, ...)
+{
+ va_list vargs;
+ int i;
+ int64_t *args;
+
+ if (unlikely(num > STP_MAXBINARYARGS))
+ num = STP_MAXBINARYARGS;
+
+ args = _stp_reserve_bytes(num * sizeof(int64_t));
+
+ if (args != NULL) {
+ va_start(vargs, num);
+ for (i = 0; i < num; i++) {
+ args[i] = va_arg(vargs, int64_t);
+ }
+ va_end(vargs);
+ }
+}
+
/** Print into the print buffer.
* Like printf, except output goes to the print buffer.
* Safe because overflowing the buffer is not allowed.