RISC OS Open
Safeguarding the past, present and future of RISC OS for everyone
ROOL
Home | News | Downloads | Bugs | Bounties | Forum | Documents | Photos | Contact us
Account
Forums → Bugs →

GSRead has never been threadsafe

Subscribe to GSRead has never been threadsafe 36 posts, 7 voices

Posts per page:

Pages: 1 2

 
Mar 7, 2023 9:11am
Avatar nemo (145) 2437 posts

gerph wrote

# FIXME

Yeah, you’ll be needing to do more than that.

And sadly your approach of effectively “repeatedly GS_Trans then read a byte” simply cannot be compatible with RISC OS. Consider the string <12345> – you’re going to be terribly disappointed when you see what OS_Read returns in RISC OS.

This is the problem with writing a new implementation from poor documentation of the actual code that has existed for 35 years, and why I keep trying to inject some sanity when anyone – in good faith of course – suggests rewriting stuff in C because “it will be easier to maintain”. If you can’t maintain the MC then you certainly aren’t going to be able to match its implementation.

Pyro AIUI isn’t trying to be RISC OS compatible per se, but your GS_Read is very different. Termination in particular doesn’t work the way you think – explore the result of GS_Trans on "Surprise" ! for some hint of the gory details.

 
Mar 7, 2023 10:09am
Avatar nemo (145) 2437 posts

This may help clarify that GSRead is more complicated (and powerful) than documented:

And I don’t know whether I’ve mentioned this before, but

The documentation is rubbish.

REM GSRead doesn't work the way you think

DIMQ%255
REM A quoted multipart string parameter with further parameters
$Q%="  ""123<256>|@|A|B<256>|J|K|L<256>|M|N|O|!<256>ABC""             !"

SYS"OS_GSInit",Q%,,0TOG%,,S%
REPEAT
 SYS"OS_GSRead",G%,,S%TOG%,C%,S%;V%
 CASETRUE OF
 WHEN(V%AND2)=2
 WHENC%>255:PRINT'"----"
 WHENC%=127ORC%<32:PRINT"<";C%">";
 OTHERWISE:VDUC%
 ENDCASE
UNTILV%AND2
PRINT'"Ended with character ";C%
 
Mar 7, 2023 10:39am
Avatar Simon Willcocks (1499) 382 posts

you don’t know when the application completes

Isn’t there a Service that’s called when the application completes?

The only use case I can think of that would really screw things up would be an application calling GSInit, optionally some GSReads, then telling another program where to call some GSReads to get the rest of the string.

It is a terrible API, which is why I’d read the whole thing in one go in GSInit, then allow the GSRead interface to read through the resulting string.

I’m not sure how that could fail.

The documentation is rubbish.

Oh, yes. Or the implementation doesn’t match it.

Code variables are interesting as well, especially if their size changes over reads.

“|!” → 384 (&180)? Strange.

 
Mar 7, 2023 11:27am
Avatar nemo (145) 2437 posts

strange

Indeed! I’ve extended the character constant syntax to support Unicode, e.g. <U+1EF00> produces a UTF-8 sequence, so |! acts benignly on that too (as the lead byte always has b7 set anyway).

Isn’t there a Service that’s called when the application completes?

This is legal:

REPEAT
 $&8300=TIME$
 SYS"OS_GSInit",&8300 TO G%,,S%
 SYS"OS_GSRead",G%,,S%
UNTIL FALSE

You don’t know when the program will have finished with the state in S% (and hence the internal context). You might hope that GSInit invalidates the previous, but that’s not true as it has always supported nested invocations.

You might hope to associate contexts with DomainID, but as you say it’s not impossible that state be passed around – it has never been illegal so one must assume that if it can be done, it has been done.

The absence of GSFinished is a design flaw.

The only use case I can think of that would really screw things up…

As I wish some other people would remember, if the only thing you can think of which disproves the theory “x+y=5 means x=3” is when y=4, then that’s the end of the theory, however attractive it may have been.

 
Mar 7, 2023 11:47am
Avatar Charles Ferguson (8243) 357 posts

And sadly your approach of effectively “repeatedly GS_Trans then read a byte” simply cannot be compatible with RISC OS. Consider the string <12345> – you’re going to be terribly disappointed when you see what OS_Read returns in RISC OS.

The point is that it doesn’t need to be (shouldn’t be) completely identical to what RISC OS Classic does. It just needs to be meeting the requirements of the documentation and expected use. And the expected use of OS_GSInit/OS_GSRead is DON’T.

Really no future implementation should attempt to be bug compatible, because there are too many bugs and misfeatures. As you’ve stated, OS_GSInit/OS_GSRead cannot be made to work safely. So don’t try beyond the basics. There is no point in carrying ancient RISC OS problems through into Aarch64 or x64. Life’s too short and unexpected behaviour is clearly bad.

Part of the purpose of Pyromaniac is to make it clear what you’re doing and what you’re not doing. Those FIXMEs are there for exactly that reason – to state that there is a deviance in behaviour and that it should be fixed. OR that it can be ignored because it’s not important. There are a lot of interfaces in RISC OS that really need to work – and OS_GSInit/OS_GSRead is not one of them.

 
Mar 7, 2023 11:56am
Avatar Simon Willcocks (1499) 382 posts

You can also write

REPEAT:DIM B% 1000:U. 0

But when the application runs out of resources, it gets an error and the memory is tidied up.

Which I know doesn’t happen with the current implementation of GSInit/GSRead, but will if the implementation always gets the result of a GSTrans (once, in GSInit) and GSRead simply returns each of the characters in the string sequentially (R0 or R2 simply pointing to the next character).

What I’m after is not having the output change as a result of another independent program’s execution. What happens if you do:

 DIM B% 100
 $B%="<MyVar>"
 OSCLI "Set MyVar Hello"
 SYS"OS_GSInit",B% TO G%,C%,S%:VDU C%
 SYS"OS_GSRead",G%,,S% TO G%,C%,S%:VDU C%
 SYS"OS_GSRead",G%,,S% TO G%,C%,S%:VDU C%
 SYS"OS_GSRead",G%,,S% TO G%,C%,S%:VDU C%
 OSCLI "Set MyVar World": REM As if another program pre-empted this one and set the variable
 SYS"OS_GSRead",G%,,S% TO G%,C%,S%:VDU C%
 SYS"OS_GSRead",G%,,S% TO G%,C%,S%:VDU C%

<Hello

 
Mar 7, 2023 4:11pm
Avatar nemo (145) 2437 posts

It just needs to be meeting the requirements of the documentation

Not after thirty five years, no. That’s fantasy.

OS_GSInit/OS_GSRead cannot be made to work safely

It can, for some tighter definition of the word “safely”.

There are a lot of interfaces in RISC OS that really need to work – and OS_GSInit/OS_GSRead is not one of them

And you do not get to be the arbiter of that, with the greatest of respect, or what you end up with is not an Operating System but an exclusive Club by invitation only.

The ridiculous thing is that compatibility is not hard… unless you don’t know what to be compatible with. Ignorance is not a virtue, and the PRMs are certainly not a Holy Book. They’re a very flawed partial description of the facts, and have rotted over time. They are not a blueprint to a More Perfect RISC OS. Far from it.

Simon suggested

You can also write…

Yes but that will always and has always failed. Whereas you were suggesting something that had not previously failed but now would (unless I misunderstood). Having a finite number of contexts with one buffer per context is the best we can do to cope with both dangling contexts (as my example creates) and safe buffering (as your eminent suggestion requires). You’ve changed my mind about buffering BTW, I’ll be switching to copying the SysVars rather than retaining pointers.

<sysvars>

