forked from ish-app/ish
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Rewrite syslog buffer to use a generic fifo
Trivia: I wrote this ring buffer implementation in half an hour during a Google interview and it somehow works better than the old one which took me half a day.
- Loading branch information
Showing
4 changed files
with
131 additions
and
56 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -94,6 +94,7 @@ src = [ | |
|
||
'util/timer.c', | ||
'util/sync.c', | ||
'util/fifo.c', | ||
|
||
'emu/memory.c', | ||
'emu/tlb.c', | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
#include <stdlib.h> | ||
#include <string.h> | ||
#include "util/fifo.h" | ||
|
||
void fifo_init(struct fifo *fifo, size_t capacity) { | ||
fifo->buf = malloc(capacity); | ||
fifo->capacity = capacity; | ||
fifo->size = fifo->start = 0; | ||
} | ||
|
||
void fifo_destroy(struct fifo *fifo) { | ||
free(fifo->buf); | ||
} | ||
|
||
size_t fifo_capacity(struct fifo *fifo) { | ||
return fifo->capacity; | ||
} | ||
size_t fifo_size(struct fifo *fifo) { | ||
return fifo->size; | ||
} | ||
size_t fifo_remaining(struct fifo *fifo) { | ||
return fifo->capacity - fifo->size; | ||
} | ||
|
||
int fifo_write(struct fifo *fifo, const void *data, size_t size, int flags) { | ||
if (size > fifo_remaining(fifo)) { | ||
if (!(flags & FIFO_OVERWRITE)) | ||
return 1; | ||
size_t excess = size - fifo_remaining(fifo); | ||
fifo->start = (fifo->start + excess) % fifo->capacity; | ||
fifo->size -= excess; | ||
} | ||
|
||
size_t first_copy_size = fifo->capacity - fifo->start - fifo->size; | ||
if (first_copy_size > size) | ||
first_copy_size = size; | ||
memcpy(&fifo->buf[fifo->start + fifo->size], data, first_copy_size); | ||
memcpy(&fifo->buf[0], (char *) data + first_copy_size, size - first_copy_size); | ||
fifo->size += size; | ||
return 0; | ||
} | ||
|
||
int fifo_read(struct fifo *fifo, void *buf, size_t size, int flags) { | ||
if (size > fifo_size(fifo)) | ||
return 1; | ||
|
||
size_t start = fifo->start; | ||
if (flags & FIFO_LAST) | ||
start = (start + (fifo->size - size)) % fifo->capacity; | ||
|
||
size_t first_copy_size = fifo->capacity - fifo->start; | ||
if (first_copy_size > size) | ||
first_copy_size = size; | ||
memcpy(buf, &fifo->buf[start], first_copy_size); | ||
memcpy((char *) buf + first_copy_size, &fifo->buf[0], size - first_copy_size); | ||
|
||
if (!(flags & FIFO_PEEK)) { | ||
fifo->start = (start + size) % fifo->capacity; | ||
fifo->size -= size; | ||
} | ||
return 0; | ||
} | ||
|
||
void fifo_flush(struct fifo *fifo) { | ||
fifo->size = 0; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
#ifndef UTIL_FIFO_H | ||
#define UTIL_FIFO_H | ||
#include <sys/types.h> | ||
|
||
struct fifo { | ||
char *buf; | ||
size_t capacity; | ||
size_t size; | ||
size_t start; | ||
}; | ||
|
||
#define FIFO_INIT(b) ((struct fifo) {.buf = b, .capacity = sizeof(b)}) | ||
void fifo_init(struct fifo *fifo, size_t capacity); | ||
void fifo_destroy(struct fifo *fifo); | ||
|
||
size_t fifo_capacity(struct fifo *fifo); | ||
size_t fifo_size(struct fifo *fifo); | ||
size_t fifo_remaining(struct fifo *fifo); | ||
|
||
// return 0 on success, 1 if size > fifo_remaining and FIFO_OVERWRITE was not specified | ||
#define FIFO_OVERWRITE 1 | ||
int fifo_write(struct fifo *fifo, const void *data, size_t size, int flags); | ||
|
||
// return 0 on success, 1 if size > fifo_size | ||
#define FIFO_PEEK 1 // don't remove the bytes | ||
#define FIFO_LAST 2 // return bytes from the end, not the start | ||
int fifo_read(struct fifo *fifo, void *buf, size_t size, int flags); | ||
|
||
void fifo_flush(struct fifo *fifo); | ||
|
||
#endif |