-
Notifications
You must be signed in to change notification settings - Fork 7
/
sfifo.c
128 lines (110 loc) · 2.9 KB
/
sfifo.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
/*
------------------------------------------------------------
SFIFO 1.3
------------------------------------------------------------
* Simple portable lock-free FIFO
* (c) 2000-2002, David Olofson
*
* Platform support:
* gcc / Linux / x86: Works
* gcc / Linux / x86 kernel: Works
* gcc / FreeBSD / x86: Works
* gcc / NetBSD / x86: Works
* gcc / Mac OS X / PPC: Works
* gcc / Win32 / x86: Works
* Borland C++ / DOS / x86RM: Works
* Borland C++ / Win32 / x86PM16: Untested
* ? / Various Un*ces / ?: Untested
* ? / Mac OS / PPC: Untested
* gcc / BeOS / x86: Untested
* gcc / BeOS / PPC: Untested
* ? / ? / Alpha: Untested
*
* 1.2: Max buffer size halved, to avoid problems with
* the sign bit...
*
* 1.3: Critical buffer allocation bug fixed! For certain
* requested buffer sizes, older version would
* allocate a buffer of insufficient size, which
* would result in memory thrashing. (Amazing that
* I've manage to use this to the extent I have
* without running into this... *heh*)
*/
/*
* Porting note:
* Reads and writes of a variable of this type in memory
* must be *atomic*! 'int' is *not* atomic on all platforms.
* A safe type should be used, and sfifo should limit the
* maximum buffer size accordingly.
*/
/*
* Newer version here: https://github.com/olofson/sfifo
*/
/*
* 2021-05-22: Extracted from ftpd.c and modified by Terje Io for grblHAL networking
*/
#include "sfifo.h"
#if FTP_ENABLE
#include <string.h>
/*
* Alloc buffer, init FIFO etc...
*/
int sfifo_init(sfifo_t *f, int size)
{
memset(f, 0, sizeof(sfifo_t));
if(size > SFIFO_MAX_BUFFER_SIZE)
return -EINVAL;
/*
* Set sufficient power-of-2 size.
*
* No, there's no bug. If you need
* room for N bytes, the buffer must
* be at least N+1 bytes. (The fifo
* can't tell 'empty' from 'full'
* without unsafe index manipulations
* otherwise.)
*/
f->size = 1;
for(; f->size <= size; f->size <<= 1);
/* Get buffer */
f->buffer = (void *)malloc(f->size + 1);
return f->buffer ? 0 : -ENOMEM;
}
/*
* Dealloc buffer etc...
*/
void sfifo_close(sfifo_t *f)
{
if(f->buffer)
free(f->buffer);
}
/*
* Write bytes to a FIFO
* Return number of bytes written, or an error code
*/
int sfifo_write(sfifo_t *f, const void *_buf, int len)
{
int total;
int i;
const char *buf = (const char *)_buf;
if(!f->buffer)
return -ENODEV; /* No buffer! */
/* total = len = min(space, len) */
total = sfifo_space(f);
if(len > total)
len = total;
else
total = len;
i = f->writepos;
if(i + len > f->size)
{
memcpy(f->buffer + i, buf, f->size - i);
buf += f->size - i;
len -= f->size - i;
i = 0;
}
memcpy(f->buffer + i, buf, len);
f->writepos = i + len;
return total;
}
#endif