I also just did a simple experiment where I tried to determine whether
making the Interrupts API virtual would make a difference. I tried booting
Linux on x86 for a fixed number of Ticks and timed it using the "time"
utility. I did that twice with no changes (once to warm up disk/memory
caches, etc.), and then twice with the three API functions declared as
virtual in the x86 Interrupts object. I did that using the following
command:

time build/X86/gem5.opt configs/example/fs.py
--kernel=x86_64-vmlinux-2.6.22.9 -m 3000000000000 && time
build/X86/gem5.opt configs/example/fs.py --kernel=x86_64-vmlinux-2.6.22.9
-m 3000000000000

The times I got were:

Unmodified:

real    2m9.827s
user    2m3.436s
sys     0m6.398s

real    2m4.269s
user    2m4.017s
sys     0m0.255s

With virtual functions:

real    2m8.724s
user    2m2.376s
sys     0m6.341s

real    2m4.282s
user    2m4.103s
sys     0m0.182s

So it looks to me like creating a base class for Interrupts that's ISA
agnostic and has those three (or two if I nuke one) virtual functions will
have no meaningful performance impact.

I'm a little surprised by that, so please let me know if there's something
wrong with my methodology, and/or if you have a better test for measuring
simulator interrupt related performance in gem5.

Gabe

On Sun, Sep 1, 2019 at 11:46 PM Gabe Black <[email protected]> wrote:

> Hi folks. Changed subject so non-ARM folks don't tune out.
>
> After studying the code some more, it looks like if you consider the
> Interrupts objects to be a stack or queue (they clearly aren't, but it's a
> useful analogy), then the API it has now can be considered roughly.
>
> bool checkInterrupts() => !empty()
> Fault getInterrupt => peek()
> void updateIntrInfo => pop()
>
> I'm not sure everybody implemented them that way, but that seems to be at
> least what x86 and Alpha (the two ISAs that have implementation for
> updateIntrInfo) are doing.
>
> This is a little redundant because the Fault returned by getInterrupt is
> opaque to the CPU, and we can already check if something is on deck with
> checkInterrupts. If we get an interrupt with getInterrupt, the only useful
> thing to do that we couldn't do with checkInterrupts is to invoke it. If
> we're going to invoke it, then there's no reason not to pop it since the
> CPU shouldn't randomly invoke the same interrupt more than once. Note that
> the interrupt controller might chose to return the same Fault object more
> than once if it should happen multiple times. That's different and is not
> something the CPU knows about.
>
> It makes sense to check for interrupts multiple times if, for instance,
> you're deciding whether to stop fetch in O3 and want to know if you still
> should do an interrupt once it's drained. That means we may want to keep
> checkInterrupts and getInterrupt separate.
>
> Alternatively you could merge checkInterrupts and getInterrupt and just
> assume checkInterrupts is false if getinterrupt returns NoFault. That would
> keep the semantics of getInterrupt where we're sort of not committing to
> invoking the exception, but then we might end up new-ing more Fault objects
> that we need to.
>
> As described above however, updateIntrInfo will pretty much always come
> after getInterrupt, and there's no reason I can think of to keep them
> separate. I think it makes sense to build updateIntrInfo into getInterrupt
> if it returns something.
>
> I thought about making the interrupt Fault itself do what updateIntrInfo
> is doing, but there are two problems I can think of from that.
>
> 1. We don't know when the Fault will be invoked, or what has happened
> since it was retrieved.
> 2. There may be non-thread context state to update in the interrupt
> controller itself.
>
> Please let me know if that makes sense to everybody and there isn't
> something important I've overlooked that will make everything break!
>
> Gabe
>
>
> On Sun, Sep 1, 2019 at 2:07 AM Gabe Black <[email protected]> wrote:
>
>> I'm thinking about how to create an ISA independent Interrupts base
>> class, and I notice that this change:
>>
>>
>> https://gem5.googlesource.com/public/gem5/+/8a476d387c84f037d0ccf3cc20dc88870ab45fec
>>
>> Modified the semantics of the API a few years ago. There isn't very much
>> information in the commit message (it fixed a bug. What bug? How did that
>> fix it?), and if that really is how it needs to be and what makes sense, I
>> think the API can be further simplified. Before really baking that in,
>> however, I'd like to understand what was going on to drive that change.
>>
>> Looking at it, one thing that worries me is whether the state that
>> determines checkInterrupts return value can change between when it's called
>> and when getinterrupt is called later. Are those calls always right next to
>> each other logically? Is there ever a time we'd call checkInterrupts and
>> then not call getInterrupt right after if it returned true?
>>
>> Gabe
>>
>
_______________________________________________
gem5-dev mailing list
[email protected]
http://m5sim.org/mailman/listinfo/gem5-dev

Reply via email to