Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


Avoid strict-aliasing related issues when compiling with optimization
[palacios.git] / linux_module / util-ringbuffer.c
1 /*\r
2  * Ringbuffer implementation\r
3  * (c) Lei Xia  2010\r
4  */\r
5  \r
6 \r
7 #include <linux/errno.h>\r
8 #include <linux/percpu.h>\r
9 #include <linux/sched.h>\r
10 \r
11 #include "palacios.h"\r
12 #include "util-ringbuffer.h"\r
13 \r
14 void init_ringbuf(struct ringbuf * ring, unsigned int size) {\r
15     ring->buf = palacios_alloc(size);\r
16 \r
17     if (!(ring->buf)) { \r
18         ERROR("Cannot allocate ring buffer data\n");\r
19         size=0;\r
20     }\r
21 \r
22     ring->size = size;\r
23   \r
24     ring->start = 0;\r
25     ring->end = 0;\r
26     ring->current_len = 0;\r
27 }\r
28 \r
29 struct ringbuf * create_ringbuf(unsigned int size) {\r
30     struct ringbuf * ring = (struct ringbuf *)palacios_alloc(sizeof(struct ringbuf));\r
31 \r
32     if (!ring) { \r
33         ERROR("Cannot allocate ring buffer\n");\r
34         return NULL;\r
35     }\r
36 \r
37     init_ringbuf(ring, size);\r
38 \r
39     return ring;\r
40 }\r
41 \r
42 void free_ringbuf(struct ringbuf * ring) {\r
43     palacios_free(ring->buf);\r
44     palacios_free(ring);\r
45 }\r
46 \r
47 static inline unsigned char * get_read_ptr(struct ringbuf * ring) {\r
48     return (unsigned char *)(ring->buf + ring->start);\r
49 }\r
50 \r
51 \r
52 static inline unsigned char * get_write_ptr(struct ringbuf * ring) {\r
53     return (unsigned char *)(ring->buf + ring->end);\r
54 }\r
55 \r
56 static inline int get_read_section_size(struct ringbuf * ring) {\r
57     return ring->size - ring->start;\r
58 }\r
59 \r
60 \r
61 static inline int get_write_section_size(struct ringbuf * ring) {\r
62     return ring->size - ring->end;\r
63 }\r
64 \r
65 \r
66 static inline int is_read_loop(struct ringbuf * ring, unsigned int len) {\r
67     if ((ring->start >= ring->end) && (ring->current_len > 0)) {\r
68         // end is past the end of the buffer\r
69         if (get_read_section_size(ring) < len) {\r
70             return 1;\r
71         }\r
72     }\r
73     return 0;\r
74 }\r
75 \r
76 \r
77 static inline int is_write_loop(struct ringbuf * ring, unsigned int len) {\r
78     if ((ring->end >= ring->start) && (ring->current_len < ring->size)) {\r
79         // end is past the end of the buffer\r
80         if (get_write_section_size(ring) < len) {\r
81             return 1;\r
82         }\r
83     }\r
84     return 0;\r
85 }\r
86 \r
87 \r
88 static inline int ringbuf_avail_space(struct ringbuf * ring) {\r
89     return ring->size - ring->current_len;\r
90 }\r
91 \r
92 \r
93 int ringbuf_data_len(struct ringbuf * ring) {\r
94     return ring->current_len;\r
95 }\r
96 \r
97 \r
98 static inline int ringbuf_capacity(struct ringbuf * ring) {\r
99     return ring->size;\r
100 }\r
101 \r
102 \r
103 int ringbuf_read(struct ringbuf * ring, unsigned char * dst, unsigned int len) {\r
104     int read_len = 0;\r
105     int ring_data_len = ring->current_len;\r
106 \r
107     read_len = (len > ring_data_len) ? ring_data_len : len;\r
108 \r
109     if (is_read_loop(ring, read_len)) {\r
110         int section_len = get_read_section_size(ring);\r
111 \r
112         memcpy(dst, get_read_ptr(ring), section_len);\r
113         memcpy(dst + section_len, ring->buf, read_len - section_len);\r
114     \r
115         ring->start = read_len - section_len;\r
116     } else {\r
117         memcpy(dst, get_read_ptr(ring), read_len);\r
118     \r
119         ring->start += read_len;\r
120     }\r
121 \r
122     ring->current_len -= read_len;\r
123 \r
124     return read_len;\r
125 }\r
126 \r
127 \r
128 #if 0\r
129 \r
130 static int ringbuf_peek(struct ringbuf * ring, unsigned char * dst, unsigned int len) {\r
131     int read_len = 0;\r
132     int ring_data_len = ring->current_len;\r
133 \r
134     read_len = (len > ring_data_len) ? ring_data_len : len;\r
135 \r
136     if (is_read_loop(ring, read_len)) {\r
137         int section_len = get_read_section_size(ring);\r
138 \r
139         memcpy(dst, get_read_ptr(ring), section_len);\r
140         memcpy(dst + section_len, ring->buf, read_len - section_len);\r
141     } else {\r
142         memcpy(dst, get_read_ptr(ring), read_len);\r
143     }\r
144 \r
145     return read_len;\r
146 }\r
147 \r
148 \r
149 static int ringbuf_delete(struct ringbuf * ring, unsigned int len) {\r
150     int del_len = 0;\r
151     int ring_data_len = ring->current_len;\r
152 \r
153     del_len = (len > ring_data_len) ? ring_data_len : len;\r
154 \r
155     if (is_read_loop(ring, del_len)) {\r
156         int section_len = get_read_section_size(ring);\r
157         ring->start = del_len - section_len;\r
158     } else {\r
159         ring->start += del_len;\r
160     }\r
161 \r
162     ring->current_len -= del_len;\r
163     return del_len;\r
164 }\r
165 #endif\r
166 \r
167 int ringbuf_write(struct ringbuf * ring, unsigned char * src, unsigned int len) {\r
168     int write_len = 0;\r
169     int ring_avail_space = ring->size - ring->current_len;\r
170   \r
171     write_len = (len > ring_avail_space) ? ring_avail_space : len;\r
172 \r
173     if (is_write_loop(ring, write_len)) {\r
174         int section_len = get_write_section_size(ring);\r
175     \r
176         memcpy(get_write_ptr(ring), src, section_len);\r
177         ring->end = 0;\r
178 \r
179         memcpy(get_write_ptr(ring), src + section_len, write_len - section_len);\r
180 \r
181         ring->end += write_len - section_len;\r
182     } else {\r
183         memcpy(get_write_ptr(ring), src, write_len);\r
184 \r
185         ring->end += write_len;\r
186     }\r
187 \r
188     ring->current_len += write_len;\r
189 \r
190     return write_len;\r
191 }\r
192 \r