1 /*
2 * Copyright (c) 2023 Institute of Parallel And Distributed Systems (IPADS), Shanghai Jiao Tong University (SJTU)
3 * Licensed under the Mulan PSL v2.
4 * You can use this software according to the terms and conditions of the Mulan PSL v2.
5 * You may obtain a copy of Mulan PSL v2 at:
6 * http://license.coscl.org.cn/MulanPSL2
7 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
8 * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
9 * PURPOSE.
10 * See the Mulan PSL v2 for more details.
11 */
12 #include <lib/ring_buffer.h>
13 #include <common/util.h>
14
15 /*
16 * next_slot returns the virtual address of the next slot to the given offset.
17 * This function should not be used by user directly, so we will not check the
18 * correctness of the offset here.
19 */
next_slot(struct ring_buffer * ring_buf,off_t off)20 static inline off_t next_slot(struct ring_buffer *ring_buf, off_t off)
21 {
22 return ((off == ring_buf->buffer_size - ring_buf->msg_size) ?
23 (sizeof(struct ring_buffer)) :
24 (off + ring_buf->msg_size));
25 }
26
get_one_msg(struct ring_buffer * ring_buf,void * msg)27 int get_one_msg(struct ring_buffer *ring_buf, void *msg)
28 {
29 off_t p_off = ring_buf->producer_offset;
30 off_t c_off = ring_buf->consumer_offset;
31
32 /* recycle_msg_buffer is empty */
33 if (p_off == c_off)
34 return MSG_OP_FAILURE;
35 vaddr_t buf = (vaddr_t)ring_buf + c_off;
36 memcpy(msg, (void *)buf, ring_buf->msg_size);
37 ring_buf->consumer_offset = next_slot(ring_buf, c_off);
38 return MSG_OP_SUCCESS;
39 }
40
41 /*
42 * Whether ring buffer is full
43 * Always keep a slot empty
44 * Max capicity = buffer_size - msg_size
45 * p_off = c_off : buffer empty
46 * c_off = next_slot(p_off) : buffer full
47 */
if_buffer_full(struct ring_buffer * ring_buf)48 int if_buffer_full(struct ring_buffer *ring_buf)
49 {
50 off_t p_off = ring_buf->producer_offset;
51 off_t c_off = ring_buf->consumer_offset;
52
53 /* recycle_msg_buffer is full */
54 if (c_off == next_slot(ring_buf, p_off))
55 return RING_BUFFER_FULL;
56
57 return RING_BUFFER_NOT_FULL;
58 }
59
set_one_msg(struct ring_buffer * ring_buf,void * msg)60 int set_one_msg(struct ring_buffer *ring_buf, void *msg)
61 {
62 if (if_buffer_full(ring_buf)) {
63 return MSG_OP_FAILURE;
64 }
65
66 off_t p_off = ring_buf->producer_offset;
67 vaddr_t buf = (vaddr_t)ring_buf + p_off;
68
69 memcpy((void *)buf, msg, ring_buf->msg_size);
70 ring_buf->producer_offset = next_slot(ring_buf, p_off);
71 return MSG_OP_SUCCESS;
72 }