[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] [xen][tracing] Introduce variable-size trace records
# HG changeset patch # User George Dunlap <gdunlap@xxxxxxxxxxxxx> # Date 1190384767 -3600 # Node ID 7ed576909132407b0c98c8374c38179cda4cfd39 # Parent 517432b9f8b585df5b22ec3682ffba416e718d22 [xen][tracing] Introduce variable-size trace records This patch introduces variable-size trace records. Each record consists of a 32-bit "header", an optional cycle count, and up to seven more 32-bit words. The header is packed with the following information: bits 0-27: The trace event. bits 28-30: The number of 32-bit "extra" words in the records bit 31: Does the trace include a 64-bit tsc? This patch standardizes behavior wrt 32 and 64-bit hypervisors and dom0s. Note that this patch requires a new version of the xentrace daemon running in dom0. The new daemon, instead of pre-pending the cpu to every record as it writes it, inserts a "cpu change" record to the trace file that record the cpu and the number of records it's about to write. Signed-off-by: George Dunlap <gdunlap@xxxxxxxxxxxxx> --- tools/xentrace/xentrace.c | 140 +++++++++++++++---- xen/common/trace.c | 323 +++++++++++++++++++++++++++++++++++---------- xen/include/public/trace.h | 43 ++++- xen/include/xen/trace.h | 85 +++++++++-- 4 files changed, 460 insertions(+), 131 deletions(-) diff -r 517432b9f8b5 -r 7ed576909132 tools/xentrace/xentrace.c --- a/tools/xentrace/xentrace.c Fri Sep 21 16:52:17 2007 +0100 +++ b/tools/xentrace/xentrace.c Fri Sep 21 15:26:07 2007 +0100 @@ -22,6 +22,7 @@ #include <signal.h> #include <inttypes.h> #include <string.h> +#include <assert.h> #include <xen/xen.h> #include <xen/trace.h> @@ -83,24 +84,58 @@ struct timespec millis_to_timespec(unsig } /** - * write_rec - output a trace record in binary format + * write_buffer - write a section of the trace buffer * @cpu - source buffer CPU ID - * @rec - trace record to output + * @start + * @size - size of write (may be less than total window size) + * @total_size - total size of the window (0 on 2nd write of wrapped windows) * @out - output stream * - * Outputs the trace record to a filestream, prepending the CPU ID of the - * source trace buffer. - */ -void write_rec(unsigned int cpu, struct t_rec *rec, FILE *out) + * Outputs the trace buffer to a filestream, prepending the CPU and size + * of the buffer write. + */ +void write_buffer(unsigned int cpu, unsigned char *start, int size, + int total_size, int outfd) { size_t written = 0; - written += fwrite(&cpu, sizeof(cpu), 1, out); - written += fwrite(rec, sizeof(*rec), 1, out); - if ( written != 2 ) - { - PERROR("Failed to write trace record"); - exit(EXIT_FAILURE); - } + + /* Write a CPU_BUF record on each buffer "window" written. Wrapped + * windows may involve two writes, so only write the record on the + * first write. */ + if(total_size) + { + struct { + uint32_t header; + struct { + unsigned cpu; + unsigned byte_count; + } extra; + } rec; + + rec.header = TRC_TRACE_CPU_CHANGE + | ((sizeof(rec.extra)/sizeof(uint32_t)) << TRACE_EXTRA_SHIFT); + rec.extra.cpu = cpu; + rec.extra.byte_count = total_size; + + written = write(outfd, &rec, sizeof(rec)); + + if(written!=sizeof(rec)) { + fprintf(stderr, "Cannot write cpu change (write returned %d)\n", + written); + goto fail; + } + } + + written = write(outfd, start, size); + if ( written != size ) { + fprintf(stderr, "Write failed! (size %d, returned %d)\n", + size, written); + goto fail; + } + return; + fail: + PERROR("Failed to write trace data"); + exit(EXIT_FAILURE); } static void get_tbufs(unsigned long *mfn, unsigned long *size) @@ -233,12 +268,12 @@ struct t_buf **init_bufs_ptrs(void *bufs * mapped in user space. Note that the trace buffer metadata contains machine * pointers - the array returned allows more convenient access to them. */ -struct t_rec **init_rec_ptrs(struct t_buf **meta, unsigned int num) +unsigned char **init_rec_ptrs(struct t_buf **meta, unsigned int num) { int i; - struct t_rec **data; - - data = calloc(num, sizeof(struct t_rec *)); + unsigned char **data; + + data = calloc(num, sizeof(unsigned char *)); if ( data == NULL ) { PERROR("Failed to allocate memory for data pointers\n"); @@ -246,7 +281,7 @@ struct t_rec **init_rec_ptrs(struct t_bu } for ( i = 0; i < num; i++ ) - data[i] = (struct t_rec *)(meta[i] + 1); + data[i] = (unsigned char *)(meta[i] + 1); return data; } @@ -281,19 +316,19 @@ unsigned int get_num_cpus(void) * monitor_tbufs - monitor the contents of tbufs and output to a file * @logfile: the FILE * representing the file to log to */ -int monitor_tbufs(FILE *logfile) +int monitor_tbufs(int outfd) { int i; void *tbufs_mapped; /* pointer to where the tbufs are mapped */ struct t_buf **meta; /* pointers to the trace buffer metadata */ - struct t_rec **data; /* pointers to the trace buffer data areas + unsigned char **data; /* pointers to the trace buffer data areas * where they are mapped into user space. */ unsigned long tbufs_mfn; /* mfn of the tbufs */ unsigned int num; /* number of trace buffers / logical CPUS */ unsigned long size; /* size of a single trace buffer */ - int size_in_recs; + unsigned long data_size; /* get number of logical CPUs (and therefore number of trace buffers) */ num = get_num_cpus(); @@ -302,7 +337,7 @@ int monitor_tbufs(FILE *logfile) get_tbufs(&tbufs_mfn, &size); tbufs_mapped = map_tbufs(tbufs_mfn, num, size); - size_in_recs = (size - sizeof(struct t_buf)) / sizeof(struct t_rec); + data_size = (size - sizeof(struct t_buf)); /* build arrays of convenience ptrs */ meta = init_bufs_ptrs(tbufs_mapped, num, size); @@ -317,13 +352,48 @@ int monitor_tbufs(FILE *logfile) { for ( i = 0; (i < num) && !interrupted; i++ ) { - while ( meta[i]->cons != meta[i]->prod ) + unsigned long start_offset, end_offset, window_size, cons, prod; + rmb(); /* read prod, then read item. */ + + /* Read window information only once. */ + cons = meta[i]->cons; + prod = meta[i]->prod; + + if(cons == prod) + continue; + + assert(prod > cons); + + window_size = prod - cons; + start_offset = cons % data_size; + end_offset = prod % data_size; + + if(end_offset > start_offset) { - rmb(); /* read prod, then read item. */ - write_rec(i, data[i] + meta[i]->cons % size_in_recs, logfile); - mb(); /* read item, then update cons. */ - meta[i]->cons++; + /* If window does not wrap, write in one big chunk */ + write_buffer(i, data[i]+start_offset, + window_size, + window_size, + outfd); } + else + { + /* If wrapped, write in two chunks: + * - first, start to the end of the buffer + * - second, start of buffer to end of window + */ + write_buffer(i, data[i]+start_offset, + data_size - start_offset, + window_size, + outfd); + write_buffer(i, data[i], + end_offset, + 0, + outfd); + } + + mb(); /* read buffer, then update cons. */ + meta[i]->cons = meta[i]->prod; } nanosleep(&opts.poll_sleep, NULL); @@ -333,7 +403,7 @@ int monitor_tbufs(FILE *logfile) free(meta); free(data); /* don't need to munmap - cleanup is automatic */ - fclose(logfile); + close(outfd); return 0; } @@ -503,7 +573,6 @@ int main(int argc, char **argv) int main(int argc, char **argv) { int outfd = 1, ret; - FILE *logfile; struct sigaction act; opts.outfile = 0; @@ -537,8 +606,6 @@ int main(int argc, char **argv) exit(EXIT_FAILURE); } - logfile = fdopen(outfd, "w"); - /* ensure that if we get a signal, we'll do cleanup, then exit */ act.sa_handler = close_handler; act.sa_flags = 0; @@ -547,7 +614,16 @@ int main(int argc, char **argv) sigaction(SIGTERM, &act, NULL); sigaction(SIGINT, &act, NULL); - ret = monitor_tbufs(logfile); + ret = monitor_tbufs(outfd); return ret; } +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ diff -r 517432b9f8b5 -r 7ed576909132 xen/common/trace.c --- a/xen/common/trace.c Fri Sep 21 16:52:17 2007 +0100 +++ b/xen/common/trace.c Fri Sep 21 15:26:07 2007 +0100 @@ -43,19 +43,14 @@ CHECK_t_buf; #define TB_COMPAT 0 #endif -typedef union { - struct t_rec *nat; - struct compat_t_rec *cmp; -} t_rec_u; - /* opt_tbuf_size: trace buffer size (in pages) */ static unsigned int opt_tbuf_size = 0; integer_param("tbuf_size", opt_tbuf_size); /* Pointers to the meta-data objects for all system trace buffers */ static DEFINE_PER_CPU(struct t_buf *, t_bufs); -static DEFINE_PER_CPU(t_rec_u, t_recs); -static int nr_recs; +static DEFINE_PER_CPU(unsigned char *, t_data); +static int data_size; /* High water mark for trace buffers; */ /* Send virtual interrupt when buffer level reaches this point */ @@ -102,8 +97,7 @@ static int alloc_trace_bufs(void) nr_pages = num_online_cpus() * opt_tbuf_size; order = get_order_from_pages(nr_pages); - nr_recs = (opt_tbuf_size * PAGE_SIZE - sizeof(struct t_buf)) / - (!TB_COMPAT ? sizeof(struct t_rec) : sizeof(struct compat_t_rec)); + data_size = (opt_tbuf_size * PAGE_SIZE - sizeof(struct t_buf)); if ( (rawbuf = alloc_xenheap_pages(order)) == NULL ) { @@ -122,10 +116,10 @@ static int alloc_trace_bufs(void) buf = per_cpu(t_bufs, i) = (struct t_buf *) &rawbuf[i*opt_tbuf_size*PAGE_SIZE]; buf->cons = buf->prod = 0; - per_cpu(t_recs, i).nat = (struct t_rec *)(buf + 1); - } - - t_buf_highwater = nr_recs >> 1; /* 50% high water */ + per_cpu(t_data, i) = (unsigned char *)(buf + 1); + } + + t_buf_highwater = data_size >> 1; /* 50% high water */ open_softirq(TRACE_SOFTIRQ, trace_notify_guest); return 0; @@ -235,6 +229,129 @@ int tb_control(xen_sysctl_tbuf_op_t *tbc return rc; } +static inline int calc_rec_size(int cycles, int extra) +{ + int rec_size; + rec_size = 4; + if(cycles) + rec_size += 8; + rec_size += extra; + return rec_size; +} + +static inline int calc_bytes_to_wrap(struct t_buf *buf) +{ + return data_size - (buf->prod % data_size); +} + +static inline unsigned calc_bytes_avail(struct t_buf *buf) +{ + return data_size - (buf->prod - buf->cons); +} + +static inline int __insert_record(struct t_buf *buf, + unsigned long event, + int extra, + int cycles, + int rec_size, + unsigned char * extra_data) +{ + struct t_rec *rec; + unsigned char * dst; + unsigned long extra_word = extra/sizeof(u32); + int local_rec_size = calc_rec_size(cycles, extra); + + BUG_ON(local_rec_size != rec_size); + + /* Double-check once more that we have enough space. + * Don't bugcheck here, in case the userland tool is doing + * something stupid. */ + if(calc_bytes_avail(buf) < rec_size ) + { + printk("%s: %u bytes left (%u - (%u - %u)) recsize %u.\n", + __func__, + data_size - (buf->prod - buf->cons), + data_size, + buf->prod, buf->cons, rec_size); + return 0; + } + rmb(); + + rec = (struct t_rec *)&this_cpu(t_data)[buf->prod % data_size]; + rec->header = event; + rec->header |= extra_word << TRACE_EXTRA_SHIFT; + if(cycles) + { + u64 tsc = (u64)get_cycles(); + + rec->header |= TRC_HD_CYCLE_FLAG; + rec->u.cycles.cycles_lo = tsc & ((((u64)1)<<32)-1); + rec->u.cycles.cycles_hi = tsc >> 32; + dst = rec->u.cycles.data; + } + else + dst = rec->u.nocycles.data; + + if(extra_data && extra) + memcpy(dst, extra_data, extra); + + wmb(); + buf->prod+=rec_size; + + return rec_size; +} + +static inline int insert_wrap_record(struct t_buf *buf, int size) +{ + int space_left = calc_bytes_to_wrap(buf); + unsigned long extra_space = space_left - sizeof(u32); + int cycles=0; + + if(space_left > size) + printk("%s: space_left %d, size %d!\n", + __func__, space_left, size); + + BUG_ON(space_left > size); + + /* We may need to add cycles to take up enough space... */ + if((extra_space/sizeof(u32)) > TRACE_EXTRA_MAX) + { + cycles = 1; + extra_space -= sizeof(u64); + + ASSERT((extra_space/sizeof(u32)) <= TRACE_EXTRA_MAX); + } + + + return __insert_record(buf, + TRC_TRACE_WRAP_BUFFER, + extra_space, + cycles, + space_left, + NULL); +} + +#define LOST_REC_SIZE 8 + +static inline int insert_lost_records(struct t_buf *buf) +{ + struct { + u32 lost_records; + } ed; + + ed.lost_records = this_cpu(lost_records); + + this_cpu(lost_records) = 0; + + return __insert_record(buf, + TRC_LOST_RECORDS, + sizeof(ed), + 0 /* !cycles */, + LOST_REC_SIZE, + (unsigned char *)&ed); +} + + /** * trace - Enters a trace tuple into the trace buffer for the current CPU. * @event: the event type being logged @@ -244,14 +361,32 @@ int tb_control(xen_sysctl_tbuf_op_t *tbc * failure, otherwise 0. Failure occurs only if the trace buffers are not yet * initialised. */ -void trace(u32 event, unsigned long d1, unsigned long d2, - unsigned long d3, unsigned long d4, unsigned long d5) +void __trace_var(u32 event, int cycles, int extra, unsigned char *extra_data) { struct t_buf *buf; - t_rec_u rec; - unsigned long flags; + unsigned long flags, bytes_to_tail, bytes_to_wrap; + int rec_size, total_size; + int extra_word; + int started_below_highwater; + + if(!tb_init_done) + return; + + /* Convert byte count into word count, rounding up */ + extra_word = (extra / sizeof(u32)); + if((extra % sizeof(u32)) != 0) + extra_word++; - BUG_ON(!tb_init_done); +#if !NDEBUG + ASSERT(extra_word<=TRACE_EXTRA_MAX); +#else + /* Not worth crashing a production system over */ + if(extra_word > TRACE_EXTRA_MAX) + extra_word = TRACE_EXTRA_MAX; +#endif + + /* Round size up to nearest word */ + extra = extra_word * sizeof(u32); if ( (tb_event_mask & event) == 0 ) return; @@ -275,73 +410,125 @@ void trace(u32 event, unsigned long d1, local_irq_save(flags); - /* Check if space for two records (we write two if there are lost recs). */ - if ( (buf->prod - buf->cons) >= (nr_recs - 1) ) + started_below_highwater = ( (buf->prod - buf->cons) < t_buf_highwater ); + + /* Calculate the record size */ + rec_size = calc_rec_size(cycles, extra); + + /* How many bytes are available in the buffer? */ + bytes_to_tail = calc_bytes_avail(buf); + + /* How many bytes until the next wrap-around? */ + bytes_to_wrap = calc_bytes_to_wrap(buf); + + /* + * Calculate expected total size to commit this record by + * doing a dry-run. + */ + total_size = 0; + + /* First, check to see if we need to include a lost_record. + * + * calc_bytes_to_wrap() involves integer division, which we'd like to + * avoid if we can. So do the math, check it in debug versions, and + * do a final check always if we happen to write a record. + */ + if(this_cpu(lost_records)) + { + if(LOST_REC_SIZE > bytes_to_wrap) + { + total_size += bytes_to_wrap; + bytes_to_wrap = data_size; + } + else + { + bytes_to_wrap -= LOST_REC_SIZE; + if(bytes_to_wrap == 0) + bytes_to_wrap == data_size; + } + total_size += LOST_REC_SIZE; + } + + ASSERT(bytes_to_wrap == calc_bytes_to_wrap(buf)); + + if(rec_size > bytes_to_wrap) + { + total_size += bytes_to_wrap; + bytes_to_wrap = data_size; + } + else + { + bytes_to_wrap -= rec_size; + } + + total_size += rec_size; + + /* Do we have enough space for everything? */ + if(total_size > bytes_to_tail) { this_cpu(lost_records)++; local_irq_restore(flags); return; } - if ( unlikely(this_cpu(lost_records) != 0) ) - { - if ( !TB_COMPAT ) + /* + * Now, actually write information + */ + bytes_to_wrap = calc_bytes_to_wrap(buf); + + if(this_cpu(lost_records)) + { + if(LOST_REC_SIZE > bytes_to_wrap) { - rec.nat = &this_cpu(t_recs).nat[buf->prod % nr_recs]; - memset(rec.nat, 0, sizeof(*rec.nat)); - rec.nat->cycles = (u64)get_cycles(); - rec.nat->event = TRC_LOST_RECORDS; - rec.nat->data[0] = this_cpu(lost_records); - this_cpu(lost_records) = 0; - } + insert_wrap_record(buf, LOST_REC_SIZE); + bytes_to_wrap = data_size; + } else { - rec.cmp = &this_cpu(t_recs).cmp[buf->prod % nr_recs]; - memset(rec.cmp, 0, sizeof(*rec.cmp)); - rec.cmp->cycles = (u64)get_cycles(); - rec.cmp->event = TRC_LOST_RECORDS; - rec.cmp->data[0] = this_cpu(lost_records); - this_cpu(lost_records) = 0; + bytes_to_wrap -= LOST_REC_SIZE; + /* LOST_REC might line up perfectly with the buffer wrap */ + if(bytes_to_wrap == 0) + bytes_to_wrap = data_size; } - - wmb(); - buf->prod++; - } - - if ( !TB_COMPAT ) - { - rec.nat = &this_cpu(t_recs).nat[buf->prod % nr_recs]; - rec.nat->cycles = (u64)get_cycles(); - rec.nat->event = event; - rec.nat->data[0] = d1; - rec.nat->data[1] = d2; - rec.nat->data[2] = d3; - rec.nat->data[3] = d4; - rec.nat->data[4] = d5; - } - else - { - rec.cmp = &this_cpu(t_recs).cmp[buf->prod % nr_recs]; - rec.cmp->cycles = (u64)get_cycles(); - rec.cmp->event = event; - rec.cmp->data[0] = d1; - rec.cmp->data[1] = d2; - rec.cmp->data[2] = d3; - rec.cmp->data[3] = d4; - rec.cmp->data[4] = d5; - } - - wmb(); - buf->prod++; + insert_lost_records(buf); + } + + ASSERT(bytes_to_wrap == calc_bytes_to_wrap(buf)); + + if(rec_size > bytes_to_wrap) + { + insert_wrap_record(buf, rec_size); + } + + /* Write the original record */ + __insert_record(buf, event, extra, cycles, rec_size, extra_data); local_irq_restore(flags); /* - * Notify trace buffer consumer that we've reached the high water mark. + * Notify trace buffer consumer that we've crossed the high water mark. * */ - if ( (buf->prod - buf->cons) == t_buf_highwater ) + if ( started_below_highwater + && ( (buf->prod - buf->cons) > t_buf_highwater ) ) raise_softirq(TRACE_SOFTIRQ); +} + + +void __trace_fixed(u32 event, unsigned long d1, unsigned long d2, + unsigned long d3, unsigned long d4, unsigned long d5) +{ + u32 extra_data[5]; + + /* In a 64-bit hypervisor, this will truncate to 32 bits. */ + extra_data[0]=d1; + extra_data[1]=d2; + extra_data[2]=d3; + extra_data[3]=d4; + extra_data[4]=d5; + + __trace_var(event, 1/* include cycles */, sizeof(*extra_data)*5, + (unsigned char *)extra_data); } /* diff -r 517432b9f8b5 -r 7ed576909132 xen/include/public/trace.h --- a/xen/include/public/trace.h Fri Sep 21 16:52:17 2007 +0100 +++ b/xen/include/public/trace.h Fri Sep 21 15:26:07 2007 +0100 @@ -26,14 +26,21 @@ #ifndef __XEN_PUBLIC_TRACE_H__ #define __XEN_PUBLIC_TRACE_H__ +#define TRACE_EXTRA_MAX 7 +#define TRACE_EXTRA_SHIFT 28 + /* Trace classes */ #define TRC_CLS_SHIFT 16 -#define TRC_GEN 0x0001f000 /* General trace */ -#define TRC_SCHED 0x0002f000 /* Xen Scheduler trace */ -#define TRC_DOM0OP 0x0004f000 /* Xen DOM0 operation trace */ -#define TRC_HVM 0x0008f000 /* Xen HVM trace */ -#define TRC_MEM 0x0010f000 /* Xen memory trace */ -#define TRC_ALL 0xfffff000 +#define TRC_GEN 0x0001f000 /* General trace */ +#define TRC_SCHED 0x0002f000 /* Xen Scheduler trace */ +#define TRC_DOM0OP 0x0004f000 /* Xen DOM0 operation trace */ +#define TRC_HVM 0x0008f000 /* Xen HVM trace */ +#define TRC_MEM 0x0010f000 /* Xen memory trace */ +#define TRC_ALL 0x0ffff000 +#define TRC_HD_TO_EVENT(x) ((x)&0x0fffffff) +#define TRC_HD_CYCLE_FLAG (1UL<<31) +#define TRC_HD_INCLUDES_CYCLE_COUNT(x) ( !!( (x) & TRC_HD_CYCLE_FLAG ) ) +#define TRC_HD_EXTRA(x) (((x)>>TRACE_EXTRA_SHIFT)&TRACE_EXTRA_MAX) /* Trace subclasses */ #define TRC_SUBCLS_SHIFT 12 @@ -44,6 +51,8 @@ /* Trace events per class */ #define TRC_LOST_RECORDS (TRC_GEN + 1) +#define TRC_TRACE_WRAP_BUFFER (TRC_GEN + 2) +#define TRC_TRACE_CPU_CHANGE (TRC_GEN + 3) #define TRC_SCHED_DOM_ADD (TRC_SCHED + 1) #define TRC_SCHED_DOM_REM (TRC_SCHED + 2) @@ -92,9 +101,19 @@ /* This structure represents a single trace buffer record. */ struct t_rec { - uint64_t cycles; /* cycle counter timestamp */ - uint32_t event; /* event ID */ - unsigned long data[5]; /* event data items */ + uint32_t header; /* 31 : Cycles included? + 30-28: # of extra words + 27- 0: event ID */ + union { + struct { + uint32_t cycles_lo, cycles_hi; /* cycle counter timestamp */ + unsigned char data[28]; /* event data items */ + } cycles; + struct { + unsigned char data[28]; /* event data items */ + } nocycles; + }u; + }; /* @@ -102,9 +121,9 @@ struct t_rec { * field, indexes into an array of struct t_rec's. */ struct t_buf { - uint32_t cons; /* Next item to be consumed by control tools. */ - uint32_t prod; /* Next item to be produced by Xen. */ - /* 'nr_recs' records follow immediately after the meta-data header. */ + uint32_t cons; /* Offset of next item to be consumed by control tools. */ + uint32_t prod; /* Offset of next item to be produced by Xen. */ + /* Records follow immediately after the meta-data header. */ }; #endif /* __XEN_PUBLIC_TRACE_H__ */ diff -r 517432b9f8b5 -r 7ed576909132 xen/include/xen/trace.h --- a/xen/include/xen/trace.h Fri Sep 21 16:52:17 2007 +0100 +++ b/xen/include/xen/trace.h Fri Sep 21 15:26:07 2007 +0100 @@ -33,27 +33,74 @@ void init_trace_bufs(void); /* used to retrieve the physical address of the trace buffers */ int tb_control(struct xen_sysctl_tbuf_op *tbc); -void trace(u32 event, unsigned long d1, unsigned long d2, +void __trace_fixed(u32 event, unsigned long d1, unsigned long d2, unsigned long d3, unsigned long d4, unsigned long d5); +void __trace_var(u32 event, int cycles, int extra, unsigned char *extra_data); -/* Avoids troubling the caller with casting their arguments to a trace macro */ -#define trace_do_casts(e,d1,d2,d3,d4,d5) \ - do { \ - if ( unlikely(tb_init_done) ) \ - trace(e, \ - (unsigned long)(d1), \ - (unsigned long)(d2), \ - (unsigned long)(d3), \ - (unsigned long)(d4), \ - (unsigned long)(d5)); \ +static inline void trace_fixed(u32 event, unsigned long d1, + unsigned long d2, unsigned long d3, + unsigned long d4, unsigned long d5) +{ + if( unlikely(tb_init_done) ) + __trace_fixed(event, d1, d2, d3, d4, d5); +} + +static inline void trace_var(u32 event, int cycles, int extra, + unsigned char *extra_data) +{ + if( unlikely(tb_init_done) ) + __trace_var(event, cycles, extra, extra_data); +} + +/* Convenience macros for calling the trace function. */ +#define TRACE_0D(_e) \ + do { \ + trace_var(_e, 1, 0, NULL); \ + } while ( 0 ) + +#define TRACE_1D(_e,_d) \ + do { \ + u32 _d1; \ + _d1 = _d; \ + trace_var(_e, 1, sizeof(_d1), (unsigned char *)&_d1); \ + } while ( 0 ) + +#define TRACE_2D(_e,d1,d2) \ + do { \ + u32 _d[2]; \ + _d[0]=d1; \ + _d[1]=d2; \ + trace_var(_e, 1, sizeof(*_d)*2, (unsigned char *)_d); \ + } while ( 0 ) + +#define TRACE_3D(_e,d1,d2,d3) \ + do { \ + u32 _d[3]; \ + _d[0]=d1; \ + _d[1]=d2; \ + _d[2]=d3; \ + trace_var(_e, 1, sizeof(*_d)*3, (unsigned char *)_d); \ + } while ( 0 ) + +#define TRACE_4D(_e,d1,d2,d3,d4) \ + do { \ + u32 _d[4]; \ + _d[0]=d1; \ + _d[1]=d2; \ + _d[2]=d3; \ + _d[3]=d4; \ + trace_var(_e, 1, sizeof(*_d)*4, (unsigned char *)_d); \ + } while ( 0 ) + +#define TRACE_5D(_e,d1,d2,d3,d4,d5) \ + do { \ + u32 _d[5]; \ + _d[0]=d1; \ + _d[1]=d2; \ + _d[2]=d3; \ + _d[3]=d4; \ + _d[4]=d5; \ + trace_var(_e, 1, sizeof(*_d)*5, (unsigned char *)_d); \ } while ( 0 ) -/* Convenience macros for calling the trace function. */ -#define TRACE_0D(event) trace_do_casts(event,0, 0, 0, 0, 0 ) -#define TRACE_1D(event,d) trace_do_casts(event,d, 0, 0, 0, 0 ) -#define TRACE_2D(event,d1,d2) trace_do_casts(event,d1,d2,0, 0, 0 ) -#define TRACE_3D(event,d1,d2,d3) trace_do_casts(event,d1,d2,d3,0, 0 ) -#define TRACE_4D(event,d1,d2,d3,d4) trace_do_casts(event,d1,d2,d3,d4,0 ) -#define TRACE_5D(event,d1,d2,d3,d4,d5) trace_do_casts(event,d1,d2,d3,d4,d5) - #endif /* __XEN_TRACE_H__ */ _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |