xref: /haiku/src/add-ons/kernel/bus_managers/ps2/packet_buffer.cpp (revision b671e9bbdbd10268a042b4f4cc4317ccd03d105e)
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
35 		= (packet_buffer *)malloc(sizeof(packet_buffer));
36 	if (buffer == NULL)
37 		return NULL;
38 
39 	buffer->buffer = create_ring_buffer(size);
40 	if (buffer->buffer == NULL) {
41 		free(buffer);
42 		return NULL;
43 	}
44 	B_INITIALIZE_SPINLOCK(&buffer->lock);
45 
46 	return buffer;
47 }
48 
49 
50 void
51 delete_packet_buffer(struct packet_buffer *buffer)
52 {
53 	delete_ring_buffer(buffer->buffer);
54 	free(buffer);
55 }
56 
57 
58 void
59 packet_buffer_clear(struct packet_buffer *buffer)
60 {
61 	cpu_status state = disable_interrupts();
62 	acquire_spinlock(&buffer->lock);
63 
64 	ring_buffer_clear(buffer->buffer);
65 
66 	release_spinlock(&buffer->lock);
67 	restore_interrupts(state);
68 }
69 
70 
71 size_t
72 packet_buffer_readable(struct packet_buffer *buffer)
73 {
74 	cpu_status state = disable_interrupts();
75 	acquire_spinlock(&buffer->lock);
76 
77 	size_t available = ring_buffer_readable(buffer->buffer);
78 
79 	release_spinlock(&buffer->lock);
80 	restore_interrupts(state);
81 
82 	return available;
83 }
84 
85 
86 size_t
87 packet_buffer_writable(struct packet_buffer *buffer)
88 {
89 	cpu_status state = disable_interrupts();
90 	acquire_spinlock(&buffer->lock);
91 
92 	size_t left = ring_buffer_writable(buffer->buffer);
93 
94 	release_spinlock(&buffer->lock);
95 	restore_interrupts(state);
96 
97 	return left;
98 }
99 
100 
101 void
102 packet_buffer_flush(struct packet_buffer *buffer, size_t length)
103 {
104 	cpu_status state = disable_interrupts();
105 	acquire_spinlock(&buffer->lock);
106 
107 	ring_buffer_flush(buffer->buffer, length);
108 
109 	release_spinlock(&buffer->lock);
110 	restore_interrupts(state);
111 }
112 
113 
114 size_t
115 packet_buffer_read(struct packet_buffer *buffer, uint8 *data, size_t length)
116 {
117 	cpu_status state = disable_interrupts();
118 	acquire_spinlock(&buffer->lock);
119 
120 	size_t bytesRead = ring_buffer_read(buffer->buffer, data, length);
121 
122 	release_spinlock(&buffer->lock);
123 	restore_interrupts(state);
124 
125 	return bytesRead;
126 }
127 
128 
129 size_t
130 packet_buffer_write(struct packet_buffer *buffer, const uint8 *data,
131 	size_t length)
132 {
133 	cpu_status state = disable_interrupts();
134 	acquire_spinlock(&buffer->lock);
135 
136 	size_t bytesWritten = ring_buffer_write(buffer->buffer, data, length);
137 
138 	release_spinlock(&buffer->lock);
139 	restore_interrupts(state);
140 
141 	return bytesWritten;
142 }
143 
144