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.


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