From: AYeryomin AT excelsior-usa DOT com (Alex Yeryomin) Newsgroups: comp.os.msdos.djgpp Subject: Re: Question about djgpp's int-wrapper Date: 10 Jun 2002 22:44:23 -0700 Organization: http://groups.google.com/ Lines: 108 Message-ID: <96eb2770.0206102144.74a87c25@posting.google.com> References: <5 DOT 0 DOT 2 DOT 1 DOT 2 DOT 20020608134608 DOT 009e4050 AT pop DOT gmx DOT net> NNTP-Posting-Host: 212.164.176.30 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 8bit X-Trace: posting.google.com 1023774263 24685 127.0.0.1 (11 Jun 2002 05:44:23 GMT) X-Complaints-To: groups-abuse AT google DOT com NNTP-Posting-Date: 11 Jun 2002 05:44:23 GMT To: djgpp AT delorie DOT com DJ-Gateway: from newsgroup comp.os.msdos.djgpp Reply-To: djgpp AT delorie DOT com Hi all. So, it means that some of DPMI providers may "block" sti/cli instruction. But if your program runs under "pure" DOS & CWSDPMI (usual DJGPP configuration), you can rely upon the fact that it works fine with privelage instructions like sti/cli, and without any CPU time overhead. Since cli and sti are privileged instructions, they will cause a protection violation and the DPMI provider will simulate the instruction. Because of the overhead involved in processing the exception, cli and sti should be used as little as possible. In general, you should expect either of these instructions to require at least 300 clocks (see below how you can test it). As a rule (near 100% of probability) the interrupt controller on your computer will work in FNI mode (Fully Nested Interrupt mode). It means that when an intterupt is raised, the interrupt controller (f.e. Intel 8259 chip) is immediatelly blocked - it will not accept any interrupt request from peripheral devices till the handler processing the current interrupt tells NON_SPECIFIC_END_OF_INTERRUPT (=0x20) to interrupt controller's control register (0x20 port for leading, 0xA0 port for driven IC). And the program should enable CPU to process interrupts to set IF flag. Of course, when the instuction "iret" is executed, it restores IF flag of CPU (and all context previously stored to the stack when the inturrupt was raised). But don't forget that if some of hardware interrupt handlers, which your program establishes, may work a long time you must give a change to others interrupts to be proccessed. It is inadmissibly to lost some important interrupts, f.e, timer, I/O interruprs and so on. An interrupt handler may look like this (it is real hardware interrupt handler for Real Time Clock to count milliseconds): static void RTC_Interrupt_Handler (void) { INTERRUPT_ENTER (); // Read status register 3 of RTC, otherwise // the interrupt will not be enabled readReg (RTC_STATUS_REG_3); // Read status register 2 of RTC // timer interrupt? if (readReg (RTC_STATUS_REG_2) & 0x40) ++TimerCount; INTERRUPT_LEAVE_BOTH (); } END_OF_STATIC_FUNCTION (RTC_Interrupt_Handler); where: #define INTERRUPT_ENTER(); asm ("sti"); /* enable maskable interrupts */ #define INTERRUPT_LEAVE(); asm ("cli"); /* disable maskable interrupts */ \ outportb (0x20, 0x20); /* End of interrupt */ #define INTERRUPT_LEAVE_BOTH(); asm ("cli"); /* disable maskable interrupts */ \ outportb (0x20, 0x20); /* End of interrupt */ \ outportb (0xA0, 0x20); /* End of interrupt */ Here, we must unblock both the leading Interrupt Controller and driven one because the RTC interrupt is mapped to the second IC. Again, in general, you should expect that "sti" or "cli" instructions to require many clocks under some DPMI provider. But used pure DOS it takes only several CPU ticks. How can you test it?It is easy. Use "rdtsc" instruction. It allows to take CPU ticks at the moment, and returns 64-bits tick counter from the computer has rebooted. It shows that "sti" takes only ~30 CPU ticks to be executed. It proves that a program under DOS & CWSDMPI has enough privelage to execute "sti" or "cli" instructions. Best regards, Alex PS Here is "rdtsc" code. ------------------------------------------- [BITS 32] [GLOBAL _Read_TSC] [SECTION .text] _Read_TSC: mov ecx, [esp+4] rdtsc mov [ecx], eax mov [ecx+4], edx ret ;_Read_TSC ------------------------------------------- typedef unsigned long long int TICK; extern void Read_TSC (TICK *tick); -------------------------------------------