├── README.md ├── kernel ├── ringbuffer.c └── ringbuffer.h └── user ├── buffer_test.c ├── ringbuffer.c └── ringbuffer.h /README.md: -------------------------------------------------------------------------------- 1 | ringbuffer 2 | ========== 3 | 4 | a ring buffer like kfifo, work in linux kernel space and user space, and test on kernel 3.16 5 | on x86, ARM platform. 6 | 7 | Please note that the data in the buffer will keep there until they be read out. If the buffer 8 | is full, the data could not be put into any more, until a read action free some space. 9 | -------------------------------------------------------------------------------- /kernel/ringbuffer.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Title : ringbuffer.c 3 | * Author : zengxianbo 4 | * Date : 2014.11 @Beijing 5 | * Description : implement an ring buffer just like kfifo. Please note that 6 | * the data in the buffer will keep there until them be read out. If the buffer 7 | * is full, the data could not be put into any more, until the read action free 8 | * some space. 9 | */ 10 | 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | #include "ringbuffer.h" 20 | 21 | struct ringbuffer *ringbuffer_create(unsigned int size, gfp_t gfp_mask) 22 | { 23 | unsigned int order; 24 | struct ringbuffer *ring_buf; 25 | /* round up to the next power of 2, so that we can use 26 | * "buf->write_pos & (buf->size – 1) instead of "buf->write_pos % buf->size" 27 | */ 28 | if (!is_power_of_2(size)) { 29 | BUG_ON(size > 0x80000000); 30 | size = roundup_pow_of_two(size); 31 | } 32 | 33 | order = order_base_2(size / PAGE_SIZE); 34 | 35 | if (order > MAX_ORDER) { 36 | pr_err("[%s:] The memory size request too big!\n", __func__); 37 | return ERR_PTR(-EINVAL); 38 | } 39 | 40 | ring_buf = kmalloc(sizeof(*ring_buf), gfp_mask); 41 | if (!ring_buf) { 42 | return ERR_PTR(-ENOMEM); 43 | } 44 | 45 | ring_buf->data = (void *)__get_free_pages(gfp_mask, order); 46 | if (!ring_buf->data) { 47 | kfree(ring_buf); 48 | return ERR_PTR(-ENOMEM); 49 | } 50 | 51 | ring_buf->size = size; 52 | ring_buf->read_pos = 0; 53 | ring_buf->write_pos = 0; 54 | 55 | return ring_buf; 56 | } 57 | 58 | void ringbuffer_destroy(struct ringbuffer *ring_buf) 59 | { 60 | free_pages((unsigned long)ring_buf->data, 61 | order_base_2(ring_buf->size / PAGE_SIZE)); 62 | ring_buf->data = NULL; 63 | kfree(ring_buf); 64 | ring_buf = NULL; 65 | } 66 | 67 | /** 68 | * ringbuffer_put - puts some data into the ringbuffer, no locking version 69 | * @ring_buf: the ringbuffer to be used. 70 | * @buffer: the data to be added. 71 | * @len: the length of the data to be added. 72 | * 73 | * This function copies at most @len bytes from the @buffer into 74 | * the ringbuffer depending on the free space, and returns the number of 75 | * bytes copied. 76 | * 77 | * Note that with only one concurrent reader and one concurrent 78 | * writer, you don't need extra locking to use these functions. 79 | */ 80 | 81 | unsigned int ringbuffer_put(struct ringbuffer *ring_buf, 82 | const unsigned char *buffer, unsigned int len) 83 | { 84 | unsigned int l; 85 | 86 | len = min(len, ring_buf->size - ring_buf->write_pos + ring_buf->read_pos); 87 | 88 | /* 89 | * Ensure that we sample the read_pos before we 90 | * start putting bytes into the ring_buf. 91 | */ 92 | 93 | smp_mb(); 94 | 95 | /* first put the data starting from write_pos to buffer end */ 96 | l = min(len, ring_buf->size - (ring_buf->write_pos & (ring_buf->size - 1))); 97 | memcpy(ring_buf->data + (ring_buf->write_pos & (ring_buf->size - 1)), buffer, l); 98 | /* then put the rest (if any) at the beginning of the buffer */ 99 | memcpy(ring_buf->data, buffer + l, len - l); 100 | /* 101 | * Ensure that we add the bytes to the ring_buf -before- 102 | * we update the ring_buf->write_pos index. 103 | */ 104 | smp_wmb(); 105 | 106 | ring_buf->write_pos += len; 107 | 108 | return len; 109 | } 110 | 111 | /** 112 | * ringbuffer_print - print ringbuf data 113 | * @ring_buf: the ringbuffer to be used. 114 | * @cnt : the number byte to be print. 115 | */ 116 | void ringbuffer_print(struct ringbuffer *ring_buf, unsigned int cnt) 117 | { 118 | print_hex_dump(KERN_DEBUG, "", 119 | DUMP_PREFIX_ADDRESS, 120 | 32, 4, 121 | ring_buf->data + ring_buf->read_pos, 122 | cnt, 123 | true); 124 | pr_debug("\n"); 125 | } 126 | 127 | /** 128 | * ringbuffer_fromio - get the data from io memory, and put them into ringbuffer 129 | * @ring_buf: the ringbuffer to be used. 130 | * @source: the io memory addr. 131 | * @len: the length of the data to be read and write. 132 | */ 133 | unsigned int ringbuffer_fromio(struct ringbuffer *ring_buf, void *source, unsigned int len) 134 | { 135 | unsigned int l, i; 136 | 137 | len = min(len, ring_buf->size - ring_buf->write_pos + ring_buf->read_pos); 138 | 139 | /* 140 | * Ensure that we sample the read_pos before we 141 | * start putting bytes into the ring_buf. 142 | */ 143 | 144 | smp_mb(); 145 | 146 | l = min(len, ring_buf->size - (ring_buf->write_pos & (ring_buf->size - 1))); 147 | 148 | /* first put the data starting from write_pos to buffer end */ 149 | //memcpy_fromio(ring_buf->data + (ring_buf->write_pos & (ring_buf->size - 1)), source, l); 150 | /* FIXME: it seems that ioread32_rep source address do not increaced automaticly */ 151 | for (i = 0; i < l % 4; ++i) { 152 | ioread8_rep(source + i, ring_buf->data + (ring_buf->write_pos & (ring_buf->size - 1)) + i, 1); 153 | } 154 | 155 | for (; i < l; i += 4) { 156 | ioread32_rep(source + i, ring_buf->data + (ring_buf->write_pos & (ring_buf->size - 1)) + i, 1); 157 | } 158 | /* then put the rest (if any) at the beginning of the buffer */ 159 | //memcpy_fromio(ring_buf->data, source + l, len - l); 160 | for (i = 0; i < (len -l) % 4; ++i) { 161 | ioread8_rep(source + l + i, ring_buf->data + i, 1); 162 | } 163 | for (; i < len -l; i += 4) { 164 | ioread32_rep(source + l + i, ring_buf->data + i, 1); 165 | } 166 | /* 167 | * Ensure that we add the bytes to the ring_buf -before- 168 | * we update the ring_buf->write_pos index. 169 | */ 170 | smp_wmb(); 171 | 172 | ring_buf->write_pos += len; 173 | 174 | return len; 175 | } 176 | 177 | 178 | /** 179 | * ringbuffer_get - gets some data from the ringbuffer, no locking version 180 | * @ring_buf: the ringbuffer to be used. 181 | * @buffer: where the data must be copied. 182 | * @len: the size of the destination buffer. 183 | * 184 | * This function copies at most @len bytes from the ringbuffer into the 185 | * @buffer and returns the number of copied bytes. 186 | * 187 | * Note that with only one concurrent reader and one concurrent 188 | * writer, you don't need extra locking to use these functions. 189 | */ 190 | unsigned int ringbuffer_get(struct ringbuffer *ring_buf, 191 | unsigned char *buffer, unsigned int len) 192 | { 193 | unsigned int l; 194 | 195 | len = min(len, ringbuffer_len(ring_buf)); 196 | 197 | /* 198 | * Ensure that we sample the ring_buf->write_pos index -before- we 199 | * start removing bytes from the kring_buf. 200 | */ 201 | 202 | smp_rmb(); 203 | 204 | /* first get the data from ring_buf->read_pos until the end of the buffer */ 205 | l = min(len, ring_buf->size - (ring_buf->read_pos & (ring_buf->size - 1))); 206 | memcpy(buffer, ring_buf->data + (ring_buf->read_pos & (ring_buf->size - 1)), l); 207 | 208 | /* then get the rest (if any) from the beginning of the buffer */ 209 | memcpy(buffer + l, ring_buf->data, len - l); 210 | 211 | /* 212 | * Ensure that we remove the bytes from the kring_buf -before- 213 | * we update the ring_buf->read_pos index. 214 | */ 215 | 216 | smp_mb(); 217 | 218 | ring_buf->read_pos += len; 219 | 220 | return len; 221 | } 222 | 223 | /** 224 | * ringbuffer_from_user - write user space data into ringbuffer 225 | * @ring_buf: the ringbuffer to be used. 226 | * @from: user buffer pointer. 227 | * @len: the length of the data to be written. 228 | * 229 | * This fucntion return the length have been written or -EFAULT if error. 230 | * 231 | */ 232 | int ringbuffer_from_user(struct ringbuffer *ring_buf, const void __user *from, unsigned long len) 233 | { 234 | unsigned long l; 235 | 236 | len = min(len, (unsigned long)(ring_buf->size - ring_buf->write_pos + ring_buf->read_pos)); 237 | 238 | /* 239 | * Ensure that we sample the read_pos before we 240 | * start putting bytes into the ring_buf. 241 | */ 242 | smp_mb(); 243 | 244 | /* first put the data starting from write_pos to buffer end */ 245 | l = min(len, (unsigned long)(ring_buf->size - (ring_buf->write_pos & (ring_buf->size - 1)))); 246 | if (copy_from_user(ring_buf->data + (ring_buf->write_pos & (ring_buf->size - 1)), from, l)) { 247 | return -EFAULT; 248 | } 249 | 250 | /* then put the rest (if any) at the beginning of the buffer */ 251 | if (copy_from_user(ring_buf->data, from + l, len - l)) { 252 | return -EFAULT; 253 | } 254 | /* 255 | * Ensure that we add the bytes to the ring_buf -before- 256 | * we update the ring_buf->write_pos index. 257 | */ 258 | smp_wmb(); 259 | 260 | ring_buf->write_pos += len; 261 | 262 | return len; 263 | } 264 | 265 | 266 | /** 267 | * ringbuffer_to_user - copy ringbuffer data to user space buffer 268 | * @ring_buf: the ringbuffer to be used. 269 | * @dest: user space address where to store the data. 270 | * @len: the length of the data to be copied. 271 | * 272 | * This function return the length have copied or or -EFAULT if error. 273 | * 274 | */ 275 | int ringbuffer_to_user(struct ringbuffer *ring_buf, void __user *dest, 276 | unsigned long len) 277 | { 278 | unsigned long l; 279 | 280 | len = min(len, (unsigned long)ringbuffer_len(ring_buf)); 281 | 282 | /* 283 | * Ensure that we sample the ring_buf->write_pos index -before- we 284 | * start removing bytes from the kring_buf. 285 | */ 286 | 287 | smp_rmb(); 288 | 289 | /* first get the data from ring_buf->read_pos until the end of the buffer */ 290 | l = min(len, (unsigned long)(ring_buf->size - (ring_buf->read_pos & (ring_buf->size - 1)))); 291 | if (copy_to_user(dest, ring_buf->data + (ring_buf->read_pos & (ring_buf->size - 1)), l)) { 292 | return -EFAULT; 293 | } 294 | 295 | if (l != len) { 296 | 297 | /* then get the rest (if any) from the beginning of the buffer */ 298 | if (copy_to_user(dest + l, ring_buf->data, len - l)) { 299 | return -EFAULT; 300 | } 301 | } 302 | /* 303 | * Ensure that we remove the bytes from the kring_buf -before- 304 | * we update the ring_buf->read_pos index. 305 | */ 306 | 307 | smp_mb(); 308 | 309 | ring_buf->read_pos += len; 310 | 311 | return len; 312 | } 313 | 314 | /** 315 | * ringbuffer_reset - removes the entire ringbuffer content 316 | * @ring_buf: address of the ringbuffer to be used 317 | * 318 | * Note: usage of ringbuffer_reset() is dangerous. It should be only called when the 319 | * ringbuffer is exclusived locked or when it is secured that no other thread is 320 | * accessing the fifo. 321 | */ 322 | void ringbuffer_reset(struct ringbuffer *ring_buf) 323 | { 324 | ring_buf->write_pos = ring_buf->read_pos = 0; 325 | } 326 | 327 | unsigned int ringbuffer_is_empty(struct ringbuffer *ring_buf) 328 | { 329 | return ring_buf->read_pos == ring_buf->write_pos; 330 | } 331 | 332 | unsigned int ringbuffer_is_full(struct ringbuffer *ring_buf) 333 | { 334 | return ring_buf->size == ring_buf->write_pos - ring_buf->read_pos; 335 | } 336 | 337 | unsigned int ringbuffer_len(struct ringbuffer *ring_buf) 338 | { 339 | return ring_buf->write_pos - ring_buf->read_pos; 340 | } 341 | 342 | -------------------------------------------------------------------------------- /kernel/ringbuffer.h: -------------------------------------------------------------------------------- 1 | #ifndef __RINGBUFFER_H 2 | #define __RINGBUFFER_H 3 | 4 | #include 5 | 6 | struct ringbuffer { 7 | void *data; 8 | unsigned int size; 9 | unsigned int read_pos; 10 | unsigned int write_pos; 11 | }; 12 | 13 | struct ringbuffer *ringbuffer_create(unsigned int byte, gfp_t gfp_mask); 14 | void ringbuffer_destroy(struct ringbuffer *ring_buf); 15 | 16 | void ringbuffer_reset(struct ringbuffer *ring_buf); 17 | 18 | unsigned int ringbuffer_put(struct ringbuffer *ring_buf, 19 | const unsigned char *buf, unsigned int len); 20 | 21 | unsigned int ringbuffer_get(struct ringbuffer *ring_buf, 22 | unsigned char *buf, unsigned int len); 23 | 24 | void ringbuffer_print(struct ringbuffer *ring_buf, unsigned int cnt); 25 | 26 | unsigned int ringbuffer_fromio(struct ringbuffer *ring_buf, void *source, unsigned int len); 27 | 28 | int ringbuffer_from_user(struct ringbuffer *ring_buf, const void __user *from, unsigned long len); 29 | int ringbuffer_to_user(struct ringbuffer *ring_buf, void __user *dest, unsigned long len); 30 | 31 | unsigned int ringbuffer_is_empty(struct ringbuffer *ring_buf); 32 | unsigned int ringbuffer_is_full(struct ringbuffer *ring_buf); 33 | 34 | unsigned int ringbuffer_len(struct ringbuffer *ring_buf); 35 | 36 | #endif 37 | -------------------------------------------------------------------------------- /user/buffer_test.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "ringbuffer.h" 9 | 10 | #define FIFO_SIZE 16 11 | 12 | 13 | void * consumer_proc(void *arg) 14 | { 15 | unsigned int cnt; 16 | struct ringbuffer *ring_buf = (struct ringbuffer *)arg; 17 | 18 | cnt = 0; 19 | 20 | while(1) 21 | { 22 | sleep(2); 23 | printf("------------------------------------------\n"); 24 | printf("get data from ring buffer.\n"); 25 | 26 | { 27 | char i; 28 | 29 | if (ringbuffer_is_empty(ring_buf)) { 30 | printf("buffer is empty !\n"); 31 | sleep(1); 32 | continue; 33 | } 34 | 35 | if (cnt !=0 && !(cnt % 16)) 36 | printf("\n"); 37 | 38 | ringbuffer_get(ring_buf, &i, sizeof(i)); 39 | 40 | printf("data is: %d \n", i); 41 | 42 | cnt++; 43 | } 44 | 45 | 46 | printf("ring buffer length: %u\n", ringbuffer_len(ring_buf)); 47 | printf("------------------------------------------\n"); 48 | } 49 | } 50 | 51 | void * producer_proc(void *arg) 52 | { 53 | struct ringbuffer *ring_buf = (struct ringbuffer *)arg; 54 | char i; 55 | 56 | i = 0; 57 | while(1) 58 | { 59 | printf("******************************************\n"); 60 | printf("put datas to ring buffer.\n"); 61 | 62 | 63 | if (ringbuffer_is_full(ring_buf)) { 64 | printf("buffer is full !\n"); 65 | sleep(1); 66 | continue; 67 | } 68 | ringbuffer_put(ring_buf, &i, sizeof(i)); 69 | i++; 70 | 71 | printf("ring buffer length: %u\n", ringbuffer_len(ring_buf)); 72 | printf("******************************************\n"); 73 | sleep(1); 74 | } 75 | } 76 | 77 | 78 | int consumer_thread(void *arg) 79 | { 80 | int err; 81 | pthread_t tid; 82 | err = pthread_create(&tid, NULL, consumer_proc, arg); 83 | if (err != 0) 84 | { 85 | fprintf(stderr, "Failed to create consumer thread.errno:%u, reason:%s\n", 86 | errno, strerror(errno)); 87 | return -1; 88 | } 89 | return tid; 90 | } 91 | int producer_thread(void *arg) 92 | { 93 | int err; 94 | pthread_t tid; 95 | err = pthread_create(&tid, NULL, producer_proc, arg); 96 | if (err != 0) 97 | { 98 | fprintf(stderr, "Failed to create consumer thread.errno:%u, reason:%s\n", 99 | errno, strerror(errno)); 100 | return -1; 101 | } 102 | return tid; 103 | } 104 | 105 | 106 | 107 | int main(void) 108 | { 109 | struct ringbuffer *ring_buf; 110 | pthread_t produce_pid, consume_pid; 111 | 112 | ring_buf = ringbuffer_create(FIFO_SIZE); 113 | if (!ring_buf) { 114 | perror("ringbuffer_create()"); 115 | exit(1); 116 | } 117 | 118 | printf("multi thread test.......\n"); 119 | 120 | produce_pid = producer_thread((void*)ring_buf); 121 | consume_pid = consumer_thread((void*)ring_buf); 122 | 123 | pthread_join(produce_pid, NULL); 124 | pthread_join(consume_pid, NULL); 125 | 126 | ringbuffer_destroy(ring_buf); 127 | 128 | return 0; 129 | } 130 | -------------------------------------------------------------------------------- /user/ringbuffer.c: -------------------------------------------------------------------------------- 1 | /** 2 | * Title : ringbuffer.c 3 | * Author : zengxianbo 4 | * Date : 2014.11 @Beijing 5 | * Description : implement an ring buffer just like kfifo. Please note that 6 | * the data in the buffer will keep there until them be read out. If the buffer 7 | * is full, the data could not be put into any more, until the read action free 8 | * some space. 9 | * 10 | * NOTE: This version used for user space. 11 | * 12 | */ 13 | 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | #include "ringbuffer.h" 23 | 24 | static inline __attribute__((const)) 25 | int is_power_of_2(unsigned long n) 26 | { 27 | return (n != 0 && ((n & (n - 1)) == 0)); 28 | } 29 | 30 | struct ringbuffer *ringbuffer_create(unsigned int size) 31 | { 32 | struct ringbuffer *ring_buf; 33 | 34 | if (!is_power_of_2(size)) { 35 | printf("The buffer size is must be power of 2!\n"); 36 | errno = EINVAL; 37 | return NULL; 38 | } 39 | 40 | ring_buf = malloc(sizeof(*ring_buf)); 41 | if (!ring_buf) { 42 | perror("malloc()"); 43 | return NULL; 44 | } 45 | 46 | ring_buf->data = malloc(size); 47 | if (!ring_buf->data) { 48 | perror("malloc()"); 49 | free(ring_buf); 50 | return NULL; 51 | } 52 | 53 | ring_buf->size = size; 54 | ring_buf->read_pos = 0; 55 | ring_buf->write_pos = 0; 56 | 57 | return ring_buf; 58 | } 59 | 60 | void ringbuffer_destroy(struct ringbuffer *ring_buf) 61 | { 62 | if (ring_buf) { 63 | if (ring_buf->data) { 64 | free(ring_buf->data); 65 | ring_buf->data = NULL; 66 | } 67 | free(ring_buf); 68 | ring_buf = NULL; 69 | } 70 | } 71 | 72 | /** 73 | * ringbuffer_put - puts some data into the ringbuffer, no locking version 74 | * @ring_buf: the ringbuffer to be used. 75 | * @buffer: the data to be added. 76 | * @len: the length of the data to be added. 77 | * 78 | * This function copies at most @len bytes from the @buffer into 79 | * the ringbuffer depending on the free space, and returns the number of 80 | * bytes copied. 81 | * 82 | * Note that with only one concurrent reader and one concurrent 83 | * writer, you don't need extra locking to use these functions. 84 | */ 85 | 86 | unsigned int ringbuffer_put(struct ringbuffer *ring_buf, 87 | const char *buffer, unsigned int len) 88 | { 89 | unsigned int l; 90 | 91 | len = min(len, ring_buf->size - ring_buf->write_pos + ring_buf->read_pos); 92 | 93 | /* first put the data starting from write_pos to buffer end */ 94 | l = min(len, ring_buf->size - (ring_buf->write_pos & (ring_buf->size - 1))); 95 | memcpy(ring_buf->data + (ring_buf->write_pos & (ring_buf->size - 1)), buffer, l); 96 | 97 | /* then put the rest (if any) at the beginning of the buffer */ 98 | memcpy(ring_buf->data, buffer + l, len - l); 99 | 100 | ring_buf->write_pos += len; 101 | 102 | return len; 103 | } 104 | 105 | /** 106 | * ringbuffer_print - print ringbuf data 107 | * @ring_buf: the ringbuffer to be used. 108 | * @cnt : the number byte to be print. 109 | */ 110 | void ringbuffer_print(struct ringbuffer *ring_buf, unsigned int cnt) 111 | { 112 | return; 113 | } 114 | 115 | /** 116 | * ringbuffer_from_dev - read data from device, and put them into ringbuffer 117 | * @fd: file descriptor of device 118 | * @ring_buf: the ringbuffer to be used. 119 | * @len: the length of the data to be read. 120 | */ 121 | ssize_t ringbuffer_from_dev(int fd, struct ringbuffer *ring_buf, unsigned int len) 122 | { 123 | unsigned int l; 124 | ssize_t ret, total; 125 | 126 | total = 0; 127 | 128 | len = min(len, ring_buf->size - ring_buf->write_pos + ring_buf->read_pos); 129 | 130 | /* first put the data starting from write_pos to buffer end */ 131 | l = min(len, ring_buf->size - (ring_buf->write_pos & (ring_buf->size - 1))); 132 | 133 | ret = read(fd, ring_buf->data + (ring_buf->write_pos & (ring_buf->size - 1)), l); 134 | if (ret < 0) { 135 | return ret; 136 | } 137 | 138 | total = ret; 139 | 140 | if (total < l) { 141 | ring_buf->write_pos += total; 142 | 143 | return total; 144 | } 145 | 146 | if (len -l) { 147 | ret = read(fd, ring_buf->data, len - l); 148 | if (ret < 0) { 149 | return ret; 150 | } 151 | 152 | total += ret; 153 | } 154 | 155 | ring_buf->write_pos += total; 156 | 157 | return total; 158 | } 159 | 160 | 161 | /** 162 | * ringbuffer_get - gets some data from the ringbuffer, no locking version 163 | * @ring_buf: the ringbuffer to be used. 164 | * @buffer: where the data must be copied. 165 | * @len: the size of the destination buffer. 166 | * 167 | * This function copies at most @len bytes from the ringbuffer into the 168 | * @buffer and returns the number of copied bytes. 169 | * 170 | * Note that with only one concurrent reader and one concurrent 171 | * writer, you don't need extra locking to use these functions. 172 | */ 173 | unsigned int ringbuffer_get(struct ringbuffer *ring_buf, 174 | char *buffer, unsigned int len) 175 | { 176 | unsigned int l; 177 | 178 | len = min(len, ring_buf->write_pos - ring_buf->read_pos); 179 | 180 | /* first get the data from ring_buf->read_pos until the end of the buffer */ 181 | l = min(len, ring_buf->size - (ring_buf->read_pos & (ring_buf->size - 1))); 182 | memcpy(buffer, ring_buf->data + (ring_buf->read_pos & (ring_buf->size - 1)), l); 183 | 184 | /* then get the rest (if any) from the beginning of the buffer */ 185 | memcpy(buffer + l, ring_buf->data, len - l); 186 | 187 | ring_buf->read_pos += len; 188 | 189 | return len; 190 | } 191 | 192 | /* FIXME: just for connection, as use "send()", for details, man 2 send */ 193 | unsigned int ringbuffer_to_socket(int socket_fd, struct ringbuffer *ring_buf, unsigned int len) 194 | { 195 | unsigned int l; 196 | unsigned int send_num; 197 | 198 | len = min(len, ring_buf->write_pos - ring_buf->read_pos); 199 | 200 | l = min(len, ring_buf->size - (ring_buf->read_pos & (ring_buf->size - 1))); 201 | 202 | send_num = send(socket_fd, ring_buf->data + (ring_buf->read_pos & (ring_buf->size - 1)), l, 0); 203 | if (send_num < 0){ 204 | perror("send()"); 205 | exit(1); 206 | } 207 | 208 | if (len - l) { 209 | send_num = send(socket_fd, ring_buf->data, len - l, 0); 210 | if (send_num < 0){ 211 | perror("send()"); 212 | exit(1); 213 | } 214 | } 215 | ring_buf->read_pos += len; 216 | 217 | return len; 218 | } 219 | 220 | 221 | /** 222 | * ringbuffer_reset - removes the entire ringbuffer content 223 | * @ring_buf: address of the ringbuffer to be used 224 | * 225 | * Note: usage of ringbuffer_reset() is dangerous. It should be only called when the 226 | * ringbuffer is exclusived locked or when it is secured that no other thread is 227 | * accessing the fifo. 228 | */ 229 | void ringbuffer_reset(struct ringbuffer *ring_buf) 230 | { 231 | ring_buf->write_pos = ring_buf->read_pos = 0; 232 | } 233 | 234 | unsigned int ringbuffer_is_empty(struct ringbuffer *ring_buf) 235 | { 236 | return ring_buf->read_pos == ring_buf->write_pos; 237 | } 238 | 239 | unsigned int ringbuffer_is_full(struct ringbuffer *ring_buf) 240 | { 241 | return ring_buf->size == ring_buf->write_pos - ring_buf->read_pos; 242 | } 243 | 244 | unsigned int ringbuffer_len(struct ringbuffer *ring_buf) 245 | { 246 | return ring_buf->write_pos - ring_buf->read_pos; 247 | } 248 | 249 | unsigned int ringbuffer_space_left(struct ringbuffer *ring_buf) 250 | { 251 | return ring_buf->size - ring_buf->write_pos + ring_buf->read_pos; 252 | } 253 | 254 | 255 | -------------------------------------------------------------------------------- /user/ringbuffer.h: -------------------------------------------------------------------------------- 1 | #ifndef __RINGBUFFER_H 2 | #define __RINGBUFFER_H 3 | 4 | #define min(x,y) ({ \ 5 | typeof(x) _x = (x); \ 6 | typeof(y) _y = (y); \ 7 | (void) (&_x == &_y); \ 8 | _x < _y ? _x : _y; }) 9 | 10 | struct ringbuffer { 11 | void *data; 12 | unsigned int size; 13 | unsigned int read_pos; 14 | unsigned int write_pos; 15 | }; 16 | 17 | struct ringbuffer *ringbuffer_create(unsigned int bytes); 18 | void ringbuffer_destroy(struct ringbuffer *ring_buf); 19 | 20 | void ringbuffer_reset(struct ringbuffer *ring_buf); 21 | 22 | unsigned int ringbuffer_put(struct ringbuffer *ring_buf, 23 | const char *buf, unsigned int len); 24 | 25 | unsigned int ringbuffer_get(struct ringbuffer *ring_buf, 26 | char *buf, unsigned int len); 27 | 28 | void ringbuffer_print(struct ringbuffer *ring_buf, unsigned int cnt); 29 | 30 | ssize_t ringbuffer_from_dev(int fd, struct ringbuffer *ring_buf, unsigned int len); 31 | 32 | unsigned int ringbuffer_is_empty(struct ringbuffer *ring_buf); 33 | unsigned int ringbuffer_is_full(struct ringbuffer *ring_buf); 34 | 35 | unsigned int ringbuffer_len(struct ringbuffer *ring_buf); 36 | unsigned int ringbuffer_space_left(struct ringbuffer *ring_buf); 37 | 38 | unsigned int ringbuffer_to_socket(int socket_fd, struct ringbuffer *ring_buf, unsigned int len); 39 | 40 | #endif 41 | --------------------------------------------------------------------------------