Skip to content

The CRT variants should collapse into one module — @@crt0 and @@crt1 differ by three lines #159

Description

@mgrossmann

@@crt0.asm and @@crt1.asm are 319 and 322 lines that differ in three, and the ecosystem has quietly settled on one of them. The variants cost more than they buy.

Measured

$ diff asm/@@crt0.asm asm/@@crt1.asm

The functional delta is one hunk:

         L     R1,=A(CTHREAD)    A(thread driver routine)      crt0: active
         LA    R0,=CL8'CTHREAD'                                crt1: commented out with ***
         IDENTIFY EPLOC=(0),ENTRY=(1)

Everything else is WTO text ('@@CRT0 - No storage for C stack' vs '@@CRT1 - …'), a header comment, the word Get in one comment column — and one place where the two copies have already drifted: in @@CTEXIT, crt0 loads the return code (L R9,0(R1)) on entry, crt1 after the BALR to @@CRTGET.

That drift is harmless@@CRTGET is a C function whose PDPEPIL ends RETURN (14,12),RC=(15), so R1 is restored — but it is an edit that landed in one copy and not the other. That is the whole argument for merging, in one line of diff.

What the ecosystem actually uses

132  startup = "crt1"
 15  startup = false        (own entry, no CRT)
  1  startup = "crt0"       (ind_file370)
  0  startup = "crtm"

Nothing uses crtm, and essentially nothing uses crt0. The variant that is used everywhere is the one without the CTHREAD IDENTIFY.

Two questions to settle before merging, not after

1. What is the IDENTIFY actually for? Several project.toml files describe crt1 as "the threading runtime" (ftpd, httplua, httprexx), while @@crt1.asm's own header says "Copy of @@crt0 without the IDENTIFY for CTHREAD". The comments and the code disagree about which one is the threading variant. IDENTIFY makes CTHREAD a named entry point so ATTACH EP=CTHREAD can find it — so the question is how threads are attached today in the 132 modules that switched it off, and whether any path still needs it.

2. What is crtm for? Its intent is legible from the code, and it is not "smaller for the sake of smaller":

  • crt0/crt1 create the C environment for the task: GETMAIN the stack, create the CLIBCRT, then @@GRTSET to anchor a CLIBGRT.
  • crtm joins an environment that already exists: it GETMAINs only a stack and calls @@CRTGET — which merely looks up the CLIBCRT for the current TCB in the PPA array (src/clib/@@crtget.c), it never creates one — and abends U0801 '@@CRTM - No CLIBCRT (C environment missing)' if there is none.

So crtm is the startup for a program that gets control inside a task whose C runtime is already up — the LINK-into-the-server case. That is exactly the shape of an httpd CGI or display module, and those are linked with crt1, which creates a second environment on a TCB that already has one. Either crtm is obsolete and should go, or the CGI path is doing the environment setup twice and crtm is the module it should have been using. That question decides crtm's fate; it should not be answered by deleting it unread.

The merge itself

The mechanism is already in the same file, three lines above the stack GETMAIN:

         WXTRN @@STKLEN
         ICM   R1,15,=V(@@STKLEN)       Get stack length address
         BZ    USEDFLT                  not there -> default

Apply it to CTHREADWXTRN CTHREAD, ICM, skip the IDENTIFY when the address is zero — and crt0 and crt1 become one module. A weak external does not drive automatic library call, so a program that does not use threads never pulls the thread driver in; one that does references the thread API anyway, so the address is there and the IDENTIFY happens. No option, no variant, no decision for the caller to get wrong.

Related, and worth reading together: mvslovers/cc370#10 (startup customization by redefining @@START, whose agreed resolution is a weak __premain() hook — same mechanism, same file) and mvslovers/cc370#99 (ld370 mishandles a weak external when a hard ER for the same name exists — not a blocker for this change, since nothing declares a hard EXTRN CTHREAD, but it is the same mechanism and worth having correct first).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions