English Amiga Board


Go Back   English Amiga Board > Coders > Coders. Asm / Hardware

 
 
Thread Tools
Old 18 January 2022, 17:30   #1
deimos
It's coming back!
 
deimos's Avatar
 
Join Date: Jul 2018
Location: comp.sys.amiga
Posts: 762
Interrupts interrupting interrupts

I have keyboard handling code that uses level 2 interrupts (PORTS), and mouse handling code in level 3 interrupts (VERTB). Both of these make changes to a global data structure, my event queue.

If I understand right, the level 3 interrupts can interrupt the level 2 interrupts? Yup?

This could obviously lead to data corruption if my VERTB code modifies the data structure as the PORTS code is part way through modifying it.

My normal, non-interrupt code consumes stuff from this queue, but disables interrupts (custom->intena = INTF_INTEN), quickly grabs what it needs, then reenables interrupts (custom->intena = INTF_SETCLR | INTF_INTEN).

Is this the correct thing to do from inside my interrupt code as well? i.e should by level 2 interrupt code disable interrupts while it's accessing that data structure? Or something else?
deimos is offline  
Old 18 January 2022, 17:53   #2
ross
Defendit numerus
 
ross's Avatar
 
Join Date: Mar 2017
Location: Crossing the Rubicon
Age: 53
Posts: 4,468
Simply raise CPU SR IPL, making the modification of shared parts atomic.

Example:

Code:
IRQ2_code:
move #$2300,SR
...
struct mods
...
move #$2200,SR
You can also avoid resetting SR if the change is done at the end of the routine as RTE resets it automatically.
ross is offline  
Old 18 January 2022, 17:55   #3
a/b
Registered User
 
Join Date: Jun 2016
Location: europe
Posts: 1,039
Quote:
Originally Posted by deimos View Post
If I understand right, the level 3 interrupts can interrupt the level 2 interrupts? Yup?
Yup.
Quote:
Originally Posted by deimos View Post
Is this the correct thing to do from inside my interrupt code as well? i.e should by level 2 interrupt code disable interrupts while it's accessing that data structure? Or something else?
You can do that (via INTENA) or change SR to $2300 to only allow lvl4+ interrupts to interrupt your lvl2 handler.
a/b is offline  
Old 18 January 2022, 18:05   #4
ross
Defendit numerus
 
ross's Avatar
 
Join Date: Mar 2017
Location: Crossing the Rubicon
Age: 53
Posts: 4,468
Quote:
Originally Posted by a/b View Post
You can do that (via INTENA)..
While this usually works, I prefer through SR as it is 'immediate'.
INTENA use Paula that send signals to the CPU lines.
And we know that in fast machines many things could happens after the write to custom registers, the most striking is having to double-write INTREQ at the end of the IRQ in some machines because of IPL delay..

EDIT:
But in fact I don't know .. Paula has input lines for IRQ2,3,6, so I don't know if something strange can happen in case of deactivation through INTENA, probably it is enough

Last edited by ross; 18 January 2022 at 18:23.
ross is offline  
Old 18 January 2022, 18:24   #5
deimos
It's coming back!
 
deimos's Avatar
 
Join Date: Jul 2018
Location: comp.sys.amiga
Posts: 762
Ok, so I need to go and understand what the SR does. Googling tells me that the important bits are an Interrupt Priority Mask, but to be comfortable I need to understand how the mask works.
deimos is offline  
Old 18 January 2022, 18:29   #6
ross
Defendit numerus
 
ross's Avatar
 
Join Date: Mar 2017
Location: Crossing the Rubicon
Age: 53
Posts: 4,468
Quote:
Originally Posted by deimos View Post
Ok, so I need to go and understand what the SR does. Googling tells me that the important bits are an Interrupt Priority Mask, but to be comfortable I need to understand how the mask works.
It's a 3 bit mask that blocks IRQs of level <= than received on processor IPL pins.
Level 0 do not stop any IRQ from happening.
Level 7 cannot be avoided (Paula cannot generate it, you need an external switch).
ross is offline  
Old 18 January 2022, 18:33   #7
deimos
It's coming back!
 
deimos's Avatar
 
Join Date: Jul 2018
Location: comp.sys.amiga
Posts: 762
Quote:
Originally Posted by ross View Post
It's a 3 bit mask that blocks IRQs of level <= than received on processor IPL pins.
Level 0 do not stop any IRQ from happening.
Level 7 cannot be avoided (Paula cannot generate it, you need an external switch).
This approach is only relavent for code within an interrupt?
deimos is offline  
Old 18 January 2022, 18:36   #8
ross
Defendit numerus
 
