summaryrefslogtreecommitdiff
path: root/Kernel/Memory/RingBuffer.h
blob: 7b35f7ac12a695f3c4d3937e5ea48a11b129ca1d (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
/*
 * Copyright (c) 2021, Sahan Fernando <sahan.h.fernando@gmail.com>.
 *
 * SPDX-License-Identifier: BSD-2-Clause
 */

#pragma once

#include <Kernel/Memory/PhysicalAddress.h>
#include <Kernel/UserOrKernelBuffer.h>

namespace Kernel::Memory {

class RingBuffer {
public:
    static ErrorOr<NonnullOwnPtr<RingBuffer>> try_create(StringView region_name, size_t capacity);

    bool has_space() const { return m_num_used_bytes < m_capacity_in_bytes; }
    bool copy_data_in(UserOrKernelBuffer const& buffer, size_t offset, size_t length, PhysicalAddress& start_of_copied_data, size_t& bytes_copied);
    ErrorOr<size_t> copy_data_out(size_t size, UserOrKernelBuffer& buffer) const;
    ErrorOr<PhysicalAddress> reserve_space(size_t size);
    void reclaim_space(PhysicalAddress chunk_start, size_t chunk_size);
    PhysicalAddress start_of_used() const;

    Spinlock<LockRank::None>& lock() { return m_lock; }
    size_t used_bytes() const { return m_num_used_bytes; }
    PhysicalAddress start_of_region() const { return m_region->physical_page(0)->paddr(); }
    VirtualAddress vaddr() const { return m_region->vaddr(); }
    size_t bytes_till_end() const { return (m_capacity_in_bytes - ((m_start_of_used + m_num_used_bytes) % m_capacity_in_bytes)) % m_capacity_in_bytes; };

private:
    RingBuffer(NonnullOwnPtr<Memory::Region> region, size_t capacity);

    NonnullOwnPtr<Memory::Region> m_region;
    Spinlock<LockRank::None> m_lock {};
    size_t m_start_of_used {};
    size_t m_num_used_bytes {};
    size_t m_capacity_in_bytes {};
};

}