diff options
| author | Dave Wilson <[email protected]> | 2015-04-29 09:48:49 -0700 |
|---|---|---|
| committer | Dave Wilson <[email protected]> | 2015-04-29 10:47:29 -0700 |
| commit | d40232638faaab19de557e70a3ee938da7a35295 (patch) | |
| tree | 14e61c973745949af186b7940e3a53d25322f5de /serial/VirtualSerial2/ringbuffer.h | |
| parent | 02e5b090a6131a7cc1b90f4a9373117c9e3c7088 (diff) | |
samples update for //build
Diffstat (limited to 'serial/VirtualSerial2/ringbuffer.h')
| -rw-r--r-- | serial/VirtualSerial2/ringbuffer.h | 117 |
1 files changed, 117 insertions, 0 deletions
diff --git a/serial/VirtualSerial2/ringbuffer.h b/serial/VirtualSerial2/ringbuffer.h new file mode 100644 index 00000000..8c5e3e39 --- /dev/null +++ b/serial/VirtualSerial2/ringbuffer.h @@ -0,0 +1,117 @@ +/*++ + +Copyright (C) Microsoft Corporation, All Rights Reserved + +Module Name: + + Ringbuffer.h + +--*/ + +#pragma once + +typedef struct _RING_BUFFER +{ + // + // The size in bytes of the ring buffer. + // + size_t Size; + + // + // A pointer to the base of the ring buffer. + // + BYTE* Base; + + // + // A pointer to the byte beyond the end of the ring buffer. Used for + // quick comparisons when determining if we need to wrap. + // + BYTE* End; + + // + // A pointer to the current read point in the ring buffer. + // + // Updates to this are not protected by any lock. This is different from + // the write pointer, which is protected by the "pending read pointer" + // lock. The reason for this difference is that in this driver, we do not + // keep write requests pending. If there is not enough space to write all + // the data that was requested, we write as much as we can and drop the + // rest (lossy data transfer). + // + // If we had multiple threads modifying this pointer, then that would + // provide yet another reason for protecting updates to the pointer using a + // lock. However, in this driver, at any given time we have only one thread + // that modifies this pointer (the thread that runs the read callback). + // This is true because we use a sequential queue for read requests. If we + // were to change our read queue to be a parallel queue, this would no + // longer be true. + // + // + BYTE* Head; + + // + // A pointer to the current write point in the ring buffer. + // + // Updates to this pointer are protected by the "pending read pointer + // lock", because we do not want a consumer thread to mark a read request + // as pending while we are in the process of writing data to the buffer. + // The reason is that the write that we are currently performing might + // actually supply enough data to satisfy the read request, in which case + // it should not be marked pending at all. + // If the read request were to be marked pending in the situation described + // above, then we would need some trigger to later retrieve the request and + // complete it. In our driver, arrival of data is the only event that can + // trigger this. So if no more data arrives, the request will remain + // pending forever, even though there is enough data in the buffer to + // complete it. Hence we do not keep a read request pending in situations + // where the read buffer contains enough data to satisfy it. + // + // If we had multiple threads modifying this pointer, then that would + // provide yet another reason for protecting updates to the pointer using a + // lock. However, in this driver, at any given time we have only one thread + // that modifies this pointer (the thread that runs the write callback). + // This is true because we use a sequential queue for write requests. If we + // were to change our write queue to be a parallel queue, this would no + // longer be true. + // + BYTE* Tail; + +} RING_BUFFER, *PRING_BUFFER; + + +VOID +RingBufferInitialize( + _In_ PRING_BUFFER Self, + _In_reads_bytes_(BufferSize) + BYTE* Buffer, + _In_ size_t BufferSize + ); + +NTSTATUS +RingBufferWrite( + _In_ PRING_BUFFER Self, + _In_reads_bytes_(DataSize) + BYTE* Data, + _In_ size_t DataSize + ); + +NTSTATUS +RingBufferRead( + _In_ PRING_BUFFER Self, + _Out_writes_bytes_to_(DataSize, *BytesCopied) + BYTE* Data, + _In_ size_t DataSize, + _Out_ size_t *BytesCopied + ); + +VOID +RingBufferGetAvailableSpace( + _In_ PRING_BUFFER Self, + _Out_ size_t *AvailableSpace + ); + +VOID +RingBufferGetAvailableData( + _In_ PRING_BUFFER Self, + _Out_ size_t *AvailableData + ); |
