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.


bbde62882984374ec678bb3da318541f17664a06
[palacios.git] / palacios / src / palacios / vmm_ringbuffer.c
1 /*
2  * This file is part of the Palacios Virtual Machine Monitor developed
3  * by the V3VEE Project with funding from the United States National 
4  * Science Foundation and the Department of Energy.  
5  *
6  * The V3VEE Project is a joint project between Northwestern University
7  * and the University of New Mexico.  You can find out more at 
8  * http://www.v3vee.org
9  *
10  * Copyright (c) 2008, Jack Lange <jarusl@cs.northwestern.edu> 
11  * Copyright (c) 2008, The V3VEE Project <http://www.v3vee.org> 
12  * All rights reserved.
13  *
14  * Author: Jack Lange <jarusl@cs.northwestern.edu>
15  *
16  * This is free software.  You are permitted to use,
17  * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
18  */
19
20 #include <palacios/vmm_ringbuffer.h>
21 #include <palacios/vmm.h>
22
23
24 void v3_init_ringbuf(struct v3_ringbuf * ring, uint_t size) {
25   ring->buf = V3_Malloc(size);
26   ring->size = size;
27   
28   ring->start = 0;
29   ring->end = 0;
30   ring->current_len = 0;
31 }
32
33
34 struct v3_ringbuf * v3_create_ringbuf(uint_t size) {
35   struct v3_ringbuf * ring = (struct v3_ringbuf *)V3_Malloc(sizeof(struct v3_ringbuf));
36
37   v3_init_ringbuf(ring, size);
38
39   return ring;
40 }
41
42 void v3_free_ringbuf(struct v3_ringbuf * ring) {
43   V3_Free(ring->buf);
44   V3_Free(ring);
45 }
46
47
48
49
50
51 static inline uchar_t * get_read_ptr(struct v3_ringbuf * ring) {
52   return (uchar_t *)(ring->buf + ring->start);
53 }
54
55 static inline uchar_t * get_write_ptr(struct v3_ringbuf * ring) {
56   return (uchar_t *)(ring->buf + ring->end);
57 }
58
59
60 static inline int get_read_section_size(struct v3_ringbuf * ring) {
61   return ring->size - ring->start;
62 }
63
64 static inline int get_write_section_size(struct v3_ringbuf * ring) {
65   return ring->size - ring->end;
66 }
67
68 static inline int is_read_loop(struct v3_ringbuf * ring, uint_t len) {
69   if ((ring->start >= ring->end) && (ring->current_len > 0)) {
70     // end is past the end of the buffer
71     if (get_read_section_size(ring) < len) {
72       return 1;
73     }
74   }
75   return 0;
76 }
77
78
79 static inline int is_write_loop(struct v3_ringbuf * ring, uint_t len) {
80   if ((ring->end >= ring->start) && (ring->current_len < ring->size)) {
81     // end is past the end of the buffer
82     if (get_write_section_size(ring) < len) {
83       return 1;
84     }
85   }
86   return 0;
87 }
88
89
90 int v3_ringbuf_data_len(struct v3_ringbuf * ring) {
91   return ring->current_len;
92 }
93
94 int v3_ringbuf_capacity(struct v3_ringbuf * ring) {
95   return ring->size;
96 }
97
98 int v3_ringbuf_read(struct v3_ringbuf * ring, uchar_t * dst, uint_t len) {
99   int read_len = 0;
100   int ring_data_len = ring->current_len;
101
102   read_len = (len > ring_data_len) ? ring_data_len : len;
103
104   if (is_read_loop(ring, read_len)) {
105     int section_len = get_read_section_size(ring);
106
107     memcpy(dst, get_read_ptr(ring), section_len);
108     memcpy(dst + section_len, ring->buf, read_len - section_len);
109     
110     ring->start = read_len - section_len;
111   } else {
112     memcpy(dst, get_read_ptr(ring), read_len);
113     
114     ring->start += read_len;
115   }
116
117   ring->current_len -= read_len;
118
119   return read_len;
120 }
121
122
123
124
125 int v3_ringbuf_peek(struct v3_ringbuf * ring, uchar_t * dst, uint_t len) {
126   int read_len = 0;
127   int ring_data_len = ring->current_len;
128
129   read_len = (len > ring_data_len) ? ring_data_len : len;
130
131   if (is_read_loop(ring, read_len)) {
132     int section_len = get_read_section_size(ring);
133
134     memcpy(dst, get_read_ptr(ring), section_len);
135     memcpy(dst + section_len, ring->buf, read_len - section_len);
136   } else {
137     memcpy(dst, get_read_ptr(ring), read_len);
138   }
139
140   return read_len;
141 }
142
143
144 int v3_ringbuf_delete(struct v3_ringbuf * ring, uint_t len) {
145   int del_len = 0;
146   int ring_data_len = ring->current_len;
147
148   del_len = (len > ring_data_len) ? ring_data_len : len;
149
150   if (is_read_loop(ring, del_len)) {
151     int section_len = get_read_section_size(ring);
152     ring->start = del_len - section_len;
153   } else {
154     ring->start += del_len;
155   }
156
157   ring->current_len -= del_len;
158   return del_len;
159 }
160
161
162 int v3_ringbuf_write(struct v3_ringbuf * ring, uchar_t * src, uint_t len) {
163   int write_len = 0;
164   int ring_avail_space = ring->size - ring->current_len;
165   
166   write_len = (len > ring_avail_space) ? ring_avail_space : len;
167
168
169   if (is_write_loop(ring, write_len)) {
170     int section_len = get_write_section_size(ring);
171     
172     memcpy(get_write_ptr(ring), src, section_len);
173     ring->end = 0;
174
175     memcpy(get_write_ptr(ring), src + section_len, write_len - section_len);
176
177     ring->end += write_len - section_len;
178   } else {
179     memcpy(get_write_ptr(ring), src, write_len);
180
181     ring->end += write_len;
182   }
183
184   ring->current_len += write_len;
185
186   return write_len;
187 }
188
189
190 void v3_print_ringbuf(struct v3_ringbuf * ring) {
191   int ctr = 0;
192   
193   for (ctr = 0; ctr < ring->current_len; ctr++) {
194     int index = (ctr + ring->start) % ring->size;
195
196     PrintDebug("Entry %d (index=%d): %c\n", ctr, index, ring->buf[index]);
197   }
198 }