• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 }