Sammelthread: Lernen aus Fehlern

Es gibt 39 Antworten in diesem Thema, welches 4.417 mal aufgerufen wurde. Der letzte Beitrag (20. April 2023 um 18:55) ist von GI-Joe.

  • Einfach mal 20 Jahre liegen lassen

    Perfekt :thumbsup: In SOLCHEN Kategorien muss man als "Retro-Coder" denken :thumbup:

    Edit: Verrätst du auch noch, wie man den "Software-Interrupt" (also BRK) KORREKT erkennt? :wink:

  • Einfach mal 20 Jahre liegen lassen

    Perfekt :thumbsup: In SOLCHEN Kategorien muss man als "Retro-Coder" denken :thumbup:

    Edit: Verrätst du auch noch, wie man den "Software-Interrupt" (also BRK) KORREKT erkennt? :wink:

    Ich tippe so wie es der Kernal macht: auf dem Stack ins Statusregister linsen und das Break-Flag anschauen:

    Code
    TSX
    LDA $0104,X
    AND #$10
    BEQ nix_brk

    ────────────────────────────────────────────────────────────
    Bitte melde dich an, um diesen Link zu sehen. - Bitte melde dich an, um diesen Link zu sehen.
    ────────────────────────────────────────────────────────────

  • Einfach mal 20 Jahre liegen lassen

    Perfekt :thumbsup: In SOLCHEN Kategorien muss man als "Retro-Coder" denken :thumbup:

    Nochmal mach ich das aber nicht, sonst ist das Publikum vorher gestorben.

    Wegen euch Hektikern so ein Stress wieder hier, echt ey :grab1:

    Edit: Verrätst du auch noch, wie man den "Software-Interrupt" (also BRK) KORREKT erkennt? :wink:

    Wo ist der Denkfehler?

    Ich bin noch nicht wieder in die Programmierung eingestiegen, hab den Bug also noch nicht gefixt und getestet.

    2 Probleme:

    1) Zwischen dem BRK-Befehl und der Erkennung in der IRQ-Routine vergeht Zeit. In der Zeit kann ein IRQ auftreten.

    - Der BRK wird dann geschlabbert. Ist ein Problem, wenn ein Thread nicht darauf vorbereitet ist.

    - Aus Sicht eines stable Rasters kann der VIC-IRQ zu früh kommen, kann bei Selbstmodifikation dann tödlich sein.

    - Wobei das Problem schon wegen erlaubter CIA-IRQs und VIC-IRQs existiert.

    2) BRK und IRQ können exakt gleichzeitig auftreten. Dann wird nicht mal im Statusregister das BRK gekennzeichnet.

    Wegen 2) denke ich, dass ich den BRK gar nicht sicher erkennen kann.

    Bin noch nicht sicher, was die beste Lösung ist.

    Entweder damit rechnen, dass BRK nicht verlässlich ist, was aber das Problem mit Stable Raster nicht löst.

    Oder einen Scheduler ohne BRK bauen, der aus IRQ und Hauptschleife aufgerufen werden kann, was aber vielleicht andere komischen Effekte haben kann.

  • Entschuldige meine Naivität, aber schließt "stable Raster" nicht sowieso JEDE andere Interrupt-Quelle als den VIC aus? :nixwiss:

    Also ich hätte jetzt erwartet, ein Multitasking-System für den C64 ("kooperativ" mit BRK, oder BRK nur für "syscalls" und preemption via CIA-timer) muss sowieso auf "raster-Effekte" verzichten? :nixwiss:

  • Ich hab mal eins gebaut, wo die Tasks dann halt allesamt im Mainloop laufen. Sprich: es wird immer nur die Returnaddresse des ansonsten nornal laufenden IRQs manipuliert.

    Hier sogar dokumentiert: Bitte melde dich an, um diesen Link zu sehen. :smile:

    ────────────────────────────────────────────────────────────
    Bitte melde dich an, um diesen Link zu sehen. - Bitte melde dich an, um diesen Link zu sehen.
    ────────────────────────────────────────────────────────────

  • Ja und mir kam noch, dass man preemption, falls man das braucht, natürlich auch an ner definierten raster-Position machen könnte, so ganz ohne CIA. Aber wie dann BRK noch ins Bild passen soll ist mir trotzdem schleierhaft :nixwiss:

  • 2) BRK und IRQ können exakt gleichzeitig auftreten. Dann wird nicht mal im Statusregister das BRK gekennzeichnet.


    Wegen 2) denke ich, dass ich den BRK gar nicht sicher erkennen kann.

    Dieser konkrete Fall ist tatsächlich gar nicht problematisch, denn der BRK wird ja dann nach der Ausführung des IRQ abgearbeitet. Wenn man BRK stabil bekommen möchte, muss man aber auch im NMI-Handler das BRK-Flag ansehen und ggfs. beachten!

    Achtung: Ich gebe nur wieder, was meine eigenen Experimente ergeben haben- ich behaupte nicht, dass BRK 100% sicher nutzbar ist. :D

    Yes, I'm the guy responsible for the Bitte melde dich an, um diesen Link zu sehen. cross assembler. And some Bitte melde dich an, um diesen Link zu sehen..

  • Wegen 2) denke ich, dass ich den BRK gar nicht sicher erkennen kann.

    Bin noch nicht sicher, was die beste Lösung ist.

    Entweder damit rechnen, dass BRK nicht verlässlich ist, was aber das Problem mit Stable Raster nicht löst.

    Einfach mal ins Blaue: Geht das vielleicht auch, wenn man statt BRK ein NMI manuell per Software auslöst? IRQ- und NMI-Vektoren sind ja getrennt.

  • Einfach mal ins Blaue: Geht das vielleicht auch, wenn man statt BRK ein NMI manuell per Software auslöst? IRQ- und NMI-Vektoren sind ja getrennt.

    NMI (vermutlich durch CIA-timer) für einen Software-Interrupt "missbrauchen" ist dann halt ganz schön umständlich .... (und man kriegt die RESTORE-Taste nicht "tot", falls das ein Issue sein sollte).

  • Ich hab mal eins gebaut, wo die Tasks dann halt allesamt im Mainloop laufen. Sprich: es wird immer nur die Returnaddresse des ansonsten nornal laufenden IRQs manipuliert.

    Hier sogar dokumentiert: Bitte melde dich an, um diesen Link zu sehen. :smile:

    Ich habe es mit TSX/TXS gemacht und für jeden Thread eigenen Speicher auf dem Stack vorgesehen. So konnte ich dann Scheibchenweise Threads mit gleicher Prio bedienen lassen.

    Entschuldige meine Naivität, aber schließt "stable Raster" nicht sowieso JEDE andere Interrupt-Quelle als den VIC aus? :nixwiss:

    Also ich hätte jetzt erwartet, ein Multitasking-System für den C64 ("kooperativ" mit BRK, oder BRK nur für "syscalls" und preemption via CIA-timer) muss sowieso auf "raster-Effekte" verzichten? :nixwiss:

    Wenn man damit rechnet, dass CIA-IRQs was am TIming verändern, dann geht es schon.

    Mit VIC + CIA muss man damit rechnen, dass VIC später kommen kann, müssten so knapp 30 Takte sein, pha, txa, pha, tya, pha, lda $dc0d, bpl xxx, cli usw. Halbe Rasterzeile verschwendet.

    Mit BRK dazu können die dann aber auch zu früh kommen. Das ganze Register-Retten ist wegen des BRK gestartet worden, just dann kommt ein IRQ vom VIC und wird sofort erkannt. Zuerst BRK über Stack erkennen müsste gehen, aber dann hat der Scheduler Prio vor dem VIC, und man muss mehrere Rasterzeilen verschenken. Taugt auch nix.

  • Dieser konkrete Fall ist tatsächlich gar nicht problematisch, denn der BRK wird ja dann nach der Ausführung des IRQ abgearbeitet.

    Ich hab's nicht selber getestet. Verstanden hab ich jedenfalls, dass der BRK ausgeführt wird, aber sein Flag nicht setzt.

    Für diesen Fall gibt es doch bestimmt schon Testcode für den Vice.

  • Mit BRK dazu können die dann aber auch zu früh kommen.

    Das hab ich noch nicht ganz gefressen. Setzt BRK etwa nicht das I-Flag?

  • Mit BRK dazu können die dann aber auch zu früh kommen.

    Das hab ich noch nicht ganz gefressen. Setzt BRK etwa nicht das I-Flag?

    Doch, tut es.
    Aus dem Gedächtnis:

    Einfachster Fall. nur VIC:

    Rasterzeile kommt, und Du kannst ganz normal abzählen, wie viele Takte verbraucht werden, bis wirklich der Stable Raster losläuft. Ich zähle 29 Takte. Plus Jitter, plus 6 für den IRQ selber.

    Komplizierter Fall, CIA+VIC ungefähr gleichzeitig

    22 Takte, bis CIA erkannt und das CLI ausgeführt wurde. Sofort (oder 1 Befehl danach?) kommt dann noch ein IRQ. Das wären dann so ca. 30 Takte, die der Stable Raster später als im einfachen Fall losläuft.

    Böse Falle, BRK + VIC

    An der Stelle bmi CIAIRQ passiert der VIC-IRQ. 19 Takte + 6 Takte für den BRK sind schon gelaufen, nach nur 10 Takten wird der stable Raster aufgerufen. Statt 35, also bis zu 25 Takte zu früh.

  • Ok, böse. Aber dann würde ich mal konstatieren: Man kann sich den ganzen Horror sparen, wenn man nur EINE IRQ-Quelle hat :biggrin:

    Übersetzt auf das Problem "Multitasking bei stabilem Raster": CIA timer aus. BRK verboten. Preemption aus einer der VIC ISRs, mittels frame-counter, FALLS man das braucht. "Cooperative" (also, yield) nicht per IRQ sondern per definiertem Flag (vllt in der ZP), das einmal pro Frame gecheckt wird.

    Ok, ich hab jetzt nicht allzu intensiv darüber nachgedacht, aber wäre das nicht VIEL einfacher? :biggrin:

  • Ok, böse. Aber dann würde ich mal konstatieren: Man kann sich den ganzen Horror sparen, wenn man nur EINE IRQ-Quelle hat :biggrin:

    Genau :thumbup:

    Bei Deiner Kooperativen Idee sehe ich noch die Lücke, wie man die Zeit zwischen "Flag setzen" und "IRQ wechselt zum anderen Thread" füllt. Oder am Besten die Rechenzeit einem anderen Thread überlässt. Da hängt noch was an Problemen dran.

    Wenn ich mich irgendwann wirklich aufraffe, dann werde ich definitiv erstmal Tests schreiben und CIA wahrscheinlich rauswerfen.

  • Bei Deiner Kooperativen Idee sehe ich noch die Lücke, wie man die Zeit zwischen "Flag setzen" und "IRQ wechselt zum anderen Thread" füllt.

    Pollen. Wenn ein Thread scheduled wird, wird das Flag 0 sein, oder? :wink: (edit: ja, das verschwendet natürlich Rechenzeit ....)

    edit2: meine ja nur, effizientes multitasking UND stable-raster klingt halt irgendwie ... kaum machbar :nixwiss:

  • edit2: meine ja nur, effizientes multitasking UND stable-raster klingt halt irgendwie ... kaum machbar :nixwiss:

    doch , mit Timer-NMI und ohne PHA/PLA - einfach A,X,Y in 3 ZP-Adressen rotzen und am Ende wieder laden, spart viel Rasterzeit gegenüber PHA/PLA wenn man z.B. in jeder Rasterline den Sideborder öffnen will. Und da der NMI auch einen IRQ unterbricht, hätte man den Rest der Rasterlines in der horzontalen frei für Mainloop oder Sound oder ....

    Und alles Timing-kritische inkl. StableRaster kann dann ja der NMI übernehmen. ggf. mit 2 CIA2-Timern falls badlines mit im Spiel sind ....

    und $DD0C vorher mit #$40 laden (Opcode für RTI) spart ja auch noch bisschen.

    Oder hab ich jetzt einen Gedankenfehler ?

    Code
    nmi_routine:
        sta $02
        stx $03
        sty $04
        dec $d016
        inc $d016
        ldy $04
        ldx $03
        lda $02
        jmp $dd0c                ; JMP$dd0c = rti+ack = 3 cycles - ack

    Viele Grüße,
    GI-Joe
    Bitte melde dich an, um diesen Link zu sehen. * Bitte melde dich an, um diesen Link zu sehen. * Bitte melde dich an, um diesen Link zu sehen. * Bitte melde dich an, um diesen Link zu sehen. * Bitte melde dich an, um diesen Link zu sehen. * Bitte melde dich an, um diesen Link zu sehen.

  • Ist das (böser SelfMod) nicht noch schneller, als über die ZP? Hab die Cycles nicht mehr im Kopf...

  • Ist das (böser SelfMod) nicht noch schneller, als über die ZP?

    Sollte Dein Code in der Zeropage laufen, ist er gleich schnell mit meinem 3 Zyklen schneller als meiner.

    Sollte Dein Code woanders laufen, ist er 3 Zyklen langsamer, da ein sta$xxxx 4 Zylen braucht und ein sta$xx nur 3 ;)

    Was Du meintest war bestimmt sta ($xx),y , das braucht 6 Zyklen und wäre langsamer als Dein SelfModCode

    Viele Grüße,
    GI-Joe
    Bitte melde dich an, um diesen Link zu sehen. * Bitte melde dich an, um diesen Link zu sehen. * Bitte melde dich an, um diesen Link zu sehen. * Bitte melde dich an, um diesen Link zu sehen. * Bitte melde dich an, um diesen Link zu sehen. * Bitte melde dich an, um diesen Link zu sehen.