Stopping the scheduler/interrupts

Anything QL Software or Programming Related.
Post Reply
Martin_Head
Aurora
Posts: 847
Joined: Tue Dec 17, 2013 1:17 pm

Stopping the scheduler/interrupts

Post by Martin_Head »

I am writing a machine code SuperBASIC Procedure, which will access parts of the operating system. Specifically the channel table, and a device drivers linkage block. So I don't want anyone opening/closing channels, or accessing the driver while my routine does it's thing.

So I want to stop the scheduler/interrupts for a while. What is the best way?

At the moment I am trying doing a TRAP #0, to enter supervisor mode. And a AND.W #$F8FF,SR to restart. However this seems to crash the system. Is this the right way to do it?

Also in the Procedure I may have to force remove a job from the system, The books say that return from this system call may be via the scheduler, so does this mean that I would have to disable the scheduler again after such a call?


User avatar
NormanDunbar
Forum Moderator
Posts: 2251
Joined: Tue Dec 14, 2010 9:04 am
Location: Leeds, West Yorkshire, UK
Contact:

Re: Stopping the scheduler/interrupts

Post by NormanDunbar »

Looking at my notes, I appear to use

Code: Select all

ANDI #$07FF,SR
to exit from supervisor mode, but that value will also disable trace mode if that is set too. You have to still be in supervisor mode to execute the above though, or you will get a privilege exception and most likely, a hung QL.

I've never needed to disable interrupts to rummage around in the channel table in SuperBASIC or QDOS, what exactly are you doing in the table? And in the device drivers too - it might help diagnose the problem.

I'm not sure why you think there might be a problem if you force remove a job, unless you still have interrupts disabled and/or supervisor mode running, I 'm not sure you want to activate the scheduler under those conditions, if memory serves me.

Cheers,
Norm.


Why do they put lightning conductors on churches?
Author of Arduino Software Internals
Author of Arduino Interrupts

No longer on Twitter, find me on https://mastodon.scot/@NormanDunbar.
User avatar
tofro
Font of All Knowledge
Posts: 2685
Joined: Sun Feb 13, 2011 10:53 pm
Location: SW Germany

Re: Stopping the scheduler/interrupts

Post by tofro »

Whether your code can be interrupted by other parts of the operating system (i.e. whether there is actually a need to stop the polling interrupt at all) depends a bit on where your code has been called from. Also note that entering supervisor mode alone will not disable external interrupts, thus will not let your code run totally undisturbed.

From an S*Basic context, I'm normally doing the following:

Code: Select all

	trap		#0			; enter supervisor mode
	ori.w	#$0700,sr		; disable interrupts
	move.l	a6,-(a7)		; save basic's a6
	
	; do critical stuff
	
	move.l	(a7)+,a6		; restore a6
	and.w	#$d8ff,sr 		; back to user mode with interrupts enabled
	
In my experience, the most common problem with crashing supervisor mode routines - apart from trying to call system routines you shouldn't - has almost always been: running out of supervisor stack space. In a standard QL, there's only about 64 bytes until you run backwards into the system variables, easy to use up once you do more than trivial stuff. In case the 64 bytes are not enough, I tend to temporarily allocate my own supervisor stack somewhere else, and restore it before restarting the scheduler - Note you must have interrupts disabled before doing that.

