source: mainline/uspace/drv/char/i8042/buffer.h@ 88dfee7

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 88dfee7 was 65ffec3, checked in by Jan Vesely <jano.vesely@…>, 14 years ago

i8042: buffer.h doxygen comments.

  • Property mode set to 100644
File size: 4.4 KB
Line 
1/*
2 * Copyright (c) 2011 Jan Vesely
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28/**
29 * @addtogroup kbd
30 * @{
31 */
32/** @file
33 * @brief Cyclic buffer structure.
34 */
35
36#ifndef BUFFER_H_
37#define BUFFER_H_
38
39#include <assert.h>
40#include <fibril_synch.h>
41
42/** Cyclic buffer that blocks on full/empty.
43 *
44 * read_head == write_head means that the buffer is empty.
45 * write_head + 1 == read_head means that the buffer is full.
46 * Attempt to insert byte into the full buffer will block until it can succeed.
47 * Attempt to read from empty buffer will block until it can succeed.
48 */
49typedef struct {
50 uint8_t *buffer; /**< Storage space. */
51 uint8_t *buffer_end; /**< End of storage place. */
52 fibril_mutex_t guard; /**< Protects buffer structures. */
53 fibril_condvar_t change; /**< Indicates change (empty/full). */
54 uint8_t *read_head; /**< Place of the next readable element. */
55 uint8_t *write_head; /**< Pointer to the next writable place. */
56} buffer_t;
57
58/** Initialize cyclic buffer using provided memory space.
59 * @param buffer Cyclic buffer structure to initialize.
60 * @param data Memory space to use.
61 * @param size Size of the memory place.
62 */
63static inline void buffer_init(buffer_t *buffer, uint8_t *data, size_t size)
64{
65 assert(buffer);
66 fibril_mutex_initialize(&buffer->guard);
67 fibril_condvar_initialize(&buffer->change);
68 buffer->buffer = data;
69 buffer->buffer_end = data + size;
70 buffer->read_head = buffer->buffer;
71 buffer->write_head = buffer->buffer;
72 bzero(buffer->buffer, size);
73}
74
75/** Write byte to cyclic buffer.
76 * @param buffer Cyclic buffer to write to.
77 * @param data Data to write.
78 */
79static inline void buffer_write(buffer_t *buffer, uint8_t data)
80{
81 fibril_mutex_lock(&buffer->guard);
82
83 /* Next position. */
84 uint8_t *new_head = buffer->write_head + 1;
85 if (new_head == buffer->buffer_end)
86 new_head = buffer->buffer;
87
88 /* Buffer full. */
89 while (new_head == buffer->read_head)
90 fibril_condvar_wait(&buffer->change, &buffer->guard);
91
92 /* Write data. */
93 *buffer->write_head = data;
94
95 /* Buffer was empty. */
96 if (buffer->write_head == buffer->read_head)
97 fibril_condvar_broadcast(&buffer->change);
98
99 /* Move head */
100 buffer->write_head = new_head;
101 fibril_mutex_unlock(&buffer->guard);
102}
103
104/** Read byte from cyclic buffer.
105 * @param buffer Cyclic buffer to read from.
106 * @return Byte read.
107 */
108static inline uint8_t buffer_read(buffer_t *buffer)
109{
110 fibril_mutex_lock(&buffer->guard);
111 /* Buffer is empty. */
112 while (buffer->write_head == buffer->read_head)
113 fibril_condvar_wait(&buffer->change, &buffer->guard);
114
115 /* Next position. */
116 uint8_t *new_head = buffer->read_head + 1;
117 if (new_head == buffer->buffer_end)
118 new_head = buffer->buffer;
119
120 /* Read data. */
121 const uint8_t data = *buffer->read_head;
122
123 /* Buffer was full. */
124 uint8_t *new_write_head = buffer->write_head + 1;
125 if (new_write_head == buffer->buffer_end)
126 new_write_head = buffer->buffer;
127 if (new_write_head == buffer->read_head)
128 fibril_condvar_broadcast(&buffer->change);
129
130 /* Move head */
131 buffer->read_head = new_head;
132
133 fibril_mutex_unlock(&buffer->guard);
134 return data;
135}
136#endif
137/**
138 * @}
139 */
Note: See TracBrowser for help on using the repository browser.