diff options
author | hunt <hunt> | 2007-03-14 16:13:33 +0000 |
---|---|---|
committer | hunt <hunt> | 2007-03-14 16:13:33 +0000 |
commit | 8c235ce57600584d3126ad86520b4fb44765c8ec (patch) | |
tree | 4a7ee542bda895a54edbb5863d68bce19d4f135f /runtime | |
parent | fbbb89fffb3533a3b4fb63c15eaeaae6956391eb (diff) | |
download | systemtap-steved-8c235ce57600584d3126ad86520b4fb44765c8ec.tar.gz systemtap-steved-8c235ce57600584d3126ad86520b4fb44765c8ec.tar.xz systemtap-steved-8c235ce57600584d3126ad86520b4fb44765c8ec.zip |
2007-03-14 Martin Hunt <hunt@redhat.com>
* bench2/bench.rb: Updated to work with new transport
and new itest.c.
* bench2/Makefile: Updated for new itest.c
* bench2/itest.c: Rewritten to use multiple threads
and automatically divide the workload among the threads.
* print.c (_stp_print_flush): Move to print_new.c and
print_old.c.
* print_new.c: New file containing _stp_print_flush()
for the new transport.
* print_old.c: Ditto for old transport.
* runtime.h (STP_OLD_TRANSPORT): Define
(errk): Define.
(MAXSTRINGLEN): Define if not already defined.
* io.c (_stp_vlog): Use _stp_ctl_write().
Diffstat (limited to 'runtime')
-rw-r--r-- | runtime/ChangeLog | 20 | ||||
-rw-r--r-- | runtime/bench2/Makefile | 2 | ||||
-rw-r--r-- | runtime/bench2/bench.rb | 70 | ||||
-rw-r--r-- | runtime/bench2/itest.c | 121 | ||||
-rwxr-xr-x | runtime/bench2/run_bench | 29 | ||||
-rwxr-xr-x | runtime/bench2/run_binary_print | 23 | ||||
-rwxr-xr-x | runtime/bench2/test_bench | 25 | ||||
-rw-r--r-- | runtime/io.c | 4 | ||||
-rw-r--r-- | runtime/map.c | 2 | ||||
-rw-r--r-- | runtime/print.c | 57 | ||||
-rw-r--r-- | runtime/print_new.c | 64 | ||||
-rw-r--r-- | runtime/print_old.c | 54 | ||||
-rw-r--r-- | runtime/runtime.h | 17 |
13 files changed, 344 insertions, 144 deletions
diff --git a/runtime/ChangeLog b/runtime/ChangeLog index 56aa0add..f21384be 100644 --- a/runtime/ChangeLog +++ b/runtime/ChangeLog @@ -1,3 +1,23 @@ +2007-03-14 Martin Hunt <hunt@redhat.com> + + * bench2/bench.rb: Updated to work with new transport + and new itest.c. + * bench2/Makefile: Updated for new itest.c + * bench2/itest.c: Rewritten to use multiple threads + and automatically divide the workload among the threads. + + * print.c (_stp_print_flush): Move to print_new.c and + print_old.c. + * print_new.c: New file containing _stp_print_flush() + for the new transport. + * print_old.c: Ditto for old transport. + + * runtime.h (STP_OLD_TRANSPORT): Define + (errk): Define. + (MAXSTRINGLEN): Define if not already defined. + + * io.c (_stp_vlog): Use _stp_ctl_write(). + 2007-03-12 Frank Ch. Eigler <fche@redhat.com> PR 4179. diff --git a/runtime/bench2/Makefile b/runtime/bench2/Makefile index 7fcfcfe4..ffb2991a 100644 --- a/runtime/bench2/Makefile +++ b/runtime/bench2/Makefile @@ -1,7 +1,7 @@ all: itest itest: itest.c - gcc -Wall -O3 -o itest itest.c + gcc -D_GNU_SOURCE -Wall -Wextra -Wstrict-prototypes -Werror -O3 -o itest itest.c -lpthread clean: /bin/rm -f itest diff --git a/runtime/bench2/bench.rb b/runtime/bench2/bench.rb index 05c6ee3e..a04582d2 100644 --- a/runtime/bench2/bench.rb +++ b/runtime/bench2/bench.rb @@ -1,5 +1,5 @@ # Benchmark Class for SystemTap -# Copyright (C) 2006 Red Hat Inc. +# Copyright (C) 2006, 2007 Red Hat Inc. # # This file is part of systemtap, and is free software. You can # redistribute it and/or modify it under the terms of the GNU General @@ -11,9 +11,8 @@ MAXFILE = "/sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq" MINFILE = "/sys/devices/system/cpu/cpu0/cpufreq/scaling_min_freq" # more constants -PROCFS = 1 -RELAYFS= 2 -UTT = 3 +STREAM = 1 +BULK= 2 at_exit {Bench.done} @@ -22,7 +21,8 @@ class Bench @desc = desc @code = nil @file = nil - @trans = 1 + @trans = STREAM + @outfile= "xxx" @failures = [] @results = [] if @@printed_header == 0 @@ -56,7 +56,7 @@ class Bench end end - attr_writer :code, :file, :trans + attr_writer :code, :file, :trans, :outfile attr_reader :failures, :results def run @@ -66,12 +66,10 @@ class Bench @@num_threads.each do |threads| load sum=0 - threads.times {|cpu| fork {exec "./itest #{threads} > #{@dir}/bench#{cpu}"}} - threads.times {Process.waitpid(-1)} # wait for itest(s) to exit + `./itest #{threads} > #{@dir}/bench` `sudo killall -HUP staprun` Process.wait # wait for staprun to exit - threads.times {|x| sum = sum + `cat #{@dir}/bench#{x}`.split[0].to_i - @@ftime} - @results[threads] = sum / (threads * threads) + @results[threads] = `cat #{@dir}/bench`.split[0].to_i - @@ftime[threads] File.open("#{@dir}/xxx.out") do |file| file.each_line do |line| m = line.match(/WARNING: There were ([\d]*)/) @@ -92,10 +90,13 @@ class Bench else printf("R") end - if @trans == RELAYFS - printf("R") - elsif @trans == UTT - printf("U""") + if @trans == BULK + printf("B") + else + printf(" ") + end + if @outfile == "/dev/null" + printf("N") else printf(" ") end @@ -120,7 +121,7 @@ class Bench protected - @@ftime = 0 + @@ftime = [] @@printed_header = 0 @@staprun = nil @@runtime = nil @@ -137,11 +138,9 @@ class Bench end def load - args = "-q -b 8" - if @trans == RELAYFS then args = "-q" end - if @trans == UTT then args = "-lq" end - fork do exec "sudo #{@@staprun} #{args} #{@dir}/bench.ko > #{@dir}/xxx 2> #{@dir}/xxx.out" end - sleep 5 + args = "-q" + fork do exec "sudo #{@@staprun} #{args} -o #{@outfile} #{@dir}/bench.ko &> #{@dir}/xxx.out" end + sleep 10 end def compile @@ -183,6 +182,7 @@ void probe_exit (void)\n{\n unregister_kprobe (&kp); \n}\n" CFLAGS += -I \"#{@@runtime}\" obj-m := bench.o " + if @trans == BULK then makefile << "CFLAGS += -DSTP_BULKMODE" end makefile.close else puts "NO CODE!" @@ -227,14 +227,15 @@ obj-m := bench.o end puts "-"*64 check_cpuspeed - @@ftime = `./itest 1`.to_i - @@ftime = `./itest 1`.to_i - puts "For comparison, function call overhead is #@@ftime nsecs." - puts "Times below are nanoseconds per probe and include kprobe overhead." + @@num_threads.each do |threads| + @@ftime[threads] = `./itest #{threads} 10000000`.to_i + end + puts "Times below are nanoseconds per probe and include kprobe overhead." puts "-"*64 - puts "+--- S = Script, R = Runtime" - puts "|+-- R = Relayfs, U = UTT \tThreads" - printf "|| NAME " + puts "+---- S = Script, R = Runtime" + puts "|+--- B = Bulk" + puts "||+-- N = No output\t\t Threads" + printf "||| NAME " @@num_threads.each {|n| printf("\t %d",n)} printf "\n" end @@ -251,6 +252,8 @@ obj-m := bench.o end end +#### STAPBENCH ###### + class Stapbench < Bench def run @@ -260,12 +263,10 @@ class Stapbench < Bench @@num_threads.each do |threads| load sum=0 - threads.times {|cpu| fork {exec "./itest #{threads} > bench#{cpu}"}} - threads.times {Process.waitpid(-1)} # wait for itest(s) to exit + `./itest #{threads} > bench` `sudo killall -HUP staprun` - Process.wait # wait for stap to exit - threads.times {|x| sum = sum + `cat bench#{x}`.split[0].to_i - @@ftime} - @results[threads] = sum / (threads * threads) + Process.wait # wait for staprun to exit + @results[threads] = `cat bench`.split[0].to_i - @@ftime[threads] File.open("xxx.out") do |file| file.each_line do |line| m = line.match(/WARNING: There were ([\d]*)/) @@ -283,9 +284,8 @@ class Stapbench < Bench def load args = "-vv" - if @trans == RELAYFS then args = "-bMvv" end - if @trans == UTT then args = "-lvv" end - fork do exec "stap #{args} bench.stp > xxx 2> xxx.out" end + if @trans == BULK then args = "-bvv" end + fork do exec "stap #{args} -o #{@outfile} bench.stp &> xxx.out" end sleep 10 end diff --git a/runtime/bench2/itest.c b/runtime/bench2/itest.c index efba623a..0578cf40 100644 --- a/runtime/bench2/itest.c +++ b/runtime/bench2/itest.c @@ -1,3 +1,13 @@ +/* + * itest - timed test program for use with bench2 + * Copyright (C) 2007 Red Hat Inc. + * + * This file is part of systemtap, and is free software. You can + * redistribute it and/or modify it under the terms of the GNU General + * Public License (GPL); either version 2, or (at your option) any + * later version. + */ + #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> @@ -6,11 +16,18 @@ #include <stdlib.h> #include <sys/resource.h> #include <unistd.h> +#include <pthread.h> +#include <semaphore.h> +#include <sched.h> typedef unsigned long long uint64; struct timeval tstart, tstop; +pthread_t tester[256]; +sem_t go; +int ncpus; +int iterations; -void start() +void start(void) { gettimeofday (&tstart, NULL); } @@ -20,7 +37,7 @@ uint64 usecs (struct timeval *tv) return tv->tv_sec * 1000000 + tv->tv_usec; } -uint64 stop() +uint64 stop(void) { gettimeofday (&tstop, NULL); return usecs(&tstop) - usecs(&tstart); @@ -28,31 +45,115 @@ uint64 stop() void usage(char *name) { - printf ("Usage %s [num_threads]\nitest will call sys_getuid() 1000000/num_threads times.\n", name); - exit(1); + printf ("Usage %s [num_threads] [total_iterations]\n", name); + printf("%s will call sys_getuid() total_iterations [default 2,000,000]\n", name); + printf("times divided across num_threads [default 1].\n\n"); + exit(1); +} + + +void *null_thread (void *data) +{ + int cpu; + cpu_set_t cpu_mask; + int thread_num = (int)(long)data; + + cpu = thread_num % ncpus; + CPU_ZERO(&cpu_mask); + CPU_SET(cpu, &cpu_mask); + if( sched_setaffinity( 0, sizeof(cpu_mask), &cpu_mask ) < 0 ) { + perror("sched_setaffinity"); + } + + + // fprintf(stderr, "starting thread %d on cpu %d num=%d\n", thread_num, cpu, iterations); + while (sem_wait(&go) == -1) ; + + return NULL; +} + +void *caller_thread (void *data) +{ + int i, cpu; + cpu_set_t cpu_mask; + int thread_num = (int)(long)data; + + /* Force threads to be distributed across all cpus. */ + /* The scheduler would probably do the right thing without this. */ + cpu = thread_num % ncpus; + CPU_ZERO(&cpu_mask); + CPU_SET(cpu, &cpu_mask); + if( sched_setaffinity( 0, sizeof(cpu_mask), &cpu_mask ) < 0 ) { + perror("sched_setaffinity"); + } + + // fprintf(stderr, "starting thread %d on cpu %d num=%d\n", thread_num, cpu, iterations); + while (sem_wait(&go) == -1) ; + + for (i = 0; i < iterations; i++) + getuid(); + + return NULL; } int main(int argc, char *argv[]) { int i, n = 1; - uint64 nsecs; + uint64 nsecs, null_usecs, caller_usecs; + int total_iterations = 2000000; - if (argc > 2) + if (argc > 3) usage(argv[0]); - if (argc == 2) { + if (argc >= 2) { n = strtol(argv[1], NULL, 10); if (n <= 0) usage(argv[0]); } + if (argc > 2) { + total_iterations = strtol(argv[2], NULL, 10); + if (total_iterations < 100000) + usage(argv[0]); + } + + ncpus = sysconf(_SC_NPROCESSORS_ONLN); + sem_init (&go, 0, 0); + iterations = total_iterations/n; + + for (i = 0; i < n; i++) { + if (pthread_create(&tester[i], NULL, null_thread, (void *)(long)i) < 0) { + perror("Error creating thread"); + return -1; + } + } start(); - for (i = 0; i < 1000000/n; i++) - getuid(); + for (i = 0; i < n; i++) + sem_post (&go); + + for (i = 0; i < n; i++) + pthread_join(tester[i], NULL); + + null_usecs = stop(); - nsecs = stop() * n / 1000; + for (i = 0; i < n; i++) { + if (pthread_create(&tester[i], NULL, caller_thread, (void *)(long)i) < 0) { + perror("Error creating thread"); + return -1; + } + } + + start(); + for (i = 0; i < n; i++) + sem_post (&go); + + for (i = 0; i < n; i++) + pthread_join(tester[i], NULL); + caller_usecs = stop(); + /* returns nanosecs per call */ + nsecs = ((caller_usecs - null_usecs) * 1000LL) / ((uint64)(n * iterations)); printf("%lld\n", nsecs); return 0; } diff --git a/runtime/bench2/run_bench b/runtime/bench2/run_bench index dad8c8ae..b77b9497 100755 --- a/runtime/bench2/run_bench +++ b/runtime/bench2/run_bench @@ -10,31 +10,21 @@ test.print # script test with empty probe test0 = Stapbench.new("empty probe") test0.code = "" +test0.trans=BULK test0.run test0.print -# script test to print 100 chars -test2a = Stapbench.new("printf 100 chars") -test2a.code = "printf(\"123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789\\n\")" -test2a.run -test2a.print - -test2a.trans = RELAYFS -test2a.run -test2a.print - -# runtime test to print 100 chars -test2 = Bench.new("printf 100 chars") -test2.code = "(void)_stp_printf (\"123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789\\n\"); - _stp_print_flush();" +# script test to printf 100 chars +test2 = Stapbench.new("printf 100 chars") +test2.code = "printf(\"123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789\\n\")" +test2.trans=BULK test2.run test2.print - -# runtime test to print 5 integers -test3 = Bench.new("printf 5 integers") -test3.code = "_stp_printf (\"%lld, %lld, %lld, %lld, %lld\\n\", 1LL, 0xffffLL, 0x8000ffffLL, 0xffff000011112222LL, 0x7000000000000000LL); - _stp_print_flush();" +# script test to print 100 chars +test3 = Stapbench.new("print 100 chars") +test3.code = "print(\"123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789\\n\")" +test3.trans=BULK test3.run test3.print @@ -42,4 +32,5 @@ test3.print test4 = Stapbench.new("printf 5 integers") test4.code = "printf(\"%d, %d, %d, %d, %d\\n\", 1, 0xffff, 0x8000ffff, 0xffff000011112222, 0x7000000000000000)" test4.run +test4.trans=BULK test4.print diff --git a/runtime/bench2/run_binary_print b/runtime/bench2/run_binary_print index bbd83180..c42bba98 100755 --- a/runtime/bench2/run_binary_print +++ b/runtime/bench2/run_binary_print @@ -1,31 +1,12 @@ #!/usr/bin/env ruby load './bench.rb' -# script test with empty probe -test0 = Stapbench.new("empty probe") -test0.code = "" -test0.run -test0.print - -# script test to binary print 4 integers -test1 = Stapbench.new("binary printf 4 integers (%8b)") -test1.code = "printf(\"%8b%8b%8b%8b\", 111,22,333,444)" -test1.run -test1.print - -# script test to binary print 4 integers -test2 = Stapbench.new("binary printf 4 integers (%4b)") -test2.code = "printf(\"%4b%4b%4b%4b\", 111,22,333,444)" -test2.run -test2.print - - # script test to binary print 4 integers test3 = Stapbench.new("binary printf 4 integers (%b)") test3.code = "printf(\"%b%b%b%b\", 111,22,333,444)" test3.run test3.print -test3.trans = RELAYFS +test3.trans = BULK test3.run test3.print @@ -34,7 +15,7 @@ test4 = Stapbench.new("_stp_print_binary 4 integers") test4.code = "stp_print_binary(4,111,22,333,444)" test4.run test4.print -test4.trans = RELAYFS +test4.trans = BULK test4.run test4.print diff --git a/runtime/bench2/test_bench b/runtime/bench2/test_bench new file mode 100755 index 00000000..4bf90744 --- /dev/null +++ b/runtime/bench2/test_bench @@ -0,0 +1,25 @@ +#!/usr/bin/env ruby +load './bench.rb' + + +# script test to printf 100 chars +test3 = Stapbench.new("printf 100 chars") +test3.code = "printf(\"123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789\\n\")" +test3.run +test3.print + +test3.trans = BULK +test3.run +test3.print + +test3.trans = STREAM +test3.outfile="/dev/null" +test3.run +test3.print + +test3.trans = BULK +test3.outfile="/dev/null" +test3.run +test3.print + + diff --git a/runtime/io.c b/runtime/io.c index 34c69727..e36381bd 100644 --- a/runtime/io.c +++ b/runtime/io.c @@ -47,7 +47,7 @@ static void _stp_vlog (enum code type, const char *func, int line, const char *f } if (type != DBUG) - _stp_write(STP_OOB_DATA, buf, start + num + 1); + _stp_ctl_write(STP_OOB_DATA, buf, start + num + 1); else { _stp_print(buf); _stp_print_flush(); @@ -93,7 +93,7 @@ void _stp_warn (const char *fmt, ...) * unload the module and exit. The module will not be * unloaded until after the current probe returns. * @note Be careful to not treat this like the Linux exit() - * call. You should probably call return immediately after + * call. You should probably call return immediately after * calling _stp_exit(). */ void _stp_exit (void) diff --git a/runtime/map.c b/runtime/map.c index dfef2f73..5748c797 100644 --- a/runtime/map.c +++ b/runtime/map.c @@ -217,7 +217,7 @@ static int _stp_map_init(MAP m, unsigned max_entries, int type, int key_size, in else _stp_allocated_memory += size * num_online_cpus(); - dbug ("allocated %lx\n", (long)tmp); +// dbug ("allocated %lx\n", (long)tmp); list_add((struct list_head *)tmp, &m->pool); ((struct map_node *)tmp)->map = m; } diff --git a/runtime/print.c b/runtime/print.c index b4c7bc49..c100bbfe 100644 --- a/runtime/print.c +++ b/runtime/print.c @@ -1,6 +1,6 @@ /* -*- linux-c -*- * Print Functions - * Copyright (C) 2005, 2006, 2007 Red Hat Inc. + * Copyright (C) 2007 Red Hat Inc. * * This file is part of systemtap, and is free software. You can * redistribute it and/or modify it under the terms of the GNU General @@ -11,6 +11,7 @@ #ifndef _PRINT_C_ #define _PRINT_C_ + #include "string.h" #include "vsprintf.c" #include "transport/transport.c" @@ -33,18 +34,8 @@ * @{ */ -#ifdef STP_RELAYFS -#define STP_TIMESTAMP_SIZE (sizeof(uint32_t)) -#else -#define STP_TIMESTAMP_SIZE 0 -#endif /* STP_RELAYFS */ - - -#define STP_PRINT_BUF_START (STP_TIMESTAMP_SIZE) - typedef struct __stp_pbuf { uint32_t len; /* bytes used in the buffer */ - char timestamp[STP_TIMESTAMP_SIZE]; char buf[STP_BUFFER_SIZE]; } _stp_pbuf; @@ -81,37 +72,15 @@ void _stp_print_cleanup (void) free_percpu(Stp_lbuf); } -/** 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) -{ - _stp_pbuf *pb = per_cpu_ptr(Stp_pbuf, smp_processor_id()); - - /* check to see if there is anything in the buffer */ - if (likely (pb->len == 0)) - return; - -#ifdef STP_RELAYFS_MERGE - /* In merge-mode, staprun expects relayfs data to start with a 4-byte length */ - /* followed by a 4-byte sequence number. In non-merge mode, anything goes. */ +/* The relayfs API changed between 2.6.15 and 2.6.16. */ +/* Use the appropriate print flush function. */ - *((uint32_t *)pb->timestamp) = _stp_seq_inc(); - - if (unlikely(_stp_transport_write(pb, pb->len+4+STP_TIMESTAMP_SIZE) < 0)) - atomic_inc (&_stp_transport_failures); +#ifdef STP_OLD_TRANSPORT +#include "print_old.c" #else - if (unlikely(_stp_transport_write(pb->buf, pb->len) < 0)) - atomic_inc (&_stp_transport_failures); +#include "print_new.c" #endif - pb->len = 0; -} - #ifndef STP_MAXBINARYARGS #define STP_MAXBINARYARGS 127 #endif @@ -119,16 +88,6 @@ void _stp_print_flush (void) /** Reserves space in the output buffer for direct I/O. */ - -#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) { _stp_pbuf *pb = per_cpu_ptr(Stp_pbuf, smp_processor_id()); @@ -145,7 +104,7 @@ static void * _stp_reserve_bytes (int numbytes) 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 diff --git a/runtime/print_new.c b/runtime/print_new.c new file mode 100644 index 00000000..a1f1274d --- /dev/null +++ b/runtime/print_new.c @@ -0,0 +1,64 @@ +/* -*- linux-c -*- + * Print Flush Function + * Copyright (C) 2007 Red Hat Inc. + * + * This file is part of systemtap, and is free software. You can + * redistribute it and/or modify it under the terms of the GNU General + * Public License (GPL); either version 2, or (at your option) any + * later version. + */ + +/** 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. + */ +spinlock_t _stp_print_lock = SPIN_LOCK_UNLOCKED; + +void _stp_print_flush (void) +{ + _stp_pbuf *pb = per_cpu_ptr(Stp_pbuf, smp_processor_id()); + uint32_t len = pb->len; + + /* check to see if there is anything in the buffer */ + if (likely (len == 0)) + return; + + pb->len = 0; + + if (unlikely(!_stp_utt || _stp_utt->trace_state != Utt_trace_running)) + return; + +#ifdef STP_BULKMODE + { +#ifdef NO_PERCPU_HEADERS + void *buf = relay_reserve(_stp_utt->rchan, len); + if (likely(buf)) + memcpy(buf, pb->buf, len); + else + atomic_inc (&_stp_transport_failures); +#else + struct _stp_trace *t = relay_reserve(_stp_utt->rchan, sizeof(*t) + len); + if (likely(t)) { + t->sequence = _stp_seq_inc(); + t->pdu_len = len; + memcpy((void *) t + sizeof(*t), pb->buf, len); + } else + atomic_inc (&_stp_transport_failures); +#endif + } +#else + { + void *buf; + spin_lock(&_stp_print_lock); + buf = relay_reserve(_stp_utt->rchan, len); + if (likely(buf)) + memcpy(buf, pb->buf, len); + else + atomic_inc (&_stp_transport_failures); + spin_unlock(&_stp_print_lock); + } +#endif /* STP_BULKMODE */ +} diff --git a/runtime/print_old.c b/runtime/print_old.c new file mode 100644 index 00000000..401d1af1 --- /dev/null +++ b/runtime/print_old.c @@ -0,0 +1,54 @@ +/* -*- linux-c -*- + * Print Flush Function + * Copyright (C) 2007 Red Hat Inc. + * + * This file is part of systemtap, and is free software. You can + * redistribute it and/or modify it under the terms of the GNU General + * Public License (GPL); either version 2, or (at your option) any + * later version. + */ + +/** 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) +{ + _stp_pbuf *pb = per_cpu_ptr(Stp_pbuf, smp_processor_id()); + uint32_t len = pb->len; + + /* check to see if there is anything in the buffer */ + if (likely (len == 0)) + return; + + pb->len = 0; + +#ifdef STP_BULKMODE + { +#ifdef NO_PERCPU_HEADERS + void *buf = relay_reserve(_stp_utt->rchan, len); + if (likely(buf)) + memcpy(buf, pb->buf, len); + else + atomic_inc (&_stp_transport_failures); +#else + struct _stp_trace *t = relay_reserve(_stp_utt->rchan, sizeof(*t) + len); + if (likely(t)) { + t->sequence = _stp_seq_inc(); + t->pdu_len = len; + memcpy((void *) t + sizeof(*t), pb->buf, len); + } else + atomic_inc (&_stp_transport_failures); +#endif + } +#else + { + if (unlikely(_stp_ctl_write(STP_REALTIME_DATA, pb->buf, len) <= 0)) + atomic_inc (&_stp_transport_failures); + } +#endif /* STP_BULKMODE */ +} diff --git a/runtime/runtime.h b/runtime/runtime.h index 4d741cf4..6fa168dc 100644 --- a/runtime/runtime.h +++ b/runtime/runtime.h @@ -1,5 +1,5 @@ /* main header file - * Copyright (C) 2005, 2006 Red Hat Inc. + * Copyright (C) 2005-2007 Red Hat Inc. * Copyright (C) 2005, 2006 Intel Corporation. * * This file is part of systemtap, and is free software. You can @@ -10,9 +10,6 @@ #ifndef _RUNTIME_H_ #define _RUNTIME_H_ -/** @file runtime.h - * @brief Main include file for runtime functions. - */ #include <linux/module.h> #include <linux/ctype.h> @@ -33,6 +30,11 @@ #include <linux/compat.h> #include <linux/mm.h> +/* the new transport requires debugfs and a newer relayfs */ +#if !defined (CONFIG_DEBUG_FS) || (LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,15)) +#define STP_OLD_TRANSPORT +#endif + #ifndef for_each_cpu #define for_each_cpu(cpu) for_each_cpu_mask((cpu), cpu_possible_map) #endif @@ -51,18 +53,17 @@ static void _stp_dbug (const char *func, int line, const char *fmt, ...); #define dbug(args...) ; #define kbug(args...) ; #endif /* DEBUG */ +#define errk(args...) {printk("Systemtap Error at %s:%d ",__FUNCTION__, __LINE__); printk(args); } /* atomic globals */ static atomic_t _stp_transport_failures = ATOMIC_INIT (0); -#ifdef STP_RELAYFS static struct { atomic_t ____cacheline_aligned_in_smp seq; } _stp_seq = { ATOMIC_INIT (0) }; #define _stp_seq_inc() (atomic_inc_return(&_stp_seq.seq)) -#endif /* RELAYFS */ /* TEST_MODE is always defined by systemtap */ #ifdef TEST_MODE @@ -72,6 +73,10 @@ static struct #define TRYLOCKDELAY 100 #endif +#ifndef MAXSTRINGLEN +#define MAXSTRINGLEN 128 +#endif + #include "alloc.c" #include "print.c" #include "string.c" |