Also, as Norman said, you should not try and force-remove a job with interrupts disabled and from SV mode. Set a flag in that routine and kill the job after you're done with SV mode stuff and you've put everything back into a clean state (or, even better: set a flag in that job or put a signal in a queue to that job and have it kill itself once it gets that signal, in case that's possible). That job will not kick in while you're in SV mode anyways. Manager Traps are only "partially atomic" and "must not be made from a job in SV mode" according to the manual - In general, what you can do with the system from SV mode is limited to calling vectors and only "guaranteed atomic" traps - That basically excludes all Manager Traps and all I/O traps, with a timeout other than 0. Everything else is prone to crash the system. (The trap re-starts the scheduler which is disabled.... Leads to nearly guaranteed hang)

If you tell us a bit more on what you're actually trying to do, we might be able to help a bit better.

Tobias


ʎɐqǝ ɯoɹɟ ǝq oʇ ƃuᴉoƃ ʇou sᴉ pɹɐoqʎǝʞ ʇxǝu ʎɯ 'ɹɐǝp ɥO
Martin_Head
Aurora
Posts: 847
Joined: Tue Dec 17, 2013 1:17 pm

Re: Stopping the scheduler/interrupts

Post by Martin_Head »

This a routine for my IP Network driver. What I am trying to do is to change the network station number/IP Address that the driver is using.

What I want to do is scan the channel table, looking for any open channels that belong to the IP Network driver. If it finds any, then the routine returns an 'in use' error. To tell the user to close them.

If it does not find any open channels, it then checks to see if the file server (FSERVE) is running. If it is, it then it removes it.

It then opens 2 new TCP_ channels, patches part of the IP Network drives Linkage block, and closes 2 old TCP_ channels, that are replaced with the new ones.

While the routine is doing it's thing, I don't want to run the risk that a IP Network channel gets opened by another job, or FSERVE, halfway through changing things.

So I thought, enter supervisor mode to do it. I don't know if I need to disable interrupts or not. I just want to make sure that no one can access the IP Network driver while my routine does it work.

If I remember correctly without looking at the code, I use MT.INF, MT.FRJOB, IO.OPEN, and IO.CLOSE system calls while in supervisor mode.

I have written the routine, and it looks like it works OK, until I add the code to enter/leave supervisor mode.

If I cannot remove the FSERVE job while in supervisor mode, could I do the MT.FRJOB, or MT.RJOB right after coming out of supervisor mode. Although this sound slightly dangerous as a channel it uses no longer exists, and I'm not sure what happens if it tries to use it before it shuts down. If push come to shove, I might be able to patch the running FSERVE job with the new channel ID (I think it is just kept in a register) and not need to shut it down. Or alternatively when I check to see if FSERVE is running I could return an 'in use' error, and make the user shut down the file server, like they would have to close any open network channels before restarting the Network driver.

Martin


User avatar
tofro
Font of All Knowledge
Posts: 2685
Joined: Sun Feb 13, 2011 10:53 pm
Location: SW Germany

Re: Stopping the scheduler/interrupts

Post by tofro »

Martin_Head wrote:This a routine for my IP Network driver. What I am trying to do is to change the network station number/IP Address that the driver is using.

What I want to do is scan the channel table, looking for any open channels that belong to the IP Network driver. If it finds any, then the routine returns an 'in use' error. To tell the user to close them.
That should work with supervisor mode alone.
Martin_Head wrote: If it does not find any open channels, it then checks to see if the file server (FSERVE) is running. If it is, it then it removes it.
That will not work from supervisor mode, as mentioned above. Killing a job involves the scheduler and entering the scheduler in SV mode is a no-no.
Martin_Head wrote: It then opens 2 new TCP_ channels, patches part of the IP Network drives Linkage block, and closes 2 old TCP_ channels, that are replaced with the new ones.
That should work from SV mode.
Martin_Head wrote: While the routine is doing it's thing, I don't want to run the risk that a IP Network channel gets opened by another job, or FSERVE, halfway through changing things.
SV mode only (interrupts enabled) should do the job as long as no ISR is fiddling with the same tables you want to work with. For the QDOS in-built drivers, this is guaranteed.
Martin_Head wrote: If I remember correctly without looking at the code, I use MT.INF, MT.FRJOB, IO.OPEN, and IO.CLOSE system calls while in supervisor mode.
As said before, MT.INF, IO.OPEN, IO.CLOSE should be fine to call from SV mode, MT.FRJOB isn't.

Martin_Head wrote: If I cannot remove the FSERVE job while in supervisor mode, could I do the MT.FRJOB, or MT.RJOB right after coming out of supervisor mode. Although this sound slightly dangerous as a channel it uses no longer exists, and I'm not sure what happens if it tries to use it before it shuts down. If push come to shove, I might be able to patch the running FSERVE job with the new channel ID (I think it is just kept in a register) and not need to shut it down. Or alternatively when I check to see if FSERVE is running I could return an 'in use' error, and make the user shut down the file server, like they would have to close any open network channels before restarting the Network driver.
What's wrong with stopping the FSERVE job before you do anything else (maybe after having checked that the new station number is really different from the old one) and re-starting id after you're done? None of the channels the job might have open would be valid after the command has run anyhow. Remind the user in the manual that changing the station number is destructive to any in-transit data. (I think TK2 does the same without a warning in the manual)

Another approach is, as you said, have the user stop the FSERVE job before changing the station number and return with an error in case you find it still running - Hotkey System II does the same by not allowing you to change hotkeys without a HOT_STOP first. If you forget that, you'll get an "IN USE" error. Not the worst solution, because after all, the user might lose data (local or remotely).

Tobias


ʎɐqǝ ɯoɹɟ ǝq oʇ ƃuᴉoƃ ʇou sᴉ pɹɐoqʎǝʞ ʇxǝu ʎɯ 'ɹɐǝp ɥO
Martin_Head
Aurora
Posts: 847
Joined: Tue Dec 17, 2013 1:17 pm

Re: Stopping the scheduler/interrupts

Post by Martin_Head »

tofro wrote:What's wrong with stopping the FSERVE job before you do anything else (maybe after having checked that the new station number is really different from the old one) and re-starting id after you're done? None of the channels the job might have open would be valid after the command has run anyhow. Remind the user in the manual that changing the station number is destructive to any in-transit data. (I think TK2 does the same without a warning in the manual)
Maybe... But I think there might be a possible problem that if any daughter jobs of FSERVE are killed while they have open channels. The channels that are owned by the job are just removed from the system, not by calling the CLOSE routine. But the IP Network driver opens another channel in the channels OPEN routine, so I suspect that channel may get left behind in the channel table as an orphan. Although I suppose if the channel was owned by "this job" then it should go too. This is why I scan the channel table first
Another approach is, as you said, have the user stop the FSERVE job before changing the station number and return with an error in case you find it still running - Hotkey System II does the same by not allowing you to change hotkeys without a HOT_STOP first. If you forget that, you'll get an "IN USE" error. Not the worst solution, because after all, the user might lose data (local or remotely).
I think I might go down this route, at least at first. Get the rest of the routine, and going into and out of supervisor mode working first.

EDIT - I had a thought, What if I suspended FSERVE before I entered supervisor mode, then when the routine had done it's thing and returned to user mode. I either restart FSERVE is there was an error, or remove it if not. (In the case of an error I would like the routine to not change anything).


Post Reply