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