Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NT_INTERRUPT issues #369

Open
Bearsoft749 opened this issue Dec 16, 2023 · 14 comments
Open

NT_INTERRUPT issues #369

Bearsoft749 opened this issue Dec 16, 2023 · 14 comments
Labels
close pending waiting for feedback to close this issue invalid This doesn't seem right

Comments

@Bearsoft749
Copy link

Bearsoft749 commented Dec 16, 2023

This code works in GCC 6.5 but does not work in GCC 13.1.
I must use "m68k-amigaos-strip" to get it to be executable in GCC 13.1.

#include <stdio.h>
#include <unistd.h>
#include <proto/exec.h>
#include <exec/execbase.h>
#include <hardware/intbits.h>

struct Interrupt *vbint2;
int counter;
int quit;
int value=0;
int valueEnd=60;

void startInterrupt(void *interruptFuncton)
{
 	vbint2=NULL;
                                                     
    if (vbint2 = (struct Interrupt *)AllocMem(sizeof(struct Interrupt), MEMF_PUBLIC|MEMF_CLEAR))
    {
        vbint2->is_Node.ln_Type = NT_INTERRUPT;
    
        vbint2->is_Node.ln_Pri = -60;	//-60
        vbint2->is_Node.ln_Name = "VertB";
        vbint2->is_Data = (APTR)&counter;
        vbint2->is_Code = (void (*)())interruptFuncton;

        AddIntServer(INTB_VERTB, vbint2); 
	}
	else 
	{
		printf("Can't allocate memory for interrupt node\n");	
	}
}

void endInterrupt()
{
	quit=1;

	 if (vbint2 != NULL)
	 {
        RemIntServer(INTB_VERTB, vbint2);
        FreeMem(vbint2, sizeof(struct Interrupt));
	
//        printf("%ld vertical blanks occurred\nRemoving server\n", counter);
	 }
}

int waitInterrupt()
{
	if (quit==2)
	{
		quit=0;
	}
	
	int tempQuit=quit;
	quit++;
	
	return tempQuit;
}

int interruptLoop()
{
	while(!waitInterrupt())
	{
		value++;
		
		if (value>=valueEnd)
		{
			value=valueEnd;
		}
	}
}

int main()
{
	startInterrupt((void*)interruptLoop);

	while(value<valueEnd)
	{
		sleep(3);
	}

	endInterrupt();

	printf("value %d\n", value);
	
	return 0;
}
@Bearsoft749
Copy link
Author

I forgot...
m68k-amigaos-g++ -w -O3 -mno-align-int -funsafe-math-optimizations -ffast-math -mhard-float -fomit-frame-pointer -m68060 -noixemul -o main main.cpp

@bebbo
Copy link
Owner

bebbo commented Oct 11, 2024

please check again

@Bearsoft749
Copy link
Author

It doesn't work... It works in 6.5.

@Bearsoft749
Copy link
Author

GCC6.5 with -S option

main6.5.txt

GCC13.1.1 with -S option

main13.1.1.txt

@Bearsoft749
Copy link
Author

You can use WinMerge to compare...

@bebbo
Copy link
Owner

bebbo commented Nov 18, 2024

What should the program do? And what is the problem?

Doesn't work is not precise enough.

@Bearsoft749
Copy link
Author

@cdhooper
Copy link

@Bearsoft749 pardon my lack of knowledge, but how does interruptLoop() get a pointer to your program globals?
I was under the impression that an AmigaOS interrupt handler functions are not in the context of the calling task, but rather receive in register a1 a pointer to the is_Data that was initialized when AddIntServer() was called. If that is the case, then I think your interruptLoop() might be out there incrementing random memory, which happens to be relative to the context of the running code which was just interrupted.

@bebbo
Copy link
Owner

bebbo commented Jan 9, 2025

did you read the linked documents?

Each link in the chain will be called in priority order until the
    chain ends or one of the servers returns with the 68000's Z condition
    code clear (indicating non-zero).  Servers on the chain should return
    with the Z flag clear if the interrupt was specifically for that
    server, and no one else.  VERTB servers should always return Z set.
    (Take care with High Level Language servers, the language may not
    have a mechanism for reliably setting the Z flag on exit).
WARNING
    Some compilers or assemblers may optimize code in unexpected ways,
    affecting the conditions codes returned from the function.  Watch
    out for a "MOVEM" instruction (which does not affect the condition
    codes) turning into "MOVE" (which does).

It's not safe to write interrupt routines in C/C++. Guess you need some asm wrapper to set the Z flag properly!

@bebbo
Copy link
Owner

bebbo commented Jan 9, 2025

Oh wait! There is __interrupt. Add it to the interrupt function and it's ok.

@bebbo bebbo added invalid This doesn't seem right close pending waiting for feedback to close this issue labels Jan 9, 2025
@cdhooper
Copy link

Oh wait! There is __interrupt. Add it to the interrupt function and it's ok.

I believe the _interrupt attribute will end the function with an rte instead of rts, which is not desirable for an AmigaOS interrupt handler. Works great, though, if you are implementing your own vector handler.

@bebbo
Copy link
Owner

bebbo commented Jan 10, 2025

Oh wait! There is __interrupt. Add it to the interrupt function and it's ok.

I believe the _interrupt attribute will end the function with an rte instead of rts, which is not desirable for an AmigaOS interrupt handler. Works great, though, if you are implementing your own vector handler.

you are right, that would end in a rte...

@bebbo
Copy link
Owner

bebbo commented Jan 10, 2025

then something like

extern "C" int __interruptLoop()
{
  // what eva?
}

int interruptLoop() {
    asm volatile ("bsr ___interruptLoop");
    return 0;
}

should do it an clear the Z flag

@cdhooper
Copy link

Great idea!
For extra confidence, one could add "attribute((noinline))" to the called __interruptLoop() function.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
close pending waiting for feedback to close this issue invalid This doesn't seem right
Projects
None yet
Development

No branches or pull requests

3 participants