• 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 
13 #include <chcore/ring_buffer.h>
14 #include <sys/mman.h>
15 #include <string.h>
16 #include <chcore/defs.h>
17 
18 /*
19  * next_slot returns the virtual address of the next slot to the given offset.
20  * This function should not be used by user directly, so we will not check the
21  * correctness of the offset here.
22  */
next_slot(struct ring_buffer * ring_buf,off_t off)23 static inline off_t next_slot(struct ring_buffer *ring_buf, off_t off)
24 {
25     return ((off == ring_buf->buffer_size - ring_buf->msg_size) ?
26                 (sizeof(struct ring_buffer)) :
27                 (off + ring_buf->msg_size));
28 }
29 
get_one_msg(struct ring_buffer * ring_buf,void * msg)30 int get_one_msg(struct ring_buffer *ring_buf, void *msg)
31 {
32     off_t p_off = ring_buf->producer_offset;
33     off_t c_off = ring_buf->consumer_offset;
34 
35     /* recycle_msg_buffer is empty */
36     if (p_off == c_off)
37         return MSG_OP_FAILURE;
38     vaddr_t buf = (vaddr_t)ring_buf + c_off;
39     memcpy(msg, (void *)buf, ring_buf->msg_size);
40     ring_buf->consumer_offset = next_slot(ring_buf, c_off);
41     return MSG_OP_SUCCESS;
42 }
43 
44 /*
45  * Whether ring buffer is full
46  * Always keep a slot empty
47  * Max capicity = buffer_size - msg_size
48  * p_off = c_off                : buffer empty
49  * c_off = next_slot(p_off)     : buffer full
50  */
if_buffer_full(struct ring_buffer * ring_buf)51 int if_buffer_full(struct ring_buffer *ring_buf)
52 {
53     off_t p_off = ring_buf->producer_offset;
54     off_t c_off = ring_buf->consumer_offset;
55 
56     /* recycle_msg_buffer is full */
57     if (c_off == next_slot(ring_buf, p_off))
58         return RING_BUFFER_FULL;
59 
60     return RING_BUFFER_NOT_FULL;
61 }
62 
set_one_msg(struct ring_buffer * ring_buf,void * msg)63 int set_one_msg(struct ring_buffer *ring_buf, void *msg)
64 {
65     if (if_buffer_full(ring_buf)) {
66         return MSG_OP_FAILURE;
67     }
68 
69     off_t p_off = ring_buf->producer_offset;
70     vaddr_t buf = (vaddr_t)ring_buf + p_off;
71 
72     memcpy((void *)buf, msg, ring_buf->msg_size);
73     ring_buf->producer_offset = next_slot(ring_buf, p_off);
74     return MSG_OP_SUCCESS;
75 }
76 
new_ringbuffer(int msg_num,size_t msg_size)77 struct ring_buffer *new_ringbuffer(int msg_num, size_t msg_size)
78 {
79     size_t buffer_size = msg_num * msg_size + sizeof(struct ring_buffer);
80     int page_num = ROUND_UP(buffer_size, 0x1000);
81     struct ring_buffer *ring_buf =
82         (struct ring_buffer *)mmap(NULL,
83                                    page_num * 0x1000,
84                                    PROT_READ | PROT_WRITE,
85                                    MAP_ANONYMOUS | MAP_PRIVATE,
86                                    -1,
87                                    0);
88     // struct ring_buffer *ring_buf = (struct ring_buffer
89     // *)malloc(buffer_size);
90     if (ring_buf == 0)
91         return NULL;
92     memset(ring_buf, 0, buffer_size);
93     ring_buf->msg_size = msg_size;
94     ring_buf->buffer_size = buffer_size;
95     ring_buf->producer_offset = (off_t)sizeof(struct ring_buffer);
96     ring_buf->consumer_offset = (off_t)sizeof(struct ring_buffer);
97     return ring_buf;
98 }
99 
free_ringbuffer(struct ring_buffer * ring_buf)100 void free_ringbuffer(struct ring_buffer *ring_buf)
101 {
102     int page_num = ROUND_UP(ring_buf->buffer_size, 0x1000);
103     munmap(ring_buf, page_num * 0x1000);
104 }