xref: /haiku/src/add-ons/kernel/bus_managers/ps2/packet_buffer.cpp (revision d3d8b26997fac34a84981e6d2b649521de2cc45a)
1 /*
2  * Copyright 2005, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
3  * Distributed under the terms of the MIT License.
4  */
5 
6 
7 #include "packet_buffer.h"
8 
9 #include <KernelExport.h>
10 #include <util/ring_buffer.h>
11 
12 #include <stdlib.h>
13 #include <string.h>
14 
15 
16 /**	The idea behind this packet buffer is to have multi-threading safe
17  *	implementation that can be used in interrupts on top of the
18  *	ring_buffer implementation provided by the kernel.
19  *	It uses a spinlock for synchronization.
20  *
21  *	IOW if you don't have such high restrictions in your environment,
22  *	you better don't want to use it at all.
23  */
24 
25 struct packet_buffer {
26 	struct ring_buffer	*buffer;
27 	spinlock			lock;
28 };
29 
30 
31 struct packet_buffer *
32 create_packet_buffer(size_t size)
33 {
34 	struct packet_buffer *buffer = (packet_buffer *)malloc(sizeof(packet_buffer));
35 	if (buffer == NULL)
36 		return NULL;
37 
38 	buffer->buffer = create_ring_buffer(size);
39 	if (buffer->buffer == NULL) {
40 		free(buffer);
41 		return NULL;
42 	}
43 	buffer->lock = 0;
44 
45 	return buffer;
46 }
47 
48 
49 void
50 delete_packet_buffer(struct packet_buffer *buffer)
51 {
52 	delete_ring_buffer(buffer->buffer);
53 	free(buffer);
54 }
55 
56 
57 void
58 packet_buffer_clear(struct packet_buffer *buffer)
59 {
60 	cpu_status state = disable_interrupts();
61 	acquire_spinlock(&buffer->lock);
62 
63 	ring_buffer_clear(buffer->buffer);
64 
65 	release_spinlock(&buffer->lock);
66 	restore_interrupts(state);
67 }
68 
69 
70 size_t
71 packet_buffer_readable(struct packet_buffer *buffer)
72 {
73 	cpu_status state = disable_interrupts();
74 	acquire_spinlock(&buffer->lock);
75 
76 	size_t available = ring_buffer_readable(buffer->buffer);
77 
78 	release_spinlock(&buffer->lock);
79 	restore_interrupts(state);
80 
81 	return available;
82 }
83 
84 
85 size_t
86 packet_buffer_writable(struct packet_buffer *buffer)
87 {
88 	cpu_status state = disable_interrupts();
89 	acquire_spinlock(&buffer->lock);
90 
91 	size_t left = ring_buffer_writable(buffer->buffer);
92 
93 	release_spinlock(&buffer->lock);
94 	restore_interrupts(state);
95 
96 	return left;
97 }
98 
99 
100 void
101 packet_buffer_flush(struct packet_buffer *buffer, size_t length)
102 {
103 	cpu_status state = disable_interrupts();
104 	acquire_spinlock(&buffer->lock);
105 
106 	ring_buffer_flush(buffer->buffer, length);
107 
108 	release_spinlock(&buffer->lock);
109 	restore_interrupts(state);
110 }
111 
112 
113 size_t
114 packet_buffer_read(struct packet_buffer *buffer, uint8 *data, size_t length)
115 {
116 	cpu_status state = disable_interrupts();
117 	acquire_spinlock(&buffer->lock);
118 
119 	size_t bytesRead = ring_buffer_read(buffer->buffer, data, length);
120 
121 	release_spinlock(&buffer->lock);
122 	restore_interrupts(state);
123 
124 	return bytesRead;
125 }
126 
127 
128 size_t
129 packet_buffer_write(struct packet_buffer *buffer, const uint8 *data, size_t length)
130 {
131 	cpu_status state = disable_interrupts();
132 	acquire_spinlock(&buffer->lock);
133 
134 	size_t bytesWritten = ring_buffer_write(buffer->buffer, data, length);
135 
136 	release_spinlock(&buffer->lock);
137 	restore_interrupts(state);
138 
139 	return bytesWritten;
140 }
141 
142