1/*
2 * Copyright (C) 2020-2022 The opuntiaOS Project Authors.
3 * + Contributed by Nikita Melekhin <nimelehin@gmail.com>
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
7 */
8
9#ifndef _KERNEL_ALGO_SYNC_RINGBUFFER_H
10#define _KERNEL_ALGO_SYNC_RINGBUFFER_H
11
12#include <algo/ringbuffer.h>
13#include <libkern/libkern.h>
14#include <libkern/lock.h>
15#include <mem/kmemzone.h>
16
17struct __sync_ringbuffer {
18 ringbuffer_t ringbuffer;
19 lock_t lock;
20};
21typedef struct __sync_ringbuffer sync_ringbuffer_t;
22
23static ALWAYS_INLINE sync_ringbuffer_t sync_ringbuffer_create(uint32_t size)
24{
25 sync_ringbuffer_t res;
26 res.ringbuffer = ringbuffer_create(size);
27 lock_init(&res.lock);
28 return res;
29}
30
31#define sync_ringbuffer_create_std() sync_ringbuffer_create(RINGBUFFER_STD_SIZE)
32static ALWAYS_INLINE void sync_ringbuffer_free(sync_ringbuffer_t* buf)
33{
34 lock_acquire(&buf->lock);
35 ringbuffer_free(&buf->ringbuffer);
36 lock_release(&buf->lock);
37}
38
39static ALWAYS_INLINE uint32_t sync_ringbuffer_space_to_read(sync_ringbuffer_t* buf)
40{
41 lock_acquire(&buf->lock);
42 uint32_t res = ringbuffer_space_to_read(&buf->ringbuffer);
43 lock_release(&buf->lock);
44 return res;
45}
46
47static ALWAYS_INLINE uint32_t sync_ringbuffer_space_to_read_with_custom_start(sync_ringbuffer_t* buf, uint32_t start)
48{
49 lock_acquire(&buf->lock);
50 uint32_t res = ringbuffer_space_to_read_with_custom_start(&buf->ringbuffer, start);
51 lock_release(&buf->lock);
52 return res;
53}
54static ALWAYS_INLINE uint32_t sync_ringbuffer_space_to_write(sync_ringbuffer_t* buf)
55{
56 lock_acquire(&buf->lock);
57 uint32_t res = ringbuffer_space_to_write(&buf->ringbuffer);
58 lock_release(&buf->lock);
59 return res;
60}
61static ALWAYS_INLINE uint32_t sync_ringbuffer_read(sync_ringbuffer_t* buf, uint8_t* v, uint32_t a)
62{
63 lock_acquire(&buf->lock);
64 uint32_t res = ringbuffer_read(&buf->ringbuffer, v, a);
65 lock_release(&buf->lock);
66 return res;
67}
68static ALWAYS_INLINE uint32_t sync_ringbuffer_read_with_start(sync_ringbuffer_t* buf, uint32_t start, uint8_t* holder, uint32_t siz)
69{
70 lock_acquire(&buf->lock);
71 uint32_t res = ringbuffer_read_with_start(&buf->ringbuffer, start, holder, siz);
72 lock_release(&buf->lock);
73 return res;
74}
75static ALWAYS_INLINE uint32_t sync_ringbuffer_write(sync_ringbuffer_t* buf, const uint8_t* v, uint32_t a)
76{
77 lock_acquire(&buf->lock);
78 uint32_t res = ringbuffer_write(&buf->ringbuffer, v, a);
79 lock_release(&buf->lock);
80 return res;
81}
82static ALWAYS_INLINE uint32_t sync_ringbuffer_write_ignore_bounds(sync_ringbuffer_t* buf, const uint8_t* holder, uint32_t siz)
83{
84 lock_acquire(&buf->lock);
85 uint32_t res = ringbuffer_write_ignore_bounds(&buf->ringbuffer, holder, siz);
86 lock_release(&buf->lock);
87 return res;
88}
89static ALWAYS_INLINE uint32_t sync_ringbuffer_read_one(sync_ringbuffer_t* buf, uint8_t* data)
90{
91 lock_acquire(&buf->lock);
92 uint32_t res = ringbuffer_read_one(&buf->ringbuffer, data);
93 lock_release(&buf->lock);
94 return res;
95}
96static ALWAYS_INLINE uint32_t sync_ringbuffer_write_one(sync_ringbuffer_t* buf, uint8_t data)
97{
98 lock_acquire(&buf->lock);
99 uint32_t res = ringbuffer_write_one(&buf->ringbuffer, data);
100 lock_release(&buf->lock);
101 return res;
102}
103
104static ALWAYS_INLINE void sync_ringbuffer_clear(sync_ringbuffer_t* buf)
105{
106 lock_acquire(&buf->lock);
107 ringbuffer_clear(&buf->ringbuffer);
108 lock_release(&buf->lock);
109}
110
111#endif //_KERNEL_ALGO_SYNC_RINGBUFFER_H