RTOS.C
上传用户:sunrenlu
上传日期:2022-06-13
资源大小:1419k
文件大小:42k
源码类别:

操作系统开发

开发平台:

DOS

  1. /*
  2.  * Copyright (c) 1990, 1999 Erick Engelke
  3.  */
  4. // #define USE_FP   /* uncomment this if you want FP emulation allowed */
  5.                     /* but it will remove the safety signature on your stack */
  6. /**************************************************************************/
  7. /* INCLUDES                                                               */
  8. /**************************************************************************/
  9. #include <stdio.h>
  10. #include <stddef.h>
  11. #include <stdlib.h>
  12. #include <cpujmp.h>
  13. #include <dos.h>
  14. #if defined( __BORLANDC ) || defined( __TURBOC__ )
  15. #include <alloc.h>
  16. #else
  17. #include <malloc.h>
  18. #endif
  19. #include <mem.h>
  20. #include <bios.h>
  21. #include <string.h>
  22. #if defined(__DJGPP__)
  23. #include <sys/time.h>
  24. #include <sys/farptr.h>
  25. #include <signal.h>
  26. #include <go32.h>
  27. #include <dpmi.h>
  28. #endif
  29. #include "rtos.h"
  30. /**************************************************************************/
  31. /* FLAGS                                                                  */
  32. /**************************************************************************/
  33. /*
  34.  * DJGPP stack does not allow us to place signature at SS:0
  35.  */
  36. #if defined(__DJGPP__)
  37. #define USE_FP
  38. #endif
  39. #define DEBUG 1
  40. #define USE_INTR
  41. #include <conio.h>
  42. /**************************************************************************/
  43. /* DEFINES                                                                */
  44. /**************************************************************************/
  45. #define DIM(x)      (sizeof(x) / sizeof((x)[0]))
  46. #define THS_THREAD  0x0001  /* is a thread */
  47. #define THS_SLEEP   0x0002  /* see th_waketime */
  48. #define THS_SYNC    0x0004  /* see th_syncptr */
  49. #define STACK_SIG   (('R' << 0) + ('T' << 8) + ('O' << 16) + ('S' << 24))
  50. #define KFASTBLOCK()   kblocked++
  51. #define KFASTUNBLOCK() kblocked--
  52. #define OCW1    0x21    /* 8259 */
  53. #define OCW2    0x20
  54. #define OCW1_2  0xA1    /* 8259 */
  55. #define OCW2_2  0xA0
  56. /**************************************************************************/
  57. /* VARIABLES                                                              */
  58. /**************************************************************************/
  59. thread_x *kmainthread = NULL;  /* the main thread pointer */
  60. thread_x *krun = NULL;  /* running list */
  61. thread_x *kwait = NULL; /* waiting list */
  62. thread_x *kdye = NULL; /* dying list */
  63. msg_x *kfreemessages = NULL;
  64. int volatile kinisr = 0;   /* ISR active, don't do thread switch */
  65. int kcheckstacksig = 1;    /* check stack signature within ISR */
  66. int _fastdos = 1;       /* set to zero if we wish to use CS's rather than
  67.                          * kblock()'s around DOS calls
  68.                          */
  69. crit_x *_dos_cs = NULL;
  70. int kusewindows = 0;
  71. int kdebug = 0;
  72. /*------------------------------------*/
  73. #define TIME_X_TOP 37287L
  74. #define TIME_X_BOT 2048L
  75. DWORD ktime = 0L;    /* system timer */
  76. WORD ktime2 = 0;
  77. DWORD kupticks = 0;
  78. #if defined( __BORLANDC__ ) || defined( __TURBOC__ )
  79. static DWORD far *sysclock = 0x46cL;    /* PC Bios clock */
  80. static BYTE far *sysoverflow = 0x470L;   /* clock went past midnight */
  81. #elif defined(__DJGPP__)
  82. static DWORD dummyclock;    /* until real clock is assigned */
  83. static DWORD *sysclock = &dummyclock;
  84. #endif
  85. static int   kirqscount = 0;
  86. static int   kirqsper = 0;
  87. DWORD kseconds = 0;
  88. /*------------------------------------*/
  89. static DWORD ktime0 = 0L;    /* used if frequency is higher than 1kHz */
  90. DWORD kincr = 55;  /* ms frequency */
  91. DWORD kincr0 = 0;
  92. static long ksinceIRQ8 = 0;
  93. thread_x *kcurthread;
  94. WORD kpreemptive = 0;
  95. volatile WORD kblocked = 0;
  96. void (*k_user_int8)(void) = NULL;
  97. int kctrlbreak = 1;
  98. /**************************************************************************/
  99. /* CODE                                                                   */
  100. /**************************************************************************/
  101. /*--------------------------------------------------------------------*/
  102. /* debugging stuff                                                    */
  103. /*--------------------------------------------------------------------*/
  104. void k_debugtest( void )
  105. {
  106.     if ( bioskey( 1 ) ) {
  107.         puts("ndebugging stopped");
  108.         exit( 3 );
  109.     }
  110. }
  111. void kblock(void)
  112. {
  113.     kblocked++;
  114. }
  115. void kunblock(void)
  116. {
  117.     if ( kblocked > 0 ) kblocked--;
  118. }
  119. void rt_cpu_block( WORD *p )
  120. {
  121. #if defined( __TURBOC__ ) || defined( __BORLANDC__ )
  122.     *p = _FLAGS;    /* save interrupt state */
  123.     disable();      /* disable interrupts for a spell */
  124. #elif defined( __DJGPP__ )
  125.     __asm__ __volatile__ (
  126.         "pushflnt"
  127.         "popl  %%eaxnt"
  128.         "clint"
  129.         : "=a" (*p));
  130. #endif
  131. }
  132. void rt_cpu_unblock( WORD *p )
  133. {
  134. #define I86_INTERRUPT_ENABLE_FLAG 0x200
  135.     if ( *p & I86_INTERRUPT_ENABLE_FLAG )
  136.         enable();
  137. }
  138. int rt_thread_status( thread_x *t )
  139. {
  140.     int result;
  141.     KFASTBLOCK();
  142.     if ( (t == kcurthread) || ( t==NULL ) )
  143.         result = TSTAT_RUNNING;
  144.     else if ( t->th_head == &krun )
  145.         result = TSTAT_WILL_RUN;
  146.     else if ( t->th_head == &kwait )
  147.         result = TSTAT_WAITING;
  148.     else if ( t->th_critical != NULL )
  149.         result = TSTAT_CRITICAL;
  150.     else
  151.         result = TSTAT_DEAD;
  152.     KFASTUNBLOCK();
  153.     return( result );
  154. }
  155. void rt_halt( char *msg )
  156. {
  157.     KFASTBLOCK();
  158.     if ( kusewindows ) {
  159.         gotoxy( 1, 25 );
  160.         clreol();
  161.     }
  162.     printf("HALT in %s: %sn", kcurthread->th_name, msg ? msg : "no message specified");
  163. #ifdef __DJGPP__
  164.     sio_exit();
  165.     rt_restoretimer();
  166.     abort();   /* produce traceback */
  167. #endif
  168.     exit( 3 );
  169. }
  170. /* internal routine to remove thread from a list */
  171. static void kremthread(  thread_x *t )
  172. {
  173.     thread_x *suc, *pred;
  174.     WORD flags;
  175.     thread_x **head;
  176.     if ( t == NULL ) t = kcurthread;
  177.     rt_cpu_block( &flags );
  178.     head = t->th_head;
  179.     suc = t->th_next;
  180.     pred = t->th_prev;
  181.     /* deal with successor */
  182.     if ( suc != NULL )
  183.         suc->th_prev = pred;
  184.     /* deal with predecssor */
  185.     if ( pred != NULL )
  186.         pred->th_next = suc;
  187.     else
  188.         *head = suc;
  189.     t->th_head = NULL;
  190.     rt_cpu_unblock( &flags );
  191. }
  192. /* add this to new list */
  193. void kaddthread( thread_x **head, thread_x *t, int howsort )
  194. {
  195.     thread_x *x, *prev;
  196.     WORD flags;
  197.     BYTE ourpriority;
  198.     rt_cpu_block( &flags );
  199.     x = *head;
  200.     prev = NULL;
  201.     do {
  202.         if ( x == NULL ) break;     /* insert it here */
  203.         /* there is at least one existing entry */
  204.         if ( howsort == TS_NOSORT )
  205.             break;             /* insert it here */
  206.         /* skip past higher priorities */
  207.         if ( howsort == TS_PRIORITY ) {
  208.             ourpriority = t->th_priority;
  209.             /* at start, x is pointing at head */
  210.             do {
  211.                 if ( x->th_priority <= ourpriority ) {
  212.                     /* skip past these more important things */
  213.                     prev = x;
  214.                     x = x->th_next;
  215.                     /* until we hit end of list */
  216.                     if ( x == NULL ) break;
  217.                 } else
  218.                     break;
  219.             } while ( 1 );
  220.             /* insert here */
  221.             break;
  222.         }
  223.         /* sort by timer */
  224.         if ( howsort == TS_SOON ) {
  225.             do {
  226.                 if (( x->th_waketime < t->th_waketime ) &&
  227.                     ( x->th_waketime2 < t->th_waketime2 )) {
  228.                     prev = x;
  229.                     x = x->th_next;
  230.                     if ( x == NULL ) break;
  231.                 } else
  232.                     break;
  233.             } while ( 1 );
  234.             /* insert here */
  235.             break;
  236.         }
  237.     } while ( 0 );
  238.     /* x = where_to_insert_before or NULL=end, prev = prev or NULL/head */
  239.     t->th_prev = prev;
  240.     if ( prev ) prev->th_next = t;
  241.     else *head = t;
  242.     t->th_next = x;
  243.     if ( x != NULL )
  244.         x->th_prev = t;
  245.     t->th_head = head;
  246.     rt_cpu_unblock( &flags );
  247.     return;
  248. }
  249. /*--------------------------------------------------------------------*/
  250. /* critical sections                                                  */
  251. /*--------------------------------------------------------------------*/
  252. crit_x *cs_alloc( void )
  253. {
  254.     return( kcalloc( sizeof( crit_x ), 1 ));
  255. }
  256. void cs_new( crit_x **cs )
  257. {
  258.     kblock();
  259.     if ( *cs == NULL )
  260.         if ( (*cs = cs_alloc()) == NULL )
  261.             rt_halt("out of memory on cs_new()");
  262.     kunblock();
  263. }
  264. void cs_free( crit_x *x )
  265. {
  266.     kfree( x );
  267. }
  268. void cs_enter( crit_x *cs )
  269. {
  270.     WORD flags;
  271.     if ( cs != NULL ) {
  272.         rt_cpu_block( &flags );
  273.         if ( (cs->cs_active == NULL ) || (cs->cs_active == kcurthread )) {
  274.             /* we take it */
  275.             cs->cs_active = kcurthread;
  276.             kcurthread->th_critical = cs;
  277.             rt_cpu_unblock(&flags);
  278.         } else {
  279.             /* we need to wait for this */
  280.             kremthread( kcurthread );       /* stop running */
  281.             kaddthread( &cs->cs_blocked, kcurthread , TS_PRIORITY);
  282.             kcurthread->th_critical = cs;
  283.             rt_cpu_unblock( &flags );
  284.             rt_yield(); /* and go to the safe one */
  285.         }
  286.         cs->cs_depth ++;
  287.     }
  288. }
  289. void cs_exit( crit_x *cs )
  290. {
  291.     thread_x *t;
  292.     WORD flags;
  293.     if ( cs != NULL ) {
  294.         rt_cpu_block(&flags);
  295.         cs->cs_depth --;
  296.         if ( cs->cs_depth == 0 ) {
  297.             kcurthread->th_critical = NULL;
  298.             if ( cs->cs_active == kcurthread ) {
  299.                 t = cs->cs_blocked;
  300.                 if ( t == NULL )
  301.                     /* nothing waiting */
  302.                     cs->cs_active = NULL;
  303.                 else {
  304.                     /* move first waiting to next executing */
  305.                     kremthread( t );
  306.                     cs->cs_active = t;
  307.                     kaddthread( &krun, t, TS_PRIORITY );
  308.                     rt_cpu_unblock( &flags );
  309.                     rt_yield();     /* go to it */
  310.                     return;
  311.                 }
  312.             }
  313.         }
  314.         rt_cpu_unblock(&flags);
  315.     }
  316. }
  317. void dos_enter( void )
  318. {
  319.     if ( _fastdos ) {
  320.         KFASTBLOCK();
  321.     } else {
  322.         cs_enter( _dos_cs );
  323.     }
  324. }
  325. void dos_exit( void )
  326. {
  327.     if ( _fastdos ) {
  328.         KFASTUNBLOCK();
  329.     } else {
  330.         cs_exit( _dos_cs );
  331.     }
  332. }
  333. /*--------------------------------------------------------------------*/
  334. /* memory allocation                                                  */
  335. /*--------------------------------------------------------------------*/
  336. DWORD kcorefree( void )
  337. {
  338.     DWORD d;
  339. #if defined(__TURBOC__) || defined(__BORALNDC__)
  340.     dos_enter();
  341.     d = coreleft();
  342. #elif defined( __DJGPP__)
  343.     __dpmi_free_mem_info mem;
  344.     dos_enter();
  345.     __dpmi_get_free_memory_information (&mem);
  346.     d = 4096 * mem.total_number_of_free_pages;
  347. #endif
  348.     dos_exit();
  349.     return( d );
  350. }
  351. void *kcalloc( WORD n, WORD size )
  352. {
  353.     void *p;
  354. #ifdef OLD
  355.     dos_enter();
  356.     p = calloc( n, size );
  357.     dos_exit();
  358.     return( p );
  359. #else
  360.     WORD sz;
  361.     mem_x *m;
  362.     sz = n * size;
  363.     dos_enter();
  364.     m = calloc( 1, sz + sizeof( mem_x ) + sizeof( DWORD ));
  365.     dos_exit();
  366.     m->mem_size = sz;
  367.     m->mem_startsig = MEM_STARTSIG;
  368.     m->mem_thread = kcurthread;
  369.     *(DWORD*) &m->mem_data [sz] = MEM_ENDSIG;
  370.     return ( &m->mem_data[0] );
  371. #endif
  372. }
  373. void kfree( void *p )
  374. {
  375. #ifdef OLD
  376.     dos_enter();
  377.     if ( p != NULL )
  378.         free( p );
  379.     dos_exit();
  380. #else
  381.     mem_x *m;
  382.     DWORD *dw;
  383.     m = (mem_x*) ((DWORD)p - offsetof(mem_x, mem_data));
  384.     if ( m->mem_startsig != MEM_STARTSIG ) {
  385.         char buf[ 256];
  386.         sprintf( buf, "kfree of mangled mem (or not kcalloc'd) %08lx", (DWORD)p );
  387.         if ( kdebug > 1 ) {
  388.             cputs( buf );
  389.             cputs( "rncontinuing without freeing bufferrn");
  390.             return;
  391.         }
  392.         rt_halt( buf );
  393.     }
  394.     dw = (DWORD*) &m->mem_data [m->mem_size];
  395.     if ( *dw != MEM_ENDSIG ) {
  396.         thread_x *th;
  397.         char buf[ 256 ];
  398.         th = m->mem_thread;
  399.         sprintf( buf, "mem overflow @ %08lx, kcalloced in %s",
  400.                  (DWORD)&m->mem_data, th->th_name );
  401.         if ( kdebug > 1 ) {
  402.             cputs( buf );
  403.             cputs( "rncontinuing without freeing bufferrn");
  404.             return;
  405.         }
  406.         rt_halt( buf );
  407.     }
  408.     dos_enter();
  409.     free( m );
  410.     dos_exit();
  411. #endif
  412. }
  413. void *krealloc( void *m, WORD size )
  414. {
  415.     void *p;
  416.     dos_enter();
  417.     p = realloc( m, size );
  418.     dos_exit();
  419.     return( p );
  420. }
  421. /*--------------------------------------------------------------------*/
  422. /* messaging stuff                                                    */
  423. /*--------------------------------------------------------------------*/
  424. /*
  425.  * kfreeallmessages - used to free all pending messages at task end time
  426.  */
  427. static void kfreeallmessages( thread_x *t )
  428. {
  429.     msg_x *firstm, *lastm, *p;
  430.     WORD flags;
  431.     firstm = t->th_messagelist;
  432.     if ( firstm != NULL ) {
  433.         lastm = firstm;
  434.         while ( (p = lastm->m_next )!=NULL) lastm = p;
  435.         rt_cpu_block( &flags );
  436.         lastm->m_next = kfreemessages;
  437.         kfreemessages = firstm;
  438.         rt_cpu_unblock( &flags );
  439.         t->th_messagelist = NULL;
  440.     }
  441. }
  442. /*--------------------------------------------------------------------*/
  443. void kmessage_on_exit( void *thread, int value, DWORD data )
  444. {
  445.     thread_x *t;
  446.     /* most likely send it to parent */
  447.     if ( thread == NULL ) t = kcurthread->th_parent;
  448.     else t = (thread_x*)thread;
  449.     kcurthread->th_end_thread = t;
  450.     kcurthread->th_end_value = value;
  451.     kcurthread->th_end_data = data;
  452. }
  453. #ifndef FIXMESSAGE
  454. static void ksendmessagebuffer( thread_x* t, int value, DWORD data, msg_x* m)
  455. {
  456.     msg_x *mm;
  457.     if (( t->th_messagewait == value ) &&( value != 0) ) {
  458.         t->th_messagewait = 0;  // cancel the wait
  459.         t->th_status &= ~THS_MESG;
  460.         kresume( t );
  461.     } else {
  462.         kfreemessages = m->m_next;  /* advance to next free one */
  463.         m->m_value = value;
  464.         m->m_data = data;
  465.         m->m_next = NULL;
  466.         /* add to end of list */
  467.         if ( t->th_messagelist == NULL ) t->th_messagelist = t->th_messagetail = m;
  468.         else if ( t->th_messagetail ) {
  469.             t->th_messagetail->m_next = m;
  470.             t->th_messagetail = m;
  471.         } else {
  472.             mm = t->th_messagelist;
  473.             while ( mm->m_next )
  474.                 mm = mm->m_next ;
  475.             t->th_messagetail = mm->m_next = m;
  476.         }
  477.         if ( t->th_status & THS_MESG ) {
  478.             /* it is blocked waiting */
  479.             /* see if waiting for general message or specialized one */
  480.             if ( t->th_messagewait == 0 ) {
  481.                 t->th_status &= ~THS_MESG;
  482.                 kresume( t );
  483.             }
  484.         }
  485.     }
  486. }
  487. int ksendmessage( void *thread , int value, DWORD data )
  488. {
  489.     msg_x *m;
  490.     WORD flags;
  491.     rt_cpu_block(&flags);
  492.     m = kfreemessages;
  493.     if ( m != NULL)
  494.       ksendmessagebuffer( thread, value, data, m);
  495.     rt_cpu_unblock(&flags);
  496.     return( m ? 1 : 0 );        // 2000.9.13 added return value
  497. }
  498. void kwritemessage( void *thread , int value, DWORD data )
  499. {
  500.     msg_x *m;
  501.     WORD flags;
  502.     rt_cpu_block(&flags);
  503.     do {
  504.         m = kfreemessages;
  505.         if ( m != NULL ) break;
  506.         rt_cpu_unblock(&flags);
  507.         rt_yield(); /* wait for a free one */
  508.         rt_cpu_block(&flags);
  509.     } while ( m == NULL );
  510.     ksendmessagebuffer( thread, value, data, m);
  511.     rt_cpu_unblock(&flags);
  512. }
  513. #else  /* old messaging */
  514. void ksendmessage( void *thread , int value, DWORD data )
  515. {
  516.     msg_x *m, *mm;
  517.     thread_x *t;
  518.     WORD flags;
  519.     t = (thread_x*) thread;
  520.     rt_cpu_block(&flags);
  521.     m = kfreemessages;
  522.     if ( m == NULL ) {
  523.         rt_cpu_unblock(&flags);
  524.         return;
  525.     }
  526.     if (( t->th_messagewait == value ) &&( value != 0) ) {
  527.         t->th_messagewait = 0;  // cancel the wait
  528.         t->th_status &= ~THS_MESG;
  529.         kresume( t );
  530.     } else {
  531.         kfreemessages = m->m_next;  /* advance to next free one */
  532.         m->m_value = value;
  533.         m->m_data = data;
  534.         m->m_next = NULL;
  535.         /* add to end of list */
  536.         if ( t->th_messagelist == NULL ) t->th_messagelist = t->th_messagetail = m;
  537.         else if ( t->th_messagetail ) {
  538.             t->th_messagetail->m_next = m;
  539.             t->th_messagetail = m;
  540.         } else {
  541.             for ( mm = t->th_messagelist; mm->m_next ; mm = mm->m_next );
  542.             t->th_messagetail = mm->m_next = m;
  543.         }
  544.         if ( t->th_status & THS_MESG ) {
  545.             /* it is blocked waiting */
  546.             /* see if waiting for general message or specialized one */
  547.             if ( t->th_messagewait == 0 ) {
  548.                 t->th_status &= ~THS_MESG;
  549.                 kresume( t );
  550.             }
  551.         }
  552.     }
  553.     rt_cpu_unblock(&flags);
  554. }
  555. void kwritemessage( void *thread , int value, DWORD data )
  556. {
  557.     msg_x *m, *mm;
  558.     thread_x *t;
  559.     WORD flags;
  560.     t = (thread_x*) thread;
  561.     rt_cpu_block(&flags);
  562.     do {
  563.         m = kfreemessages;
  564.         if ( m != NULL ) break;
  565.         rt_cpu_unblock(&flags);
  566.         rt_yield(); /* wait for a free one */
  567.         rt_cpu_block(&flags);
  568.     } while ( m == NULL );
  569.     kfreemessages = m->m_next;  /* advance to next free one */
  570.     m->m_value = value;
  571.     m->m_data = data;
  572.     m->m_next = NULL;
  573.     /* add to end of list */
  574.     if ( t->th_messagelist == NULL ) t->th_messagelist = t->th_messagetail = m;
  575.     else if ( t->th_messagetail ) {
  576.         t->th_messagetail->m_next = m;
  577.         t->th_messagetail = m;
  578.     } else {
  579.         for ( mm = t->th_messagelist; mm->m_next ; mm = mm->m_next );
  580.         t->th_messagetail = mm->m_next = m;
  581.     }
  582.     if ( t->th_status & THS_MESG ) {
  583.         /* it is blocked waiting */
  584.         t->th_status &= ~THS_MESG;
  585.         kresume( t );
  586.     }
  587.     rt_cpu_unblock(&flags);
  588. }
  589. #endif
  590. /* non-blocking version */
  591. int kgetmessage( int *value, DWORD *data )
  592. {
  593.     msg_x *m;
  594.     WORD flags;
  595.     rt_cpu_block( &flags );
  596.     if ( (m = kcurthread->th_messagelist) != NULL ) {
  597.         *value = m->m_value;
  598.         *data = m->m_data;
  599.         kcurthread->th_messagelist = m->m_next;
  600.         if ( kcurthread->th_messagetail == m )
  601.             kcurthread->th_messagetail = NULL;
  602.         /* return it to the freelist */
  603.         m->m_next = kfreemessages;
  604.         kfreemessages = m;
  605. //      kfree( (BYTE*) m );
  606.         rt_cpu_unblock(&flags);
  607.         return( 1 );
  608.     }
  609.     rt_cpu_unblock(&flags);
  610.     return( 0 );
  611. }
  612. int kreadmessage( int *value, DWORD *data )
  613. {
  614.     WORD flags;
  615.     rt_cpu_block( &flags );
  616.     while ( kcurthread->th_messagelist == NULL ) {
  617.         kcurthread->th_status |= THS_MESG;
  618.         ksuspend(kcurthread);
  619.         rt_cpu_unblock( &flags );
  620.         rt_yield();
  621.     }
  622.     rt_cpu_unblock( &flags );
  623.     return( kgetmessage( value, data ));
  624. }
  625. void kreadspecialmessage( int value )
  626. {
  627.     WORD flags;
  628.     rt_cpu_block( &flags );
  629.     if ( kcurthread->th_messagelist ) {
  630.         msg_x **mm = &kcurthread->th_messagelist;
  631.         msg_x *m = *mm;
  632.         while ( m ) {
  633.             if ( m->m_value == value ) {
  634.                 /* found msg, remove it */
  635.                 *mm = m->m_next;
  636.                 m->m_next = kfreemessages;
  637.                 kfreemessages = m;
  638.                 rt_cpu_unblock( &flags );
  639.                 return;
  640.             }
  641.             mm = &m->m_next;
  642.             m = *mm;
  643.         }
  644.     }
  645.     kcurthread->th_messagewait = value;
  646.     kcurthread->th_status |= THS_MESG;
  647.     ksuspend(kcurthread);
  648.     rt_cpu_unblock( &flags );
  649.     rt_yield();
  650. }
  651. DWORD knumthreads( void )
  652. {
  653.     DWORD i;
  654.     thread_x *t;
  655.     KFASTBLOCK();
  656.     for (i = 0 , t = krun ; t ; t = t->th_next ) {
  657.      dos_enter();
  658.         printf("running : %srn", t->th_name );
  659.         dos_exit();
  660.         i++;
  661.     }
  662.     for ( t = kwait ; t ; t= t->th_next ) {
  663.      dos_enter();
  664.         printf("waiting : %srn", t->th_name );
  665.         dos_exit();
  666.         i++;
  667.     }
  668.     KFASTUNBLOCK();
  669.     return( i );
  670. }
  671. void ksuspendhow( thread_x *t, thread_x **newlist )
  672. {
  673.     KFASTBLOCK();
  674.     if ( t == NULL ) t = kcurthread;
  675.     kremthread( t );
  676.     kaddthread( newlist, t, TS_NOSORT );
  677.     KFASTUNBLOCK();
  678. }
  679. void ksuspend( thread_x *t )
  680. {
  681.     KFASTBLOCK();
  682.     if ( t == NULL ) t = kcurthread;
  683.     kremthread( t );
  684.     kaddthread( &kwait, t, TS_PRIORITY );
  685.     KFASTUNBLOCK();
  686. }
  687. void kresume( thread_x *t)
  688. {
  689.     thread_x **head;
  690.     KFASTBLOCK();
  691.     if ( t == NULL ) t = kcurthread;
  692.     if ( t->th_sig != TH_SIG )
  693.         rt_halt("attempt to resume dead thread");
  694.     head = t->th_head;
  695.     /* don't do anything if already running */
  696.     if ( head != &krun ) {
  697.         kremthread( t);
  698.         kaddthread( &krun, t , TS_PRIORITY);
  699.     }
  700.     KFASTUNBLOCK();
  701. }
  702. void kdestroythread( thread_x *t )
  703. {
  704.     bq_str *bq;
  705.     // crit_x *cr;
  706.     WORD flags;
  707.     KFASTBLOCK();
  708.     if ( t == NULL ) t = kcurthread;
  709.     if ( t->th_main ) exit( 0 );
  710.     rt_cpu_block( &flags );
  711.     /* ensure we do not get restarted by byte queue or crit x */
  712.     /* NOT needed, kremthread removes us from this list
  713.      * if ( (cr = t->th_crit) != NULL ) {
  714.      *   if ( cr->cs_blocked == t )
  715.      *       cr->cs_blocked = NULL;
  716.      * }
  717.     */
  718.     if ( (bq = t->th_bq) != NULL ) {
  719.         if ( bq->bq_sendwait == kcurthread ) bq->bq_sendwait = NULL;
  720.         if ( bq->bq_recvwait == kcurthread ) bq->bq_recvwait = NULL;
  721.     }
  722.     rt_cpu_unblock( &flags );
  723.     kremthread( t );
  724.     kaddthread( &kdye, t , TS_NOSORT );
  725.     KFASTUNBLOCK();
  726.     kfreeallmessages( t );  /* return message list to pool */
  727.     rt_nextthread();    /* and we'll never run again */
  728. }
  729. void kfinaldeath( thread_x *t )
  730. {
  731.     t->th_sig = 0;
  732.     kremthread( t );
  733.     if ( t->th_stack )
  734.         kfree( t->th_stack );   /* kill this stack */
  735.     kfree( t );
  736. }
  737. char *kthreadname( void )
  738. {
  739.     return( kcurthread->th_name );
  740. }
  741. #ifdef NEVER
  742. /*
  743.  * sync_test - attempt to set a byte to 1
  744.  */
  745. BYTE sync_test( void *p )
  746. {
  747.     _asm {
  748.         push    es
  749.         push    di
  750.         les     di, p
  751.         mov     ax, 1
  752.         xchg    es:[di], al
  753.         pop     di
  754.         pop     es
  755.     }
  756.     return( _AL );
  757. }
  758. #endif
  759. /*
  760.  * rt_clocktest - test waiting threads for clock reference
  761.  */
  762. void rt_clocktest( void )
  763. {
  764.     WORD st;
  765.     thread_x *t, *next;
  766. //  static DWORD lasttime = 0;
  767.     WORD flags;
  768. //    int status;
  769.     rt_cpu_block( &flags );
  770.     /* do we need to do this ? */
  771. //    if ( lasttime == ktime ) return;
  772.     /* look through inactive list */
  773.     for ( t = kwait ; t ; t = next ) {
  774.         next = t->th_next;  /* learn this now while still valid */
  775.         st = t->th_status;
  776.         if ( st & THS_SLEEP ) {
  777.             WORD oldstatus;
  778.             DWORD oldwaketime;
  779.             WORD oldwaketime2;
  780.             if ( (t->th_waketime2 < ktime2 ) ||
  781.              ( (( t->th_waketime <= ktime ) &&
  782.                 ( t->th_waketime2 == ktime2 )))) {
  783.                 oldstatus = t->th_status;
  784.                 oldwaketime = t->th_waketime;
  785.                 oldwaketime2= t->th_waketime2;
  786.                 t->th_status &= ~THS_SLEEP;
  787.                 t->th_waketime = 0;
  788.                 t->th_waketime2 = 0;
  789.                 if ( !ksendmessage( t, EMSG_TIMER, 0 )) {
  790.                     t->th_status = oldstatus;
  791.                     t->th_waketime =  oldwaketime;
  792.                     t->th_waketime2 = oldwaketime2;
  793.                 }
  794.             }
  795.         }
  796.     }
  797.     rt_cpu_unblock( &flags );
  798. }
  799. void rt_nextthread(void)
  800. {
  801. //  WORD bestpri, testpri, st;
  802.     thread_x *bestt;
  803. //  thread_x *t, *next;
  804. //  int hitcur;
  805. //  WORD flags;
  806.     if ( kblocked > 0 ) {
  807.         return;
  808.     }
  809.     KFASTBLOCK();
  810.     if ( kusewindows ) {
  811.         kcurthread->th_x = wherex();
  812.         kcurthread->th_y = wherey();
  813.     }
  814.     /* save current CPU state - returns 0 and skips this now */
  815.     /* later when we execute cpulongjmp we will return here */
  816. #if defined(__TURBOC__)||defined(__BORLANDC__)
  817.     if ( cpusetjmp( &kcurthread->th_ptr ) ) {
  818. #elif defined(__DJGPP__)
  819.     if ( setjmp( &kcurthread->th_ptr ) ) {
  820. #endif
  821.         /* kill dead tasks */
  822.         while ( kdye )
  823.             kfinaldeath( kdye );
  824.         if ( kcurthread->th_sig != TH_SIG )
  825.             rt_halt("dead thread still in task queue");
  826.         if ( kcurthread != kmainthread ) {
  827.             if ( kcheckstacksig ) {
  828.                 if ( *(DWORD*)kcurthread->th_stack != STACK_SIG )
  829.                     rt_halt( "stack overflow - signature");
  830.             }
  831. #if defined(__TURBOC__) || defined(__BORLANDC__)
  832. //          if ( kcurthread->th_ptr.j_sp < FP_OFF( kcurthread->th_stack ))
  833.             if ( kcurthread->th_ptr.j_sp > kcurthread->th_stacklen )
  834. #elif defined(__DJGPP__)
  835.          // if ( 0 )
  836.             if (kcurthread->th_ptr.__esp < (kcurthread->th_stack - kcurthread->th_stacklen))
  837. #endif
  838.                 rt_halt( "stack overflow - size");
  839.         }
  840.         if ( kusewindows ) {
  841.             window( kcurthread->th_left,
  842.                 kcurthread->th_top,
  843.                 kcurthread->th_right,
  844.                 kcurthread->th_bottom);
  845.             gotoxy( kcurthread->th_x,
  846.                 kcurthread->th_y);
  847.         }
  848.         KFASTUNBLOCK();
  849.         return;
  850.     }
  851.     do {
  852.         if ( kcurthread->th_head != &krun )
  853.             /* go to head of list */
  854.             bestt = krun;
  855.         else {
  856.             /* use next thread */
  857.             bestt = kcurthread->th_next;
  858.             if ( bestt != NULL ) {
  859.                 if ( bestt->th_priority > krun->th_priority )
  860.                     bestt = krun;
  861.             } else
  862.                 bestt = krun;
  863.         }
  864.         if ( bestt == krun )
  865.             rt_clocktest();
  866.         if ( kdebug > 0 )
  867.             k_debugtest();
  868.         /* run the process with the best priority */
  869.         if ( bestt != NULL ) {
  870.             kcurthread = bestt;
  871.             if ( kcurthread->th_sig != TH_SIG )
  872.                 rt_halt( "signature on thread overwritten by application");
  873.             if ( kcurthread->th_ptrsig != TH_SIG )
  874.                 rt_halt( "signature error on registers");
  875. #if defined(__TURBOC__)||defined(__BORLANDC__)
  876.             cpulongjmp( &kcurthread->th_ptr , 1 );
  877. #elif defined(__DJGPP__)
  878.             longjmp( &kcurthread->th_ptr, 1 );
  879. #endif
  880.         } else
  881.             rt_clocktest();
  882.     } while ( 1 );
  883. }
  884. void xrt_yield( char *file, int line )
  885. {
  886.   if ( kblocked > 0 ) {
  887.       char buf[ 256 ];
  888.       sprintf( buf, "yield called when kblocked > 0, %s line %un", file, line );
  889.       rt_halt( buf );
  890.   }
  891.   rt_nextthread();
  892. }
  893. /*--------------------------------------------------------------------*/
  894. /* timer                                                              */
  895. /*--------------------------------------------------------------------*/
  896. #if defined(__TURBOC__)||defined(__BORLANDC__)
  897. typedef struct _false_int {
  898.     BYTE pushf1;
  899.     BYTE call;
  900.     void interrupt (*isr1)();
  901.     BYTE jmp2;
  902.     void interrupt (*isr2)();
  903. };
  904. struct _false_int false_int = {
  905.     0x9c, 0x9a, NULL,
  906.     0xcf, NULL };
  907. #endif
  908.  /*
  909.   * ktimer()
  910.   */
  911. #if defined(__TURBOC__)||defined(__BORLANDC__)
  912. static void interrupt (*koldtimer)(void) = NULL;
  913. static void interrupt ktimer(void)
  914. #elif defined(__DJGPP__)
  915. static void ktimer( void )
  916. #endif
  917. {
  918.     DWORD oldtime;
  919.     
  920. #if defined(__TURBOC__) || defined(__BORLANDC__)
  921.     static WORD *screen = MK_FP( 0xb800, 0);
  922.   
  923.     if (kdebug > 1 )
  924.         *screen = kblocked + 0x0f30;
  925. #elif defined(__DJGPP__)
  926.     if (kdebug > 1)
  927.        _farpokew (_dos_ds, 0xB8000, kblocked + '0' + (15 << 8));
  928. #endif
  929.     /* update eRTOS internal clock */
  930.     if ( kincr != 0 ) {
  931.         oldtime = ktime;
  932.         ktime += kincr;
  933.         if ( ktime < oldtime ) ktime2++;
  934.         ksinceIRQ8 += kincr;
  935.     } else {
  936.         ktime0 += kincr0;
  937.         if ( ktime0 >= 10 ) {
  938.             ktime++;
  939.             if ( ktime == 0 ) ktime2++;
  940.             ksinceIRQ8 ++;
  941.             ktime0 = 0;
  942.         }
  943.     }
  944. //  outportb( 0x20, 0x20 );
  945.     /* see if we should chain to old or send EOI ourselves */
  946.     if ( ksinceIRQ8 >= 55 ) {
  947.         ksinceIRQ8 -= 55;
  948.         kupticks++;
  949. #if defined(__TURBOC__)||defined(__BORLANDC__)
  950.         koldtimer();
  951. #endif
  952.     }
  953. #if defined(__TURBOC__)||defined(__BORLANDC__)
  954.     else
  955.         outportb( 0x20, 0x20 );
  956.     enable();
  957. #endif
  958.     /* adjust count for BIOS clock */
  959. #define END_OF_DAY (24L*60L*60L)
  960. #define LAST_UPDATES (END_OF_DAY - 10L)
  961.     if ( kirqsper ) {
  962.       kirqscount++;       /* clock fixer */
  963.       if ( kirqscount >= kirqsper ) {
  964.           kirqscount -= kirqsper;
  965.           kseconds ++;
  966.           if ( kseconds >= END_OF_DAY ) {
  967.               kseconds = 0;
  968.           }
  969.           // let system do it's own rollover
  970. #if defined(__TURBOC__)||defined(__BORLANDC__)
  971.           if ( (kseconds > 10 ) && (kseconds < LAST_UPDATES))
  972.             *sysclock = (kseconds * TIME_X_TOP)/TIME_X_BOT;
  973. #endif
  974.       }
  975.     }
  976.     if (kinisr)
  977.        return;
  978.     if (k_user_int8 != 0)  /* user timer tick */
  979.       (*k_user_int8)();
  980.     if ( kpreemptive && kblocked == 0 &&
  981.          kcurthread->th_inkernel == 0 ) {  /* !! where is this set? */
  982.          rt_nextthread();
  983.     }
  984. }
  985. // mimick settime()
  986. void rt_settime( struct time *timep)
  987. {
  988.     kseconds = ((timep->ti_hour * 60)+ timep->ti_min) * 60L + timep->ti_sec;
  989.     kirqscount = 0;
  990. }
  991. #if defined(__TURBOC__) || defined(__BORLANDC__)
  992. // mimick stime
  993. void rt_stime( time_t *t )
  994. {
  995.     struct tm *tm;
  996.     struct time ti;
  997.     dos_enter();
  998.     tm = localtime( t );
  999.     ti.ti_hour = tm->tm_hour;
  1000.     ti.ti_min  = tm->tm_min;
  1001.     ti.ti_sec  = tm->tm_sec;
  1002.     stime( t );
  1003.     rt_settime( &ti );
  1004.     dos_exit();
  1005. }
  1006. static void rt_settimer0( DWORD divisor )
  1007. {
  1008.     //if ( divisor > 65535 ) divisor = 65535;
  1009.     disable();
  1010.     //outportb( 0x43, 0x36 );             /* set mode */
  1011.     //outportb( 0x40, divisor & 255 );    /* LSB */
  1012.     //outportb( 0x40, divisor >> 8 );
  1013.     outpw(0xff52,divisor);
  1014.     enable();
  1015. }
  1016. #endif
  1017. void rt_timerfreq( WORD persec )
  1018. {
  1019. #if defined(__TURBOC__) || defined(__BORLANDC__)
  1020. //    rt_settimer0( 1193180 / persec );
  1021. rt_settimer0(312909/persec); //陈道理 2005-05-31 11:21,313计数是1ms
  1022. #elif defined(__DJGPP__)
  1023.     struct itimerval tim;
  1024.     tim.it_interval.tv_usec = 1000000/ persec;
  1025.     tim.it_interval.tv_sec = 0;
  1026.     tim.it_value =tim.it_interval;
  1027.     setitimer( ITIMER_REAL, &tim, NULL );
  1028. #endif
  1029.     kirqsper = persec;
  1030.     kseconds = (*sysclock * TIME_X_BOT) / TIME_X_TOP;
  1031.     kirqscount = 0;
  1032.     if ( persec <= 1000 ) {
  1033.         kincr = 1000 / persec;
  1034.         kincr0 = 0;
  1035.     } else {
  1036.         kincr = 0;
  1037.         kincr0 = 10000 / persec;
  1038.     }
  1039. }
  1040. void rt_restoretimer( void )
  1041. {
  1042. #if defined(__TURBOC__) || defined(__BORLANDC__)
  1043. //    rt_settimer0( 65535 );
  1044. rt_settimer0( 17210 ); //陈道理,2005-05-31 11:54
  1045.     if ( koldtimer != NULL)
  1046.         setvect( 0x8, koldtimer );
  1047. #endif
  1048. }
  1049. #pragma exit rt_restoretimer 100
  1050. /*--------------------------------------------------------------------*/
  1051. int kctrlbrkhandler( void )
  1052. {
  1053.     /* ctrlbrk */
  1054.     if ( kctrlbreak )
  1055.         rt_halt("user pressed control break");
  1056.     return( 1 );    /* continue execution unhamperred */
  1057. }
  1058. /*--------------------------------------------------------------------*/
  1059. void rt_init( DWORD msgcount )
  1060. {
  1061.     thread_x *t;
  1062.     DWORD i;
  1063.     msg_x *m;
  1064. #ifdef USE_FP /* allow FP regs to be saved on stack */
  1065.     kcheckstacksig = 0;     /* SS:0 may have FP data */
  1066. #endif
  1067.     KFASTBLOCK();
  1068.     
  1069. #if defined(__TURBOC__) || defined(__BORLANDC__)
  1070.     /* handle Ctrl Break */
  1071.     ctrlbrk( kctrlbrkhandler );
  1072.     koldtimer = getvect( 0x8 );
  1073.     false_int.isr1 = ktimer;
  1074.     /* rt_restoretimer will restore this at shutdown */
  1075.     setvect( 0x8, (void interrupt (*)())&false_int );
  1076. #elif defined(__DJGPP__)
  1077.     {
  1078.         struct itimerval tim;
  1079.         tim.it_interval.tv_usec = 54945; /* 1000000/18.2 */
  1080.         tim.it_interval.tv_sec = 0;
  1081.         tim.it_value =tim.it_interval;
  1082.         signal( SIGALRM, (void(*)(int))ktimer );
  1083.         setitimer( ITIMER_REAL, &tim, NULL );
  1084.     }
  1085. #endif
  1086.     kmainthread = t = kcalloc( sizeof( thread_x ), 1 );
  1087.     kcurthread = t;
  1088.     t->th_sig = TH_SIG;
  1089.     t->th_ptrsig = TH_SIG;
  1090.     t->th_status = THS_THREAD;
  1091.     t->th_priority = 64;
  1092.     t->th_main = 1;
  1093.     t->th_name = "main";
  1094. #if defined(__TURBOC__) || defined(__BORLANDC__)
  1095.     t->th_stack = MK_FP( _SS, 0 );
  1096.     t->th_stacklen = 0xffff;    /* main thread has no limit */
  1097.     *(DWORD*)t->th_stack = STACK_SIG;
  1098. #elif defined(__DJGPP__)
  1099.     t->th_stack = 0;
  1100.     t->th_stacklen = 0xffffffff;
  1101. #endif
  1102.     kaddthread( &krun, t , TS_PRIORITY);
  1103.     /* allocate close to the number of messages we were asked for */
  1104.     i = kcorefree();
  1105.     if (i < (msgcount * sizeof( msg_x )))
  1106.         msgcount = (i /2) / sizeof( msg_x );
  1107.     kfreemessages = kcalloc( msgcount, sizeof( msg_x ));
  1108.     if ( kfreemessages != NULL ) {
  1109.         for ( i = 0 ; i < (msgcount-1) ; ++i ) {
  1110.             m = &kfreemessages[ i ];
  1111.             m->m_next = &kfreemessages[ i + 1 ];
  1112.         }
  1113.     }
  1114.     /* actual last one has NULL as m_next thanks to kcalloc */
  1115.     _dos_cs = cs_alloc();
  1116.     KFASTUNBLOCK();
  1117. }
  1118. /*--------------------------------------------------------------------*/
  1119. void rt_setpriority( thread_x *t, BYTE priority )
  1120. {
  1121.     thread_x **head;
  1122.     if ( t == NULL ) t = kcurthread;
  1123.     if ( priority == 0 ) priority = kcurthread->th_priority;
  1124.     if ( t->th_priority != priority ) {
  1125.         /* easiest way is to remove from current queue, then re-insert it */
  1126.         head = t->th_head;
  1127.         kremthread( t );
  1128.         t->th_priority = priority;
  1129.         kaddthread( head, t, TS_PRIORITY );
  1130.     }
  1131.     if ( t != kcurthread ) {
  1132.         if ( krun )
  1133.             if ( krun->th_priority < kcurthread->th_priority ) {
  1134.                 /* another thread is more deserving than us */
  1135.                     if ( kblocked == 0 )
  1136.                         rt_yield();
  1137.             }
  1138.     }
  1139. }
  1140. /*--------------------------------------------------------------------*/
  1141. /*--------------------------------------------------------------------*/
  1142. void *rt_newthread( void (*ptr)(), DWORD arg, WORD stklength,
  1143.         BYTE priority, char *name )
  1144. {
  1145.     BYTE *stkptr;
  1146. //  WORD i;
  1147.     thread_x *t;
  1148.     stkptr = kcalloc( stklength, 1 );
  1149.     t = kcalloc( sizeof( thread_x ), 1 );
  1150.     if ( (t == NULL) || (stkptr == NULL))
  1151.         rt_halt("unable to allocate new thread");
  1152.     t->th_sig = TH_SIG;
  1153.     t->th_ptrsig = TH_SIG;
  1154.     t->th_parent = kcurthread;
  1155.     t->th_priority = priority ? priority : kcurthread->th_priority;
  1156.     t->th_status = THS_THREAD;
  1157.     t->th_fn = ptr;
  1158.     t->th_fnarg = arg;
  1159.     t->th_name = name;
  1160.     KFASTBLOCK();
  1161. #if defined(__TURBOC__)||defined(__BORLANDC__)
  1162.     if ( cpusetjmp( &t->th_ptr ) > 0 ) {
  1163. #elif defined(__DJGPP__)
  1164.     if ( setjmp( &t->th_ptr ) > 0 ) {
  1165. #endif
  1166.         /* in context of thread now */
  1167.         KFASTUNBLOCK();
  1168.         (*kcurthread->th_fn)(kcurthread->th_fnarg);
  1169.         if (kcurthread->th_end_value)
  1170.             ksendmessage( kcurthread->th_end_thread,
  1171.                           kcurthread->th_end_value,
  1172.                           kcurthread->th_end_data );
  1173.         kdestroythread( NULL );
  1174. //      rt_killcurthread();
  1175.     }
  1176.     /* The following allows the floating point emulator to work.  That
  1177.      * code assumes SS:0 to SS:415 can be used for register storage,
  1178.      * whereas kcalloc() returns Seg:04 and we use the next 4 bytes
  1179.      * for the stack signature.
  1180.      * So your choice is either to have the safety stack signature,
  1181.      * or support for FP emulation.
  1182.      * One still has to use a CS, because eRTOS does not save FP regs
  1183.      * at thread switch time.
  1184.      */
  1185. #ifdef USE_FP /* allow FP regs to be saved on stack */
  1186. #if defined(__TURBOC__) || defined(__BORLANDC__)
  1187.     t->th_ptr.j_ss = FP_SEG( stkptr ) + 1;
  1188.     t->th_ptr.j_sp = FP_OFF( stkptr ) + stklength - sizeof( &t->th_ptr) - 16;
  1189. #elif defined(__DJGPP__)
  1190.     t->th_ptr.__esp = (DWORD)(stkptr) + stklength - sizeof( &t->th_ptr) - 16;
  1191. #endif  // DJGPP
  1192.         
  1193. #else  /* default, offer a stack safety signature which may catch overflows*/
  1194.     *(DWORD*) stkptr = STACK_SIG ; /* R T O S */
  1195. #if defined(__TURBOC__) || defined(__BORLANDC__)
  1196.     t->th_ptr.j_ss = FP_SEG( stkptr );
  1197.     t->th_ptr.j_sp = FP_OFF( stkptr ) + stklength - sizeof( &t->th_ptr);
  1198. #endif // BORLANDC
  1199. #endif // USE_FP
  1200.     t->th_stack = stkptr;
  1201.     t->th_stacklen = stklength;
  1202.     kaddthread( &krun, t , TS_PRIORITY);
  1203.     KFASTUNBLOCK();
  1204.     return( t );
  1205. }
  1206. /*--------------------------------------------------------------------*/
  1207. int rt_stackused( thread_x *t)
  1208. {
  1209.     int len;
  1210.     char *p;
  1211.     if ( t == NULL ) t = kcurthread;
  1212.     if ( t == kmainthread) return( 0xffff );    /* cannot check stack of main thread */
  1213.     for ( len = sizeof( STACK_SIG ), p = t->th_stack + len ;
  1214.           (*p == 0) && (len < t->th_stacklen) ;
  1215.           len++, p++ );
  1216.     return( t->th_stacklen - len );
  1217. }
  1218. /*--------------------------------------------------------------------*/
  1219. static void add48( DWORD alo, WORD ahi, DWORD blo, DWORD *rlo, WORD *rhi )
  1220. #if defined( __TURBOC__ ) || defined( __BORLANDC__ )
  1221. {
  1222.     *rlo = blo + alo;
  1223.     asm jnc over
  1224.     ahi ++;
  1225. over:
  1226.     *rhi = ahi;
  1227. }
  1228. #elif defined( __DJGPP__ )
  1229. {
  1230.     *rlo = blo + alo;
  1231.     if ( *rlo < alo ) ahi++;
  1232.     *rhi = ahi;
  1233. }
  1234. #endif
  1235. void xrt_sleep( DWORD ms, char *file, int line )
  1236. {
  1237.     WORD flags;
  1238.    if ( kblocked > 0 ) {
  1239.       char buf[ 256 ];
  1240.       sprintf( buf, "sleep called when kblocked > 0, %s line %un", file, line );
  1241.       rt_halt( buf );
  1242.    }
  1243.     KFASTBLOCK();
  1244.     /* need to block so clock is not updating as we reference it */
  1245.     rt_cpu_block( &flags );
  1246.     {
  1247. //      WORD msg;
  1248. //      DWORD data;
  1249.         add48( ktime, ktime2, ms, &kcurthread->th_waketime, &kcurthread->th_waketime2);
  1250.         kcurthread->th_status |= THS_SLEEP;
  1251.         rt_cpu_unblock( &flags );
  1252.         KFASTUNBLOCK();
  1253. //      kreadmessage( &msg, &data );
  1254.         kreadspecialmessage( EMSG_TIMER );
  1255.     }
  1256. }
  1257. void kwindow( int left, int top, int right, int bottom )
  1258. {
  1259.     kusewindows = 1;
  1260.     KFASTBLOCK();
  1261.     kcurthread->th_left = left+1;
  1262.     kcurthread->th_right = right-1;
  1263.     kcurthread->th_top = top+1;
  1264.     kcurthread->th_bottom = bottom-1;
  1265.     window( left, top, right, bottom );
  1266.     textbackground( WHITE );
  1267.     clrscr();
  1268.     window( left+1, top+1, right-1, bottom-1 );
  1269.     textbackground( BLACK );
  1270.     clrscr();
  1271.     KFASTUNBLOCK();
  1272. }
  1273. /*--------------------------------------------------------------------*/
  1274. #if defined( __BORLANDC__ ) || defined( __TURBOC__ )
  1275. //void interrupt *rt_enableirq( int irq, void interrupt (*isr)() )
  1276. void interrupt (far *rt_enableirq (int irq, void interrupt (*isr)()))()
  1277. {
  1278.     void interrupt (*oldisr)() = NULL;
  1279.     if ( irq < 8 ) {
  1280.         oldisr = getvect( 8 + irq );
  1281.         setvect( 8 + irq, isr );
  1282.         /* turn on 8259 PIC */
  1283.         outportb( OCW1, inportb( OCW1 ) & ~ (1 << irq ));
  1284.     } else {
  1285.         irq -= 8;
  1286.         oldisr = getvect( 0x70 + irq );
  1287.         setvect( 0x70 + irq, isr );
  1288.         /* turn on 8259 PIC */
  1289.         outportb( OCW1_2, inport( OCW1_2 ) & ~ ( 1 << irq ));
  1290.     }
  1291.     return( oldisr );
  1292. }
  1293. /*--------------------------------------------------------------------*/
  1294. void rt_disableirq( int irq, void interrupt (*oldisr)() )
  1295. {
  1296.     if ( irq < 8 ) {
  1297.         /* turn off 8259 PIC */
  1298.         outportb( OCW1 , inportb( OCW1) | (1 << irq ));
  1299.         setvect( irq + 8, oldisr );
  1300.     } else {
  1301.         irq -= 8;
  1302.         /* turn off 8259 PIC2 */
  1303.         outportb( OCW1_2, inportb( OCW1_2) | (1 << irq ));
  1304.         setvect( irq + 0x70, oldisr );
  1305.     }
  1306. }
  1307. #elif defined(__DJGPP__)
  1308. static struct irq_handler_info isr[16];
  1309. irq_handler_info *rt_enableirq (int irq, void (*irq_handler)())
  1310. {
  1311.   struct irq_handler_info *inf = isr + irq;
  1312.   BYTE   intr = (irq < 8) ? (irq + 8) : (irq + 0x70-8);
  1313.   if (irq < 0 || irq >= DIM(isr) || inf->new_handler.pm_offset)
  1314.      return (NULL);
  1315.   if (_go32_dpmi_get_protected_mode_interrupt_vector (intr,&inf->old_handler))
  1316.      return (NULL);
  1317.   inf->new_handler.pm_offset = (unsigned long) irq_handler;
  1318.   if (_go32_dpmi_allocate_iret_wrapper (&inf->new_handler))
  1319.   {
  1320.     inf->new_handler.pm_offset = 0;
  1321.     return (NULL);
  1322.   }
  1323.   _go32_dpmi_set_protected_mode_interrupt_vector (intr,&inf->new_handler);
  1324.   if ( irq < 8 )
  1325.   {
  1326.     /* turn on 8259 PIC */
  1327.     outportb (OCW1, inportb(OCW1) & ~(1 << irq));
  1328.   }
  1329.   else
  1330.   {
  1331.     irq -= 8;
  1332.     /* turn on 8259 PIC */
  1333.     outportb (OCW1_2, inportb(OCW1_2) & ~(1 << irq));
  1334.   }
  1335.   return (inf);
  1336. }
  1337. void rt_disableirq (int irq, irq_handler_info *inf)
  1338. {
  1339.   BYTE intr = (irq < 8) ? (irq + 8) : (irq + 0x70-8);
  1340.   if (irq < 0 || irq >= DIM(isr) || !inf->new_handler.pm_offset)
  1341.      return;
  1342.   if (irq < 8)
  1343.   {
  1344.     /* turn off 8259 PIC */
  1345.     outportb (OCW1 , inportb(OCW1) | (1 << irq));
  1346.   }
  1347.   else
  1348.   {
  1349.     irq -= 8;
  1350.     /* turn off 8259 PIC2 */
  1351.     outportb( OCW1_2, inportb(OCW1_2) | (1 << irq));
  1352.   }
  1353.   _go32_dpmi_set_protected_mode_interrupt_vector (intr, &inf->old_handler);
  1354.   _go32_dpmi_free_iret_wrapper (&inf->new_handler);
  1355.   inf->new_handler.pm_offset = isr[irq].new_handler.pm_offset = 0;
  1356. }
  1357. #endif // TURBOC BORLANDC
  1358. /*--------------------------------------------------------------------*/
  1359. void rt_eoi( int irq )
  1360. {
  1361.     if ( irq < 8 )
  1362.         outportb( OCW2, 0x20 );
  1363.     else
  1364.         outportb( OCW2_2, 0x20 );
  1365. }
  1366. /*--------------------------------------------------------------------*/
  1367. char *kstrdup( const char *s )
  1368. {
  1369.     char *p;
  1370.     if ( s == NULL )
  1371.         return( NULL );
  1372.     if ( ( p = kcalloc( strlen( s ) + 1, 1 )) != NULL )
  1373.         strcpy( p, s );
  1374.     return( p );
  1375. }