[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] xentrace: Allow xentrace to handle >4G of trace data.
# HG changeset patch # User Keir Fraser <keir.fraser@xxxxxxxxxx> # Date 1202723181 0 # Node ID 98e9d5d4b309c82886d7740aa88c29c334a4fff9 # Parent 7d03c0b0750482ec96ec9fcf93c2b585f7740af5 xentrace: Allow xentrace to handle >4G of trace data. It was previously assert'ing when it hit 4G. Also, because the trace buffer is not a power of 2 in size, using modulo arithmetic to address the buffer does not work when the index wraps around 2^32. This patch fixes both issues, and as a side effect, removes all integer division from the hypervisor side of the trace mechanism. Signed-off-by: Michael A Fetterman <Michael.Fetterman@xxxxxxxxxxxx> --- tools/xentrace/xentrace.c | 15 +++++++-- xen/common/trace.c | 71 +++++++++++++++++++++++++++++++++------------ xen/include/public/trace.h | 8 +++++ 3 files changed, 73 insertions(+), 21 deletions(-) diff -r 7d03c0b07504 -r 98e9d5d4b309 tools/xentrace/xentrace.c --- a/tools/xentrace/xentrace.c Mon Feb 11 09:45:36 2008 +0000 +++ b/tools/xentrace/xentrace.c Mon Feb 11 09:46:21 2008 +0000 @@ -362,9 +362,18 @@ int monitor_tbufs(int outfd) if ( cons == prod ) continue; - assert(prod > cons); - - window_size = prod - cons; + assert(cons < 2*data_size); + assert(prod < 2*data_size); + + // NB: if (prod<cons), then (prod-cons)%data_size will not yield + // the correct answer because data_size is not a power of 2. + if ( prod < cons ) + window_size = (prod + 2*data_size) - cons; + else + window_size = prod - cons; + assert(window_size > 0); + assert(window_size <= data_size); + start_offset = cons % data_size; end_offset = prod % data_size; diff -r 7d03c0b07504 -r 98e9d5d4b309 xen/common/trace.c --- a/xen/common/trace.c Mon Feb 11 09:45:36 2008 +0000 +++ b/xen/common/trace.c Mon Feb 11 09:46:21 2008 +0000 @@ -239,14 +239,46 @@ static inline int calc_rec_size(int cycl return rec_size; } +static inline int calc_unconsumed_bytes(struct t_buf *buf) +{ + int x = buf->prod - buf->cons; + if ( x < 0 ) + x += 2*data_size; + + ASSERT(x >= 0); + ASSERT(x <= data_size); + + return x; +} + 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); + int x = data_size - buf->prod; + if ( x <= 0 ) + x += data_size; + + ASSERT(x > 0); + ASSERT(x <= data_size); + + return x; +} + +static inline int calc_bytes_avail(struct t_buf *buf) +{ + return data_size - calc_unconsumed_bytes(buf); +} + +static inline struct t_rec * +next_record(struct t_buf *buf) +{ + int x = buf->prod; + if ( x >= data_size ) + x -= data_size; + + ASSERT(x >= 0); + ASSERT(x < data_size); + + return (struct t_rec *)&this_cpu(t_data)[x]; } static inline int __insert_record(struct t_buf *buf, @@ -260,24 +292,25 @@ static inline int __insert_record(struct unsigned char *dst; unsigned long extra_word = extra/sizeof(u32); int local_rec_size = calc_rec_size(cycles, extra); + uint32_t next; BUG_ON(local_rec_size != rec_size); + BUG_ON(extra & 3); /* 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", + printk("%s: %u bytes left (%u - ((%u - %u) %% %u) recsize %u.\n", __func__, - data_size - (buf->prod - buf->cons), - data_size, - buf->prod, buf->cons, rec_size); + calc_bytes_avail(buf), + data_size, buf->prod, buf->cons, data_size, rec_size); return 0; } rmb(); - rec = (struct t_rec *)&this_cpu(t_data)[buf->prod % data_size]; + rec = next_record(buf); rec->event = event; rec->extra_u32 = extra_word; dst = (unsigned char *)rec->u.nocycles.extra_u32; @@ -293,7 +326,13 @@ static inline int __insert_record(struct memcpy(dst, extra_data, extra); wmb(); - buf->prod += rec_size; + + next = buf->prod + rec_size; + if ( next >= 2*data_size ) + next -= 2*data_size; + ASSERT(next >= 0); + ASSERT(next < 2*data_size); + buf->prod = next; return rec_size; } @@ -395,7 +434,7 @@ void __trace_var(u32 event, int cycles, local_irq_save(flags); - started_below_highwater = ((buf->prod - buf->cons) < t_buf_highwater); + started_below_highwater = (calc_unconsumed_bytes(buf) < t_buf_highwater); /* Calculate the record size */ rec_size = calc_rec_size(cycles, extra); @@ -413,10 +452,6 @@ void __trace_var(u32 event, int cycles, 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) ) { @@ -477,7 +512,7 @@ void __trace_var(u32 event, int cycles, /* Notify trace buffer consumer that we've crossed the high water mark. */ if ( started_below_highwater && - ((buf->prod - buf->cons) >= t_buf_highwater) ) + (calc_unconsumed_bytes(buf) >= t_buf_highwater) ) raise_softirq(TRACE_SOFTIRQ); } diff -r 7d03c0b07504 -r 98e9d5d4b309 xen/include/public/trace.h --- a/xen/include/public/trace.h Mon Feb 11 09:45:36 2008 +0000 +++ b/xen/include/public/trace.h Mon Feb 11 09:46:21 2008 +0000 @@ -141,6 +141,14 @@ struct t_rec { * field, indexes into an array of struct t_rec's. */ struct t_buf { + /* Assume the data buffer size is X. X is generally not a power of 2. + * CONS and PROD are incremented modulo (2*X): + * 0 <= cons < 2*X + * 0 <= prod < 2*X + * This is done because addition modulo X breaks at 2^32 when X is not a + * power of 2: + * (((2^32 - 1) % X) + 1) % X != (2^32) % X + */ 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. */ _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |