On Mon, 2008-09-29 at 11:50 -0400, Mathieu Desnoyers wrote:
The only compiler dependant thing in there is the bitfield, which could
be recoded using regular bitops.
I'm not seeing anything particularly worrysome about that.
You can do
stop:
cpu_buffer->stop=1;
smp_wmb();
sched_sync();
start:
smp_wmb();
cpu_buffer->stop=0;
write:
if (unlikely(smp_rmb(), cpu_buffer->stop))) {
return -EBUSY;
or
while (cpu_buffer->stop)
cpu_relax();
}
The read in the fast path is just a read, nothing fancy...
Sure, its probably possible to rework the merge-iterator to use consume,
but that would require it having storage for 1 event, which might be a
bit messy.
How would your locking deal with this? - it really is a requirement to
be able to merge-sort-iterate the output from kernel space..
Not so, these types are buffer package types, not actual event types, I
think thats a useful distinction.
But then you'd need a sub-buffer header, which in itself takes space,
this padding solution seems like a fine middle-ground, it only takes
space when you need it and it free otherwise.
The sub-buffer headers would always take space.
You and Martin have been telling it does ;-)
I'm really not seeing what any of these proposals have on top of what
Steve currently has. We have the ability to encode up to 28 bytes of
payload in a 4 bytes header, which should suffice for most entries,
right?
Still not quite understanding where you get the MSBs from, how do you
tell if two LSBs are from the same period?
Discarting the whole sub-buffer idea, it could be used to validate
whichever time-stamp logic.
Personally I don't particulary like the sub-buffer concept, and I don't
think we need it.
Why have sub-buffers at all?
I don't think you _ever_ want to insert actual video memory in the
trace, what you _might_ possibly want to do, is insert a copy of a
frame, but that you can do with paged buffers like we have, just add an
entry with 3840*1200*4 bytes (one screen in my case), and use sub-writes
to copy everything to page-alinged chunks.
There is nothing techinically prohibiting this in Steve's scheme, except
for Linus telling you you're an idiot for doing it.
The NOP packets you dislike allow us to align regular entries with page
boundaries, which in turn allows this 0-copy stuff. If you use the
sub-write iterator stuff we taked about a while ago, you can leave out
the NOPs.
Having both makes sense (if you want the large packets stuff), use the
regular page aligned 0-copy stuff for regular small packets, and use the
sub-write iterator stuff for your huge packets.
How does it differ from your linked list implementation? Reaslistically,
we want but a single locking scheme for the trace buffer stuff. So
factoring it out doesn't really make sense.
I think that can work just fine on top of Steve's stuff too, it needs a
bit of trimming etc.. but afaict there isn't anything stopping us from
implementing his reserve function as light as you want:
int reserve(buffer, size, flags)
{
preempt_disable()
cpu = smp_processor_id();
cpu_buf = buffer->buffers[cpu];
if (cpu_buf->stop) {
ret = -EBUSY;
goto out;
}
again:
pos = cpu_buf->write_pos;
if (flags & CONTIG) {
new_pos = pos + size;
} else {
if (size > PAGE_SIZE) {
ret = -ENOSPACE;
goto out;
}
if ((pos + size) & PAGE_MASK != pos & PAGE_MASK) {
insert_nops();
}
new_pos = pos + size;
}
if (cmpxchg(&cpu_buf->write_pos, pos, new_pos) != pos)
goto again;
return pos;
out:
preempt_enable();
return ret;
}
If you put the offset&PAGE_MASK in each page-frame you can use that to
easily detect when you need to flip to the next page.
Which I imagine is similar to what you have... although I must admit to
not being sure how to deal with over-write here, I guess your buffer
must be large enough to ensure no nesting depth allows you to
wrap-around while having an even un-commited.
--