ross's Avatar
 
Join Date: Mar 2017
Location: Crossing the Rubicon
Age: 53
Posts: 4,468
Quote:
Originally Posted by deimos View Post
This approach is only relavent for code within an interrupt?
No, when in Supervisor state you can set SR I bit as you like, of course also outside the IRQ code.
This can be useful in the case of critical (and very quick to execute) code.
ross is offline  
Old 18 January 2022, 18:37   #9
paraj
Registered User
 
paraj's Avatar
 
Join Date: Feb 2017
Location: Denmark
Posts: 1,098
Check section 6.3.2 of MC68000UM ("currrent processor priority" is what's in the IPL part of SR) for the authoritative source (though ross is obviously close enough )

@ross: Isn't the double write to INTREQ on accelerated machines just done to ensure delay so the same interrupt isn't triggered twice? I think (but haven't tested) that another custom write would also be fine.
paraj is offline  
Old 18 January 2022, 18:41   #10
deimos
It's coming back!
 
deimos's Avatar
 
Join Date: Jul 2018
Location: comp.sys.amiga
Posts: 762
Quote:
Originally Posted by ross View Post
No, when in Supervisor state you can set SR I bit as you like, of course also outside the IRQ code.
This can be useful in the case of critical (and very quick to execute) code.
Ok, but for my purposes, I’ll only be in supervisor within interrupt code, right? I can’t just move myself into supervisor state for everything, can I?
deimos is offline  
Old 18 January 2022, 18:58   #11
ross
Defendit numerus
 
ross's Avatar
 
Join Date: Mar 2017
Location: Crossing the Rubicon
Age: 53
Posts: 4,468
Quote:
Originally Posted by paraj View Post
@ross: Isn't the double write to INTREQ on accelerated machines just done to ensure delay so the same interrupt isn't triggered twice? I think (but haven't tested) that another custom write would also be fine.
It is needed because 68040/060 is too fast (with cache enabled and fast RAM) and the write to INTREQ don't reset physical CPU IPL lines (because Paula need a small delay to do it).
The second write guarantee the two CCK delay that are enough to be sure that IPL lines are proper set.
So in theory anything that generates such a delay would be fine (generic access to a custom register), but there is conflicting information on this, some claim that double writing is mandatory.
ross is offline  
Old 18 January 2022, 19:00   #12
ross
Defendit numerus
 
ross's Avatar
 
Join Date: Mar 2017
Location: Crossing the Rubicon
Age: 53
Posts: 4,468
Quote:
Originally Posted by deimos View Post
I can’t just move myself into supervisor state for everything, can I?
Sure you can, many games/demos do it (disabling SO of course)
ross is offline  
Old 18 January 2022, 19:16   #13
deimos
It's coming back!
 
deimos's Avatar
 
Join Date: Jul 2018
Location: comp.sys.amiga
Posts: 762
Quote:
Originally Posted by ross View Post
Sure you can, many games/demos do it (disabling SO of course)
Isn’t access to supervisor only by exception or interrupt? If so, how is this done? Divide by zero and run the rest of the demo in the exception handler? That can’t be right. It doesn’t feel right.
deimos is offline  
Old 18 January 2022, 19:35   #14
ross
Defendit numerus
 
ross's Avatar
 
Join Date: Mar 2017
Location: Crossing the Rubicon
Age: 53
Posts: 4,468
Quote:
Originally Posted by deimos View Post
Isn’t access to supervisor only by exception or interrupt? If so, how is this done? Divide by zero and run the rest of the demo in the exception handler? That can’t be right. It doesn’t feel right.
You need exec.library Supervisor() or SuperState().
It is the only way to be sure of going into supervisor state on any processor.

Yes, many games/demos do it using a TRAP # instruction (or modifying other exception vectors), but because they assume that the VBR is 0..
ross is offline  
Old 18 January 2022, 19:44   #15
deimos
It's coming back!
 
deimos's Avatar
 
Join Date: Jul 2018
Location: comp.sys.amiga
Posts: 762
Quote:
Originally Posted by ross View Post
You need exec.library Supervisor() or SuperState().
It is the only way to be sure of going into supervisor state on any processor.

Yes, many games/demos do it using a TRAP # instruction (or modifying other exception vectors), but because they assume that the VBR is 0..
Ok then, apart from controlling interrupts more precisely than hitting the hardware registers, are there any other benefits to doing this? For something that will never return to the operating system?
deimos is offline  
Old 18 January 2022, 19:57   #16
ross
Defendit numerus
 
ross's Avatar
 
Join Date: Mar 2017
Location: Crossing the Rubicon
Age: 53
Posts: 4,468
Quote:
Originally Posted by deimos View Post
Ok then, apart from controlling interrupts more precisely than hitting the hardware registers, are there any other benefits to doing this? For something that will never return to the operating system?
Not much.
The first that come to mind: single stack (therefore less memory used theoretically), and direct usage of some privileged instuction, like MOVE SR, on 010+ processors, but this is bad programming).
Basically on the Amiga there is no point in writing code that only works in supervisor state (excluding of course SO code or something that 'replaces' it).

For other machines with 68k architecture it could be very different, for example it may not be possible to write to custom registers if in user state, or others where all the code (ROM or user) is executed exclusively in supervisor state.
ross is offline  
Old 19 January 2022, 00:04   #17
mc6809e
Registered User
 
Join Date: Jan 2012
Location: USA
Posts: 372
Quote:
Originally Posted by ross View Post
Simply raise CPU SR IPL, making the modification of shared parts atomic.

Example:

Code:
IRQ2_code:
move #$2300,SR
...
struct mods
...
move #$2200,SR
You can also avoid resetting SR if the change is done at the end of the routine as RTE resets it automatically.
I didn't want to like this solution, thinking that there was some sort of locking type scheme that might be used instead.

But it's so damn simple that it's awesome.

The idea of letting RTE restore the old mask is good too as it makes the solution more general (with a move #$2700, SR at the beginning of the critical section).
mc6809e is offline  
Old 19 January 2022, 14:03   #18
deimos
It's coming back!
 
deimos's Avatar
 
Join Date: Jul 2018
Location: comp.sys.amiga
Posts: 762
So, I think my mainline code, the bit outside the interrupts that consumes the queue, should be:

Code:
    void ProcessEventQueue() {
        using namespace input;

        for (;;) {
            Event event;

            asm volatile (" move %#0x2300, %%sr \n" ::: "cc", "memory"); // allow only level 4 or higher interrupts

            BOOL isEmpty = eventQueue.isEmpty();
            if (!isEmpty) {
                WORD offset = eventQueue.dequeue();
                event = * ((Event *) ((BYTE *) eventQueue.events + offset));
            }

            asm volatile (" move %#0x2000, %%sr \n" ::: "cc", "memory"); // allow all interrupts

            if (isEmpty)
                break;

            ProcessEvent(event);
        }
    }
The move to SR will also wipe out the condition codes, right? They're in the same place, so I need the "cc" in the clobbers, and the "memory" bit ensures that the optimiser doesn't reorder the assembly parts, what's between them should stay between them.
deimos is offline  
Old 19 January 2022, 14:16   #19
a/b
Registered User
 
Join Date: Jun 2016
Location: europe
Posts: 1,039
Yeah, CCR will be erased by a move. You can use or.w #0x0300,sr and and.w #~0x0300,sr instead, if that's a problem.
a/b is offline  
Old 19 January 2022, 15:41   #20
deimos
It's coming back!
 
deimos's Avatar
 
Join Date: Jul 2018
Location: comp.sys.amiga
Posts: 762
Quote:
Originally Posted by a/b View Post
Yeah, CCR will be erased by a move. You can use or.w #0x0300,sr and and.w #~0x0300,sr instead, if that's a problem.
I should probably do that to make sure bit 15 isn't cleared? I assume that's used by debuggers?
deimos is offline  
 


Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
 
Thread Tools

Similar Threads
Thread Thread Starter Forum Replies Last Post
How to: Proper no-OS interrupts Peregrine Coders. Asm / Hardware 0 12 April 2021 20:52
Interrupts? oRBIT Coders. Asm / Hardware 2 09 April 2021 15:50
BLITHOG and Interrupts Ernst Blofeld Coders. Asm / Hardware 22 26 November 2020 14:45
Damn Interrupts mcgeezer Coders. Asm / Hardware 10 24 March 2019 16:50
CIA interrupts... bloodline Coders. System 6 18 January 2018 10:33

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT +2. The time now is 13:40.

Top

Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2024, vBulletin Solutions Inc.
Page generated in 0.10394 seconds with 13 queries