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

操作系统开发

开发平台:

DOS

  1. //#define OLD
  2. #define NEW
  3. #define NEWEST
  4. /*
  5.  * bqueue.c - BYTE queue for serial/parallel interfacing
  6.  * Copyright (c) 1990, 1999 Erick Engelke
  7.  */
  8. #include <stdio.h>
  9. #include "rtos.h"
  10. void bq_msg( bq_str *bq, int type )
  11. {
  12.     if ( type == EMSG_BQ_WAITING ) bq->bq_msg_waiting = kcurthread;
  13.     if ( type == EMSG_BQ_AVAIL   ) bq->bq_msg_avail = kcurthread;
  14.     /* start a siphon */
  15.     if ( bq->bq_msg_waiting && (bq->bq_head != bq->bq_tail))
  16.         ksendmessage( bq->bq_msg_waiting, EMSG_BQ_WAITING, 0 );
  17.     else
  18.         ksendmessage( bq->bq_msg_avail, EMSG_BQ_AVAIL, 0 );
  19. }
  20. bq_str *bq_alloc( int queuesize )
  21. {
  22.     bq_str *b;
  23.     BYTE *p;
  24.     p = kcalloc( queuesize, 1 );
  25.     if ( p == NULL ) return( NULL );
  26.     b = kcalloc( sizeof( bq_str ), 1 );
  27.     if ( b == NULL ) {
  28.         kfree( p );
  29.         return( NULL );
  30.     }
  31.     b->bq_size = queuesize;
  32.     b->bq_queue = p;
  33.     b->bq_head = 0;
  34.     b->bq_tail = 0;
  35.     b->bq_sendwait = NULL;
  36.     b->bq_recvwait = NULL;
  37.     b->bq_msg_waiting = NULL;
  38.     b->bq_msg_avail = NULL;
  39.     return( b );
  40. }
  41. void bq_free( bq_str *bq )
  42. {
  43.     kfree( bq->bq_queue );
  44.     kfree( bq );
  45. }
  46. /*
  47.  * bq_semdbyte - nonblock write of BYTE, does not detect buffer overflow
  48.  */
  49. void bq_sendbyte( bq_str *bq, BYTE b )
  50. {
  51.     WORD i;
  52.     WORD flags, newhead;
  53.     thread_x *t;
  54.     rt_cpu_block( &flags );
  55.     i = bq->bq_head;
  56.     bq->bq_queue[ i ] = b;
  57.     newhead = ( i + 1 ) % bq->bq_size;
  58.     rt_cpu_unblock( &flags );
  59.     if ( newhead == bq->bq_tail ) return;  /* no room */
  60.     bq->bq_head = newhead;
  61.     /*  time to poke receiver if he is waiting */
  62.     if ( bq->bq_head != bq->bq_tail ) {
  63.         if ( bq->bq_msg_waiting )
  64.             ksendmessage( bq->bq_msg_waiting, EMSG_BQ_WAITING, 0 );
  65.         rt_cpu_block( &flags );
  66.         if ( (t = bq->bq_recvwait) != NULL ) {
  67. #ifdef NEW
  68.             bq->bq_recvwait = NULL;
  69.             t->th_bq = NULL;
  70.             ksendmessage( t , EMSG_BQ_WAITING , 0 );
  71.             rt_cpu_unblock( &flags );
  72. #else
  73.             bq->bq_recvwait = NULL;
  74.             t->th_bq = NULL;
  75.             kresume( t );
  76.             rt_cpu_unblock( &flags );
  77. #endif
  78.             return;
  79.         }
  80.         rt_cpu_unblock( &flags );
  81.     }
  82. }
  83. /*
  84.  * bq_getbyte - nonblock read of BYTE
  85.  *            - returns 1 if a byte is available
  86.  */
  87. int bq_getbyte( bq_str *bq, BYTE *b )
  88. {
  89.     WORD i, flags, newtail;
  90.     thread_x *t;
  91.     rt_cpu_block( &flags );
  92.     i = bq->bq_tail;
  93.     if ( i != bq->bq_head ) {
  94.         *b = bq->bq_queue[ i ];
  95.         newtail = i + 1;
  96.         if ( newtail == bq->bq_size ) newtail = 0;
  97.         bq->bq_tail = newtail;
  98.         rt_cpu_unblock( &flags );
  99.         /*  time to poke sender if he is waiting */
  100.     
  101.         rt_cpu_block( &flags );
  102.         if (( t = bq->bq_sendwait) != NULL ) {
  103. #ifdef NEW
  104.             bq->bq_sendwait = NULL;
  105.             t->th_bq = NULL;
  106.             ksendmessage( t, EMSG_BQ_AVAIL, 0 );
  107. #else
  108.             bq->bq_sendwait = NULL;
  109.             t->th_bq = NULL;
  110.             kresume( t );
  111. #endif
  112.         }
  113.         rt_cpu_unblock( &flags );
  114.         /* inform peer it can write more */
  115.         if ( bq->bq_msg_avail )
  116.             ksendmessage( bq->bq_msg_avail, EMSG_BQ_AVAIL, 0 );
  117.         return( 1 );
  118.     }
  119.     rt_cpu_unblock( &flags );
  120.     return( 0 );
  121. }
  122. /*
  123.  * bq_writebyte - block write of BYTE, does not allow buffer overflow
  124.  */
  125. void bq_writebyte( bq_str *bq, BYTE b )
  126. {
  127.     WORD newhead, head, tail, size, flags;
  128.     thread_x *t;
  129.     size = bq->bq_size;
  130.     do {
  131.         rt_cpu_block( &flags );
  132.         head = bq->bq_head;
  133.         tail = bq->bq_tail;
  134.         rt_cpu_unblock( &flags );
  135.         newhead = head + 1;
  136.         if ( newhead == size ) newhead = 0;
  137.         /* we block if tail was where we want to move into */
  138.         if ( newhead != tail ) break;
  139. #ifdef OLD
  140.         rt_sleep(0);
  141. #else
  142. #ifdef NEW
  143.         rt_cpu_block( &flags );
  144.         kcurthread->th_bq = bq;
  145.         bq->bq_sendwait = kcurthread;
  146.         rt_cpu_unblock( &flags );
  147. #ifdef NEWEST
  148.         kreadspecialmessage( EMSG_BQ_AVAIL );
  149.         bq->bq_sendwait = NULL;     /* clear the messaging requirement */
  150. #else // just NEW
  151.         {
  152.             int msg;
  153.             DWORD data;
  154.             kreadmessage( &msg, &data );
  155.         }
  156. #endif // NEWEST
  157. #else
  158. #error fails
  159.         rt_cpu_block( &flags );
  160.         kcurthread->th_bq = bq;
  161.         ksuspendhow( kcurthread, &bq->bq_sendwait );
  162.         rt_cpu_unblock( &flags );
  163.         rt_yield();
  164. #endif
  165. #endif
  166.         
  167.     } while ( 1 );
  168.     /* don't need to block interrupts because orderred correctly */
  169.     bq->bq_queue[ head ] = b;
  170.     bq->bq_head = newhead;
  171.     /* inform peer */
  172.     if ( bq->bq_msg_waiting )
  173.         ksendmessage( bq->bq_msg_waiting, EMSG_BQ_WAITING, 0 );
  174.     rt_cpu_block( &flags );
  175.     if (( t = bq->bq_recvwait) != NULL ) {
  176. #ifdef NEW
  177.         bq->bq_recvwait = NULL;
  178.         t->th_bq = NULL;
  179.         ksendmessage( t , EMSG_BQ_WAITING , 0 );
  180. #else
  181.         bq->bq_recvwait = NULL;
  182.         t->th_bq = NULL;
  183.         kresume( t );
  184. #endif
  185.     }
  186.     rt_cpu_unblock( &flags );
  187. }
  188. /*
  189.  * bq_readbyte - block of read of BYTE
  190.  */
  191. int bq_readbyte( bq_str *bq, BYTE *b )
  192. {
  193.     WORD head, tail, size;
  194.     WORD flags;
  195.     size = bq->bq_size;
  196.     rt_cpu_block( &flags );
  197.     do {
  198.         tail = bq->bq_tail;
  199.         head = bq->bq_head;
  200.         if ( tail != head ) {
  201.             *b = bq->bq_queue[ tail++ ];
  202.             bq->bq_tail = tail % size;
  203.             rt_cpu_unblock( &flags );
  204.             /* inform peer it can write more */
  205.             if ( bq->bq_msg_avail )
  206.                 ksendmessage( bq->bq_msg_avail, EMSG_BQ_AVAIL, 0 );
  207.             if ( bq->bq_sendwait  )
  208.                 ksendmessage( bq->bq_sendwait, EMSG_BQ_AVAIL, 0 );
  209.             return( 1 );
  210.         }
  211.         rt_cpu_unblock( &flags );
  212. #ifdef OLD
  213.         rt_sleep( 0 );
  214. #else
  215. #ifdef NEW
  216.         rt_cpu_block( &flags );
  217.         kcurthread->th_bq = bq;
  218.         bq->bq_recvwait = kcurthread;
  219.         rt_cpu_unblock( &flags );
  220. #ifdef NEWEST
  221.         kreadspecialmessage( EMSG_BQ_WAITING );
  222. #else // just NEW
  223.         {
  224.             int msg;
  225.             DWORD data;
  226.             kreadmessage( &msg, &data );
  227.         }
  228. #endif // NEWEST
  229. #else
  230. #error fails
  231.         rt_cpu_block( &flags );
  232.         kcurthread->th_bq = bq;
  233. //      bq->bq_recvwait = kcurthread;
  234.         ksuspendhow( kcurthread, &bq->bq_recvwait );
  235.         rt_cpu_unblock( &flags );
  236.         rt_yield();
  237. #endif
  238. #endif
  239.     } while ( 1 );
  240. }
  241. /*
  242.  * bq_readcount - returns number of BYTEs left to read
  243.  *              - not async
  244.  */
  245. WORD bq_readcount( bq_str *bq )
  246. {
  247.     WORD i;
  248.     WORD flags;
  249.     rt_cpu_block( &flags );
  250.     i = bq->bq_tail;
  251.     if ( bq->bq_head == i )
  252.         i = 0;
  253.     else if ( bq->bq_head > i )
  254.         i = bq->bq_head - i;
  255.     else
  256.         i = bq->bq_size - i + bq->bq_head;
  257.     rt_cpu_unblock( &flags );
  258.     return( i );
  259. }