Thread overview | ||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
September 21, 2003 Preemptive multitasker for DM - mtask2.dm.zip | ||||
---|---|---|---|---|
| ||||
Attachments: | This multitasking library is a port of something I originally wrote for real-mode DOS with Borland C. Porting it to DM allowed me to break the 640K barrier and it was an easy and pleasant job due to the excellent compiler´s features. It was originally written for educational purposes, since I use it for teaching operating systems and IPC primitives. However, I think now it is perfectly usable for professional applications. This software is public domain. Please don´t hesitate to send me any feedback, whether criticism, bug reports or improvements. Hugo Etchegoyen Buenos Aires, Argentina hee@fibertel.com.ar hetchegoyen@hasar.com |
September 22, 2003 Re: Preemptive multitasker for DM - mtask2.dm.zip | ||||
---|---|---|---|---|
| ||||
Posted in reply to hee | <hee@fibertel.com.ar> wrote in message news:bkj3vu$ht5$1@digitaldaemon.com... > This multitasking library is a port of something I originally wrote for real-mode DOS with Borland C. Porting it to DM allowed me to break the 640K > barrier and it was an easy and pleasant job due to the excellent compiler´s > features. It was originally written for educational purposes, since I use it for > teaching operating systems and IPC primitives. However, I think now it is perfectly usable for professional applications. Great! The documentation is here: www.digitalmars.com/user/mtask.html |
September 22, 2003 Re: Preemptive multitasker for DM - mtask2.dm.zip | ||||
---|---|---|---|---|
| ||||
Posted in reply to hee | Looks nice. Certainly better than a couple of method I have seen before (e.g. J.English, S. Kofoed etc) Since you are using timer int, it is relatively easier to change the counter value to achieve something like a task switch of say 1000Hz. In this way, you can also have true milliseconds sleep function. To set clock rate (real mode) - originally published in Byte.com: static void setclkrate(unsigned short timerval) { __asm mov al, 0x36 __asm out 0x43, al __asm mov ax, timerval __asm out 0x40, al __asm mov al, ah __asm out 0x40, al } Then have a couple of counters to track original 55ms static unsigned short clkdiv, clkdivh, clkdivl, clkmod; static void __interrupt clkint() { // Call the clock interrrupt here;;;; __asm mov ax, clkdivl __asm add clkmod, ax __asm mov ax, clkdivh __asm adc ax, 0 __asm jnz cint8 __asm mov al, 0x20 __asm out 020H, al __asm jmp cint7 cint8: (*oldvec)(); // Old clock interrupt cint7: __asm mov ax, clkdiv __asm cmp ax, clkdivl __asm je exit __asm push ax __asm call setclkrate __asm pop ax __asm mov clkdivl, ax __asm cmp ax, 1 __asm mov clkdivh, 0 __asm adc clkdivh, 0 exit: ; } <hee@fibertel.com.ar> wrote in message news:bkj3vu$ht5$1@digitaldaemon.com... > This multitasking library is a port of something I originally wrote for real-mode DOS with Borland C. Porting it to DM allowed me to break the 640K barrier and it was an easy and pleasant job due to the excellent compiler´s features. It was originally written for educational purposes, since I use it for teaching operating systems and IPC primitives. However, I think now it is perfectly usable for professional applications. > > This software is public domain. Please don´t hesitate to send me any feedback, whether criticism, bug reports or improvements. > > > Hugo Etchegoyen > Buenos Aires, Argentina > hee@fibertel.com.ar > hetchegoyen@hasar.com > |
September 22, 2003 Re: Preemptive multitasker for DM - mtask2.dm.zip | ||||
---|---|---|---|---|
| ||||
Posted in reply to KarL | In article <bklr7g$290s$1@digitaldaemon.com>, KarL says... > >Looks nice. Certainly better than a couple of method I have seen before (e.g. J.English, S. Kofoed etc) > >Since you are using timer int, it is relatively easier to change the counter value to achieve something like a task switch of say 1000Hz. In this way, you can also have true milliseconds sleep function. > >To set clock rate (real mode) - originally published in Byte.com: > >static void setclkrate(unsigned short timerval) >{ > __asm mov al, 0x36 > __asm out 0x43, al > __asm mov ax, timerval > __asm out 0x40, al > __asm mov al, ah > __asm out 0x40, al >} > >Then have a couple of counters to track original 55ms > >static unsigned short clkdiv, clkdivh, clkdivl, clkmod; > >static void __interrupt clkint() >{ > > // Call the clock interrrupt here;;;; > > __asm mov ax, clkdivl > __asm add clkmod, ax > __asm mov ax, clkdivh > __asm adc ax, 0 > __asm jnz cint8 > __asm mov al, 0x20 > __asm out 020H, al > __asm jmp cint7 > >cint8: > (*oldvec)(); // Old clock interrupt > >cint7: > __asm mov ax, clkdiv > __asm cmp ax, clkdivl > __asm je exit > __asm push ax > __asm call setclkrate > __asm pop ax > __asm mov clkdivl, ax > __asm cmp ax, 1 > __asm mov clkdivh, 0 > __asm adc clkdivh, 0 >exit: ; >} > You are right, Karl, there is a lot to be improved in the handling of the timer interrupt. Certainly a 1 kHz interrupt calling the old vector once every 55 counts would be ideal, since 'timer ticks' would be the same as 'milliseconds', my only concern here is whether the overhead of 1k interrupts per second would not be too much. Probably a configurable time granularity would be best, then you could set it to the best compromise according to your needs and to your hardware. Also trapping the real time interrupt from the application level is not possible right now, since it is trapped in the kernel. It would be nice if the application could install callbacks to be called from the timer interrupt every so many milliseconds, something like the poll feature in Unix. I don't promise dates, but I will try to include these features. If someone does it before, please tell me. Thank you, Hugo. |
September 22, 2003 Re: Preemptive multitasker for DM - mtask2.dm.zip | ||||
---|---|---|---|---|
| ||||
Posted in reply to Hugo Etchegoyen | You should look into the mmtimer of windows, which has a rate of up to 1ms , is very accurate and can call code in a dll you supply,
chris
Hugo Etchegoyen wrote:
> In article <bklr7g$290s$1@digitaldaemon.com>, KarL says...
>
>>Looks nice. Certainly better than a couple of method I have seen
>>before (e.g. J.English, S. Kofoed etc)
>>
>>Since you are using timer int, it is relatively easier to change the
>>counter value to achieve something like a task switch of say
>>1000Hz. In this way, you can also have true milliseconds sleep
>>function.
>>
>>To set clock rate (real mode) - originally published in Byte.com:
>>
>>static void setclkrate(unsigned short timerval)
>>{
>> __asm mov al, 0x36
>> __asm out 0x43, al
>> __asm mov ax, timerval
>> __asm out 0x40, al
>> __asm mov al, ah
>> __asm out 0x40, al
>>}
>>
>>Then have a couple of counters to track original 55ms
>>
>>static unsigned short clkdiv, clkdivh, clkdivl, clkmod;
>>
>>static void __interrupt clkint()
>>{
>>
>> // Call the clock interrrupt here;;;;
>>
>> __asm mov ax, clkdivl
>> __asm add clkmod, ax
>> __asm mov ax, clkdivh
>> __asm adc ax, 0
>> __asm jnz cint8
>> __asm mov al, 0x20
>> __asm out 020H, al
>> __asm jmp cint7
>>
>>cint8:
>> (*oldvec)(); // Old clock interrupt
>>
>>cint7:
>> __asm mov ax, clkdiv
>> __asm cmp ax, clkdivl
>> __asm je exit
>> __asm push ax
>> __asm call setclkrate
>> __asm pop ax
>> __asm mov clkdivl, ax
>> __asm cmp ax, 1
>> __asm mov clkdivh, 0
>> __asm adc clkdivh, 0
>>exit: ;
>>}
>>
>
>
> You are right, Karl, there is a lot to be improved in the handling of the timer
> interrupt.
>
> Certainly a 1 kHz interrupt calling the old vector once every 55 counts would be
> ideal, since 'timer ticks' would be the same as 'milliseconds', my only concern
> here is whether the overhead of 1k interrupts per second would not be too much.
> Probably a configurable time granularity would be best, then you could set it to
> the best compromise according to your needs and to your hardware.
>
> Also trapping the real time interrupt from the application level is not possible
> right now, since it is trapped in the kernel. It would be nice if the
> application could install callbacks to be called from the timer interrupt every
> so many milliseconds, something like the poll feature in Unix.
>
> I don't promise dates, but I will try to include these features. If someone does
> it before, please tell me.
>
> Thank you,
>
> Hugo.
>
>
|
September 22, 2003 Re: Preemptive multitasker for DM - mtask2.dm.zip | ||||
---|---|---|---|---|
| ||||
Posted in reply to chris elliott | Sorry Chris, we are talking about DOSX running in embedded systems. "chris elliott" <biol75@york.ac.uk> wrote in message news:bkms4k$1r5e$1@digitaldaemon.com... > You should look into the mmtimer of windows, which has a rate of up to 1ms , is very accurate and can call code in a dll you supply, > > chris > > Hugo Etchegoyen wrote: > > > In article <bklr7g$290s$1@digitaldaemon.com>, KarL says... > > > >>Looks nice. Certainly better than a couple of method I have seen before (e.g. J.English, S. Kofoed etc) > >> > >>Since you are using timer int, it is relatively easier to change the counter value to achieve something like a task switch of say 1000Hz. In this way, you can also have true milliseconds sleep function. > >> > >>To set clock rate (real mode) - originally published in Byte.com: > >> > >>static void setclkrate(unsigned short timerval) > >>{ > >> __asm mov al, 0x36 > >> __asm out 0x43, al > >> __asm mov ax, timerval > >> __asm out 0x40, al > >> __asm mov al, ah > >> __asm out 0x40, al > >>} > >> > >>Then have a couple of counters to track original 55ms > >> > >>static unsigned short clkdiv, clkdivh, clkdivl, clkmod; > >> > >>static void __interrupt clkint() > >>{ > >> > >> // Call the clock interrrupt here;;;; > >> > >> __asm mov ax, clkdivl > >> __asm add clkmod, ax > >> __asm mov ax, clkdivh > >> __asm adc ax, 0 > >> __asm jnz cint8 > >> __asm mov al, 0x20 > >> __asm out 020H, al > >> __asm jmp cint7 > >> > >>cint8: > >> (*oldvec)(); // Old clock interrupt > >> > >>cint7: > >> __asm mov ax, clkdiv > >> __asm cmp ax, clkdivl > >> __asm je exit > >> __asm push ax > >> __asm call setclkrate > >> __asm pop ax > >> __asm mov clkdivl, ax > >> __asm cmp ax, 1 > >> __asm mov clkdivh, 0 > >> __asm adc clkdivh, 0 > >>exit: ; > >>} > >> > > > > > > You are right, Karl, there is a lot to be improved in the handling of the timer interrupt. > > > > Certainly a 1 kHz interrupt calling the old vector once every 55 counts would be ideal, since 'timer ticks' would be the same as 'milliseconds', my only concern here is whether the overhead of 1k interrupts per second would not be too much. Probably a configurable time granularity would be best, then you could set it to the best compromise according to your needs and to your hardware. > > > > Also trapping the real time interrupt from the application level is not possible right now, since it is trapped in the kernel. It would be nice if the application could install callbacks to be called from the timer interrupt every so many milliseconds, something like the poll feature in Unix. > > > > I don't promise dates, but I will try to include these features. If someone does it before, please tell me. > > > > Thank you, > > > > Hugo. > > > > > |
September 23, 2003 Re: Preemptive multitasker for DM - mtask2.dm.zip | ||||
---|---|---|---|---|
| ||||
Posted in reply to Hugo Etchegoyen Attachments:
| Actually, I do have one. I modified S Kofoed's original version available from Nov. 1995 DDJ to include a few features: 1) ± 1ms resolution sleep(n) function. 2) Real time callback at 1ms. 3) Actived time log. I found the 1kHz thread switch doesn't cause much overheads. In fact, if I increase the clock to 5kHz, I get better timing resolution without compromising speed. For what I need, my timing requirements are about 2 to 3 milliseconds. With the 1kHz callback, I can drive DAC output or sound chip waveform controls quite accurately. It is not pre-emptive but with good coorporative thread design, I am able to use it to run on embedded PC-104 board beautifully. It is not DOSX yet. I might port it one day but since you have done the pre-emptive version, I might leave it as that. I also have a couple of graphics libraries, serial comms, associated with that library. If Walter thinks it is a good idea, I would eventually document them and put it on my web site for all. I haven't done so is because I am too embarass I still don't write good template class. So those code still has some ugly C stuff. Here's the header file for the portable thread: // Thread.h//// Based on S. Kofoed, Doctor Dobb's Journal Nov. 1995//// Patched by Kar G Lim to include://// 1. 1 ms Real Time callback Task// 2. Sleep function with 1 ms resolution// 3. Active milliseconds lapsed record//// Fixed critical section bug #ifndef THREAD_H#define THREAD_H #include <setjmp.h> class Thread { friend class Queue, Semaphore; bool m_bAllocated; // used or free unsigned m_nBlocksize; // block size void (*m_pThreadFn)(const void *); // pointer to thread function static void (*sm_pmstask)(); // pointer to millisecond task function void *m_pFnArg; // argument to thread function unsigned m_nStackSze; // requested stack size volatile unsigned m_nSleepTime; volatile unsigned m_nActiveTime; protected: jmp_buf m_jmpb; // non-local jumpbuf Thread *m_pNextThread; // pointer to next control block Thread *m_pChain; // next thread in ready or semaphore queue static void schedule(); static void stackalloc(Thread *, unsigned); static void timekeeper(); public: static void sleep(unsigned N); // relinquish executing control for next N ms static unsigned activetime(); // get the number of ms current thread has used static void yield(); // Voluntary relinquish executing control // to allow other thread to execute static void init(unsigned, unsigned); // To be called once // Creates a new Thread with runnable function, initial argument and stacksize static bool create(void (*)(const void *), void *, unsigned); // Set real time millisecond task - use NULL to clear millisecond task static void setmstask(void (*)(void));}; class Queue { // Simple Queue implementationfriend class Thread;protected: Thread *m_pHead, *m_pTail; // pointer to first and last element public: Queue() { m_pHead = NULL; } void append(Thread *p); Thread *getfirst();}; class Semaphore : private Queue // Simple Semaphore implementation{ private: int m_nCount; public: Semaphore() { m_nCount = 0; } void signal(); void wait();}; #endif // THREAD_H "Hugo Etchegoyen" <Hugo_member@pathlink.com> wrote in message news:bkmq3h$1ckf$1@digitaldaemon.com... > You are right, Karl, there is a lot to be improved in the handling of the timer interrupt. > > Certainly a 1 kHz interrupt calling the old vector once every 55 counts would be ideal, since 'timer ticks' would be the same as 'milliseconds', my only concern here is whether the overhead of 1k interrupts per second would not be too much. Probably a configurable time granularity would be best, then you could set it to the best compromise according to your needs and to your hardware. > > Also trapping the real time interrupt from the application level is not possible right now, since it is trapped in the kernel. It would be nice if the application could install callbacks to be called from the timer interrupt every so many milliseconds, something like the poll feature in Unix. > > I don't promise dates, but I will try to include these features. If someone does it before, please tell me. > > Thank you, > > Hugo. > > |
September 23, 2003 Re: Preemptive multitasker for DM - mtask2.dm.zip | ||||
---|---|---|---|---|
| ||||
Posted in reply to Hugo Etchegoyen | Hi, Nice, very nice. I know on DOSX and pure dos mode, tick interrupt can go as fast as 40KHz with a reliability of around 2-3 micoseconds. For that, when the tick is running that fast, the program must _never_ go 16 bit and back to 32 bit that means it must _never_ call bios: - mouse driver must be rewritten 32 bits, or lock mouse interrupt - keyboard driver must be rewritten 32 bits or lock keyboard interrupt, - no disk access I have some "raw" source to deal with the timer, int 8 and int 1ch. Comments are in french and it may be usable only after a lot of work on it. Just ask, I can give them and answer precise questions. Just in case .. roland |
September 25, 2003 Re: Preemptive multitasker for DM | ||||
---|---|---|---|---|
| ||||
Posted in reply to roland | Hi everybody Thanks Karl, Roland and Chris. I´ve been working on your proposals and I have a new version of the multitasker (DM 2.01). I think I improved time handling substancially by making the following changes: - The kernel now measures times directly in milliseconds - no more ticks. - InitMtask() now has two parameters: the timer frequency in milliseconds per tick (range 1-55), which is used to program the real time counter, and the time slice in milliseconds. If you pass 0 for these arguments the default (version 2.00) values are used (55 and 110 msecs. respectively). Upon program termination the DOS timer frecuency (55 msecs.) is restored. - I added a GetTime() function that returns the elapsed time in milliseconds fron MTask initialization. - I added a DelayUntil() primitive that allows precise timing of periodic tasks. I also added a test program (ptime.exe) to show the improvement. - I have not added timer callbacks yet. Precisely timed, high-priority periodic tasks offer more or less the same functionality (except that they can be defeated by another task getting into non-preemptive mode, timer callbacks can only be defeated by disabling interrupts or IRQ 0). I will probably add them in 2.02. - The timer interrupt is trapped by the kernel and cannot be hooked by the application, but version 2.00 did not enforce that. In 2.01, if you try to trap IRQ 0 you get a Panic(). Walter, I don´t want to clobber the newsgroup with big postings. I got the idea that I should post the zip file and the documentation in www.digitalmars.com/users and then place a link here, but I don´t know how to do that. Please advise. Hugo. |
September 25, 2003 Re: Preemptive multitasker for DM | ||||
---|---|---|---|---|
| ||||
Posted in reply to Hugo Etchegoyen | > Walter, I don´t want to clobber the newsgroup with big postings. I got the idea that I should post the zip file and the documentation in www.digitalmars.com/users and then place a link here, but I don´t know how to do that. Please advise.
Yes, I could setup a user page for you.
Thanks!
ManiaC++
Jan Knepper
|
Copyright © 1999-2021 by the D Language Foundation