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.


Context-based output infrastructure (V3_Print, etc) and modifications to use it
[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
25
26 void NO_INST v3_init_ringbuf(struct v3_ringbuf * ring, uint_t size) {
27     ring->buf = V3_Malloc(size);
28
29     if (!(ring->buf)) {
30         PrintError(VM_NONE, VCORE_NONE, "Cannot init a ring buffer\n");
31         return;
32     }
33
34     ring->size = size;
35   
36     ring->start = 0;
37     ring->end = 0;
38     ring->current_len = 0;
39 }
40
41 NO_INST 
42 struct v3_ringbuf * v3_create_ringbuf(uint_t size) {
43     struct v3_ringbuf * ring = (struct v3_ringbuf *)V3_Malloc(sizeof(struct v3_ringbuf));
44
45     if (!ring) {
46         PrintError(VM_NONE, VCORE_NONE, "Cannot allocate a ring buffer\n");
47         return NULL;
48     }
49
50     v3_init_ringbuf(ring, size);
51
52     return ring;
53 }
54
55 NO_INST 
56 void v3_free_ringbuf(struct v3_ringbuf * ring) {
57     V3_Free(ring->buf);
58     V3_Free(ring);
59 }
60
61
62 NO_INST 
63 static inline uchar_t * get_read_ptr(struct v3_ringbuf * ring) {
64     return (uchar_t *)(ring->buf + ring->start);
65 }
66
67 NO_INST 
68 static inline uchar_t * get_write_ptr(struct v3_ringbuf * ring) {
69     return (uchar_t *)(ring->buf + ring->end);
70 }
71
72 NO_INST 
73 static inline int get_read_section_size(struct v3_ringbuf * ring) {
74     return ring->size - ring->start;
75 }
76
77 NO_INST 
78 static inline int get_write_section_size(struct v3_ringbuf * ring) {
79     return ring->size - ring->end;
80 }
81
82 NO_INST 
83 static inline int is_read_loop(struct v3_ringbuf * ring, uint_t len) {
84     if ((ring->start >= ring->end) && (ring->current_len > 0)) {
85         // end is past the end of the buffer
86         if (get_read_section_size(ring) < len) {
87             return 1;
88         }
89     }
90     return 0;
91 }
92
93 NO_INST 
94 static inline int is_write_loop(struct v3_ringbuf * ring, uint_t len) {
95     if ((ring->end >= ring->start) && (ring->current_len < ring->size)) {
96         // end is past the end of the buffer
97         if (get_write_section_size(ring) < len) {
98             return 1;
99         }
100     }
101     return 0;
102 }
103
104 NO_INST 
105 int v3_ringbuf_avail_space(struct v3_ringbuf * ring) {
106     return ring->size - ring->current_len;
107 }
108
109 NO_INST 
110 int v3_ringbuf_data_len(struct v3_ringbuf * ring) {
111     return ring->current_len;
112 }
113
114 NO_INST 
115 int v3_ringbuf_capacity(struct v3_ringbuf * ring) {
116     return ring->size;
117 }
118
119 NO_INST 
120 int v3_ringbuf_read(struct v3_ringbuf * ring, uchar_t * dst, uint_t len) {
121     int read_len = 0;
122     int ring_data_len = ring->current_len;
123
124     read_len = (len > ring_data_len) ? ring_data_len : len;
125
126     if (is_read_loop(ring, read_len)) {
127         int section_len = get_read_section_size(ring);
128
129         memcpy(dst, get_read_ptr(ring), section_len);
130         memcpy(dst + section_len, ring->buf, read_len - section_len);
131     
132         ring->start = read_len - section_len;
133     } else {
134         memcpy(dst, get_read_ptr(ring), read_len);
135     
136         ring->start += read_len;
137     }
138
139     ring->current_len -= read_len;
140
141     return read_len;
142 }
143
144
145 NO_INST 
146 int v3_ringbuf_peek(struct v3_ringbuf * ring, uchar_t * dst, uint_t len) {
147     int read_len = 0;
148     int ring_data_len = ring->current_len;
149
150     read_len = (len > ring_data_len) ? ring_data_len : len;
151
152     if (is_read_loop(ring, read_len)) {
153         int section_len = get_read_section_size(ring);
154
155         memcpy(dst, get_read_ptr(ring), section_len);
156         memcpy(dst + section_len, ring->buf, read_len - section_len);
157     } else {
158         memcpy(dst, get_read_ptr(ring), read_len);
159     }
160
161     return read_len;
162 }
163
164
165 NO_INST 
166 int v3_ringbuf_delete(struct v3_ringbuf * ring, uint_t len) {
167     int del_len = 0;
168     int ring_data_len = ring->current_len;
169
170     del_len = (len > ring_data_len) ? ring_data_len : len;
171
172     if (is_read_loop(ring, del_len)) {
173         int section_len = get_read_section_size(ring);
174         ring->start = del_len - section_len;
175     } else {
176         ring->start += del_len;
177     }
178
179     ring->current_len -= del_len;
180     return del_len;
181 }
182
183
184 NO_INST 
185 int v3_ringbuf_write(struct v3_ringbuf * ring, uchar_t * src, uint_t len) {
186     int write_len = 0;
187     int ring_avail_space = ring->size - ring->current_len;
188   
189     write_len = (len > ring_avail_space) ? ring_avail_space : len;
190
191
192     if (is_write_loop(ring, write_len)) {
193         int section_len = get_write_section_size(ring);
194
195         //  PrintDebug(info->vm_info, info, "Write loop: write_ptr=%p, src=%p, sec_len=%d\n", 
196         //             (void *)get_write_ptr(ring),(void*)src, section_len);
197     
198         memcpy(get_write_ptr(ring), src, section_len);
199         ring->end = 0;
200
201         memcpy(get_write_ptr(ring), src + section_len, write_len - section_len);
202
203         ring->end += write_len - section_len;
204     } else {
205         //    PrintDebug(info->vm_info, info, "Writing: write_ptr=%p, src=%p, write_len=%d\n", 
206         //             (void *)get_write_ptr(ring),(void*)src, write_len);
207
208         memcpy(get_write_ptr(ring), src, write_len);
209
210         ring->end += write_len;
211     }
212
213     ring->current_len += write_len;
214
215     return write_len;
216 }
217
218
219 NO_INST 
220 void v3_print_ringbuf(struct v3_ringbuf * ring) {
221     int ctr = 0;
222   
223     for (ctr = 0; ctr < ring->current_len; ctr++) {
224         int index = (ctr + ring->start) % ring->size;
225
226         PrintDebug(VM_NONE, VCORE_NONE, "Entry %d (index=%d): %c\n", ctr, index, ring->buf[index]);
227     }
228 }