blob: 6c18277fdfc9fc681bb03363a2ed8a46fe9fa448 (
plain) (
blame)
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
|
#ifndef _FEATHER_BUFFER_H_
#define _FEATHER_BUFFER_H_
/* requires UINT_MAX and memcpy */
#define SLOT_FREE 0
#define SLOT_BUSY 1
#define SLOT_READY 2
struct ft_buffer {
unsigned int slot_count;
unsigned int slot_size;
int free_count;
unsigned int write_idx;
unsigned int read_idx;
char* slots;
void* buffer_mem;
unsigned int failed_writes;
};
static inline int init_ft_buffer(struct ft_buffer* buf,
unsigned int slot_count,
unsigned int slot_size,
char* slots,
void* buffer_mem)
{
int i = 0;
if (!slot_count || UINT_MAX % slot_count != slot_count - 1) {
/* The slot count must divide UNIT_MAX + 1 so that when it
* wraps around the index correctly points to 0.
*/
return 0;
} else {
buf->slot_count = slot_count;
buf->slot_size = slot_size;
buf->slots = slots;
buf->buffer_mem = buffer_mem;
buf->free_count = slot_count;
buf->write_idx = 0;
buf->read_idx = 0;
buf->failed_writes = 0;
for (i = 0; i < slot_count; i++)
buf->slots[i] = SLOT_FREE;
return 1;
}
}
static inline int ft_buffer_start_write(struct ft_buffer* buf, void **ptr)
{
int free = fetch_and_dec(&buf->free_count);
unsigned int idx;
if (free <= 0) {
fetch_and_inc(&buf->free_count);
*ptr = 0;
fetch_and_inc(&buf->failed_writes);
return 0;
} else {
idx = fetch_and_inc((int*) &buf->write_idx) % buf->slot_count;
buf->slots[idx] = SLOT_BUSY;
*ptr = ((char*) buf->buffer_mem) + idx * buf->slot_size;
return 1;
}
}
static inline void ft_buffer_finish_write(struct ft_buffer* buf, void *ptr)
{
unsigned int idx = ((char*) ptr - (char*) buf->buffer_mem) / buf->slot_size;
buf->slots[idx] = SLOT_READY;
}
/* exclusive reader access is assumed */
static inline int ft_buffer_read(struct ft_buffer* buf, void* dest)
{
unsigned int idx;
if (buf->free_count == buf->slot_count)
/* nothing available */
return 0;
idx = buf->read_idx % buf->slot_count;
if (buf->slots[idx] == SLOT_READY) {
memcpy(dest, ((char*) buf->buffer_mem) + idx * buf->slot_size,
buf->slot_size);
buf->slots[idx] = SLOT_FREE;
buf->read_idx++;
fetch_and_inc(&buf->free_count);
return 1;
} else
return 0;
}
#endif
|