[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Is it possilble to use timer interrupt in Apple II?



Albert D. Kallal wrote:
"bluebird" <mildstorm@gmail.com> wrote in message 5b2e7db1-50d9-4fe9-a554-fe267fcd0c66@h14g2000pri.googlegroups.com">news:5b2e7db1-50d9-4fe9-a554-fe267fcd0c66@h14g2000pri.googlegroups.com...

That's very bad news.

Then we can't make any operating system in Apple II environment.

Is there any workaround for multi-threading without any expansion slot
card?



The above is not true at all, ask yourself in a game how you can have two or three objects moving in all different directions on the screen at the same time, and process keyboard and mouse clicks at the same time?

Actually, most cases of multiple objects moving on the screen is
done by simply advancing all objects by one time step in a common
routine, not by assigning different threads to each object.

This is the usual way of supporting _apparent_ concurrency on a single-
threaded machine.

What it means if you write an operating system in this type of environment, you'll not use a preemptive, or timing mechanism to service the processes that run.

So you can make an operating system, but perhaps not the type you want.

One of the most common is a "service loop" style, where the program
constantly executes a loop in which short service routines run if a
condition is met.

This style is quite common in embedded controller programming, and
on the Apple II it is often done even in Applesoft!

I remember lots of programming and coding using applesoft basic. One of the things I really missed is that when a screen was repotting you could not type ahead. You could not use the type the head buffer, because there was no type ahead buffer!

This was purely a Microsoft design decision.  The Applesoft interpreter
is constantly interrogating the keyboard, but is looking only for the
ctl-C character to cause a "break".  It could have easily implemented
a type-ahead capability with no more overhead, but didn't.

However if you ever programmed using the UCSD Pascal system, you would notice that while the screen is re plotting and displaying text, you had a full type ahead buffer for as long as you wanted to type. And note carefully how this type ahead buffer was implemented. There was NO keyboard interrupt occurring here. That means as you pressed a key, there was ONLY a built in buffer of ONE key in the hardware. (and to be totally fair, I actually think the Pascal operating system had a limit of 59 characters?? Someone do jump in to correct me on how many characters the UCSD type ahead buffer was)

So the next question you have to ask yourself is how one earth did the UCSD Pascal development system have an very nice type ahead buffer and accomplish feat this without keyboard interrupts or without a timer system to stop the current code that's running, and then tell the system please check the keyboard?

The answer is that (like Applesoft) Pascal is a fully interpretive
system, and it is easy to embed a keyboard poll into the interpreter
so that it is tested very frequently during execution.

In fact, this implements an "interpreter interrupt", exactly analogous
to the way a hardware interrupt is polled by the fetch/execute loop of
the processor.

Timer based hardware interrupted systems = preemptive multitasking:

In this type of system, the operating system will only give a program so much time before it chops its legs off, stops that program and then has the processor go to work on the next program that happens to be running in the operating system. In this kind of software development environment, the program running does not have to worry about trying to give up or release its processing to other applications that may be running. It is a single thread.

Software based, or what we call cooperative multitasking means that each piece of code you write in that system has to have at certain points in the code or by the software compiler design have parts in the code that will release itself back to the operating system.

So for example the UCSD Pascal system had display routines that during drawing characters and data to the screen it also had calls to service the keyboard input buffer. In fact, even for programming on the apple Macintosh, or other systems before preemptive multitasking occurred, you often had to write your own main event loop in your software eg:

loop
       call code to service display screen update

       call code to service input buffer routines

       Call code to server disk drive activity

       Call code to service printer activity

       call code to get users menu choice
       select menu choice
           Call menu option 1
           Call menu option 2
           Call menu option 3
      end select

repeat


So, you can most certainly design and develop an operating system that's not based on preemptive multitasking. There was a good many operating systems that worked in this fashion, and the Pascal UCSD system for the apple was an perfect example of such a OS.

You cannot imagine what a delightful experience it was to work on the apple II using UCSD and Pascal.

Not only was code editing and writing of programs absolutely beautiful and butter smooth with type-ahead, you also had the ability to have parts of the applications dynamically load right off the floppy drive.

I once compiled one of my text input routines to be dynamically loaded on the Apple II. This would mean that as long as you typed on the keyboard the floppy drive would actually spin and run for every character you typed (as it loaded the code). Really amazing, but the REST of the os (screen, keyboard input) etc. ALL continued to run butter smooth WHILE the floppy disk drive was running and loading code. If you kept typing, the floppy would spin! (and, that it was pretty cool because you made sure you type a few more characters before the floppy drive timeout occurred! If the floppy drive stopped, then type the a character, it took quite a while for the floppy drive spin back up to speed).

Actually, though you can easily poll the keyboard between disk
operations (like read block or write block), you cannot do any polling
of anything else while a disk read or write is occurring.  This includes
at least the rotational latency while the disk driver is reading,
waiting for the correct sector header.

Of course, if disk I/O is performed by the system one block at a time,
then it can poll between blocks.  Still, the latency for polling would
vary between the rotational span of one block and that time plus a full
rotation, or about 100-200 milliseconds (which would be a problem for
a fast typer).

Contrast the above behavior as to when using Applesoft BASIC and you executed a load from the floppy drive - all the code and virtually everything else like the display froze during the disk drive load/activity .

Because DOS and ProDOS disk operations do not poll between blocks, not
because of anything fundamental.

Type-ahead requires not only thorough support by the programming
environment and OS, but also recovery code to occasionally purge
the type-ahead buffer (for example, when an error occurs and the
buffer is likely to be useless).

Many users find type-ahead buffering confusing in some cases, since
it decouples the user's input from the system's operations.  While
an experienced command line user might be quite at home with it,
a user running an accounting package where keys switch screens might
prefer to wait to see the actual state of the program before proceeding
with his next input.

Although you used it only as an example, it is not difficult to see
how one design team could choose to implement it and another might
not.

So, just to be clear here you CAN write a OS on the Apple II. And, you can even write an multitasking system on the apple II. However, without a timer, it's going to be very difficult (if not impossible) without interrupts to write a preemptive multitasking system. In theory inserting some type of board with a timer would allow the interrupts to force the os to move on to the next program that requires servicing. (that next program might be disk i/o, display, or another user program).

It is useful to regard interrupts as "procedure calls from heaven",
in the sense that the "call" occurs only when a hardware poll in the
processor's fetch/execute loop observes the assertion of the interrupt
request line (after masking).

Any interpretive system can easily implement "interpretive interrupts"
based on polling any condition in the hardware or software.  (In fact,
interpreters often "interrupt" if their stack or heap overflows.)

As a practical matter, saving and restoring state, either during
interrupt processing or during a task/thread swap, is a frequent
activity, and therefore must be relatively efficient.  The 6502's
lovely page zero, with all its "address registers", becomes a real
liability if it must be saved and restored.  Therefore most practical
multithreading approaches for the 6502 choose to severely restrict
a task's/thread's use of page zero to save overhead.

-michael

NadaNet and AppleCrate II: parallel computing for Apple II computers!
Home page: http://home.comcast.net/~mjmahon

"The wastebasket is our most important design
tool--and it's seriously underused."