"...system will copy block 1 of the currently open file into one of the system
buffers. BLOCK also leaves on the stack the address of the beginning of the
buffer (1024 bytes, remember) that it used. The contents of this buffer are
guaranteed to stay valid until you execute a word from the set of procedures
with `multitasking impact', like EMIT or TYPE".
1. Actually, why EMIT, which simply outputs a character on the screen, should
affect contents of any buffer prepared to hold block contents?
2. How one should understand this "multitasking impact" exactly?
3. What are the words with "multitasking impact"? And which of the words
have such impact (but EMIT and TYPE)?
Zbiggy <zbigniew2011REM...@gmail.remove.com> wrote:
> There is a statement in "Starting Forth":
> "...system will copy block 1 of the currently open file into one of the system
> buffers. BLOCK also leaves on the stack the address of the beginning of the
> buffer (1024 bytes, remember) that it used. The contents of this buffer are
> guaranteed to stay valid until you execute a word from the set of procedures
> with `multitasking impact', like EMIT or TYPE".
> 1. Actually, why EMIT, which simply outputs a character on the screen, should
> affect contents of any buffer prepared to hold block contents?
Because EMIT might block waiting to send a character to the device, so
this is an opportunity to switch to another task, if there is one.
That other task might call BLOCK and invalidate the buffer.
> 2. How one should understand this "multitasking impact" exactly?
On Feb 13, 7:17 am, Zbiggy <zbigniew2011REM...@gmail.REMOVE.com>
wrote:
> 2. How one should understand this "multitasking impact" exactly?
Any word that calls PAUSE. Usually I/O words. Perhaps in some Forths
tasks share buffers. I'm not sure this applies to modern Forths, since
sharing buffers to save memory is no longer necessary. If you even use
buffers (most people use only files).
> --
> Forth is a preserver of health (Hippocrates)
It didn't work out that way for Jeff. Maybe the wrong dialect?
Brad <hwfw...@gmail.com> wrote:
> On Feb 13, 7:17?am, Zbiggy <zbigniew2011REM...@gmail.REMOVE.com>
> wrote:
>> 2. How one should understand this "multitasking impact" exactly?
> Any word that calls PAUSE. Usually I/O words. Perhaps in some Forths
> tasks share buffers.
In all of them: it's not just about space saving, it's about
correctness. You don't want tasks with different opinions about the
contents of a particular block.
On Feb 13, 9:26 am, Andrew Haley <andre...@littlepinkcloud.invalid>
wrote:
> In all of them: it's not just about space saving, it's about
> correctness. You don't want tasks with different opinions about the
> contents of a particular block.
I was going to say that embedded Forthers like me wouldn't use blocks,
but then it just occurred to me that blocks would be a great way for a
16-bit Forth to deal with large SPI flash.
In comp.lang.forth, Brad wrote:
> Any word that calls PAUSE. Usually I/O words. Perhaps in some Forths
> tasks share buffers. I'm not sure this applies to modern Forths, since
> sharing buffers to save memory is no longer necessary. If you even use
> buffers (most people use only files).
Thanks, Brad and Andrew. But I understand, that all this is related only
to multitasking-capable Forths, and the "simpler" ones are free of the
restriction (I mean: I don't have to worry that by executing EMIT sometimes
I can change assigned buffer's contents, by giving "green light" to another
task etc.)?
The mentioned restriction is strictly related to multitasking ability, right?
>> --
>> Forth is a preserver of health (Hippocrates)
> It didn't work out that way for Jeff. Maybe the wrong dialect?
Well, who knows? We're unable to find out, how long he would live _without_
Forth...
-- Forth is a preserver of health (Hippocrates)
> "...system will copy block 1 of the currently open file into one of the system
> buffers. BLOCK also leaves on the stack the address of the beginning of the
> buffer (1024 bytes, remember) that it used. The contents of this buffer are
> guaranteed to stay valid until you execute a word from the set of procedures
> with `multitasking impact', like EMIT or TYPE".
> 1. Actually, why EMIT, which simply outputs a character on the screen, should
> affect contents of any buffer prepared to hold block contents?
> 2. How one should understand this "multitasking impact" exactly?
> 3. What are the words with "multitasking impact"? And which of the words
> have such impact (but EMIT and TYPE)?
The other responses answer your question, but I'll provide a little more background.
The classic Forth multitasker (originally developed by Chuck and still in use in many native & embedded Forths) is "cooperative" -- a task voluntarily relinquishes the CPU. One advantage of this is that there is far less context to save and restore, so task switches are much faster than with pre-emptive algorithms. Another advantage is that the programmer knows when the program is doing something that may cause a task switch.
The disadvantage is that a task may "hog" the CPU and prevent other tasks from having timely access. The compromise which makes the cooperative algorithm work is that whenever a task performs an I/O operation it must relinquish the CPU. This is brilliant because I/O takes a long time, comparatively speaking, and in most applications (especially control systems, for which Forth was originally designed) there isn't a lot to do between I/O operations. So this makes very efficient use of the CPU, making the majority of its cycles available for doing real work.
One must take a broad view of what defines I/O: for example, writing a character to a screen is I/O, even if the "screen" is in a local frame buffer. And any drivers that the programmer adds must also follow the rule. So long as everyone respects this rule, cooperative multitasking is effortless and in over 30 years of application programming I don't recall any problems.
There are several ways to implement this. One is the high-level word PAUSE, which someone mentioned. PAUSE relinquishes the CPU for exactly one pass through the task list. A more sophisticated way, appropriate in an interrupt-driven system, is to deactivate the task when the I/O is initiated, and let the interrupt driver that responds when the action is completed set its status to be active again.
And Andrew makes an important point about BLOCK buffers: they must be shared in a multitasking system, to avoid the possibility of multiple copies of a block with different contents. Sound application design avoids conflicts. It's true that most modern Forths that run under a host OS don't use BLOCK for disk I/O, but blocks are, indeed, quite useful for managing flash or other mass storage.
Cheers,
Elizabeth
-- ==================================================
Elizabeth D. Rather (US & Canada) 800-55-FORTH
FORTH Inc. +1 310.999.6784
5959 West Century Blvd. Suite 700
Los Angeles, CA 90045
http://www.forth.com
"Forth-based products and Services for real-time
applications since 1973."
==================================================
>> Any word that calls PAUSE. Usually I/O words. Perhaps in some Forths
>> tasks share buffers. I'm not sure this applies to modern Forths, since
>> sharing buffers to save memory is no longer necessary. If you even use
>> buffers (most people use only files).
> Thanks, Brad and Andrew. But I understand, that all this is related only
> to multitasking-capable Forths, and the "simpler" ones are free of the
> restriction (I mean: I don't have to worry that by executing EMIT sometimes
> I can change assigned buffer's contents, by giving "green light" to another
> task etc.)?
> The mentioned restriction is strictly related to multitasking ability, right?
>>> --
>>> Forth is a preserver of health (Hippocrates)
>> It didn't work out that way for Jeff. Maybe the wrong dialect?
> Well, who knows? We're unable to find out, how long he would live _without_
> Forth...
If you're writing portable code that may run on a multitasked Forth you should respect the rule.
Cheers,
Elizabeth
-- ==================================================
Elizabeth D. Rather (US & Canada) 800-55-FORTH
FORTH Inc. +1 310.999.6784
5959 West Century Blvd. Suite 700
Los Angeles, CA 90045
http://www.forth.com
"Forth-based products and Services for real-time
applications since 1973."
==================================================
> If you're writing portable code that may run on a multitasked Forth you > should respect the rule.
Of course, but I had in mind the ability of blocks - mentioned in SF - which
I particularly like: to use it as kind of "swap partition" equivalent. It
seems, it should be used with much greater care, than I thought at first: we
don't want data "swapped" to blocks to get corrupted.
Or maybe it's not possible at all in multitasked environment - at least not
in the way similar to one, in which Linux uses its swap partitions/files:
actually, we cannot block I/O operations at all just to make sure, they won't
allow buffers affection. The machine would be unusable.
-- Forth is a preserver of health (Hippocrates)
> One must take a broad view of what defines I/O: for example, writing a > character to a screen is I/O, even if the "screen" is in a local frame > buffer. And any drivers that the programmer adds must also follow the > rule. So long as everyone respects this rule, cooperative multitasking > is effortless and in over 30 years of application programming I don't > recall any problems.
I'm afraid, I didn't completely understood: what you mean by writing, that
"cooperative multitasking is effortless"? What it was unable to do?
-- Forth is a preserver of health (Hippocrates)
In comp.lang.forth, Zbiggy wrote:
> I'm afraid, I didn't completely understood: what you mean by writing, that
> "cooperative multitasking is effortless"? What it was unable to do?
Did you mean perhaps, that by obeying the mentioned rule there wasn't any
problems with taking over entire CPU time?
-- Forth is a preserver of health (Hippocrates)
>> I'm afraid, I didn't completely understood: what you mean by writing, that
>> "cooperative multitasking is effortless"? What it was unable to do?
> Did you mean perhaps, that by obeying the mentioned rule there wasn't any
> problems with taking over entire CPU time?
That's exactly what I mean: you don't have to *do* anything other than respecting the rules to make everything work ok.
Cheers,
Elizabeth
-- ==================================================
Elizabeth D. Rather (US & Canada) 800-55-FORTH
FORTH Inc. +1 310.999.6784
5959 West Century Blvd. Suite 700
Los Angeles, CA 90045
http://www.forth.com
"Forth-based products and Services for real-time
applications since 1973."
==================================================
In article <b6d4be14-a3dc-49f3-a90a-be9086b68...@18g2000yqe.googlegroups.com>,
Brad <hwfw...@gmail.com> wrote:
>On Feb 13, 9:26=A0am, Andrew Haley <andre...@littlepinkcloud.invalid>
>wrote:
>> In all of them: it's not just about space saving, it's about
>> correctness. =A0You don't want tasks with different opinions about the
>> contents of a particular block.
>I was going to say that embedded Forthers like me wouldn't use blocks,
>but then it just occurred to me that blocks would be a great way for a
>16-bit Forth to deal with large SPI flash.
Or on chip flash for that matter.
My renesas ciforth takes advantage of a 1 Mbyte on chip flash
to store the library. Bottom line is that it behaves much like
a lina or wina system. It has renesas specific code to make a
turnkey, such that e.g. after reset it behaves as a clock
playing big ben at the hours.
See also renesas.html on my site below.
>-Brad
Groetjes Albert
--
-- Albert van der Horst, UTRECHT,THE NETHERLANDS
Economic growth -- being exponential -- ultimately falters.
albert@spe&ar&c.xs4all.nl &=n http://home.hccnet.nl/a.w.m.van.der.horst
Andrew Haley <andre...@littlepinkcloud.invalid> writes:
> In all of them: it's not just about space saving, it's about
> correctness. You don't want tasks with different opinions about the
> contents of a particular block.
But that sounds pretty awful-- a task allocates a buffer and another
task can go and mess with it if you do a debugging print? It sounds
like a potential source of bugs, given no obvious way to tell whether a
given word might have some i/o effect. I'd have expected in a memory
constrained system, to just put a single task in charge of any buffers
on a particular file.
> Andrew Haley<andre...@littlepinkcloud.invalid> writes:
>> In all of them: it's not just about space saving, it's about
>> correctness. You don't want tasks with different opinions about the
>> contents of a particular block.
> But that sounds pretty awful-- a task allocates a buffer and another
> task can go and mess with it if you do a debugging print? It sounds
> like a potential source of bugs, given no obvious way to tell whether a
> given word might have some i/o effect. I'd have expected in a memory
> constrained system, to just put a single task in charge of any buffers
> on a particular file.
There's really a lot of design involved in the block management scheme, really more than it's possible to summarize neatly here. If you have access to my Forth Programmer's Handbook (pdf included in SwiftForth free eval) there's an extended discussion of multitasking, blocks and buffers, and all that jazz.
Briefly, buffers aren't "allocated". They are configured as a part of the architecture of the system. They're always there. The disk management system (which includes the word BLOCK, BUFFER, and the rest of the machinery, makes a block in a buffer available to any task that requests it. Actual reads and writes are transparent.
As for knowing "whether a given word might have some I/O effect," it's really pretty obvious: you know when you accept input, display text, read or write disk, or access any application-specific device, etc., don't you?
Cheers,
Elizabeth
-- ==================================================
Elizabeth D. Rather (US & Canada) 800-55-FORTH
FORTH Inc. +1 310.999.6784
5959 West Century Blvd. Suite 700
Los Angeles, CA 90045
http://www.forth.com
"Forth-based products and Services for real-time
applications since 1973."
==================================================
> One must take a broad view of what defines I/O: for example, writing a
> character to a screen is I/O, even if the "screen" is in a local frame
> buffer. And any drivers that the programmer adds must also follow the
> rule. So long as everyone respects this rule, cooperative multitasking
> is effortless and in over 30 years of application programming I don't
> recall any problems.
Well... in a system with different task priority levels (eg PLCs) one usually wants deterministic time behaviour and triggered emergency programs.
It can become quite fiddlish to do it with cooperative multitasking only.
But fortunately not all RT systems demand it. So generally you are right.
>> One must take a broad view of what defines I/O: for example, writing a
>> character to a screen is I/O, even if the "screen" is in a local frame
>> buffer. And any drivers that the programmer adds must also follow the
>> rule. So long as everyone respects this rule, cooperative multitasking
>> is effortless and in over 30 years of application programming I don't
>> recall any problems.
> Well... in a system with different task priority levels (eg PLCs) one
> usually wants deterministic time behaviour and triggered emergency
> programs.
> It can become quite fiddlish to do it with cooperative multitasking only.
> But fortunately not all RT systems demand it. So generally you are right.
Depending on what response time you require, it's usually possible to ensure adequate response. Actually, I only remember one occasion in which we had to tweak the algorithm a bit, and that was 20+ years ago, when processors were a lot slower than they are today. Guaranteeing response times with a millisecond is no problem, and usually you can do much better.
Cheers,
Elizabeth
-- ==================================================
Elizabeth D. Rather (US & Canada) 800-55-FORTH
FORTH Inc. +1 310.999.6784
5959 West Century Blvd. Suite 700
Los Angeles, CA 90045
http://www.forth.com
"Forth-based products and Services for real-time
applications since 1973."
==================================================
Zbiggy <zbigniew2011REM...@gmail.remove.com> wrote:
> In comp.lang.forth, Elizabeth D. Rather wrote:
>> If you're writing portable code that may run on a multitasked Forth you >> should respect the rule.
> Of course, but I had in mind the ability of blocks - mentioned in SF
> - which I particularly like: to use it as kind of "swap partition"
> equivalent. It seems, it should be used with much greater care, than
> I thought at first: we don't want data "swapped" to blocks to get
> corrupted.
> Or maybe it's not possible at all in multitasked environment - at
> least not in the way similar to one, in which Linux uses its swap
> partitions/files: actually, we cannot block I/O operations at all
> just to make sure, they won't allow buffers affection. The machine
> would be unusable.
In practice it's not a problem. If you want an array on disk you can
do something like
A. K. <a...@nospam.org> wrote:
> On 13.02.2012 19:23, Elizabeth D. Rather wrote:
>> One must take a broad view of what defines I/O: for example, writing a
>> character to a screen is I/O, even if the "screen" is in a local frame
>> buffer. And any drivers that the programmer adds must also follow the
>> rule. So long as everyone respects this rule, cooperative multitasking
>> is effortless and in over 30 years of application programming I don't
>> recall any problems.
> Well... in a system with different task priority levels (eg PLCs) one > usually wants deterministic time behaviour and triggered emergency programs.
> It can become quite fiddlish to do it with cooperative multitasking only.
> But fortunately not all RT systems demand it. So generally you are right.
The "trick", if you can call it one, is that the multi-tasker is so
lightweight that it has almost no overhead. Deterministic behaviour
to guarantee strict response times can be achieved by doing things
that really need to be done immediately (i.e. microseconds) in an
interrupt routine and passing the rest to a task. Because a task
switch is done on every I/O operation, the multi-tasker is running
very much faster than conventional time-sliced systems, perhaps
thousands of times faster. A task switch is not much more expensive
than a call, and usually most tasks will be sleeping most of the time.
So, the time between an interrupt happening and the associated task
doing the work can be very short. Millisecond response times are not
hard to do at all, and that was true even on the processors of twenty
years ago.
In article <slrnjjir92.ald.zbigniew2011REM...@Tichy.myhome.org>,
Zbiggy <zbigniew2011REM...@gmail.REMOVE.com> wrote:
>In comp.lang.forth, Elizabeth D. Rather wrote:
>> If you're writing portable code that may run on a multitasked Forth you
>> should respect the rule.
>Of course, but I had in mind the ability of blocks - mentioned in SF - which
>I particularly like: to use it as kind of "swap partition" equivalent. It
>seems, it should be used with much greater care, than I thought at first: we
>don't want data "swapped" to blocks to get corrupted.
It is not too bad. Each time you use the BLOCK word, it is checked
whether the BLOCK is in memory.
E.g.
HEX 10 0 DO I #LINE * DUP BLOCK + #LINE TYPE CR LOOP
Don't do the BLOCK outside of the loop!
>Or maybe it's not possible at all in multitasked environment - at least not
>in the way similar to one, in which Linux uses its swap partitions/files:
>actually, we cannot block I/O operations at all just to make sure, they won't
>allow buffers affection. The machine would be unusable.
Groetjes Albert
--
-- Albert van der Horst, UTRECHT,THE NETHERLANDS
Economic growth -- being exponential -- ultimately falters.
albert@spe&ar&c.xs4all.nl &=n http://home.hccnet.nl/a.w.m.van.der.horst
> A. K.<a...@nospam.org> wrote:
>> On 13.02.2012 19:23, Elizabeth D. Rather wrote:
>>> One must take a broad view of what defines I/O: for example, writing a
>>> character to a screen is I/O, even if the "screen" is in a local frame
>>> buffer. And any drivers that the programmer adds must also follow the
>>> rule. So long as everyone respects this rule, cooperative multitasking
>>> is effortless and in over 30 years of application programming I don't
>>> recall any problems.
>> Well... in a system with different task priority levels (eg PLCs) one
>> usually wants deterministic time behaviour and triggered emergency programs.
>> It can become quite fiddlish to do it with cooperative multitasking only.
>> But fortunately not all RT systems demand it. So generally you are right.
> The "trick", if you can call it one, is that the multi-tasker is so
> lightweight that it has almost no overhead. Deterministic behaviour
> to guarantee strict response times can be achieved by doing things
> that really need to be done immediately (i.e. microseconds) in an
> interrupt routine and passing the rest to a task. Because a task
> switch is done on every I/O operation, the multi-tasker is running
> very much faster than conventional time-sliced systems, perhaps
> thousands of times faster. A task switch is not much more expensive
> than a call, and usually most tasks will be sleeping most of the time.
> So, the time between an interrupt happening and the associated task
> doing the work can be very short. Millisecond response times are not
> hard to do at all, and that was true even on the processors of twenty
> years ago.
> Andrew.
Yeah, you're right, of course.
However in some RT systems you need to implement a scheduler. It manages interrupt handling priorities, monitors time slices, and kills blocked tasks or stops tasks that do not behave nicely (eg that overuse their assigned time contingent).
Then it's a bit more than PAUSE. ;-)
And: cooperative multitasking offends against Murphy's law. :-))
> In article <slrnjjir92.ald.zbigniew2011REM...@Tichy.myhome.org>,
> Zbiggy <zbigniew2011REM...@gmail.REMOVE.com> wrote:
>>In comp.lang.forth, Elizabeth D. Rather wrote:
>>> If you're writing portable code that may run on a multitasked Forth you
>>> should respect the rule.
>>Of course, but I had in mind the ability of blocks - mentioned in SF - which
>>I particularly like: to use it as kind of "swap partition" equivalent. It
>>seems, it should be used with much greater care, than I thought at first: we
>>don't want data "swapped" to blocks to get corrupted.
> It is not too bad. Each time you use the BLOCK word, it is checked
> whether the BLOCK is in memory.
> E.g.
> HEX 10 0 DO I #LINE * DUP BLOCK + #LINE TYPE CR LOOP
That won't work: you need to copy the line to e.g. PAD before calling
TYPE. Forth, Inc have always included a word to do this.
A. K. <a...@nospam.org> wrote:
> However in some RT systems you need to implement a scheduler. It
> manages interrupt handling priorities, monitors time slices, and
> kills blocked tasks or stops tasks that do not behave nicely (eg
> that overuse their assigned time contingent).
I suspect that a lot of the heroic efforts made by systems with
priority schedulers really just compensate for the fact that they're
not fast enough. Also, as soon as you have pre-emption you need a lot
of code to handle mutexes, semaphores, and so on, and this slows down
the system even more.
It's different, of course, if you are sharing a general-purpose
operating system with untrusted code, but that's a very different kind
of system.
> Then it's a bit more than PAUSE. ;-)
> And: cooperative multitasking offends against Murphy's law. :-))
I don't think so: if you have all that code that depends on priorities
to work correctly, you have a lot more that can go wrong.
>> However in some RT systems you need to implement a scheduler. It
>> manages interrupt handling priorities, monitors time slices, and
>> kills blocked tasks or stops tasks that do not behave nicely (eg
>> that overuse their assigned time contingent).
> I suspect that a lot of the heroic efforts made by systems with
> priority schedulers really just compensate for the fact that they're
> not fast enough.
Sad but true. But industry automation cannot afford to chase after every hardware innovation of the semiconductor industry. Typical DCS life spans are 15 years.
> Also, as soon as you have pre-emption you need a lot
> of code to handle mutexes, semaphores, and so on, and this slows down
> the system even more.
But whether you do this on top of a RTOS or as part of your Forth application doesn't matter. You have to spend processor cycles on managing RT events either way.
> It's different, of course, if you are sharing a general-purpose
> operating system with untrusted code, but that's a very different kind
> of system.
Why untrusted? Just because it's developed by others? How can you be sure that your own code is bug-free?
A. K. <a...@nospam.org> wrote:
> On 14.02.2012 14:52, Andrew Haley wrote:
>> A. K.<a...@nospam.org> wrote:
>> Also, as soon as you have pre-emption you need a lot of code to
>> handle mutexes, semaphores, and so on, and this slows down the
>> system even more.
> But whether you do this on top of a RTOS or as part of your Forth > application doesn't matter. You have to spend processor cycles on > managing RT events either way.
Of course, but that's way different from doing things that are only
necessary because of the type of scheduler in use.
>> It's different, of course, if you are sharing a general-purpose
>> operating system with untrusted code, but that's a very different
>> kind of system.
> Why untrusted? Just because it's developed by others? How can you be > sure that your own code is bug-free?
You can't, but pre-emption doesn't necessarily make the system as a
whole any more reliable. If you end up with a system that is more
complex than it needs to be then there's more of it to go wrong.
Adding things like pre-emption for tasks that have run too long is
just sticking plaster. Sure, it's always good to have a watchdog, and
this will trigger if any task runs too long, but that's really for
hardware failures. It's a poor substitute for getting the software
right.