HERE & THERE was published by FIFTH GENERATION SYSTEMS for about a year until they were acquired by SYMANTAC. SYMANTEC was the publisher of pcANYWHERE the number one remote control product at the time. The end for HERE & THERE. Not? Read on.
HERE & THERE has many advantages.
HERE & THERE was a DOS product. OEM applications developed using the real time multitasking kernel include SYMBOL technology’s DM800 industrial data collection terminal.
HERE & THERE a registered trademark of DSTechnology was authored by Breck Auten and myself. Breck wrote most of the code, and is the major developer. My roll was of a system architect. The real time multitasking kernel and COM protocol where my major code designs as was the overall modular task and library interfaces. I was working for TrueData and Symbol during most of the development period of the origional Here & There product. This was origionally part of my employment agreement with TrueData. I later joined DST now DSTechnology where I eventually rewrote the real time kernel and implemented it in a windows VXD making HERE & THERE a windows product.
For a current look at what DSTechnology is doing. Check it out!!
HERE & THERE is no longer on the market. DSTechnology currently owns the product. It runs with WINDOWS and DOS. I currently use it to support my customers remotely.
I would like to brag about the kernel a little if I may keep your attention a little longer. Read ON:
For you AMIGA fans 'Me too!' The real-time kernel was based a lot on the AMIGA DOS programming interface and the TOPS-10 time sharing operating system by DIGITAL EQUIPMENT CORP. It provides a resident program library interface that could be opened by programs loaded afterward. Event queues provided the same functionality as AMIGA DOS. Tasks could block until an event occurred. Events can be posted by tasks, interrupt or sched level by servers. Resource queues allow exclusive use of a shared resource. For you windows programmers a resource here is not an object but a single threaded piece of code that can only be executed by one task at a time. The display is a resource that only one task is allowed to update at a time.
Device handlers are divided in to two separate parts, the hardware device driver interface, and the logical server interface. These are separately loadable modules. The hardware device driver part provided the physical interface to setup the device, start I/O, and handle interrupts (getting data from the device or putting data to the device). The logical server part calls the device to start output, enable input, providing the address of the code to handle the data interrupts. The server makes calls to the device to send and receive data or end the interrupt when I/O is completed at interrupt level. The server provided the task level interface usually as a public library.
An example of this abstraction is COM device drivers for the 8250(16450, 16550) and the 8530 where written. These are common serial chips. The 8250 type used in the PC's and the 8530 is used on the MAC. The device driver for the 8250-type device runs on a standard PC. And the 8530 driver runs on the DM800 data collection terminal. Servers where written that provided the standard PC int. 14h serial interface, the HERE & THERE virtual circuit protocol, SYMBOL's multidrop polling protocol, and the multidrop polled protocol. All the server modules ran on the DM800 terminals as well as PC's. That's not new you say, the PC does that now with it's int. 14H serial interface. You missed the concept. The interface above allows logical handling of data at interrupt level. Data is passed from the device driver to the server modules at interrupt level thus reducing the overhead of handling the data multiple times. The server interrupt logic is written as a sequence of instructions making calls to the device to get and put characters. The current state is saved in the call stack. This makes writing COM protocol drivers very easy, efficient and device independent.
But wait, there’s more. Servers could post routines to be run at sched level. Sched level is between interrupt and task level. Sched routines run before returning to task level, after all interrupts have been serviced. If an interrupt routine or a sched routine sets the sched flag, the scheduler is called after running all sched routines, just before returning to task level and a task switch may result (Preemptive scheduling). Sched level routines are used to reduce time spent in interrupt routines, as they are interruptible,
The scheduler algorithm and "sched level" was based on the TOPS-TEN operating system. TOPS TEN ran on DEC system 10's built by DIGITAL EQUIPMENT CORP. unlike TOPS TEN tasks are implemented as a control structure. There may be any number of tasks as long they all fit in memory. Our kernel’s primary goal was to schedule resident tasks handling communications. Run queues are structures containing lists of tasks to be run. Each queue specified the time allotted to a task and a queue to transfer the task to when the time runs out. A task would be put on the end of the transfer queue when its time expired. This queue could be the same or another (usually lower priority) queue. A preempted task would be placed on the front of the queue from which it came. When ever a user input request returned the transfer queue of the task is set to its priority queue.
What does that mean?
All right the normal run queue configuration consisted of several priority run queues followed by the normal run queues, of which are where two. The priority queues transferred expired tasks to them selves. The normal run queues, priority 0 tasks and expired priority 0 tasks, call then N queue and X queue. Priority 0 tasks start in N queue and transferred to X queue once their allotted time is expired in N. N tasks where given a short time (3 ticks) If a task where getting characters it would stay in the N queue. But when it is compute bound it would transfer to the lower priority X queue. Tasks in the X queue ran for much longer periods (30 ticks, 1/2 second) before expiring. The scheduler looks for a task to run starting from highest run queue searching to the lowest. One other thing! Each queue has a fairness count and counter. Each time a queue provides a task to run the fairness counter is decremented and on zero the skip this queue flag is set. When the scheduler encounters a queue with the flag set the fairness counter is reset with the fairness count and if it is not now zero the queue is skipped. The N queue has a fairness count of say ten. A task in the X queue will run every tenth time a task (if there are any) in the N queue is run. Of course X queue tasks would always run when there no tasks in the N queue.
Note that this scheduler punishes tasks polling for input, as a compute bound task in the X queue would hold the processor for 30 seconds at a time. A task waiting for input would immediately go to the N queue when a character a received. And would be a candidate to run before the X queue tasks as when ever a task is transfers to any run queue the scheduler will be called before returning to task level.
DOS and WINDOWS were treated as one task operating under the control of our kernel. You know, Microsoft told me it was impossible to do what I did. I was able to keep real mode tasks running (that is, that were running before windows loaded) running after windows loaded. And new tasks could be started in a DOS box.