-
Notifications
You must be signed in to change notification settings - Fork 0
TSI
Per-processor field controlling atomic thread switching state in JNode's hybrid scheduler.
TSI (Thread Switch Indicator) is a volatile Word field stored as the first field in the VmProcessor class, making it accessible at a fixed zero offset for atomic operations from assembly code. It serves as the central coordination mechanism for JNode's hybrid preemptive/cooperative thread scheduler, enabling safe thread switches while preventing race conditions between interrupt handlers and the scheduler.
The TSI field is manipulated from both Java code (VmProcessor.java) and assembly code (vm-ints.asm, unsafe.asm) using atomic operations to ensure thread safety. When a thread reaches a yieldpoint (compiler-injected checkpoint), the assembly handler examines the TSI to determine whether a thread switch should occur, and uses atomic operations to coordinate the switch state.
| Class / File | Role |
|---|---|
core/src/core/org/jnode/vm/scheduler/VmProcessor.java |
Core TSI implementation with atomic state constants and manipulation methods |
core/src/native/x86/vm-ints.asm |
Yieldpoint handler, TSI state transitions during thread switch |
core/src/native/x86/unsafe.asm |
TSI checking for switch requests |
builder/src/test/org/jnode/jnasm/jnode32.asm |
TSI constant definitions (VmProcessor_TSI_*) |
The TSI is a 4-bit state machine:
Bit 0: TSI_SWITCH_NEEDED (0x0001) - Thread requests a context switch
Bit 1: TSI_SYSTEM_READY (0x0002) - System is ready for switching (idle thread started)
Bit 2: TSI_SWITCH_ACTIVE (0x0004) - Thread switch is in progress
Bit 3: TSI_BLOCK_SWITCH (0x0008) - Thread switching is blocked (GC, etc.)
The combined value TSI_SWITCH_REQUESTED (0x0003 = NEEDED | SYSTEM_READY) indicates a valid state for switching.
TSI is accessed atomically via the getTSIAddress() method which returns the address of the first field:
// From VmProcessor.java:322
getTSIAddress().atomicOr(Word.fromIntSignExtend(TSI_BLOCK_SWITCH));
// From VmProcessor.java:343
getTSIAddress().atomicAnd(Word.fromIntSignExtend(~TSI_BLOCK_SWITCH));The assembly code uses direct memory access via the processor pointer (FS register in 32-bit, R12 in 64-bit):
; From vm-ints.asm:126-127
or THREADSWITCHINDICATOR,VmProcessor_TSI_SWITCH_ACTIVE
and THREADSWITCHINDICATOR,~VmProcessor_TSI_SWITCH_NEEDED-
Normal operation: TSI starts at 0, idle thread calls
systemReadyForThreadSwitch()to set SYSTEM_READY -
Thread yields: Java code sets SWITCH_NEEDED, checks for SWITCH_REQUESTED (0x3), calls
Unsafe.yieldPoint() -
Yieldpoint handling: Assembly sets SWITCH_ACTIVE, clears SWITCH_NEEDED, calls
VmProcessor.reschedule() - Switch completion: Scheduler picks new thread, returns from yieldpoint handler
TSI is tightly coupled with the yieldpoint mechanism. When JIT-compiled code reaches a yieldpoint:
- CPU executes
INT 0x30(yieldpoint trap) - Assembly handler checks TSI bits
- If SWITCH_NEEDED && SYSTEM_READY && !BLOCK_SWITCH: proceed with switch
- The TSI_SWITCH_ACTIVE flag prevents nested switches
-
TSI must be first field: The VmProcessor class explicitly orders TSI as the first field (
"KEEP THIS THE FIRST FIELD!!!") so assembly can compute its address as processor base + 0 - Atomic operations required: Non-atomic TSI modifications can cause race conditions between Java code and interrupt handlers
- BLOCK_SWITCH during GC: The GC acquires the scheduler lock and sets BLOCK_SWITCH to prevent yieldpoints from triggering during critical sections
- SWITCH_ACTIVE prevents recursion: Once set, SWITCH_ACTIVE prevents another thread switch until cleared, avoiding nested reschedule() calls
- Yield validation: The yield() method validates that TSI becomes exactly SWITCH_REQUESTED (0x3); any other value triggers a fatal error
- Core-Thread-Scheduling - Parent concept covering the full scheduler
- Yieldpoint - Compiler-injected checkpoints that trigger TSI checks
- Thread-Scheduling - Overview of thread scheduling
- Interrupt-Handling - Where TSI manipulation occurs during IRQ handling
- VmProcessor - Processor abstraction containing TSI field