Click here to Skip to main content
Click here to Skip to main content

Real time.Windows Runs in the Ring2

By , 28 Jun 2012
 

Introduction

For a variety of business and technical reasons, Microsoft Windows Vista, XP/2000 operating systems are increasingly being considered as a platform for deployment of real-time systems. The reasons include:

  1. The many applications available on the platform
  2. The variety of development tools available on the platform
  3. The richness of the Microsoft Win32 application programming interface (API)
  4. The large number of developers, support personnel, and end users who are familiar with the system

The Hadcon's real time module (RTM) has been developed to bring "hard " real time capabilities (such as creation of timers, system thread, of management by resources – memory, ports, interrupts) to Windows, excepting necessity of creating of the driver.

RTM Architecture

Precise execution of events is critical in a real-time system. RTM provides complete flexibility to the developer to determine the appropriate timer resolution for their system. Timer interval values can be set between 100 microsecond and 1 millisecond (100,200,500,1000). The timer interval is default inside of [AddNewInst] section rtmdrv.inf file's HKR,,TimerQuantum,,500.

RTM uses the "mixed" code i.e. timer's, interrupt's routines (working in Ring 0) and user routines (working in Ring 3) are incorporated in one DLL module.
Real-time components (timer, system thread and interrupt routines) must be locked in memory to avoid latencies due to page faults. Therefore RTM defines its own sections for location of a code, data and stack using the data_seg, code_seg, and bss_seg pragmas.

//
//
#pragma code_seg( "RTMCODE ")

Specifies a code section where functions are to be allocated.
For example:

#pragma code_seg( "RTMCODE ")

void timer1(unsigned dwmess )
{
/*
code
*/
..................
}

#pragma code_seg()

#pragma data_seg( "RTMDATA ")

Specifies a code section where initialized data are to be allocated.
For example:

#pragma data_seg( "RTMDATA ")

char buff[10] = {0};
int k1 = 0;

#pragma data_seg()

#pragma bss_seg( "RTMBSS ")

char buff[10];
int k1;

#pragma bss_seg()

Timers

RTM uses the system timer.The system timer generates system ticks at a fixed rate of one tick per millisecond(or 100, 200 ,500 microsecond), which is the rate at which a timer interrupt is generated and serviced by the operating system (interrupt service routine ISR).
RTmCreateTimer function lets you attach a handling routine to an timer interrupt, much the same way that the RTM timer routines allow you to associate a handling routine with a given timer expiration.
RTM timers are not synchronization objects which means threads cannot wait for single objects with an RTM timer handle.

This is in contrast to the Windows waitable timer, which is an object on which a thread can wait, or against which a thread can receive notification.

Example Code

