Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

169 lines
5.1 KiB

/*--------------------------------------------------------------------------
| queue.c - queue code. This queue code serves the following need:
It provides circular queue code which is fast and it does so without
requiring a lock or semaphore between the get and put side of the queue.
Simpler queue code exists which keeps a qcount member, but this requires
a lock or semaphore in the implementation. By calculating everything
based on the indexes we can run without a lock. This index arithmetic
is a bit hairy(and may contain some additional overhead), but when
working with a complex multiprocessor OS's, the ellimination of the lock
is very handy.
Copyright 1996-97 Comtrol Corporation. All rights reserved.
|--------------------------------------------------------------------------*/
#include "precomp.h"
// much of the queue implementation are macros in the header file.
/*--------------------------------------------------------------------------
| q_flush_count_put - flush the queue and return number of bytes flushed
from it. Assume Put side of queue will not be in a state of flux.
|--------------------------------------------------------------------------*/
int q_flush_count_put(Queue *queue)
{
int Count, QGet;
// use a copy of QGet, since it may be changing at ISR level while we work.
QGet = queue->QGet;
// figure the number of bytes in the queue
if ((Count = queue->QPut - QGet) < 0)
Count += queue->QSize; // adjust for wrap
// flush by setting QGet=QPut;
queue->QPut = QGet;
return Count; // return count of flushed chars
}
/*--------------------------------------------------------------------------
| q_flush_count_get - flush the queue and return number of bytes flushed
from it. Assume Get side of queue will not be in a state of flux.
|--------------------------------------------------------------------------*/
int q_flush_count_get(Queue *queue)
{
int Count, QPut;
// use a copy of QPut, since it may be changing at ISR level while we work.
QPut = queue->QPut;
// figure the number of bytes in the queue
if ((Count = QPut - queue->QGet) < 0)
Count += queue->QSize; // adjust for wrap
// flush by setting QGet=QPut;
queue->QGet = QPut;
return Count; // return count of flushed chars
}
/*----------------------------------
q_room - return number of chars room in queue we can put.
|----------------------------------*/
int q_room(Queue *queue)
{
int QCount;
if ((QCount = (queue->QPut - queue->QGet)) < 0)
QCount += queue->QSize;
return (queue->QSize - QCount - 1);
}
/*----------------------------------
q_count - return number of chars in queue we can get.
|----------------------------------*/
int q_count(Queue *queue)
{
int QCount;
if ((QCount = (queue->QPut - queue->QGet)) < 0)
QCount += queue->QSize;
return QCount;
}
/*--------------------------------------------------------------------------
| q_get - Get bytes from queue.
queue : our queue
buf : buffer to put the data into
Count : Max number of bytes to get
Returns int value equal to number of bytes transferred.
|--------------------------------------------------------------------------*/
int q_get(Queue *queue, unsigned char *buf, int Count)
{
int get1, get2, ToMove;
if ((ToMove = queue->QPut - queue->QGet) < 0)
ToMove += queue->QSize; // adjust for wrap
if (Count > ToMove) // only move whats asked
{
Count = ToMove;
}
if (Count == 0) // if nothing asked or nothing available
return 0;
get1 = queue->QSize - queue->QGet; // space till wrap point
if (get1 < Count)
{
get2 = Count - get1; // two moves required
}
else // only one move required
{
get2 = 0;
get1 = Count;
}
memcpy(buf, &queue->QBase[queue->QGet], get1);
queue->QGet = (queue->QGet + get1) % queue->QSize;
if (get2)
{
memcpy(&buf[get1], &queue->QBase[0], get2);
queue->QGet = get2;
}
return Count;
}
/*--------------------------------------------------------------------------
| q_put - Put data into the Queue.
queue : our queue
buf : buffer to get the data from
Count : Max number of bytes to put
Returns int value equal to number of bytes transferred.
|--------------------------------------------------------------------------*/
int q_put(Queue *queue, unsigned char *buf, int Count)
{
int put1, put2, room;
if ((room = queue->QGet - queue->QPut - 1) < 0)
room += queue->QSize; // adjust for wrap
if (Count > room)
Count = room;
if (Count <= 0) // if nothing asked or nothing available
return 0;
put1 = queue->QSize - queue->QPut;
if (put1 < Count)
{
put2 = Count - put1; // two moves required
}
else // only one move required
{
put2 = 0;
put1 = Count;
}
memcpy(&queue->QBase[queue->QPut], buf, put1);
queue->QPut = (queue->QPut + put1) % queue->QSize;
if (put2)
{
memcpy(&queue->QBase[0], &buf[put1], put2);
queue->QPut = put2;
}
return Count;
}