-
Notifications
You must be signed in to change notification settings - Fork 0
/
buffer.h
163 lines (146 loc) · 4.53 KB
/
buffer.h
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
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
/*
* Copyright 2012+ Michal Soltys <[email protected]>
*
* This file is part of Yancat.
*
* Yancat is free software: you can redistribute it and/or modify it under the
* terms of the GNU General Public License as published by the Free Software
* Foundation, either version 3 of the License, or (at your option) any later
* version.
*
* Yancat is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* Yancat. If not, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
#ifndef __buffer_h__
#define __buffer_h__
#include <stdint.h>
#include "common.h"
#include "crc.h"
#include "shmw.h"
#define M_LINER 0x01
#define M_LINEW 0x02
#define M_HUGE 0x04
#define M_SHM 0x08
#define M_CIR 0x10
struct buf_s {
struct shm_s buf, scr; /* buf and bounce areas */
uint8_t *ptr, *rchunk, *wchunk;
size_t size, mask;
size_t got, did;
size_t rblk, wblk, rmin, wmin, rsp, rsp_inv, wsp;
int fastr, fastw, flags, dorcrc, dowcrc, iscir, wstall, rstall;
unsigned long long int allin, allout;
CRCINT rcrc, wcrc;
};
void ibuf_commit_rbounce(struct buf_s *restrict buf, size_t chunk);
uint8_t * ibuf_fetch_wbounce(struct buf_s * restrict buf, size_t chunk);
/*
* on mingw we support only subset of full functionality - among those there's
* no possibility for circular buffer; OTOH on any unix it's almost guaranteed
*/
static inline uint8_t *
buf_fetch_r(struct buf_s *restrict buf, size_t chunk)
{
#ifdef h_mingw
if (likely(buf->got + chunk <= buf->size) || buf->iscir) {
#else
if (likely(buf->iscir) || buf->got + chunk <= buf->size) {
#endif
buf->fastr = 1;
return buf->ptr + buf->got;
} else {
buf->fastr = 0;
return buf->rchunk;
}
}
/* see comment above */
static inline uint8_t *
buf_fetch_w(struct buf_s * restrict buf, size_t chunk)
{
#ifdef h_mingw
if (likely(buf->did + chunk <= buf->size) || buf->iscir) {
#else
if (likely(buf->iscir) || buf->did + chunk <= buf->size) {
#endif
buf->fastw = 1;
return buf->ptr + buf->did;
} else
return ibuf_fetch_wbounce(buf, chunk);
}
static inline uint8_t *
buf_forcefetch_w(struct buf_s * restrict buf, size_t chunk)
{
return ibuf_fetch_wbounce(buf, chunk);
}
static inline void
buf_commit_r(struct buf_s *restrict buf, size_t chunk)
{
buf->allin += chunk;
if likely(buf->fastr) {
if unlikely(buf->dorcrc)
buf->rcrc = crc_calc(buf->rcrc, buf->ptr + buf->got, chunk);
} else
ibuf_commit_rbounce(buf, chunk);
}
static inline void
buf_commit_w(struct buf_s * restrict buf, size_t chunk)
{
buf->allout += chunk;
if unlikely(buf->dowcrc) {
if likely(buf->fastw) {
buf->wcrc = crc_calc(buf->wcrc, buf->ptr + buf->did, chunk);
} else {
buf->wcrc = crc_calc(buf->wcrc, buf->wchunk, chunk);
}
}
}
#if 0
static inline void
buf_crc_w(struct buf_s * restrict buf, const uint8_t * restrict ptr, size_t chunk)
{
buf->wcrc = crc_calc(buf->wcrc, ptr, chunk);
}
static inline void
buf_crc_r(struct buf_s * restrict buf, const uint8_t * restrict ptr, size_t chunk)
{
buf->rcrc = crc_calc(buf->rcrc, ptr, chunk);
}
#endif
/*
* commit functions are split into r/rf and w/wf, because .f versions
* modify values and we have no guarantees about atomicity - at the same time
* funcions making decisions (buf_can_r/w) would be reading those values
*/
static inline void
buf_commit_rf(struct buf_s *restrict buf, size_t chunk)
{
buf->got = (buf->got + chunk) & buf->mask;
}
static inline void
buf_commit_wf(struct buf_s *restrict buf, size_t chunk)
{
buf->did = (buf->did + chunk) & buf->mask;
}
/* common interface follows */
int buf_ctor(struct buf_s *buf, size_t bsiz, size_t rblk, size_t wblk, size_t hpage);
void buf_dtor(struct buf_s *buf);
void buf_dt(struct buf_s *buf);
int buf_setextra(struct buf_s *buf, int rline, int wline, int rcrc, int wcrc, double rs, double ws);
void buf_report_init(struct buf_s *buf);
void buf_report_stats(struct buf_s *buf);
void buf_setlinew(struct buf_s *buf);
size_t buf_can_r(struct buf_s *restrict buf);
uint8_t *buf_fetch_r(struct buf_s *restrict buf, size_t chunk);
void buf_commit_r(struct buf_s *restrict buf, size_t chunk);
void buf_commit_rf(struct buf_s *restrict buf, size_t chunk);
size_t buf_can_w(struct buf_s *restrict buf);
uint8_t *buf_fetch_w(struct buf_s *restrict buf, size_t chunk);
void buf_commit_w(struct buf_s *restrict buf, size_t chunk);
void buf_commit_wf(struct buf_s *restrict buf, size_t chunk);
#endif