#pragma code_seg( "RTMCODE ")
//
//
void timer1(unsigned dwmess )
{
 int i;
 unsigned nstate;
 unsigned nvalue;
 unsigned short ndigport;

      if(nstop ) return ;

      if(initLpt == 0)
      {
       _asm {
         mov dx,378h
         mov ax,0
         out dx,ax ;//outp(BASE_LPT,0);
         add dx,2; CR
         mov ax,2eh
         out dx,ax ;//outp(BASE_LPT+CR,0x2e);
      }
      initLpt =1;

      rtmsqrt(1.5);
/*
code
*/
..................

}

#pragma code_seg()

void func()
{
  int error;
  HANDLE tm;

       if(RtmInit(hRTMDLL,KERNEL_MODE) == -1) return 0;

         RtmDebug(hRTMDLL ,TRUE);
         tm = RtmCreateTimer
            (hRTMDLL ,timer_anl,0x2000,stanl.quantum,KERNEL_MODE);
         RtmStartTimer(hRTMDLL ,tm,0x3000);
         error = RtmTimerPostMessage(hRTMDLL ,tm,0x100);
}

Using Threads

The RtmCreateThread function creates a system thread (See: PsCreateSystemThread in the DDK for Windows XP/2000).
You can set the priority value for the specified thread using KeSetPriorityThread and KeSetBasePriorityThread functions.
Inside of the body thread function, we can use majority DDK functions.
RTM thread defines own sections for location of a code.

#pragma code_seg( "RTMTHR ")
//
// thread code
//
#pragma code_seg()

Example Code

#pragma code_seg( "RTMTHR ")
//
//
void writetofile(PWSTR pfl,UINT addr,int nsize)
{
   IO_STATUS_BLOCK IoStatus;
   OBJECT_ATTRIBUTES objectAttributes;
   HANDLE FileHandle = NULL;
   UNICODE_STRING fileName1;
   NTSTATUS status;

        fileName1.Buffer = NULL;
        fileName1.Length = 0;
        fileName1.MaximumLength = 256;
        DbgPrint("start");

        fileName1.Buffer = (unsigned short *)ExAllocatePool(PagedPool,
        fileName1.MaximumLength);

        DbgPrint("111");

        RtlZeroMemory(fileName1.Buffer, fileName1.MaximumLength);
        status = RtlAppendUnicodeToString(&fileName1, pfl);
        InitializeObjectAttributes (&objectAttributes,
        (PUNICODE_STRING)&fileName1,
         OBJ_CASE_INSENSITIVE,
         NULL,
        NULL );

       status = ZwCreateFile(&FileHandle,
        FILE_APPEND_DATA,
        &objectAttributes,
        &IoStatus,
        0,
        FILE_ATTRIBUTE_NORMAL,
        FILE_SHARE_WRITE,
        FILE_OPEN_IF,
        FILE_SYNCHRONOUS_IO_NONALERT,
        NULL,
        0 );

       if(NT_SUCCESS(status))
      {

        ZwWriteFile(FileHandle,
         NULL,
         NULL,
         NULL,
         &IoStatus,
         (void *)addr,
         nsize,
         NULL,
         NULL );

        ZwClose(FileHandle);
        DbgPrint ("Close file");
      }

       if(fileName1.Buffer)
       ExFreePool(fileName1.Buffer);
}

int systhread(void *param)
{
 unsigned int _cr3 = 0;
 PVOID pv;
 PHYSICAL_ADDRESS pf;


        n_count_task++;
       if(n_count_task == 10)
       {
        _asm mov eax,cr3
        _asm mov _cr3,eax


        pf.HighPart = 0;
        pf.LowPart = _cr3;
        pv = MmGetVirtualForPhysical (pf);
        writetofile(L"\\??\\C:\\tmp\\qqq1",(UINT)pv ,0x1000);
       }

       return 0;
}

#pragma code_seg()

void func()
{
 int error;
 HANDLE tm;
 HANDLE th;

        if(RtmInit(hRTMDLL,KERNEL_MODE) == -1) return 0;

        th = RtmCreateThread(hRTMDLL ,(THREAD_START_ROUTINE)systhread,NULL);
}

Interrupts

RTM allows a process to directly interface with a device without having to write a Windows driver via RtmConnectInterrupt or RtmHookInterrupt functions. A process can attach to an interrupt handler using RtmConnectInterrupt function (See: HalGetInterruptVector in the DDK for Windows XP/2000).
The RtmHookInterrupt function allows to hook an interrupt.

typedef struct _tagRTMINTERUPT {
  INTERFACE_TYPE itype;
  ULONG nVector ;
  ULONG BusNumber ;
  ULONG VenID ;
  ULONG DevID;
  unsigned char bShared;
  void *lpParameter;
  INTERRUPT_ROUTINE newintr;

) RTMINTERRUPT; 

Example Code

#pragma data_seg( "RTMDATA ")
int _isr = 0;
#pragma data_seg()
//
//
void newintr(void *pv)
{
       _isr++;
/*
-------------------------
*/
}
int func1()
{
 HANDLE tm; int count;
 RTMCONNINTERRUPT cinter;
 HANDLE pi,pi1;

      if(RtmInit(hRTMDLL, KERNEL_MODE) == -1) return 0;

         cinter.BusNumber = 1;
         cinter.DevID = 0x2f00;
         cinter.nVector =0;
         cinter.VenID = 0x14f1;
         cinter.itype = PCIBus;
         cinter.lpParameter = NULL;
         cinter.newintr = newintr;

         pi = RtmConnectInterrupt(hRTMDLL ,&cinter);
         cinter.BusNumber = 0;
         cinter.nVector =1;
         cinter.itype = Isa;
         cinter.lpParameter = NULL;
         cinter.newintr = newintr;


         pi1 = RtmHookInterrupt (hRTMDLL ,&cinter);
         count = _isr;
         count = _isr;
         count = _isr;

         RtmUnhookInterrupt (hRTMDLL ,pi1);
}

E-mail: info@hadcon.ru
URL: http://www.hadcon.ru

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

khavkin@sandy.ru
Russian Federation Russian Federation
Member
No Biography provided

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
Generalvisual studio 2005 LNK1104 LIBC.LIB not foundmemberdevCoder30 May '09 - 2:43 
you may need to make a new build for rtm
GeneralIOPL_x macro or const not definedmemberdevCoder30 May '09 - 3:52 
BOOL RtmStartTimer(HANDLE s_handle , HANDLE tmhandle, int dwiopl );
Generaldemo does not work-and missing function exporting from dllmemberdevCoder30 May '09 - 22:26 
simply does not work Laugh | :laugh: buddy.
Generaldevioctl.hmembersmart_dummies12 Mar '09 - 21:54 
I cannot compile the source code and the error message is:
 
Error 1 fatal error C1083: Cannot open include file: 'devioctl.h': No such file or directory
 
How can I resolve this?
 
Thank you
GeneralRe: devioctl.hmemberkhavkin@sandy.ru12 Mar '09 - 23:19 
You can delete this line
GeneralRe: devioctl.hmembersmart_dummies13 Mar '09 - 2:45 
strange, I got another error message and I have no idea what should I do..
 
Error 2 error LNK2019: unresolved external symbol _getlibdbg referenced in function _RtmInit rtmlib.lib
Error 3 fatal error LNK1120: 1 unresolved externals C:\WINDOWS\system32\rtmtcon.dll
 
what do these errors mean?
GeneralHardware RealTimememberJarin6 Jan '09 - 11:55 
5 years already use to manage their own CNC machines driver that overrides mask interruption in memory hal.dll that is allready used before the entry into PIC8259.
Our hardware then generates 1ms interupt, which has the highest priority. Response to the interruption is in all circumstances a maximum of 3-100us. It works but only on the version Halacpi.dll and halapic.dll. For multiprocessor versions I have not managed still. Quite I wonder source for libraries. What actually trick HAL?
General[Message Deleted]memberMikael Sundfors25 Nov '08 - 11:49 

GeneralRe: My vote of 1memberkhavkin@sandy.ru26 Nov '08 - 1:58 
I began this work 4 years ago for miniCNC .(because there were no similar ideas) if you know other sources can specify them
GeneralDid not heal mememberNGS 54967225 Nov '08 - 5:51 
Last week my Dr. told me I have cancer. In my grief I was not watching closely and fell down the stairs and broke my leg. This gave me extra time to visit CodeProject and I found this article.
I downloaded and installed the software and ran it just fine, but it is worthless because it didn't cure my cancer or heal my broken leg. It is just incomprehensible that anyone would post some software that doesn't do at least this minimum. I was so astonished that I ran it again, and again, and again, but to no avail. I expected that it would cure and heal me in real time. Hard real time, dammit!
And there is insufficient documentation in the source that I didn't read. I am now despondent. In fact, I am posting this message from an internet cafe because I have murdered my PC at home and plan to end my own life as soon as I can conveniently arrange to do so.
 
Good-bye. Poke tongue | ;-P
Generallib fielsmemberJimmyO16 Dec '07 - 23:55 
Hello,
 
Why differents libs for W2K & WinXP ?
 
Libs for Vista ?
 
Our software must run under W2K, XP, Vista.
Would be nice, have only 1 lib for all platforms.
 
Jimmy
QuestionWhere is the source code ?memberBruce Zhao30 Sep '07 - 3:14 
In Codeproject, you must open source. Where is the source code of the .lib??? Open it pls.Mad | :mad:
Generaluseless & unstablememberhledejto17 Sep '07 - 21:38 
I recommend Codeproject admins to remove this article since it's nothing but advertisement, provided source code cannot be compiled (missing *.h, libs and dlls).
 
This "extension" uses LAPIC timer, and like Ardence RTX, it doesn't handle CLI or SMI, thus it's NOT hard real time
 
Stability of this solution is one big joke, even demo application crashes whole system.
 
IRQL_NOT_LESS_OR_EQUAL (a)
An attempt was made to access a pageable (or completely invalid) address at an
interrupt request level (IRQL) that is too high. This is usually
caused by drivers using improper addresses.
If a kernel debugger is available get the stack backtrace.
Arguments:
Arg1: 00000028, memory referenced
Arg2: 00000002, IRQL
Arg3: 00000000, value 0 = read operation, 1 = write operation
Arg4: 804f22b8, address which referenced memory
 
Debugging Details:
------------------
...
PROCESS_NAME: RtmDemo.exe

GeneralRe: useless & unstablememberkhavkin@sandy.ru17 Sep '07 - 23:34 
Use the reference :download latest version
Within 2-3 days we shall make the demo version with (h. lib .dll)
 

GeneralRe: useless & unstablememberkhavkin@sandy.ru26 Sep '07 - 1:05 
in the previous article in file newdll.cpp
there was a mistake
....................................
pkt = KeGetCurrentThread();
writetofile(L"\\??\\C:\\tmp\\kthread",(UINT)pkt ,0x1000);- it's error
writetofile(L"\\??\\C:\\tmp\\kthread",(UINT)pkt ,0x100);
.................................................
which could cause
IRQL_NOT_LESS_OR_EQUAL
PAGED_FAULT_IN_NONPAGED_AREA
exceptions

QuestionRealtime applications?memberShawn Poulson4 Sep '07 - 2:40 
What are the applications for an environment like this?
 
---
Shawn Poulson
spoulson@explodingcoder.com

QuestionHard job to do this.....memberkennychou3 Sep '07 - 23:15 
:-DHi, in my experience, the most difficult thing is how to lock your ring3 code in the physical memory(in XP).
My method is that load EXE(or DLL) into Ring0 memory, then I could jump from one DPC to my code section.
How could you receive a interrupt and jump to the ring3 code?
Could you appoint loader to load the specific code section into physical memory in the ring3?
I think you do a very difficult work!
 

 
Kenny
GeneralCompilation ErrormemberVep3 Sep '07 - 21:51 
Hello,
 
Nice article.
 
While compilation, I get a lot of error and devioctl.h is missing.
 
Which compiler version are you using ?.
 

 
vep
GeneralRe: Compilation Errormemberkhavkin@sandy.ru3 Sep '07 - 22:44 
href="http://www.hadcon.ru/download/RtmDemo.exe

GeneralRe: Compilation Errormemberkhavkin@sandy.ru26 Sep '07 - 1:01 
Now you can upload RTM (with source ,h,lib,dll)
26.09.2007
GeneralNaive.....memberAnton Bassov3 Sep '07 - 13:00 
The whole thing is really naive.....
 
To begin with, x86 architecture in itself is just unsuitable for RT tasks, due to relatively high interrupt latency at the hardware level.
 
When it comes to the software one, you just cannot turn Windows NT-based system into RTOS, unless you *COMPLETELY* replace its kernel. After all, even if you achieve a better timer precision, , in practical terms, it does not lead you anywhere - the only thing timer interrupt handler does is updating system time and queuing a DPC, which does the *actual* job of thread dispatching. Once DPC routine does not get invoked until IRQL goes below DISPATCH_LEVEL, you just have no chance to speed up things to the level that is required by RTOS. In order to do it, you have to change *ABSOLUELY* everything, which, in practical terms, means that your driver has to completely hijack all kernel's and HAL's operations. If you write a driver like that..... well, then you will already have your own OS....
 
Anton Bassov
GeneralRe: Naive.....memberkhavkin@sandy.ru3 Sep '07 - 22:40 
Naturally that to receive RTOS
"you have to change *ABSOLUTELY* everything"
But we did not set such a goal.
 
There are a lot of problems(tasks) demanding the use of:
- timers with the resolution 500, 1000 us
(and with direct access to hardware resources)
- system's thread
 
The main feature is that all users
work in Win32 application

GeneralRe: Naive..... [modified]memberValery A. Boronin6 Sep '07 - 0:35 
I agreed with Anton.
 
Windows is not RTOS. Period.
 
There is no any limits in any 2K/XP specs which are set maximum time someone's kernel code may/must spent in DPC. Moreover, number of DPCs in the queue might be significant - total delay might be critical for realtime purposes. Thus, to break all construction is enough just either one "non-RT driver" in stack or several "RT drivers", which are (surprisingly) can't live together in a "real-time" fashion, sorry.
 

I wouldn't like even touch CPU's "System Maintenance Mode" related issues Smile | :)
Search for Jake Oshins's posts on forums, if you are wondering...
 

