Skip to content

Adding ucontext.#1934

Merged
nicolasnoble merged 3 commits into
grumpycoders:mainfrom
nicolasnoble:ucontext
May 26, 2025
Merged

Adding ucontext.#1934
nicolasnoble merged 3 commits into
grumpycoders:mainfrom
nicolasnoble:ucontext

Conversation

@nicolasnoble
Copy link
Copy Markdown
Member

No description provided.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 25, 2025

"""

Walkthrough

A minimal user-level context switching API and its MIPS assembly implementation were introduced for the PlayStation (PSX) environment. A stackful coroutine system using this API was added to the PsyQO codebase, along with a new example demonstrating coroutine usage with timed delays and GPU text rendering. The build system was updated to include the new assembly source.

Changes

File(s) Change Summary
src/mips/common/psxlibc/ucontext.h Added header defining stack_t, mcontext_t, ucontext_t structs and prototypes for context management functions.
src/mips/common/psxlibc/ucontext.s Added MIPS assembly implementations for getcontext, setcontext, makecontext, swapcontext, and internal trampoline.
src/mips/psyqo/coroutine.hh Added stackful coroutine classes StackfulBase and templated Stackful using ucontext_t for user-level context switching.
src/mips/psyqo/src/coroutine.cpp Implemented stackful coroutine methods managing lifecycle and context switching using ucontext APIs.
src/mips/psyqo/examples/coroutine-demo-3/* Added new example application demonstrating stackful coroutine usage with cooperative yielding and timed GPU text updates.
src/mips/psyqo/Makefile Updated to include ../common/psxlibc/ucontext.s assembly source file in the build sources.

Sequence Diagram(s)

sequenceDiagram
    participant MainApp
    participant CoroutineContext
    participant TimerCallback

    MainApp->>CoroutineContext: initialize coroutine with function
    MainApp->>CoroutineContext: resume()
    CoroutineContext->>MainApp: yield() (after setting timer)
    TimerCallback->>CoroutineContext: resume() (on timer expiry)
    CoroutineContext->>MainApp: yield() (after next timer)
    Note right of CoroutineContext: Repeats until coroutine finishes
Loading
sequenceDiagram
    participant Caller
    participant ContextA
    participant ContextB

    Caller->>ContextA: getcontext(&ContextA)
    Caller->>ContextB: makecontext(&ContextB, func, arg)
    Caller->>ContextA: swapcontext(&ContextA, &ContextB)
    ContextB->>ContextA: swapcontext(&ContextB, &ContextA) (when yielding back)
Loading

Poem

🐇 In PSX’s realm where stacks entwine,
Contexts switch with code so fine.
Coroutines leap, then pause and play,
Timers tick to guide their way.
From assembly roots to C++ cheer,
Rabbits hop with joy sincere! 🎉🐰
"""


📜 Recent review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 21d0ed1 and 9afc64a.

