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