oprofile: preliminary design for queues between cores and device

Each core will put its results in a block. The per-cpu-buffer
contains a pointer to the block and an offset. Since we know
the block size, reserving space in the block and putting data
into it is easy.

The long term plan is that once the block is out of
room, the per-core code pushes it onto the per-core
fullqueue. The timer code, which runs on core 0, pulls
full blocks off the per-core full queue and pushes
empty blocks onto the per-core empty queue. In this way,
the cores run with very little overhead for saving data
(pointer/offset) and the messy work gets done on core "0".

Further, the per-core code can decide, for an even, that it's been
a long time since data has been pushed and push it even when the
block is not full. We may in the end want an interrupt at, say, once
per second to make sure stale data does not just hang around.

I'm open to changes and improvements in this idea; consider it
a straw man. We should try to work out what we want this week
however.

Signed-off-by: Ronald G. Minnich <rminnich@google.com>