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.


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