blob: 251b4208b2bac9ee719e3809ec28ee7cdb2c8f06 [file] [log] [blame]
Allan MacKinnon4359d522018-06-19 13:57:04 -07001/*
2 * Copyright 2017 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can
5 * be found in the LICENSE file.
6 *
7 */
8
9//
10//
11//
12
13#include <stdbool.h>
14
15#include "extent_ring.h"
16#include "macros.h"
17
18//
19//
20//
21
22void
23skc_extent_ring_init(struct skc_extent_ring * const ring,
24 skc_uint const size_pow2,
25 skc_uint const size_snap,
26 skc_uint const size_elem)
27{
28 ring->head = NULL;
29 ring->last = NULL;
30
31 ring->outer.rw = (skc_uint2){ 0 };
32 ring->inner.rw = (skc_uint2){ 0 };
33
34 // FIXME -- assert size is pow2 -- either here or statically in the config
35
36 ring->size.pow2 = size_pow2;
37 ring->size.mask = size_pow2 - 1;
38 ring->size.snap = size_snap;
39 ring->size.elem = size_elem;
40}
41
42//
43//
44//
45
46skc_uint
47skc_extent_ring_rem(struct skc_extent_ring const * const ring)
48{
49 return ring->size.pow2 - (ring->outer.writes - ring->outer.reads);
50}
51
52skc_bool
53skc_extent_ring_is_full(struct skc_extent_ring const * const ring)
54{
55 return (ring->outer.writes - ring->outer.reads) == ring->size.pow2;
56}
57
58skc_uint
59skc_extent_ring_wip_count(struct skc_extent_ring const * const ring)
60{
61 return ring->outer.writes - ring->inner.reads;
62}
63
64skc_uint
65skc_extent_ring_wip_rem(struct skc_extent_ring const * const ring)
66{
67 return SKC_MIN_MACRO(skc_extent_ring_rem(ring),ring->size.snap) - skc_extent_ring_wip_count(ring);
68}
69
70skc_bool
71skc_extent_ring_wip_is_full(struct skc_extent_ring const * const ring)
72{
73 return skc_extent_ring_wip_count(ring) == SKC_MIN_MACRO(skc_extent_ring_rem(ring),ring->size.snap);
74}
75
76skc_uint
77skc_extent_ring_wip_index_inc(struct skc_extent_ring * const ring)
78{
79 return ring->outer.writes++ & ring->size.mask;
80}
81
82//
83//
84//
85
86void
87skc_extent_ring_checkpoint(struct skc_extent_ring * const ring)
88{
89 ring->inner.writes = ring->outer.writes;
90}
91
92//
93//
94//
95
96struct skc_extent_ring_snap *
97skc_extent_ring_snap_alloc(struct skc_runtime * const runtime,
98 struct skc_extent_ring * const ring)
99{
100 skc_subbuf_id_t id;
101
Hal Canary14195342018-07-11 16:10:14 -0400102 struct skc_extent_ring_snap * snap =
Allan MacKinnon4359d522018-06-19 13:57:04 -0700103 skc_runtime_host_temp_alloc(runtime,
104 SKC_MEM_FLAGS_READ_WRITE,
105 sizeof(*snap),&id,NULL);
106 // save the id
107 snap->id = id;
Hal Canary14195342018-07-11 16:10:14 -0400108
Allan MacKinnon4359d522018-06-19 13:57:04 -0700109 // back point to parent
110 snap->ring = ring;
111 snap->next = NULL;
Hal Canary14195342018-07-11 16:10:14 -0400112
Allan MacKinnon4359d522018-06-19 13:57:04 -0700113 // save the inner boundaries of the ring to the snapshot
114 snap->reads = ring->inner.reads;
115 snap->writes = ring->inner.reads = ring->inner.writes;
116
117 // mark not free
118 snap->is_free = false;
119
120 // attach snap to ring
121 if (ring->head == NULL)
122 {
123 ring->head = snap;
124 ring->last = snap;
125 }
Hal Canary14195342018-07-11 16:10:14 -0400126 else
Allan MacKinnon4359d522018-06-19 13:57:04 -0700127 {
128 ring->last->next = snap;
129 ring->last = snap;
130 }
131
132 return snap;
133}
134
135//
136//
137//
138
139void
140skc_extent_ring_snap_free(struct skc_runtime * const runtime,
141 struct skc_extent_ring_snap * const snap)
142{
143 // snap will be lazily freed
144 snap->is_free = true;
145
146 //
147 // if this snapshot is no longer referenced then try to dispose of
148 // the ring buffer's leading unreferenced snapshots
149 //
150 struct skc_extent_ring * const ring = snap->ring;
151 struct skc_extent_ring_snap * curr = ring->head;
152
153 if (!curr->is_free)
154 return;
155
156 do {
157 // increment read counter
158 ring->outer.reads = curr->writes;
Hal Canary14195342018-07-11 16:10:14 -0400159
Allan MacKinnon4359d522018-06-19 13:57:04 -0700160 struct skc_extent_ring_snap * const next = curr->next;
161
162 skc_runtime_host_temp_free(runtime,curr,curr->id);
163
164 curr = next;
165
166 // this was the last snap...
Hal Canary14195342018-07-11 16:10:14 -0400167 if (curr == NULL)
Allan MacKinnon4359d522018-06-19 13:57:04 -0700168 {
169 ring->last = NULL;
170 break;
171 }
172
173 // is the next free?
174 } while (curr->is_free);
175
176 // update head
177 ring->head = curr;
178}
179
180//
181//
182//
183
184skc_uint
185skc_extent_ring_snap_count(struct skc_extent_ring_snap const * const snap)
186{
187 return snap->writes - snap->reads;
188}
189
190skc_uint
191skc_extent_ring_snap_from(struct skc_extent_ring_snap const * const snap)
192{
193 return snap->reads & snap->ring->size.mask;
194}
195
196skc_uint
197skc_extent_ring_snap_to(struct skc_extent_ring_snap const * const snap)
198{
199 return snap->writes & snap->ring->size.mask;
200}
201
202//
203//
204//