aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/compute/skc/extent_ring.c
blob: 251b4208b2bac9ee719e3809ec28ee7cdb2c8f06 (plain)
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
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
/*
 * Copyright 2017 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can
 * be found in the LICENSE file.
 *
 */

//
//
//

#include <stdbool.h>

#include "extent_ring.h"
#include "macros.h"

//
//
//

void
skc_extent_ring_init(struct skc_extent_ring * const ring,
                     skc_uint                 const size_pow2,
                     skc_uint                 const size_snap,
                     skc_uint                 const size_elem)
{
  ring->head      = NULL;
  ring->last      = NULL;

  ring->outer.rw  = (skc_uint2){ 0 };
  ring->inner.rw  = (skc_uint2){ 0 };

  // FIXME -- assert size is pow2 -- either here or statically in the config

  ring->size.pow2 = size_pow2;
  ring->size.mask = size_pow2 - 1;
  ring->size.snap = size_snap;
  ring->size.elem = size_elem;
}

//
//
//

skc_uint
skc_extent_ring_rem(struct skc_extent_ring const * const ring)
{
  return ring->size.pow2 - (ring->outer.writes - ring->outer.reads);
}

skc_bool
skc_extent_ring_is_full(struct skc_extent_ring const * const ring)
{
  return (ring->outer.writes - ring->outer.reads) == ring->size.pow2;
}

skc_uint
skc_extent_ring_wip_count(struct skc_extent_ring const * const ring)
{
  return ring->outer.writes - ring->inner.reads;
}

skc_uint
skc_extent_ring_wip_rem(struct skc_extent_ring const * const ring)
{
  return SKC_MIN_MACRO(skc_extent_ring_rem(ring),ring->size.snap) - skc_extent_ring_wip_count(ring);
}

skc_bool
skc_extent_ring_wip_is_full(struct skc_extent_ring const * const ring)
{
  return skc_extent_ring_wip_count(ring) == SKC_MIN_MACRO(skc_extent_ring_rem(ring),ring->size.snap);
}

skc_uint
skc_extent_ring_wip_index_inc(struct skc_extent_ring * const ring)
{
  return ring->outer.writes++ & ring->size.mask;
}

//
//
//

void
skc_extent_ring_checkpoint(struct skc_extent_ring * const ring)
{
  ring->inner.writes = ring->outer.writes;
}

//
//
//

struct skc_extent_ring_snap *
skc_extent_ring_snap_alloc(struct skc_runtime     * const runtime,
                           struct skc_extent_ring * const ring)
{
  skc_subbuf_id_t id;

  struct skc_extent_ring_snap * snap =
    skc_runtime_host_temp_alloc(runtime,
                                SKC_MEM_FLAGS_READ_WRITE,
                                sizeof(*snap),&id,NULL);
  // save the id
  snap->id      = id;

  // back point to parent
  snap->ring    = ring;
  snap->next    = NULL;

  // save the inner boundaries of the ring to the snapshot
  snap->reads   = ring->inner.reads;
  snap->writes  = ring->inner.reads = ring->inner.writes;

  // mark not free
  snap->is_free = false;

  // attach snap to ring
  if (ring->head == NULL)
    {
      ring->head = snap;
      ring->last = snap;
    }
  else
    {
      ring->last->next = snap;
      ring->last       = snap;
    }

  return snap;
}

//
//
//

void
skc_extent_ring_snap_free(struct skc_runtime          * const runtime,
                          struct skc_extent_ring_snap * const snap)
{
  // snap will be lazily freed
  snap->is_free = true;

  //
  // if this snapshot is no longer referenced then try to dispose of
  // the ring buffer's leading unreferenced snapshots
  //
  struct skc_extent_ring      * const ring = snap->ring;
  struct skc_extent_ring_snap *       curr = ring->head;

  if (!curr->is_free)
    return;

  do {
    // increment read counter
    ring->outer.reads = curr->writes;

    struct skc_extent_ring_snap * const next = curr->next;

    skc_runtime_host_temp_free(runtime,curr,curr->id);

    curr = next;

    // this was the last snap...
    if (curr == NULL)
      {
        ring->last = NULL;
        break;
      }

    // is the next free?
  } while (curr->is_free);

  // update head
  ring->head = curr;
}

//
//
//

skc_uint
skc_extent_ring_snap_count(struct skc_extent_ring_snap const * const snap)
{
  return snap->writes - snap->reads;
}

skc_uint
skc_extent_ring_snap_from(struct skc_extent_ring_snap const * const snap)
{
  return snap->reads & snap->ring->size.mask;
}

skc_uint
skc_extent_ring_snap_to(struct skc_extent_ring_snap const * const snap)
{
  return snap->writes & snap->ring->size.mask;
}

//
//
//