summaryrefslogtreecommitdiff
path: root/serial/VirtualSerial2/ringbuffer.h
diff options
context:
space:
mode:
authorDave Wilson <[email protected]>2015-04-29 09:48:49 -0700
committerDave Wilson <[email protected]>2015-04-29 10:47:29 -0700
commitd40232638faaab19de557e70a3ee938da7a35295 (patch)
tree14e61c973745949af186b7940e3a53d25322f5de /serial/VirtualSerial2/ringbuffer.h
parent02e5b090a6131a7cc1b90f4a9373117c9e3c7088 (diff)
samples update for //build
Diffstat (limited to 'serial/VirtualSerial2/ringbuffer.h')
-rw-r--r--serial/VirtualSerial2/ringbuffer.h117
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
+ );