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
