blob: 0aca8d4eef18b3891c59d96d32e12ee702e0fc50 [file] [log] [blame]
// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
//
//
#include "ring.h"
#include <assert.h>
//
// A barebones ring
//
void
spn_ring_init(struct spn_ring * const ring, uint32_t const size)
{
assert(size >= 1);
ring->size = size;
ring->head = 0;
ring->tail = 0;
ring->rem = size;
}
bool
spn_ring_is_empty(struct spn_ring const * const ring)
{
return ring->rem == 0;
}
bool
spn_ring_is_full(struct spn_ring const * const ring)
{
return ring->rem == ring->size;
}
bool
spn_ring_is_tail(struct spn_ring const * const ring, uint32_t const idx)
{
return ring->tail == idx;
}
uint32_t
spn_ring_dropped(struct spn_ring const * const ring)
{
return ring->size - ring->rem;
}
uint32_t
spn_ring_rem_nowrap(struct spn_ring const * const ring)
{
return ring->size - ring->head;
}
uint32_t
spn_ring_acquire_1(struct spn_ring * const ring)
{
//
// CAUTION: this is unguarded so always test before acquiring
//
ring->rem -= 1;
uint32_t const idx = ring->head;
uint32_t const head = idx + 1;
ring->head = (head < ring->size) ? head : 0;
return idx;
}
void
spn_ring_drop_1(struct spn_ring * const ring)
{
//
// CAUTION: this is unguarded so always test before acquiring
//
ring->rem -= 1;
uint32_t const idx = ring->head;
uint32_t const head = idx + 1;
ring->head = (head < ring->size) ? head : 0;
}
void
spn_ring_drop_n(struct spn_ring * const ring, uint32_t const n)
{
//
// CAUTION: this is unguarded so always test before acquiring
//
ring->rem -= n;
uint32_t const idx = ring->head;
uint32_t const head = idx + n;
ring->head = (head < ring->size) ? head : head - ring->size;
}
void
spn_ring_release_n(struct spn_ring * const ring, uint32_t const n)
{
//
// CAUTION: assumes conservation so no need to test before release
//
ring->rem += n;
uint32_t const tail = ring->tail + n;
ring->tail = (tail < ring->size) ? tail : tail - ring->size;
}
//
// A subsidiary ring for when space is known to be implicitly
// available.
//
void
spn_next_init(struct spn_next * const next, uint32_t const size)
{
next->size = size;
next->head = 0;
}
uint32_t
spn_next_acquire_1(struct spn_next * const next)
{
uint32_t const idx = next->head;
uint32_t const head = idx + 1;
next->head = (head < next->size) ? head : 0;
return idx;
}
uint32_t
spn_next_acquire_2(struct spn_next * const next)
{
uint32_t const idx = next->head;
if (idx + 1 < next->size)
{
uint32_t const head = idx + 2;
next->head = (head < next->size) ? head : 0;
return idx;
}
else // we need two continguous slots
{
next->head = 2;
return 0;
}
}
void
spn_next_drop_n(struct spn_next * const next, uint32_t const n)
{
uint32_t const idx = next->head;
uint32_t const head = idx + n;
next->head = (head < next->size) ? head : head - next->size;
}
//
//
//