So that, Anton's words are really matter: if you want real realtime in Windows, do load yours GDT/IDT/TSS tables into CPU (it means all NT kernel is actually moved away). Then, write your own small OS - it would be realtime since. This OS would give control to Windows OS time to time - voila. But I suspect it's already implemented and not just once...
 
PS I suspect, with almost same effect old good Multimedia Timers (see timeXxx API) might be used to simulate realtime (up to 5 ms they are quite good for machines not in stress/special conditions) - no need driver development and affecting whole OS stability/performance by given code, just Win32 code and it's even available in Win95 and NT 3.1, as stated in MSDN Wink | ;)
 
--
Valery A. Boronin,
C/C++. Win32/64. System development. Windows NT4/2K/XP/2K3/Vista Filesystems and Drivers. Security.
GeneralRe: Naive.....memberkhavkin@sandy.ru6 Sep '07 - 2:24 
Thanks
But you probably did not read the previous reply

GeneralRe: Naive.....memberAnton Bassov7 Sep '07 - 8:23 
Valery,
 
> There is no any limits in any 2K/XP specs which are
> set maximum time someone's kernel code may/must spent in > DPC.
 
IIRC, there is such a limit for those who want their drivers to be certified by MSFT - in order to be able to pass WHQL certification, you cannot spend more than 100 microseconds in DPC routine. However, as it turned out in one of our discussions on OSR, StartForce found a "brilliant" workaround - it makes DPC routine re-queue
itself to the end of the queue. As a result, it makes the CPU spend up too 3 seconds!!! at DPC level, effectively freezing the machine.......but still it is certified by MSFT
 
Anton Bassov

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web03 | 2.6.130516.1 | Last Updated 28 Jun 2012
Article Copyright 2007 by khavkin@sandy.ru
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid