The x86 and x64 have interesting hacks in the asm they generate. For example, thread switching is done not by a conditional jump, but by self-modifying code (there's some nops in the main loop, and they get overwritten with a jmp when it's time to preempt). What cool architecture-specific hacks does the ARM version use?
I assume you refer to the co-operative thread switching done by the GHC runtime to achieve co-operative multitasking with Haskell's green threads? I thought this was done by trashing all the registers (pushing live regs to stack) in the compiler back end and then swapping the stack pointer in the runtime. Are you sure about the nop's in the main loop?
I, too, would like to know how this works on ARM and other non-x86 platforms. Do they even have this feature supported on ARM? (ie. compile with ghc --threaded and then add RTS parameters as needed when executing)
GHC uses pre-emptive thread switching, not co-operative thread switching. Threads are forced by the runtime to be switched out -- they have no choice in the matter -- based on rts interrupts.
Typically, threads will be switched when they allocate.
> GHC uses pre-emptive thread switching, not co-operative thread switching.
> Threads may be switched when they allocate.
If threads are scheduled in and out when they allocate memory or are about to issue a possibly blocking system call, it's called co-operative multithreading, isn't it?
If the thread execution was stopped using external means like a timer interrupt, that would be pre-emptive. Some definitions of pre-emptive involve the ability to stop a lower priority thread in favor of a higher priority thread that becomes ready when a syscall is finished.
The best I understand the situation, Haskell's green threads voluntarily (co-operatively) give up their time slice (for another green thread) when allocating memory or doing I/O. Haskell's green threads run on top of several native threads that are pre-emptively scheduled by the operating system.
What you describe is the actual procedure of switching threads. What cheatercheater describes is the mechanics of initiating this switch. You have "checkpoints" in the thread, where the thread finds out if it is to be descheduled and performs a conditional branch to the code that does what you described.
Apparently in GHC code, there is no conditional branch instruction, an unconditional jump is generated on the fly, probably to avoid branch mispredictions.