Yes, t’was always so. And GSRead’s behaviour with Code Variables is even worse – claiming temporary ownership of SysVar memory is one thing, but when it’s a CodeVar it retains a pointer into its internal buffer. Very nasty.

This has been a useful discussion Simon, you’ve changed my mind about the buffering.

 
Mar 8, 2023 12:22am
Avatar David J. Ruck (33) 1372 posts

The ridiculous thing is that compatibility is not hard… unless you don’t know what to be compatible with. Ignorance is not a virtue, and the PRMs are certainly not a Holy Book. They’re a very flawed partial description of the facts, and have rotted over time. They are not a blueprint to a More Perfect RISC OS. Far from it.

That is not the right way to go. If the PRMs need updating, then so be it, but they are the contract that specify how RISC OS delivers its services, they aren’t there to legitimise bugs, omissions and misbehaviour by certain versions of the operating system.

Insisting on bug for bug compatibility, isn’t OS development, it’s maintaining a legacy emulator.

 
Mar 8, 2023 11:20am
Avatar nemo (145) 2437 posts

Have the PRMs never changed?
Have Errata not been published?
Have new editions not corrected previous editions?

It cannot be your position that demonstrable evidence from 35 years’ of OS and software is irrelevant until somebody else (who?) changes a piece of paper.

Don’t be daft.

Take RemV. Every version of the PRMs has claimed that the byte removed is in R0 but if examined the byte is in R2. Is that what you’re calling “the contract”?

Because every version of the Kernel has relied on the byte always being in R0 in some places, and other parts rely on it being in R2. It’s been like that for 35 years1.

And 35 years’ of software has been written against an OS that behaves like that. You do not now get to break all that software because of an error in the documentation and a delusional belief in the power of paper.

And once you acknowledge as you must the fallibility of the documentation, then writing an implementation against docs known to be wrong is a fool’s errand.

1 I first discovered it 30 years ago when I wrote the keyboard emulation for Prentke Romich talkers. I rediscovered it 25 years ago writing the MMK keyboard handler, and again more than 20 years ago when I made DeepKeys… and decided I needed my own documentation because I was sick of scribbling in the margins of the hopeless PRMs. So to see people venerating these piles of misinformation from either a position of naive ignorance or fervent fundamentalism is dispiriting, and the exact opposite of engineering. Reality is inconvenient.

 
Mar 9, 2023 3:25pm
Avatar David J. Ruck (33) 1372 posts

There is a big difference between correcting a mistake in the PRMs as in that case, and using the PRMs to document specific misfeature’s of certain implementations which was being discussed before.

 
May 31, 2023 7:00pm
Avatar Simon Willcocks (1499) 382 posts

Just FYI, if anyone gets around to re-implementing this, OS_EvaluateExpression currently sometimes bypasses the GSRead step and makes assumptions about what’s in r0 and r2 (specifically changing r0, which I was using to point to the base of the internal buffer). The side-effects are interesting, to say the least.

Pages: 1 2

Reply

To post replies, please first log in.

Forums → Bugs →

Search forums

Social

Follow us on and

ROOL Store

Buy RISC OS Open merchandise here, including SD cards for Raspberry Pi and more.

Donate! Why?

Help ROOL make things happen – please consider donating!

RISC OS IPR

RISC OS is an Open Source operating system owned by RISC OS Developments Ltd and licensed primarily under the Apache 2.0 license.

Description

Bug discussions that aren’t covered by the bugs database.

Voices

  • nemo (145)
  • Simon Willcocks (1499)
  • Charles Ferguson (8243)
  • David J. Ruck (33)

Options

  • Forums
  • Login
Site design © RISC OS Open Limited 2018 except where indicated
The RISC OS Open Beast theme is based on Beast's default layout

Valid XHTML 1.0  |  Valid CSS

Powered by Beast © 2006 Josh Goebel and Rick Olson
This site runs on Rails

Hosted by Arachsys