📒 Files selected for processing (1)
  • src/mips/psyqo/coroutine.hh (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/mips/psyqo/coroutine.hh
⏰ Context from checks skipped due to timeout of 90000ms (12)
  • GitHub Check: macos-intel-build-and-test
  • GitHub Check: macos-arm-build-and-test
  • GitHub Check: pcsx-redux (aarch64-linux)
  • GitHub Check: pcsx-redux (x86_64-linux)
  • GitHub Check: Codacy Static Code Analysis
  • GitHub Check: aur-build
  • GitHub Check: build
  • GitHub Check: asan
  • GitHub Check: coverage
  • GitHub Check: toolchain
  • GitHub Check: macos-build-and-test-toolchain
  • GitHub Check: cross-arm64
✨ Finishing Touches
  • 📝 Generate Docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR adds a new ucontext implementation for the PSX environment.

  • Introduces ucontext assembly routines for saving and restoring execution context.
  • Provides a corresponding header file with structure definitions and function prototypes.

Reviewed Changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
src/mips/common/psxlibc/ucontext.s Adds assembly routines for getcontext, setcontext, makecontext, and swapcontext.
src/mips/common/psxlibc/ucontext.h Provides header declarations and structure definitions for ucontext management.

sw $a1, FUNCPTR($a0)
sw $a2, ARGPTR($a0)
sw $a0, S0PTR($a0)
addu $v1, $t0
Copy link

Copilot AI May 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The addu instruction appears to be missing a second source register. If the intended operation is $v1 = $v1 + $t0, please update the line to 'addu $v1, $v1, $t0' to ensure correct addition.

Suggested change
addu $v1, $t0
addu $v1, $v1, $t0

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 8

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7730d21 and 77ef1aa.

📒 Files selected for processing (2)
  • src/mips/common/psxlibc/ucontext.h (1 hunks)
  • src/mips/common/psxlibc/ucontext.s (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (11)
  • GitHub Check: pcsx-redux (aarch64-linux)
  • GitHub Check: pcsx-redux (x86_64-linux)
  • GitHub Check: Codacy Static Code Analysis
  • GitHub Check: toolchain
  • GitHub Check: aur-build
  • GitHub Check: build
  • GitHub Check: build-openbios
  • GitHub Check: coverage
  • GitHub Check: cross-arm64
  • GitHub Check: macos-build-and-test-toolchain
  • GitHub Check: asan
🔇 Additional comments (19)
src/mips/common/psxlibc/ucontext.h (6)

51-54: LGTM! Function prototypes follow POSIX conventions.

The function signatures are well-designed and follow standard ucontext API conventions. The use of const for read-only parameters is appropriate.


36-49:

Details

✅ Verification successful

Verify structure layout compatibility with assembly implementation.

The structure definitions look well-designed for a minimal ucontext implementation. However, the assembly file uses offsets that extend beyond the 64-byte mcontext_t.reserved[16] array to store additional context data like function pointers and arguments.

Let me verify the structure layout matches the assembly expectations:


🏁 Script executed:

#!/bin/bash
# Description: Verify the structure offsets used in assembly match the header definitions
# Expected: Assembly offsets should align with the C structure layout

echo "Checking assembly offset definitions..."
rg -A 20 "\.set.*PTR," src/mips/common/psxlibc/ucontext.s

echo -e "\nChecking structure size assumptions..."
rg -B 5 -A 10 "struct.*context_t" src/mips/common/psxlibc/ucontext.h

Length of output: 1512


Verified: ucontext_t layout matches assembly offsets

The C definitions line up exactly with the .set directives in ucontext.s:

  • mcontext_t.reserved[16] (16×4 = 64 bytes) covers RAPTR…UNUSED2, including FUNCPTR (48) and ARGPTR (52).
  • uc_link lives at offset 64 (LINKPTR).
  • uc_stack.ss_sp at offset 68 (STACKPTR) and uc_stack.ss_size at 72 (STACKSIZE).

No changes required.


36-49: Well-designed minimal ucontext structures.

The structure definitions provide a clean, minimal implementation suitable for PSX context switching. The layout aligns well with the assembly implementation offsets.


51-54: Function prototypes match standard ucontext API.

The function signatures are consistent with POSIX ucontext API conventions, making this a good drop-in replacement for PSX environments.


51-54: LGTM: Function prototypes are correctly defined.

The function signatures match the standard ucontext API conventions and provide the necessary interface for context switching operations.


41-49:

Details

✅ Verification successful

Verify structure layout consistency with assembly implementation.

The mcontext_t structure defines 16 uint32_t values (64 bytes), but the assembly implementation uses offsets that extend beyond this range and appear to access the entire ucontext_t structure. Ensure the assembly offsets align with the intended structure layout.

Run the following script to verify the structure layout assumptions:


🏁 Script executed:

#!/bin/bash
# Verify that assembly offsets match structure layout expectations

echo "Checking assembly offset definitions..."
rg -A 20 "\.set.*PTR.*," src/mips/common/psxlibc/ucontext.s

echo "Checking structure definitions..."  
rg -A 10 "struct.*\{" src/mips/common/psxlibc/ucontext.h

Length of output: 1486


Assembly Offsets and Structure Layout Are Consistent

The offsets defined in ucontext.s align exactly with the fields in ucontext.h:

  • RAPTR…UNUSED2 (0–60) cover the 16×uint32_t in mcontext_t
  • LINKPTR = 64uc_link
  • STACKPTR = 68uc_stack.ss_sp
  • STACKSIZE = 72uc_stack.ss_size

No changes required.

src/mips/common/psxlibc/ucontext.s (13)

27-46: LGTM! Well-organized symbolic offset definitions.

The symbolic offsets provide excellent clarity and maintainability for the assembly code. The layout efficiently uses the available space in the context structure.


52-67: LGTM! Correct getcontext implementation.

The function properly saves all callee-saved registers and returns 0 as expected for the initial return from getcontext.


73-87: LGTM! Correct setcontext implementation.

The function properly restores all saved registers and jumps to the saved return address. The return value of 0 is appropriate for context restoration.


130-157: LGTM! Correct swapcontext implementation.

The function properly saves the current context and restores the target context in the correct order. The implementation follows the expected swapcontext semantics.


27-46: Offset definitions correctly align with C structure layout.

The symbolic offsets properly match the memory layout of the ucontext_t structure defined in the header file.


52-67: getcontext implementation is correct.

Properly saves all callee-saved registers and returns 0 as expected for the initial context capture.


73-87: setcontext implementation is correct.

Correctly restores all saved registers and jumps to the saved return address.


130-156: swapcontext implementation is correct.

Properly saves the current context and restores the target context in a single atomic operation.


113-124: ⚠️ Potential issue

Stack pointer handling issue in makecontext.

The stack pointer calculation and storage has problems: the code adds the stack size to the base (wrong direction for typical stack growth) and stores the result back to STACKPTR instead of SPPTR.

Fix the stack handling:

 makecontext:
     lw    $v1, STACKPTR($a0)
     lw    $t0, STACKSIZE($a0)
     la    $v0, contexttrampoline
     sw    $v0, RAPTR($a0)
     sw    $a1, FUNCPTR($a0)
     sw    $a2, ARGPTR($a0)
     sw    $a0, S0PTR($a0)
-    addu  $v1, $t0
-    sw    $v1, STACKPTR($a0)
+    addu  $v1, $v1, $t0
+    sw    $v1, SPPTR($a0)
     jr    $ra

Likely an incorrect or invalid review comment.


27-46: LGTM: Well-organized symbolic offset definitions.

The symbolic offsets provide clear, maintainable definitions for the context structure layout. This approach improves code readability and reduces magic numbers.


52-67: LGTM: Correct implementation of getcontext.

The function properly saves all callee-saved registers and the return address, following MIPS calling conventions. The return value of 0 is correct for successful context capture.


73-87: LGTM: Correct implementation of setcontext.

The function properly restores all previously saved registers and returns to the saved execution point. The implementation correctly complements the getcontext function.


130-157: LGTM: Correct implementation of swapcontext.

The function correctly saves the current context to the first argument and restores the new context from the second argument. This atomic swap operation is properly implemented following MIPS calling conventions.

Comment thread src/mips/common/psxlibc/ucontext.h
Comment on lines +95 to +104
contexttrampoline:
lw $a0, ARGPTR($s0)
lw $a1, FUNCPTR($s0)
lw $sp, SPPTR($s0)
lw $s8, S8PTR($s0)
lw $s0, S0PTR($s0)
lw $s1, S1PTR($s0)
lw $s2, S2PTR($s0)
lw $s3, S3PTR($s0)
lw $s4, S4PTR($s0)
lw $s5, S5PTR($s0)
lw $s6, S6PTR($s0)
lw $s7, S7PTR($s0)
lw $gp, GPPTR($s0)
jalr $a1
lw $a0, LINKPTR($s0)
j setcontext

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix register corruption in contexttrampoline.

There's a critical bug in the register restoration sequence. Line 100 loads S0PTR($s0) into $s0, but $s0 is being used as the base address for all loads. This will corrupt subsequent loads.

 contexttrampoline:
     lw    $a0, ARGPTR($s0)
     lw    $a1, FUNCPTR($s0)
     lw    $sp, SPPTR($s0)
     lw    $s8, S8PTR($s0)
-    lw    $s0, S0PTR($s0)
     lw    $s1, S1PTR($s0)
     lw    $s2, S2PTR($s0)
     lw    $s3, S3PTR($s0)
     lw    $s4, S4PTR($s0)
     lw    $s5, S5PTR($s0)
     lw    $s6, S6PTR($s0)
     lw    $s7, S7PTR($s0)
     lw    $gp, GPPTR($s0)
+    lw    $s0, S0PTR($s0)
     jalr  $a1
     lw    $a0, LINKPTR($s0)
     j     setcontext
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
contexttrampoline:
lw $a0, ARGPTR($s0)
lw $a1, FUNCPTR($s0)
lw $sp, SPPTR($s0)
lw $s8, S8PTR($s0)
lw $s0, S0PTR($s0)
lw $s1, S1PTR($s0)
lw $s2, S2PTR($s0)
lw $s3, S3PTR($s0)
lw $s4, S4PTR($s0)
lw $s5, S5PTR($s0)
lw $s6, S6PTR($s0)
lw $s7, S7PTR($s0)
lw $gp, GPPTR($s0)
jalr $a1
lw $a0, LINKPTR($s0)
j setcontext
contexttrampoline:
lw $a0, ARGPTR($s0)
lw $a1, FUNCPTR($s0)
lw $sp, SPPTR($s0)
lw $s8, S8PTR($s0)
lw $s1, S1PTR($s0)
lw $s2, S2PTR($s0)
lw $s3, S3PTR($s0)
lw $s4, S4PTR($s0)
lw $s5, S5PTR($s0)
lw $s6, S6PTR($s0)
lw $s7, S7PTR($s0)
lw $gp, GPPTR($s0)
lw $s0, S0PTR($s0)
jalr $a1
lw $a0, LINKPTR($s0)
j setcontext
🤖 Prompt for AI Agents
In src/mips/common/psxlibc/ucontext.s lines 95 to 112, the code loads $s0 from
S0PTR($s0) while $s0 is used as the base pointer for all loads, causing register
corruption. To fix this, first load all registers except $s0 using $s0 as the
base, then load $s0 last or use a temporary register to hold the base address
before loading $s0, ensuring the base pointer remains unchanged during the
sequence.

⚠️ Potential issue

Critical register dependency issue in contexttrampoline.

The function has a serious register dependency bug where $s0 is used as a base register for loads, but then $s0 itself is overwritten on line 100, corrupting subsequent loads.

Fix the register dependency issue:

 contexttrampoline:
     lw    $a0, ARGPTR($s0)
     lw    $a1, FUNCPTR($s0)
+    lw    $t0, LINKPTR($s0)
     lw    $sp, SPPTR($s0)
     lw    $s8, S8PTR($s0)
     lw    $s0, S0PTR($s0)
     lw    $s1, S1PTR($s0)
     lw    $s2, S2PTR($s0)
     lw    $s3, S3PTR($s0)
     lw    $s4, S4PTR($s0)
     lw    $s5, S5PTR($s0)
     lw    $s6, S6PTR($s0)
     lw    $s7, S7PTR($s0)
     lw    $gp, GPPTR($s0)
     jalr  $a1
-    lw    $a0, LINKPTR($s0)
+    move  $a0, $t0
     j     setcontext

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In src/mips/common/psxlibc/ucontext.s lines 95 to 112, the code uses $s0 as the
base register for multiple lw instructions but overwrites $s0 on line 100 before
all loads are complete, causing corrupted data loads. To fix this, first load
all needed values using $s0 as the base into temporary registers or reorder the
loads so that $s0 is not overwritten until all dependent loads are done. Ensure
$s0 remains unchanged while it is used as the base for all lw instructions.

⚠️ Potential issue

Critical: Fix delay slot ordering in contexttrampoline.

The instruction on line 110 (lw $a0, LINKPTR($s0)) is in the delay slot of the jalr instruction and will execute before the function call, corrupting the function argument.

Fix the delay slot issue:

-    jalr  $a1
-    lw    $a0, LINKPTR($s0)
+    jalr  $a1
+    nop
+    lw    $a0, LINKPTR($s0)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
contexttrampoline:
lw $a0, ARGPTR($s0)
lw $a1, FUNCPTR($s0)
lw $sp, SPPTR($s0)
lw $s8, S8PTR($s0)
lw $s0, S0PTR($s0)
lw $s1, S1PTR($s0)
lw $s2, S2PTR($s0)
lw $s3, S3PTR($s0)
lw $s4, S4PTR($s0)
lw $s5, S5PTR($s0)
lw $s6, S6PTR($s0)
lw $s7, S7PTR($s0)
lw $gp, GPPTR($s0)
jalr $a1
lw $a0, LINKPTR($s0)
j setcontext
contexttrampoline:
lw $a0, ARGPTR($s0)
lw $a1, FUNCPTR($s0)
lw $sp, SPPTR($s0)
lw $s8, S8PTR($s0)
lw $s0, S0PTR($s0)
lw $s1, S1PTR($s0)
lw $s2, S2PTR($s0)
lw $s3, S3PTR($s0)
lw $s4, S4PTR($s0)
lw $s5, S5PTR($s0)
lw $s6, S6PTR($s0)
lw $s7, S7PTR($s0)
lw $gp, GPPTR($s0)
jalr $a1
nop
lw $a0, LINKPTR($s0)
j setcontext
🤖 Prompt for AI Agents
In src/mips/common/psxlibc/ucontext.s between lines 95 and 112, the instruction
'lw $a0, LINKPTR($s0)' is incorrectly placed in the delay slot of the 'jalr $a1'
instruction, causing it to execute before the function call and corrupt the
argument. To fix this, move the 'lw $a0, LINKPTR($s0)' instruction so it
executes after the 'jalr' call, ensuring the delay slot contains a safe
instruction or a nop, preserving correct argument passing.

Comment thread src/mips/common/psxlibc/ucontext.s
Comment thread src/mips/common/psxlibc/ucontext.h
@nicolasnoble nicolasnoble force-pushed the ucontext branch 2 times, most recently from fb70401 to e19d916 Compare May 25, 2025 15:00
@codecov
Copy link
Copy Markdown

codecov Bot commented May 25, 2025

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 9.30%. Comparing base (d222c2d) to head (e19d916).
Report is 17 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #1934   +/-   ##
=======================================
  Coverage    9.30%    9.30%           
=======================================
  Files         469      469           
  Lines      145099   145099           
=======================================
  Hits        13508    13508           
  Misses     131591   131591           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (1)
src/mips/psyqo/coroutine.hh (1)

214-217: Consider adding error handling to the public interface.

The current interface doesn't provide feedback on initialization or operation failures. Consider whether error reporting is needed for this low-level API.

If error handling is desired, consider:

-    void initializeInternal(eastl::function<void()>&& func, void* ss_sp, unsigned ss_size);
+    bool initializeInternal(eastl::function<void()>&& func, void* ss_sp, unsigned ss_size);
-    void resume();
+    bool resume();
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e7fca3d and a13aedd.

📒 Files selected for processing (4)
  • src/mips/psyqo/Makefile (1 hunks)
  • src/mips/psyqo/coroutine.hh (2 hunks)
  • src/mips/psyqo/examples/coroutine-demo-3/Makefile (1 hunks)
  • src/mips/psyqo/examples/coroutine-demo-3/coroutine-demo-3.cpp (1 hunks)
✅ Files skipped from review due to trivial changes (2)
  • src/mips/psyqo/examples/coroutine-demo-3/Makefile
  • src/mips/psyqo/Makefile
⏰ Context from checks skipped due to timeout of 90000ms (10)
  • GitHub Check: pcsx-redux (x86_64-linux)
  • GitHub Check: Codacy Static Code Analysis
  • GitHub Check: macos-build-and-test-toolchain
  • GitHub Check: build-openbios
  • GitHub Check: coverage
  • GitHub Check: toolchain
  • GitHub Check: cross-arm64
  • GitHub Check: build
  • GitHub Check: asan
  • GitHub Check: aur-build
🔇 Additional comments (9)
src/mips/psyqo/coroutine.hh (4)

32-32: Good addition of ucontext dependency.

The include for "common/psxlibc/ucontext.h" is appropriately placed and necessary for the new stackful coroutine functionality.


224-227: Static trampoline pattern implemented correctly.

The static trampoline function properly bridges C-style callbacks to C++ member functions, which is essential for the ucontext makecontext integration.


248-251: Stack size alignment calculation is correct.

The compile-time calculation (StackSize + 7) & ~7 properly ensures 8-byte alignment of the stack, which is important for MIPS architecture requirements.


299-302: Stack structure alignment looks good.

The alignas(8) directive on the Stack struct ensures proper alignment, and the stack buffer sizing uses the aligned constant correctly.

src/mips/psyqo/examples/coroutine-demo-3/coroutine-demo-3.cpp (5)

61-68: GPU configuration setup looks appropriate.

The configuration choices (320x240, auto video mode, 15-bit color, progressive scan) are reasonable for a PSX demo application.


75-79: Coroutine initialization and startup handled correctly.

Good practice to assert the start reason and immediately resume the coroutine after initialization to begin execution.


52-52: Stack size selection is appropriate.

The 65536-byte (64KB) stack size should be sufficient for the simple coroutine logic in this demo, and matches the default stack size in the template.


84-88: Timer and yield pattern correctly implemented.

The pattern of setting a timer with a lambda callback that updates text and resumes the coroutine, followed by yielding, is the correct cooperative multitasking approach.

Also applies to: 90-94, 96-100


108-113: Frame rendering implementation is clean.

Simple and effective rendering that clears the background and displays the current text state.

Comment on lines +212 to +233
class StackfulBase {
protected:
void initializeInternal(eastl::function<void()>&& func, void* ss_sp, unsigned ss_size);
void resume();
void yield();
[[nodiscard]] bool isAlive() const { return m_isAlive; }

StackfulBase() = default;
StackfulBase(const StackfulBase&) = delete;
StackfulBase& operator=(const StackfulBase&) = delete;

private:
static void trampoline(void* arg) {
StackfulBase* self = static_cast<StackfulBase*>(arg);
self->trampoline();
}
void trampoline();
ucontext_t m_coroutine;
ucontext_t m_return;
eastl::function<void()> m_func;
bool m_isAlive = false;
};
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

StackfulBase implementation looks solid but missing destructor.

The base class design is well-structured with proper encapsulation. However, consider adding a virtual destructor to ensure proper cleanup of ucontext resources.

 class StackfulBase {
   protected:
+    virtual ~StackfulBase() = default;
     void initializeInternal(eastl::function<void()>&& func, void* ss_sp, unsigned ss_size);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
class StackfulBase {
protected:
void initializeInternal(eastl::function<void()>&& func, void* ss_sp, unsigned ss_size);
void resume();
void yield();
[[nodiscard]] bool isAlive() const { return m_isAlive; }
StackfulBase() = default;
StackfulBase(const StackfulBase&) = delete;
StackfulBase& operator=(const StackfulBase&) = delete;
private:
static void trampoline(void* arg) {
StackfulBase* self = static_cast<StackfulBase*>(arg);
self->trampoline();
}
void trampoline();
ucontext_t m_coroutine;
ucontext_t m_return;
eastl::function<void()> m_func;
bool m_isAlive = false;
};
class StackfulBase {
protected:
virtual ~StackfulBase() = default;
void initializeInternal(eastl::function<void()>&& func, void* ss_sp, unsigned ss_size);
void resume();
void yield();
[[nodiscard]] bool isAlive() const { return m_isAlive; }
StackfulBase() = default;
StackfulBase(const StackfulBase&) = delete;
StackfulBase& operator=(const StackfulBase&) = delete;
private:
static void trampoline(void* arg) {
StackfulBase* self = static_cast<StackfulBase*>(arg);
self->trampoline();
}
void trampoline();
ucontext_t m_coroutine;
ucontext_t m_return;
eastl::function<void()> m_func;
bool m_isAlive = false;
};
🤖 Prompt for AI Agents
In src/mips/psyqo/coroutine.hh around lines 212 to 233, the StackfulBase class
lacks a virtual destructor, which is necessary for proper cleanup when derived
classes are deleted through a base class pointer. Add a virtual destructor to
the StackfulBase class to ensure correct resource management and avoid potential
memory leaks or undefined behavior.

Comment thread src/mips/psyqo/examples/coroutine-demo-3/coroutine-demo-3.cpp
@nicolasnoble nicolasnoble requested a review from Copilot May 25, 2025 19:43
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

Adds a PSX-compatible ucontext API and a stackful coroutine example to demonstrate delayed execution via timers.

  • Introduces ucontext.h/ucontext.s for context switching on PSX.
  • Extends psyqo::Stackful with ucontext-based trampoline, resume, and yield.
  • Provides a new coroutine-demo-3 example and updates Makefiles to include the ucontext implementation.

Reviewed Changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated no comments.

Show a summary per file
File Description
src/mips/psyqo/examples/coroutine-demo-3/coroutine-demo-3.cpp New demo showing stackful coroutine usage with timed sleeps
src/mips/psyqo/examples/coroutine-demo-3/Makefile Build configuration for the coroutine-demo-3 example
src/mips/psyqo/coroutine.hh Added StackfulBase declarations and ucontext include
src/mips/psyqo/Makefile Included ucontext.s in the build of psyqo library
src/mips/common/psxlibc/ucontext.s Assembly implementation of getcontext, setcontext, etc.
src/mips/common/psxlibc/ucontext.h Header definitions for PSX ucontext structures and functions
Comments suppressed due to low confidence (4)

src/mips/psyqo/examples/coroutine-demo-3/coroutine-demo-3.cpp:91

  • [nitpick] The status message is identical to the previous sleep stage and may confuse readers; consider updating it to clearly indicate this is the final 5s sleep, e.g., "Starting final 5s sleep".
m_text = "Waking up... sleeping for 5s this time";

src/mips/common/psxlibc/ucontext.s:47

  • The new assembly routines for context switching (getcontext, setcontext, makecontext, swapcontext) lack dedicated tests; consider adding unit tests to validate correct register saving/restoring and stack behavior.
.section .text.getcontext, "ax", @progbits

src/mips/psyqo/examples/coroutine-demo-3/coroutine-demo-3.cpp:106

  • The coroutine function returns immediately after scheduling the final timer without yielding; add a m_coroutine.yield() before exit so the "All done." callback can resume this coroutine correctly.
}

src/mips/psyqo/coroutine.hh:214

  • Methods initializeInternal, resume, and yield are declared but not defined in any translation unit, which will cause linker errors; add their implementations in a corresponding .cpp file.
void initializeInternal(eastl::function<void()>&& func, void* ss_sp, unsigned ss_size);

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1d09e04 and 21d0ed1.

📒 Files selected for processing (5)
  • src/mips/psyqo/Makefile (1 hunks)
  • src/mips/psyqo/coroutine.hh (2 hunks)
  • src/mips/psyqo/examples/coroutine-demo-3/Makefile (1 hunks)
  • src/mips/psyqo/examples/coroutine-demo-3/coroutine-demo-3.cpp (1 hunks)
  • src/mips/psyqo/src/coroutine.cpp (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (4)
  • src/mips/psyqo/Makefile
  • src/mips/psyqo/examples/coroutine-demo-3/Makefile
  • src/mips/psyqo/examples/coroutine-demo-3/coroutine-demo-3.cpp
  • src/mips/psyqo/coroutine.hh
🧰 Additional context used
🧬 Code Graph Analysis (1)
src/mips/psyqo/src/coroutine.cpp (1)
src/mips/common/psxlibc/ucontext.h (3)
  • getcontext (55-55)
  • makecontext (57-57)
  • swapcontext (58-58)
⏰ Context from checks skipped due to timeout of 90000ms (11)
  • GitHub Check: pcsx-redux (x86_64-linux)
  • GitHub Check: pcsx-redux (aarch64-linux)
  • GitHub Check: Codacy Static Code Analysis
  • GitHub Check: macos-build-and-test-toolchain
  • GitHub Check: cross-arm64
  • GitHub Check: asan
  • GitHub Check: toolchain
  • GitHub Check: build
  • GitHub Check: aur-build
  • GitHub Check: coverage
  • GitHub Check: build-openbios
🔇 Additional comments (5)
src/mips/psyqo/src/coroutine.cpp (5)

1-25: LGTM: Standard MIT license header.

The license header is properly formatted and appropriate for the project.


27-27: LGTM: Include directive is correct.

The include properly references the coroutine header file.


29-37: LGTM: Coroutine initialization logic is sound.

The initialization method correctly:

  • Sets the coroutine as alive
  • Moves the function to avoid unnecessary copying
  • Sets up the ucontext structure with stack parameters
  • Links the return context for proper cleanup
  • Binds the trampoline function to the coroutine context

44-47: LGTM: Resume method implementation is correct.

The method properly:

  • Checks if the coroutine is alive before attempting to resume
  • Uses swapcontext to switch from caller context to coroutine context
  • Handles the case where the coroutine has already completed

49-52: LGTM: Yield method implementation is correct.

The method properly:

  • Checks if the coroutine is alive before yielding
  • Uses swapcontext to switch from coroutine context back to caller context
  • Prevents yielding from a dead coroutine

Comment thread src/mips/psyqo/src/coroutine.cpp
@nicolasnoble nicolasnoble merged commit 0c18816 into grumpycoders:main May 26, 2025
21 of 22 checks passed
@nicolasnoble nicolasnoble deleted the ucontext branch May 26, 2025 01:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants