The scheduler uses lightweight user threads with an M-to-N scheduler; that is, there are M Java threads mapped across N native threads. Each native thread has its own queue of Java threads. The native threads are periodically preempted, and control changes to the next ready Java thread in the queue. Work is transferred from busy processors to idle processors via transfer queues.
The files for the scheduler are contained in the Scheduler/ subdirectory.
The implementation is still very preliminary. Wait queues, sleeping, interrupting, etc. are not yet implemented.
The system uses a small piece of assembly code to quickly switch between Java threads. The code is contained in native.cpp/set_current_context. Notice that it currently uses the stack of the Java thread to restore the registers and the program counter! Thus, we have to guarantee that the stack pointer is always valid whenever a thread switch can occur.
The system uses jq_NativeThread-local synchronization-free allocators for fast allocation. Thus, thread switches are disabled while in the allocator. (Note: the current implementation may cause an unfair bias towards allocation-heavy threads. A good solution may be to rewrite the return address in the allocator to call the scheduler after the allocation call has completed.)