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.


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