RTOS.C
上传用户:sunrenlu
上传日期:2022-06-13
资源大小:1419k
文件大小:42k
- /*
- * Copyright (c) 1990, 1999 Erick Engelke
- */
- // #define USE_FP /* uncomment this if you want FP emulation allowed */
- /* but it will remove the safety signature on your stack */
- /**************************************************************************/
- /* INCLUDES */
- /**************************************************************************/
- #include <stdio.h>
- #include <stddef.h>
- #include <stdlib.h>
- #include <cpujmp.h>
- #include <dos.h>
- #if defined( __BORLANDC ) || defined( __TURBOC__ )
- #include <alloc.h>
- #else
- #include <malloc.h>
- #endif
- #include <mem.h>
- #include <bios.h>
- #include <string.h>
- #if defined(__DJGPP__)
- #include <sys/time.h>
- #include <sys/farptr.h>
- #include <signal.h>
- #include <go32.h>
- #include <dpmi.h>
- #endif
- #include "rtos.h"
- /**************************************************************************/
- /* FLAGS */
- /**************************************************************************/
- /*
- * DJGPP stack does not allow us to place signature at SS:0
- */
- #if defined(__DJGPP__)
- #define USE_FP
- #endif
- #define DEBUG 1
- #define USE_INTR
- #include <conio.h>
- /**************************************************************************/
- /* DEFINES */
- /**************************************************************************/
- #define DIM(x) (sizeof(x) / sizeof((x)[0]))
- #define THS_THREAD 0x0001 /* is a thread */
- #define THS_SLEEP 0x0002 /* see th_waketime */
- #define THS_SYNC 0x0004 /* see th_syncptr */
- #define STACK_SIG (('R' << 0) + ('T' << 8) + ('O' << 16) + ('S' << 24))
- #define KFASTBLOCK() kblocked++
- #define KFASTUNBLOCK() kblocked--
- #define OCW1 0x21 /* 8259 */
- #define OCW2 0x20
- #define OCW1_2 0xA1 /* 8259 */
- #define OCW2_2 0xA0
- /**************************************************************************/
- /* VARIABLES */
- /**************************************************************************/
- thread_x *kmainthread = NULL; /* the main thread pointer */
- thread_x *krun = NULL; /* running list */
- thread_x *kwait = NULL; /* waiting list */
- thread_x *kdye = NULL; /* dying list */
- msg_x *kfreemessages = NULL;
- int volatile kinisr = 0; /* ISR active, don't do thread switch */
- int kcheckstacksig = 1; /* check stack signature within ISR */
- int _fastdos = 1; /* set to zero if we wish to use CS's rather than
- * kblock()'s around DOS calls
- */
- crit_x *_dos_cs = NULL;
- int kusewindows = 0;
- int kdebug = 0;
- /*------------------------------------*/
- #define TIME_X_TOP 37287L
- #define TIME_X_BOT 2048L
- DWORD ktime = 0L; /* system timer */
- WORD ktime2 = 0;
- DWORD kupticks = 0;
- #if defined( __BORLANDC__ ) || defined( __TURBOC__ )
- static DWORD far *sysclock = 0x46cL; /* PC Bios clock */
- static BYTE far *sysoverflow = 0x470L; /* clock went past midnight */
- #elif defined(__DJGPP__)
- static DWORD dummyclock; /* until real clock is assigned */
- static DWORD *sysclock = &dummyclock;
- #endif
- static int kirqscount = 0;
- static int kirqsper = 0;
- DWORD kseconds = 0;
- /*------------------------------------*/
- static DWORD ktime0 = 0L; /* used if frequency is higher than 1kHz */
- DWORD kincr = 55; /* ms frequency */
- DWORD kincr0 = 0;
- static long ksinceIRQ8 = 0;
- thread_x *kcurthread;
- WORD kpreemptive = 0;
- volatile WORD kblocked = 0;
- void (*k_user_int8)(void) = NULL;
- int kctrlbreak = 1;
- /**************************************************************************/
- /* CODE */
- /**************************************************************************/
- /*--------------------------------------------------------------------*/
- /* debugging stuff */
- /*--------------------------------------------------------------------*/
- void k_debugtest( void )
- {
- if ( bioskey( 1 ) ) {
- puts("ndebugging stopped");
- exit( 3 );
- }
- }
- void kblock(void)
- {
- kblocked++;
- }
- void kunblock(void)
- {
- if ( kblocked > 0 ) kblocked--;
- }
- void rt_cpu_block( WORD *p )
- {
- #if defined( __TURBOC__ ) || defined( __BORLANDC__ )
- *p = _FLAGS; /* save interrupt state */
- disable(); /* disable interrupts for a spell */
- #elif defined( __DJGPP__ )
- __asm__ __volatile__ (
- "pushflnt"
- "popl %%eaxnt"
- "clint"
- : "=a" (*p));
- #endif
- }
- void rt_cpu_unblock( WORD *p )
- {
- #define I86_INTERRUPT_ENABLE_FLAG 0x200
- if ( *p & I86_INTERRUPT_ENABLE_FLAG )
- enable();
- }
- int rt_thread_status( thread_x *t )
- {
- int result;
- KFASTBLOCK();
- if ( (t == kcurthread) || ( t==NULL ) )
- result = TSTAT_RUNNING;
- else if ( t->th_head == &krun )
- result = TSTAT_WILL_RUN;
- else if ( t->th_head == &kwait )
- result = TSTAT_WAITING;
- else if ( t->th_critical != NULL )
- result = TSTAT_CRITICAL;
- else
- result = TSTAT_DEAD;
- KFASTUNBLOCK();
- return( result );
- }
- void rt_halt( char *msg )
- {
- KFASTBLOCK();
- if ( kusewindows ) {
- gotoxy( 1, 25 );
- clreol();
- }
- printf("HALT in %s: %sn", kcurthread->th_name, msg ? msg : "no message specified");
- #ifdef __DJGPP__
- sio_exit();
- rt_restoretimer();
- abort(); /* produce traceback */
- #endif
- exit( 3 );
- }
- /* internal routine to remove thread from a list */
- static void kremthread( thread_x *t )
- {
- thread_x *suc, *pred;
- WORD flags;
- thread_x **head;
- if ( t == NULL ) t = kcurthread;
- rt_cpu_block( &flags );
- head = t->th_head;
- suc = t->th_next;
- pred = t->th_prev;
- /* deal with successor */
- if ( suc != NULL )
- suc->th_prev = pred;
- /* deal with predecssor */
- if ( pred != NULL )
- pred->th_next = suc;
- else
- *head = suc;
- t->th_head = NULL;
- rt_cpu_unblock( &flags );
- }
- /* add this to new list */
- void kaddthread( thread_x **head, thread_x *t, int howsort )
- {
- thread_x *x, *prev;
- WORD flags;
- BYTE ourpriority;
- rt_cpu_block( &flags );
- x = *head;
- prev = NULL;
- do {
- if ( x == NULL ) break; /* insert it here */
- /* there is at least one existing entry */
- if ( howsort == TS_NOSORT )
- break; /* insert it here */
- /* skip past higher priorities */
- if ( howsort == TS_PRIORITY ) {
- ourpriority = t->th_priority;
- /* at start, x is pointing at head */
- do {
- if ( x->th_priority <= ourpriority ) {
- /* skip past these more important things */
- prev = x;
- x = x->th_next;
- /* until we hit end of list */
- if ( x == NULL ) break;
- } else
- break;
- } while ( 1 );
- /* insert here */
- break;
- }
- /* sort by timer */
- if ( howsort == TS_SOON ) {
- do {
- if (( x->th_waketime < t->th_waketime ) &&
- ( x->th_waketime2 < t->th_waketime2 )) {
- prev = x;
- x = x->th_next;
- if ( x == NULL ) break;
- } else
- break;
- } while ( 1 );
- /* insert here */
- break;
- }
- } while ( 0 );
- /* x = where_to_insert_before or NULL=end, prev = prev or NULL/head */
- t->th_prev = prev;
- if ( prev ) prev->th_next = t;
- else *head = t;
- t->th_next = x;
- if ( x != NULL )
- x->th_prev = t;
- t->th_head = head;
- rt_cpu_unblock( &flags );
- return;
- }
- /*--------------------------------------------------------------------*/
- /* critical sections */
- /*--------------------------------------------------------------------*/
- crit_x *cs_alloc( void )
- {
- return( kcalloc( sizeof( crit_x ), 1 ));
- }
- void cs_new( crit_x **cs )
- {
- kblock();
- if ( *cs == NULL )
- if ( (*cs = cs_alloc()) == NULL )
- rt_halt("out of memory on cs_new()");
- kunblock();
- }
- void cs_free( crit_x *x )
- {
- kfree( x );
- }
- void cs_enter( crit_x *cs )
- {
- WORD flags;
- if ( cs != NULL ) {
- rt_cpu_block( &flags );
- if ( (cs->cs_active == NULL ) || (cs->cs_active == kcurthread )) {
- /* we take it */
- cs->cs_active = kcurthread;
- kcurthread->th_critical = cs;
- rt_cpu_unblock(&flags);
- } else {
- /* we need to wait for this */
- kremthread( kcurthread ); /* stop running */
- kaddthread( &cs->cs_blocked, kcurthread , TS_PRIORITY);
- kcurthread->th_critical = cs;
- rt_cpu_unblock( &flags );
- rt_yield(); /* and go to the safe one */
- }
- cs->cs_depth ++;
- }
- }
- void cs_exit( crit_x *cs )
- {
- thread_x *t;
- WORD flags;
- if ( cs != NULL ) {
- rt_cpu_block(&flags);
- cs->cs_depth --;
- if ( cs->cs_depth == 0 ) {
- kcurthread->th_critical = NULL;
- if ( cs->cs_active == kcurthread ) {
- t = cs->cs_blocked;
- if ( t == NULL )
- /* nothing waiting */
- cs->cs_active = NULL;
- else {
- /* move first waiting to next executing */
- kremthread( t );
- cs->cs_active = t;
- kaddthread( &krun, t, TS_PRIORITY );
- rt_cpu_unblock( &flags );
- rt_yield(); /* go to it */
- return;
- }
- }
- }
- rt_cpu_unblock(&flags);
- }
- }
- void dos_enter( void )
- {
- if ( _fastdos ) {
- KFASTBLOCK();
- } else {
- cs_enter( _dos_cs );
- }
- }
- void dos_exit( void )
- {
- if ( _fastdos ) {
- KFASTUNBLOCK();
- } else {
- cs_exit( _dos_cs );
- }
- }
- /*--------------------------------------------------------------------*/
- /* memory allocation */
- /*--------------------------------------------------------------------*/
- DWORD kcorefree( void )
- {
- DWORD d;
- #if defined(__TURBOC__) || defined(__BORALNDC__)
- dos_enter();
- d = coreleft();
- #elif defined( __DJGPP__)
- __dpmi_free_mem_info mem;
- dos_enter();
- __dpmi_get_free_memory_information (&mem);
- d = 4096 * mem.total_number_of_free_pages;
- #endif
- dos_exit();
- return( d );
- }
- void *kcalloc( WORD n, WORD size )
- {
- void *p;
- #ifdef OLD
- dos_enter();
- p = calloc( n, size );
- dos_exit();
- return( p );
- #else
- WORD sz;
- mem_x *m;
- sz = n * size;
- dos_enter();
- m = calloc( 1, sz + sizeof( mem_x ) + sizeof( DWORD ));
- dos_exit();
- m->mem_size = sz;
- m->mem_startsig = MEM_STARTSIG;
- m->mem_thread = kcurthread;
- *(DWORD*) &m->mem_data [sz] = MEM_ENDSIG;
- return ( &m->mem_data[0] );
- #endif
- }
- void kfree( void *p )
- {
- #ifdef OLD
- dos_enter();
- if ( p != NULL )
- free( p );
- dos_exit();
- #else
- mem_x *m;
- DWORD *dw;
- m = (mem_x*) ((DWORD)p - offsetof(mem_x, mem_data));
- if ( m->mem_startsig != MEM_STARTSIG ) {
- char buf[ 256];
- sprintf( buf, "kfree of mangled mem (or not kcalloc'd) %08lx", (DWORD)p );
- if ( kdebug > 1 ) {
- cputs( buf );
- cputs( "rncontinuing without freeing bufferrn");
- return;
- }
- rt_halt( buf );
- }
- dw = (DWORD*) &m->mem_data [m->mem_size];
- if ( *dw != MEM_ENDSIG ) {
- thread_x *th;
- char buf[ 256 ];
- th = m->mem_thread;
- sprintf( buf, "mem overflow @ %08lx, kcalloced in %s",
- (DWORD)&m->mem_data, th->th_name );
- if ( kdebug > 1 ) {
- cputs( buf );
- cputs( "rncontinuing without freeing bufferrn");
- return;
- }
- rt_halt( buf );
- }
- dos_enter();
- free( m );
- dos_exit();
- #endif
- }
- void *krealloc( void *m, WORD size )
- {
- void *p;
- dos_enter();
- p = realloc( m, size );
- dos_exit();
- return( p );
- }
- /*--------------------------------------------------------------------*/
- /* messaging stuff */
- /*--------------------------------------------------------------------*/
- /*
- * kfreeallmessages - used to free all pending messages at task end time
- */
- static void kfreeallmessages( thread_x *t )
- {
- msg_x *firstm, *lastm, *p;
- WORD flags;
- firstm = t->th_messagelist;
- if ( firstm != NULL ) {
- lastm = firstm;
- while ( (p = lastm->m_next )!=NULL) lastm = p;
- rt_cpu_block( &flags );
- lastm->m_next = kfreemessages;
- kfreemessages = firstm;
- rt_cpu_unblock( &flags );
- t->th_messagelist = NULL;
- }
- }
- /*--------------------------------------------------------------------*/
- void kmessage_on_exit( void *thread, int value, DWORD data )
- {
- thread_x *t;
- /* most likely send it to parent */
- if ( thread == NULL ) t = kcurthread->th_parent;
- else t = (thread_x*)thread;
- kcurthread->th_end_thread = t;
- kcurthread->th_end_value = value;
- kcurthread->th_end_data = data;
- }
- #ifndef FIXMESSAGE
- static void ksendmessagebuffer( thread_x* t, int value, DWORD data, msg_x* m)
- {
- msg_x *mm;
- if (( t->th_messagewait == value ) &&( value != 0) ) {
- t->th_messagewait = 0; // cancel the wait
- t->th_status &= ~THS_MESG;
- kresume( t );
- } else {
- kfreemessages = m->m_next; /* advance to next free one */
- m->m_value = value;
- m->m_data = data;
- m->m_next = NULL;
- /* add to end of list */
- if ( t->th_messagelist == NULL ) t->th_messagelist = t->th_messagetail = m;
- else if ( t->th_messagetail ) {
- t->th_messagetail->m_next = m;
- t->th_messagetail = m;
- } else {
- mm = t->th_messagelist;
- while ( mm->m_next )
- mm = mm->m_next ;
- t->th_messagetail = mm->m_next = m;
- }
- if ( t->th_status & THS_MESG ) {
- /* it is blocked waiting */
- /* see if waiting for general message or specialized one */
- if ( t->th_messagewait == 0 ) {
- t->th_status &= ~THS_MESG;
- kresume( t );
- }
- }
- }
- }
- int ksendmessage( void *thread , int value, DWORD data )
- {
- msg_x *m;
- WORD flags;
- rt_cpu_block(&flags);
- m = kfreemessages;
- if ( m != NULL)
- ksendmessagebuffer( thread, value, data, m);
- rt_cpu_unblock(&flags);
- return( m ? 1 : 0 ); // 2000.9.13 added return value
- }
- void kwritemessage( void *thread , int value, DWORD data )
- {
- msg_x *m;
- WORD flags;
- rt_cpu_block(&flags);
- do {
- m = kfreemessages;
- if ( m != NULL ) break;
- rt_cpu_unblock(&flags);
- rt_yield(); /* wait for a free one */
- rt_cpu_block(&flags);
- } while ( m == NULL );
- ksendmessagebuffer( thread, value, data, m);
- rt_cpu_unblock(&flags);
- }
- #else /* old messaging */
- void ksendmessage( void *thread , int value, DWORD data )
- {
- msg_x *m, *mm;
- thread_x *t;
- WORD flags;
- t = (thread_x*) thread;
- rt_cpu_block(&flags);
- m = kfreemessages;
- if ( m == NULL ) {
- rt_cpu_unblock(&flags);
- return;
- }
- if (( t->th_messagewait == value ) &&( value != 0) ) {
- t->th_messagewait = 0; // cancel the wait
- t->th_status &= ~THS_MESG;
- kresume( t );
- } else {
- kfreemessages = m->m_next; /* advance to next free one */
- m->m_value = value;
- m->m_data = data;
- m->m_next = NULL;
- /* add to end of list */
- if ( t->th_messagelist == NULL ) t->th_messagelist = t->th_messagetail = m;
- else if ( t->th_messagetail ) {
- t->th_messagetail->m_next = m;
- t->th_messagetail = m;
- } else {
- for ( mm = t->th_messagelist; mm->m_next ; mm = mm->m_next );
- t->th_messagetail = mm->m_next = m;
- }
- if ( t->th_status & THS_MESG ) {
- /* it is blocked waiting */
- /* see if waiting for general message or specialized one */
- if ( t->th_messagewait == 0 ) {
- t->th_status &= ~THS_MESG;
- kresume( t );
- }
- }
- }
- rt_cpu_unblock(&flags);
- }
- void kwritemessage( void *thread , int value, DWORD data )
- {
- msg_x *m, *mm;
- thread_x *t;
- WORD flags;
- t = (thread_x*) thread;
- rt_cpu_block(&flags);
- do {
- m = kfreemessages;
- if ( m != NULL ) break;
- rt_cpu_unblock(&flags);
- rt_yield(); /* wait for a free one */
- rt_cpu_block(&flags);
- } while ( m == NULL );
- kfreemessages = m->m_next; /* advance to next free one */
- m->m_value = value;
- m->m_data = data;
- m->m_next = NULL;
- /* add to end of list */
- if ( t->th_messagelist == NULL ) t->th_messagelist = t->th_messagetail = m;
- else if ( t->th_messagetail ) {
- t->th_messagetail->m_next = m;
- t->th_messagetail = m;
- } else {
- for ( mm = t->th_messagelist; mm->m_next ; mm = mm->m_next );
- t->th_messagetail = mm->m_next = m;
- }
- if ( t->th_status & THS_MESG ) {
- /* it is blocked waiting */
- t->th_status &= ~THS_MESG;
- kresume( t );
- }
- rt_cpu_unblock(&flags);
- }
- #endif
- /* non-blocking version */
- int kgetmessage( int *value, DWORD *data )
- {
- msg_x *m;
- WORD flags;
- rt_cpu_block( &flags );
- if ( (m = kcurthread->th_messagelist) != NULL ) {
- *value = m->m_value;
- *data = m->m_data;
- kcurthread->th_messagelist = m->m_next;
- if ( kcurthread->th_messagetail == m )
- kcurthread->th_messagetail = NULL;
- /* return it to the freelist */
- m->m_next = kfreemessages;
- kfreemessages = m;
- // kfree( (BYTE*) m );
- rt_cpu_unblock(&flags);
- return( 1 );
- }
- rt_cpu_unblock(&flags);
- return( 0 );
- }
- int kreadmessage( int *value, DWORD *data )
- {
- WORD flags;
- rt_cpu_block( &flags );
- while ( kcurthread->th_messagelist == NULL ) {
- kcurthread->th_status |= THS_MESG;
- ksuspend(kcurthread);
- rt_cpu_unblock( &flags );
- rt_yield();
- }
- rt_cpu_unblock( &flags );
- return( kgetmessage( value, data ));
- }
- void kreadspecialmessage( int value )
- {
- WORD flags;
- rt_cpu_block( &flags );
- if ( kcurthread->th_messagelist ) {
- msg_x **mm = &kcurthread->th_messagelist;
- msg_x *m = *mm;
- while ( m ) {
- if ( m->m_value == value ) {
- /* found msg, remove it */
- *mm = m->m_next;
- m->m_next = kfreemessages;
- kfreemessages = m;
- rt_cpu_unblock( &flags );
- return;
- }
- mm = &m->m_next;
- m = *mm;
- }
- }
- kcurthread->th_messagewait = value;
- kcurthread->th_status |= THS_MESG;
- ksuspend(kcurthread);
- rt_cpu_unblock( &flags );
- rt_yield();
- }
- DWORD knumthreads( void )
- {
- DWORD i;
- thread_x *t;
- KFASTBLOCK();
- for (i = 0 , t = krun ; t ; t = t->th_next ) {
- dos_enter();
- printf("running : %srn", t->th_name );
- dos_exit();
- i++;
- }
- for ( t = kwait ; t ; t= t->th_next ) {
- dos_enter();
- printf("waiting : %srn", t->th_name );
- dos_exit();
- i++;
- }
- KFASTUNBLOCK();
- return( i );
- }
- void ksuspendhow( thread_x *t, thread_x **newlist )
- {
- KFASTBLOCK();
- if ( t == NULL ) t = kcurthread;
- kremthread( t );
- kaddthread( newlist, t, TS_NOSORT );
- KFASTUNBLOCK();
- }
- void ksuspend( thread_x *t )
- {
- KFASTBLOCK();
- if ( t == NULL ) t = kcurthread;
- kremthread( t );
- kaddthread( &kwait, t, TS_PRIORITY );
- KFASTUNBLOCK();
- }
- void kresume( thread_x *t)
- {
- thread_x **head;
- KFASTBLOCK();
- if ( t == NULL ) t = kcurthread;
- if ( t->th_sig != TH_SIG )
- rt_halt("attempt to resume dead thread");
- head = t->th_head;
- /* don't do anything if already running */
- if ( head != &krun ) {
- kremthread( t);
- kaddthread( &krun, t , TS_PRIORITY);
- }
- KFASTUNBLOCK();
- }
- void kdestroythread( thread_x *t )
- {
- bq_str *bq;
- // crit_x *cr;
- WORD flags;
- KFASTBLOCK();
- if ( t == NULL ) t = kcurthread;
- if ( t->th_main ) exit( 0 );
- rt_cpu_block( &flags );
- /* ensure we do not get restarted by byte queue or crit x */
- /* NOT needed, kremthread removes us from this list
- * if ( (cr = t->th_crit) != NULL ) {
- * if ( cr->cs_blocked == t )
- * cr->cs_blocked = NULL;
- * }
- */
- if ( (bq = t->th_bq) != NULL ) {
- if ( bq->bq_sendwait == kcurthread ) bq->bq_sendwait = NULL;
- if ( bq->bq_recvwait == kcurthread ) bq->bq_recvwait = NULL;
- }
- rt_cpu_unblock( &flags );
- kremthread( t );
- kaddthread( &kdye, t , TS_NOSORT );
- KFASTUNBLOCK();
- kfreeallmessages( t ); /* return message list to pool */
- rt_nextthread(); /* and we'll never run again */
- }
- void kfinaldeath( thread_x *t )
- {
- t->th_sig = 0;
- kremthread( t );
- if ( t->th_stack )
- kfree( t->th_stack ); /* kill this stack */
- kfree( t );
- }
- char *kthreadname( void )
- {
- return( kcurthread->th_name );
- }
- #ifdef NEVER
- /*
- * sync_test - attempt to set a byte to 1
- */
- BYTE sync_test( void *p )
- {
- _asm {
- push es
- push di
- les di, p
- mov ax, 1
- xchg es:[di], al
- pop di
- pop es
- }
- return( _AL );
- }
- #endif
- /*
- * rt_clocktest - test waiting threads for clock reference
- */
- void rt_clocktest( void )
- {
- WORD st;
- thread_x *t, *next;
- // static DWORD lasttime = 0;
- WORD flags;
- // int status;
- rt_cpu_block( &flags );
- /* do we need to do this ? */
- // if ( lasttime == ktime ) return;
- /* look through inactive list */
- for ( t = kwait ; t ; t = next ) {
- next = t->th_next; /* learn this now while still valid */
- st = t->th_status;
- if ( st & THS_SLEEP ) {
- WORD oldstatus;
- DWORD oldwaketime;
- WORD oldwaketime2;
- if ( (t->th_waketime2 < ktime2 ) ||
- ( (( t->th_waketime <= ktime ) &&
- ( t->th_waketime2 == ktime2 )))) {
- oldstatus = t->th_status;
- oldwaketime = t->th_waketime;
- oldwaketime2= t->th_waketime2;
- t->th_status &= ~THS_SLEEP;
- t->th_waketime = 0;
- t->th_waketime2 = 0;
- if ( !ksendmessage( t, EMSG_TIMER, 0 )) {
- t->th_status = oldstatus;
- t->th_waketime = oldwaketime;
- t->th_waketime2 = oldwaketime2;
- }
- }
- }
- }
- rt_cpu_unblock( &flags );
- }
- void rt_nextthread(void)
- {
- // WORD bestpri, testpri, st;
- thread_x *bestt;
- // thread_x *t, *next;
- // int hitcur;
- // WORD flags;
- if ( kblocked > 0 ) {
- return;
- }
- KFASTBLOCK();
- if ( kusewindows ) {
- kcurthread->th_x = wherex();
- kcurthread->th_y = wherey();
- }
- /* save current CPU state - returns 0 and skips this now */
- /* later when we execute cpulongjmp we will return here */
- #if defined(__TURBOC__)||defined(__BORLANDC__)
- if ( cpusetjmp( &kcurthread->th_ptr ) ) {
- #elif defined(__DJGPP__)
- if ( setjmp( &kcurthread->th_ptr ) ) {
- #endif
- /* kill dead tasks */
- while ( kdye )
- kfinaldeath( kdye );
- if ( kcurthread->th_sig != TH_SIG )
- rt_halt("dead thread still in task queue");
- if ( kcurthread != kmainthread ) {
- if ( kcheckstacksig ) {
- if ( *(DWORD*)kcurthread->th_stack != STACK_SIG )
- rt_halt( "stack overflow - signature");
- }
- #if defined(__TURBOC__) || defined(__BORLANDC__)
- // if ( kcurthread->th_ptr.j_sp < FP_OFF( kcurthread->th_stack ))
- if ( kcurthread->th_ptr.j_sp > kcurthread->th_stacklen )
- #elif defined(__DJGPP__)
- // if ( 0 )
- if (kcurthread->th_ptr.__esp < (kcurthread->th_stack - kcurthread->th_stacklen))
- #endif
- rt_halt( "stack overflow - size");
- }
- if ( kusewindows ) {
- window( kcurthread->th_left,
- kcurthread->th_top,
- kcurthread->th_right,
- kcurthread->th_bottom);
- gotoxy( kcurthread->th_x,
- kcurthread->th_y);
- }
- KFASTUNBLOCK();
- return;
- }
- do {
- if ( kcurthread->th_head != &krun )
- /* go to head of list */
- bestt = krun;
- else {
- /* use next thread */
- bestt = kcurthread->th_next;
- if ( bestt != NULL ) {
- if ( bestt->th_priority > krun->th_priority )
- bestt = krun;
- } else
- bestt = krun;
- }
- if ( bestt == krun )
- rt_clocktest();
- if ( kdebug > 0 )
- k_debugtest();
- /* run the process with the best priority */
- if ( bestt != NULL ) {
- kcurthread = bestt;
- if ( kcurthread->th_sig != TH_SIG )
- rt_halt( "signature on thread overwritten by application");
- if ( kcurthread->th_ptrsig != TH_SIG )
- rt_halt( "signature error on registers");
- #if defined(__TURBOC__)||defined(__BORLANDC__)
- cpulongjmp( &kcurthread->th_ptr , 1 );
- #elif defined(__DJGPP__)
- longjmp( &kcurthread->th_ptr, 1 );
- #endif
- } else
- rt_clocktest();
- } while ( 1 );
- }
- void xrt_yield( char *file, int line )
- {
- if ( kblocked > 0 ) {
- char buf[ 256 ];
- sprintf( buf, "yield called when kblocked > 0, %s line %un", file, line );
- rt_halt( buf );
- }
- rt_nextthread();
- }
- /*--------------------------------------------------------------------*/
- /* timer */
- /*--------------------------------------------------------------------*/
- #if defined(__TURBOC__)||defined(__BORLANDC__)
- typedef struct _false_int {
- BYTE pushf1;
- BYTE call;
- void interrupt (*isr1)();
- BYTE jmp2;
- void interrupt (*isr2)();
- };
- struct _false_int false_int = {
- 0x9c, 0x9a, NULL,
- 0xcf, NULL };
- #endif
- /*
- * ktimer()
- */
- #if defined(__TURBOC__)||defined(__BORLANDC__)
- static void interrupt (*koldtimer)(void) = NULL;
- static void interrupt ktimer(void)
- #elif defined(__DJGPP__)
- static void ktimer( void )
- #endif
- {
- DWORD oldtime;
-
- #if defined(__TURBOC__) || defined(__BORLANDC__)
- static WORD *screen = MK_FP( 0xb800, 0);
-
- if (kdebug > 1 )
- *screen = kblocked + 0x0f30;
- #elif defined(__DJGPP__)
- if (kdebug > 1)
- _farpokew (_dos_ds, 0xB8000, kblocked + '0' + (15 << 8));
- #endif
- /* update eRTOS internal clock */
- if ( kincr != 0 ) {
- oldtime = ktime;
- ktime += kincr;
- if ( ktime < oldtime ) ktime2++;
- ksinceIRQ8 += kincr;
- } else {
- ktime0 += kincr0;
- if ( ktime0 >= 10 ) {
- ktime++;
- if ( ktime == 0 ) ktime2++;
- ksinceIRQ8 ++;
- ktime0 = 0;
- }
- }
- // outportb( 0x20, 0x20 );
- /* see if we should chain to old or send EOI ourselves */
- if ( ksinceIRQ8 >= 55 ) {
- ksinceIRQ8 -= 55;
- kupticks++;
- #if defined(__TURBOC__)||defined(__BORLANDC__)
- koldtimer();
- #endif
- }
- #if defined(__TURBOC__)||defined(__BORLANDC__)
- else
- outportb( 0x20, 0x20 );
- enable();
- #endif
- /* adjust count for BIOS clock */
- #define END_OF_DAY (24L*60L*60L)
- #define LAST_UPDATES (END_OF_DAY - 10L)
- if ( kirqsper ) {
- kirqscount++; /* clock fixer */
- if ( kirqscount >= kirqsper ) {
- kirqscount -= kirqsper;
- kseconds ++;
- if ( kseconds >= END_OF_DAY ) {
- kseconds = 0;
- }
- // let system do it's own rollover
- #if defined(__TURBOC__)||defined(__BORLANDC__)
- if ( (kseconds > 10 ) && (kseconds < LAST_UPDATES))
- *sysclock = (kseconds * TIME_X_TOP)/TIME_X_BOT;
- #endif
- }
- }
- if (kinisr)
- return;
- if (k_user_int8 != 0) /* user timer tick */
- (*k_user_int8)();
- if ( kpreemptive && kblocked == 0 &&
- kcurthread->th_inkernel == 0 ) { /* !! where is this set? */
- rt_nextthread();
- }
- }
- // mimick settime()
- void rt_settime( struct time *timep)
- {
- kseconds = ((timep->ti_hour * 60)+ timep->ti_min) * 60L + timep->ti_sec;
- kirqscount = 0;
- }
- #if defined(__TURBOC__) || defined(__BORLANDC__)
- // mimick stime
- void rt_stime( time_t *t )
- {
- struct tm *tm;
- struct time ti;
- dos_enter();
- tm = localtime( t );
- ti.ti_hour = tm->tm_hour;
- ti.ti_min = tm->tm_min;
- ti.ti_sec = tm->tm_sec;
- stime( t );
- rt_settime( &ti );
- dos_exit();
- }
- static void rt_settimer0( DWORD divisor )
- {
- //if ( divisor > 65535 ) divisor = 65535;
- disable();
- //outportb( 0x43, 0x36 ); /* set mode */
- //outportb( 0x40, divisor & 255 ); /* LSB */
- //outportb( 0x40, divisor >> 8 );
- outpw(0xff52,divisor);
- enable();
- }
- #endif
- void rt_timerfreq( WORD persec )
- {
- #if defined(__TURBOC__) || defined(__BORLANDC__)
- // rt_settimer0( 1193180 / persec );
- rt_settimer0(312909/persec); //陈道理 2005-05-31 11:21,313计数是1ms
- #elif defined(__DJGPP__)
- struct itimerval tim;
- tim.it_interval.tv_usec = 1000000/ persec;
- tim.it_interval.tv_sec = 0;
- tim.it_value =tim.it_interval;
- setitimer( ITIMER_REAL, &tim, NULL );
- #endif
- kirqsper = persec;
- kseconds = (*sysclock * TIME_X_BOT) / TIME_X_TOP;
- kirqscount = 0;
- if ( persec <= 1000 ) {
- kincr = 1000 / persec;
- kincr0 = 0;
- } else {
- kincr = 0;
- kincr0 = 10000 / persec;
- }
- }
- void rt_restoretimer( void )
- {
- #if defined(__TURBOC__) || defined(__BORLANDC__)
- // rt_settimer0( 65535 );
- rt_settimer0( 17210 ); //陈道理,2005-05-31 11:54
-
- if ( koldtimer != NULL)
- setvect( 0x8, koldtimer );
- #endif
- }
- #pragma exit rt_restoretimer 100
- /*--------------------------------------------------------------------*/
- int kctrlbrkhandler( void )
- {
- /* ctrlbrk */
- if ( kctrlbreak )
- rt_halt("user pressed control break");
- return( 1 ); /* continue execution unhamperred */
- }
- /*--------------------------------------------------------------------*/
- void rt_init( DWORD msgcount )
- {
- thread_x *t;
- DWORD i;
- msg_x *m;
- #ifdef USE_FP /* allow FP regs to be saved on stack */
- kcheckstacksig = 0; /* SS:0 may have FP data */
- #endif
- KFASTBLOCK();
-
- #if defined(__TURBOC__) || defined(__BORLANDC__)
- /* handle Ctrl Break */
- ctrlbrk( kctrlbrkhandler );
- koldtimer = getvect( 0x8 );
- false_int.isr1 = ktimer;
- /* rt_restoretimer will restore this at shutdown */
- setvect( 0x8, (void interrupt (*)())&false_int );
- #elif defined(__DJGPP__)
- {
- struct itimerval tim;
- tim.it_interval.tv_usec = 54945; /* 1000000/18.2 */
- tim.it_interval.tv_sec = 0;
- tim.it_value =tim.it_interval;
- signal( SIGALRM, (void(*)(int))ktimer );
- setitimer( ITIMER_REAL, &tim, NULL );
- }
- #endif
- kmainthread = t = kcalloc( sizeof( thread_x ), 1 );
- kcurthread = t;
- t->th_sig = TH_SIG;
- t->th_ptrsig = TH_SIG;
- t->th_status = THS_THREAD;
- t->th_priority = 64;
- t->th_main = 1;
- t->th_name = "main";
- #if defined(__TURBOC__) || defined(__BORLANDC__)
- t->th_stack = MK_FP( _SS, 0 );
- t->th_stacklen = 0xffff; /* main thread has no limit */
- *(DWORD*)t->th_stack = STACK_SIG;
- #elif defined(__DJGPP__)
- t->th_stack = 0;
- t->th_stacklen = 0xffffffff;
- #endif
- kaddthread( &krun, t , TS_PRIORITY);
- /* allocate close to the number of messages we were asked for */
- i = kcorefree();
- if (i < (msgcount * sizeof( msg_x )))
- msgcount = (i /2) / sizeof( msg_x );
- kfreemessages = kcalloc( msgcount, sizeof( msg_x ));
- if ( kfreemessages != NULL ) {
- for ( i = 0 ; i < (msgcount-1) ; ++i ) {
- m = &kfreemessages[ i ];
- m->m_next = &kfreemessages[ i + 1 ];
- }
- }
- /* actual last one has NULL as m_next thanks to kcalloc */
- _dos_cs = cs_alloc();
- KFASTUNBLOCK();
- }
- /*--------------------------------------------------------------------*/
- void rt_setpriority( thread_x *t, BYTE priority )
- {
- thread_x **head;
- if ( t == NULL ) t = kcurthread;
- if ( priority == 0 ) priority = kcurthread->th_priority;
- if ( t->th_priority != priority ) {
- /* easiest way is to remove from current queue, then re-insert it */
- head = t->th_head;
- kremthread( t );
- t->th_priority = priority;
- kaddthread( head, t, TS_PRIORITY );
- }
- if ( t != kcurthread ) {
- if ( krun )
- if ( krun->th_priority < kcurthread->th_priority ) {
- /* another thread is more deserving than us */
- if ( kblocked == 0 )
- rt_yield();
- }
- }
- }
- /*--------------------------------------------------------------------*/
- /*--------------------------------------------------------------------*/
- void *rt_newthread( void (*ptr)(), DWORD arg, WORD stklength,
- BYTE priority, char *name )
- {
- BYTE *stkptr;
- // WORD i;
- thread_x *t;
- stkptr = kcalloc( stklength, 1 );
- t = kcalloc( sizeof( thread_x ), 1 );
- if ( (t == NULL) || (stkptr == NULL))
- rt_halt("unable to allocate new thread");
- t->th_sig = TH_SIG;
- t->th_ptrsig = TH_SIG;
- t->th_parent = kcurthread;
- t->th_priority = priority ? priority : kcurthread->th_priority;
- t->th_status = THS_THREAD;
- t->th_fn = ptr;
- t->th_fnarg = arg;
- t->th_name = name;
- KFASTBLOCK();
- #if defined(__TURBOC__)||defined(__BORLANDC__)
- if ( cpusetjmp( &t->th_ptr ) > 0 ) {
- #elif defined(__DJGPP__)
- if ( setjmp( &t->th_ptr ) > 0 ) {
- #endif
- /* in context of thread now */
- KFASTUNBLOCK();
- (*kcurthread->th_fn)(kcurthread->th_fnarg);
- if (kcurthread->th_end_value)
- ksendmessage( kcurthread->th_end_thread,
- kcurthread->th_end_value,
- kcurthread->th_end_data );
- kdestroythread( NULL );
- // rt_killcurthread();
- }
- /* The following allows the floating point emulator to work. That
- * code assumes SS:0 to SS:415 can be used for register storage,
- * whereas kcalloc() returns Seg:04 and we use the next 4 bytes
- * for the stack signature.
- * So your choice is either to have the safety stack signature,
- * or support for FP emulation.
- * One still has to use a CS, because eRTOS does not save FP regs
- * at thread switch time.
- */
- #ifdef USE_FP /* allow FP regs to be saved on stack */
- #if defined(__TURBOC__) || defined(__BORLANDC__)
- t->th_ptr.j_ss = FP_SEG( stkptr ) + 1;
- t->th_ptr.j_sp = FP_OFF( stkptr ) + stklength - sizeof( &t->th_ptr) - 16;
- #elif defined(__DJGPP__)
- t->th_ptr.__esp = (DWORD)(stkptr) + stklength - sizeof( &t->th_ptr) - 16;
- #endif // DJGPP
-
- #else /* default, offer a stack safety signature which may catch overflows*/
- *(DWORD*) stkptr = STACK_SIG ; /* R T O S */
- #if defined(__TURBOC__) || defined(__BORLANDC__)
- t->th_ptr.j_ss = FP_SEG( stkptr );
- t->th_ptr.j_sp = FP_OFF( stkptr ) + stklength - sizeof( &t->th_ptr);
- #endif // BORLANDC
- #endif // USE_FP
- t->th_stack = stkptr;
- t->th_stacklen = stklength;
- kaddthread( &krun, t , TS_PRIORITY);
- KFASTUNBLOCK();
- return( t );
- }
- /*--------------------------------------------------------------------*/
- int rt_stackused( thread_x *t)
- {
- int len;
- char *p;
- if ( t == NULL ) t = kcurthread;
- if ( t == kmainthread) return( 0xffff ); /* cannot check stack of main thread */
- for ( len = sizeof( STACK_SIG ), p = t->th_stack + len ;
- (*p == 0) && (len < t->th_stacklen) ;
- len++, p++ );
- return( t->th_stacklen - len );
- }
- /*--------------------------------------------------------------------*/
- static void add48( DWORD alo, WORD ahi, DWORD blo, DWORD *rlo, WORD *rhi )
- #if defined( __TURBOC__ ) || defined( __BORLANDC__ )
- {
- *rlo = blo + alo;
- asm jnc over
- ahi ++;
- over:
- *rhi = ahi;
- }
- #elif defined( __DJGPP__ )
- {
- *rlo = blo + alo;
- if ( *rlo < alo ) ahi++;
- *rhi = ahi;
- }
- #endif
- void xrt_sleep( DWORD ms, char *file, int line )
- {
- WORD flags;
- if ( kblocked > 0 ) {
- char buf[ 256 ];
- sprintf( buf, "sleep called when kblocked > 0, %s line %un", file, line );
- rt_halt( buf );
- }
- KFASTBLOCK();
- /* need to block so clock is not updating as we reference it */
- rt_cpu_block( &flags );
- {
- // WORD msg;
- // DWORD data;
- add48( ktime, ktime2, ms, &kcurthread->th_waketime, &kcurthread->th_waketime2);
- kcurthread->th_status |= THS_SLEEP;
- rt_cpu_unblock( &flags );
- KFASTUNBLOCK();
- // kreadmessage( &msg, &data );
- kreadspecialmessage( EMSG_TIMER );
- }
- }
- void kwindow( int left, int top, int right, int bottom )
- {
- kusewindows = 1;
- KFASTBLOCK();
- kcurthread->th_left = left+1;
- kcurthread->th_right = right-1;
- kcurthread->th_top = top+1;
- kcurthread->th_bottom = bottom-1;
- window( left, top, right, bottom );
- textbackground( WHITE );
- clrscr();
- window( left+1, top+1, right-1, bottom-1 );
- textbackground( BLACK );
- clrscr();
- KFASTUNBLOCK();
- }
- /*--------------------------------------------------------------------*/
- #if defined( __BORLANDC__ ) || defined( __TURBOC__ )
- //void interrupt *rt_enableirq( int irq, void interrupt (*isr)() )
- void interrupt (far *rt_enableirq (int irq, void interrupt (*isr)()))()
- {
- void interrupt (*oldisr)() = NULL;
- if ( irq < 8 ) {
- oldisr = getvect( 8 + irq );
- setvect( 8 + irq, isr );
- /* turn on 8259 PIC */
- outportb( OCW1, inportb( OCW1 ) & ~ (1 << irq ));
- } else {
- irq -= 8;
- oldisr = getvect( 0x70 + irq );
- setvect( 0x70 + irq, isr );
- /* turn on 8259 PIC */
- outportb( OCW1_2, inport( OCW1_2 ) & ~ ( 1 << irq ));
- }
- return( oldisr );
- }
- /*--------------------------------------------------------------------*/
- void rt_disableirq( int irq, void interrupt (*oldisr)() )
- {
- if ( irq < 8 ) {
- /* turn off 8259 PIC */
- outportb( OCW1 , inportb( OCW1) | (1 << irq ));
- setvect( irq + 8, oldisr );
- } else {
- irq -= 8;
- /* turn off 8259 PIC2 */
- outportb( OCW1_2, inportb( OCW1_2) | (1 << irq ));
- setvect( irq + 0x70, oldisr );
- }
- }
- #elif defined(__DJGPP__)
- static struct irq_handler_info isr[16];
- irq_handler_info *rt_enableirq (int irq, void (*irq_handler)())
- {
- struct irq_handler_info *inf = isr + irq;
- BYTE intr = (irq < 8) ? (irq + 8) : (irq + 0x70-8);
- if (irq < 0 || irq >= DIM(isr) || inf->new_handler.pm_offset)
- return (NULL);
- if (_go32_dpmi_get_protected_mode_interrupt_vector (intr,&inf->old_handler))
- return (NULL);
- inf->new_handler.pm_offset = (unsigned long) irq_handler;
- if (_go32_dpmi_allocate_iret_wrapper (&inf->new_handler))
- {
- inf->new_handler.pm_offset = 0;
- return (NULL);
- }
- _go32_dpmi_set_protected_mode_interrupt_vector (intr,&inf->new_handler);
- if ( irq < 8 )
- {
- /* turn on 8259 PIC */
- outportb (OCW1, inportb(OCW1) & ~(1 << irq));
- }
- else
- {
- irq -= 8;
- /* turn on 8259 PIC */
- outportb (OCW1_2, inportb(OCW1_2) & ~(1 << irq));
- }
- return (inf);
- }
- void rt_disableirq (int irq, irq_handler_info *inf)
- {
- BYTE intr = (irq < 8) ? (irq + 8) : (irq + 0x70-8);
- if (irq < 0 || irq >= DIM(isr) || !inf->new_handler.pm_offset)
- return;
- if (irq < 8)
- {
- /* turn off 8259 PIC */
- outportb (OCW1 , inportb(OCW1) | (1 << irq));
- }
- else
- {
- irq -= 8;
- /* turn off 8259 PIC2 */
- outportb( OCW1_2, inportb(OCW1_2) | (1 << irq));
- }
- _go32_dpmi_set_protected_mode_interrupt_vector (intr, &inf->old_handler);
- _go32_dpmi_free_iret_wrapper (&inf->new_handler);
- inf->new_handler.pm_offset = isr[irq].new_handler.pm_offset = 0;
- }
- #endif // TURBOC BORLANDC
- /*--------------------------------------------------------------------*/
- void rt_eoi( int irq )
- {
- if ( irq < 8 )
- outportb( OCW2, 0x20 );
- else
- outportb( OCW2_2, 0x20 );
- }
- /*--------------------------------------------------------------------*/
- char *kstrdup( const char *s )
- {
- char *p;
- if ( s == NULL )
- return( NULL );
- if ( ( p = kcalloc( strlen( s ) + 1, 1 )) != NULL )
- strcpy( p, s );
- return( p );
- }