Pre-emptive thread scheduling using MMC3 irqs?

Discuss technical or other issues relating to programming the Nintendo Entertainment System, Famicom, or compatible systems. See the NESdev wiki for more information.

Moderator: Moderators

User avatar
GradualGames
Posts: 1106
Joined: Sun Nov 09, 2008 9:18 pm
Location: Pennsylvania, USA
Contact:

Pre-emptive thread scheduling using MMC3 irqs?

Post by GradualGames »

My current game uses coroutines, which are kind of like threads that pre-empt themselves, but how hard would it be to fully implement threads on an NES? I was wondering in the context of this conversation whether such a technique could be used to implement 300hz animation updates and then adjust how often the animation threads are updated on PAL or NTSC.

I don't personally feel motivated to go as far as implementing threading myself, but as I have spotted "threads" mentioned in some games' source code and by some homebrewers, it is making me wonder what the possibilities are. Note I'm well aware one often refers to the "main thread" and the "nmi thread," and I fully understand why that terminology was adopted, since these do behave like threads and you have to deal with concurrency issues, but I'm specifically asking about implementing a general pre-emptive threading scheme.
lidnariq
Posts: 11432
Joined: Sun Apr 13, 2008 11:12 am

Re: Pre-emptive thread scheduling using MMC3 irqs?

Post by lidnariq »

Context switches are expensive; when one uses coroutines there's much less state to save and restore. I'd be worried about the overhead overwhelming the benefits...
User avatar
GradualGames
Posts: 1106
Joined: Sun Nov 09, 2008 9:18 pm
Location: Pennsylvania, USA
Contact:

Re: Pre-emptive thread scheduling using MMC3 irqs?

Post by GradualGames »

lidnariq wrote:Context switches are expensive; when one uses coroutines there's much less state to save and restore. I'd be worried about the overhead overwhelming the benefits...
Good point, one would have to have a full copy of all cpu registers at the time a thread is pre-empted, whereas with coroutines all I need is the state associated with the coroutine (in my game's case, just the current entity's state)...(and the PC)

Given that, I'm guessing any time I've seen the word "thread" used in an NES game's source code, it is probably really a coroutine or similar idea...
User avatar
pubby
Posts: 583
Joined: Thu Mar 31, 2016 11:15 am

Re: Pre-emptive thread scheduling using MMC3 irqs?

Post by pubby »

I don't see why you need threads for this or what benefit they would have.
User avatar
GradualGames
Posts: 1106
Joined: Sun Nov 09, 2008 9:18 pm
Location: Pennsylvania, USA
Contact:

Re: Pre-emptive thread scheduling using MMC3 irqs?

Post by GradualGames »

pubby wrote:I don't see why you need threads for this or what benefit they would have.
I don't; but I am accustomed to discovering that many folks here do things in ways I would have never thought of so I thought I'd ask and see if it's something anybody has done or is doing. Especially since I've seen it in source code and mentioned more than once.

If anything; it'd be a fun demo to write...
User avatar
Dwedit
Posts: 4924
Joined: Fri Nov 19, 2004 7:35 pm
Contact:

Re: Pre-emptive thread scheduling using MMC3 irqs?

Post by Dwedit »

Interrupts (NMI and other IRQs) are already multiple threads that can preempt a main thread.
Here come the fortune cookies! Here come the fortune cookies! They're wearing paper hats!
Oziphantom
Posts: 1565
Joined: Tue Feb 07, 2017 2:03 am

Re: Pre-emptive thread scheduling using MMC3 irqs?

Post by Oziphantom »

http://codebase64.org/doku.php?id=base: ... n_the_6502

However what you are probably thinking of is best left for a C128 or a 65816 based system.
User avatar
Bregalad
Posts: 8056
Joined: Fri Nov 12, 2004 2:49 pm
Location: Divonne-les-bains, France

Re: Pre-emptive thread scheduling using MMC3 irqs?

Post by Bregalad »

At the risk of angering you for not answering the question, there is absolutely zero reason to do such a thing in the first place. The point of pre-emptive multitasking is that if a program crashes, the whole system does not crash. If I'm not mistaking this was introduced rather late in the history of computers - perhaps with Windows 95. So that if an application crashed it was possible to resume computer usage without hard rebooting.

In the case of an embedded video game console where no 3rd party software you don't control is used, there is zero reason to do such a thing. Basically you're trying to solve a problem that doesn't even exist in your case. If one of your thread crashes, you should fix it - you should not hope it'll go unnoticed and hide it with pre-emptive thread switching.

Now if you're asking if this is possible technically, then the answer is probably yes - but does it make any sense in the case of a NES platform, the answer is no.
Oziphantom
Posts: 1565
Joined: Tue Feb 07, 2017 2:03 am

Re: Pre-emptive thread scheduling using MMC3 irqs?

Post by Oziphantom »

Sinclair QDos of 84 had it, but that machine had a lot of issues. It's main announcement to the world was the A1000 of 85. Windows kind of had it since 2.1 but yeah not really. 95 was when it got it for real. MacOS got it in 2001 when they ditched the old OS and used NextStep. There were some DOS hacks that added it as well I think, but none really took off.
User avatar
rainwarrior
Posts: 8732
Joined: Sun Jan 22, 2012 12:03 pm
Location: Canada
Contact:

Re: Pre-emptive thread scheduling using MMC3 irqs?

Post by rainwarrior »

lidnariq wrote:Context switches are expensive; when one uses coroutines there's much less state to save and restore. I'd be worried about the overhead overwhelming the benefits...
Hmm, what would a context switch look like here? Something like:

IRQ, save registers, some IRQ upkeep, move stack pointer, restore registers, return from IRQ.

I wonder if bankable WRAM could help here too, you could let the different threads independently use memory that way.


Though, aside from running a multitasking operating system with independent programs that come and go, I don't really understand the use for threads on a 6502. For multi-core systems threads are a very important way to parallelize. On a single core system, they can't do that.

In a game... the first situation that comes to mind is running AI for a chess game, where you want to let that run independently and keep doing user interface updates for the player in the meanwhile. For that, though, you only need one more thread... a single IRQ is already good enough to do that (if not just the NMI by itself).

Threads were also common for things like background loading, or background decompression, but the NES doesn't really have enough RAM for decompression to ever take that long, and its only loading device is the FDS... but again even for this kind of thing a single IRQ is already enough for this case too?

So I'd be quite curious to know of a good use case for it, as I can't think of anything, myself.


Coroutines on the other hand do make a lot of interesting code structures possible, especially for AI, but we're not talking about interrupts anymore with that. Coroutines aren't to be confused with "threads", at least in my understanding of them; it's a very different paradigm.
User avatar
Dwedit
Posts: 4924
Joined: Fri Nov 19, 2004 7:35 pm
Contact:

Re: Pre-emptive thread scheduling using MMC3 irqs?

Post by Dwedit »

Bregalad wrote:At the risk of angering you for not answering the question, there is absolutely zero reason to do such a thing in the first place. The point of pre-emptive multitasking is that if a program crashes, the whole system does not crash.
Preemptive multithreading also lets a single task do something that takes a long time, while doing something else at the same time. So if you have something like a long pathfinding sequence, you can interrupt it for something else.
Here come the fortune cookies! Here come the fortune cookies! They're wearing paper hats!
ccovell
Posts: 1045
Joined: Sun Mar 19, 2006 9:44 pm
Location: Japan
Contact:

Re: Pre-emptive thread scheduling using MMC3 irqs?

Post by ccovell »

If I recall, Tepples, or some other person here, made a "Sprite" demo where each sprite was its own thread. So a demo has been made.
User avatar
Bregalad
Posts: 8056
Joined: Fri Nov 12, 2004 2:49 pm
Location: Divonne-les-bains, France

Re: Pre-emptive thread scheduling using MMC3 irqs?

Post by Bregalad »

Dwedit wrote: Preemptive multithreading also lets a single task do something that takes a long time, while doing something else at the same time. So if you have something like a long pathfinding sequence, you can interrupt it for something else.
True, I see some applications for that such as chess game AI or whatever, but then it could just be a specialized implementation for one specific CPU-intensive task, rather than general purpose pre-emptive multithreading.
User avatar
GradualGames
Posts: 1106
Joined: Sun Nov 09, 2008 9:18 pm
Location: Pennsylvania, USA
Contact:

Re: Pre-emptive thread scheduling using MMC3 irqs?

Post by GradualGames »

...so what really prompted my thread was that the word "Thread" is present in the old Neotoxin source code. I also have heard at least one fellow homebrewer refer to things as "threads" in his code. I was just curious what these things actually were. Probably not "real" threads.
tepples
Posts: 22708
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: Pre-emptive thread scheduling using MMC3 irqs?

Post by tepples »

rainwarrior wrote:Threads were also common for things like background loading, or background decompression, but the NES doesn't really have enough RAM for decompression to ever take that long, and its only loading device is the FDS
NOR flash prices began to rise half a year ago, as I mentioned earlier. If this trend continues, there'll be more pressure to store the majority of the program on a serial flash (SPI, eMMC, microSD, etc.) and load the rest to a bankable 128Kx8 PRG RAM during the copyright screen, between levels, or even in the background if you can structure the level stream that way.
rainwarrior wrote:... but again even for this kind of thing a single IRQ is already enough for this case too?
True. On 8- and 16-bit consoles, I don't see a use for more than three preemptive contexts in a game: video memory updates and music, game logic, and graphics decompression, software rendering, or heavyweight AI.
ccovell wrote:If I recall, Tepples, or some other person here, made a "Sprite" demo where each sprite was its own thread.
It wasn't me. Neither the old version nor the 2011 version of the Sprite Cans demo uses anything thread-like. In fact, it probably uses the simplest possible NMI handler.
Post Reply