direct-io.hg

view tools/python/xen/lowlevel/xu/xu.c @ 2714:77fbe6c094f2

bitkeeper revision 1.1159.1.261 (41792d94c9Ck-m72kpZkL5_a2aSoZA)

Merge freefall.cl.cam.ac.uk:/auto/groups/xeno/users/cl349/BK/xeno.bk-26dom0
into freefall.cl.cam.ac.uk:/local/scratch/cl349/xeno.bk-24dom0
author cl349@freefall.cl.cam.ac.uk
date Fri Oct 22 15:56:04 2004 +0000 (2004-10-22)
parents 081dd58e4d58 06527e1d6757
children 057ea964561d
line source
1 /******************************************************************************
2 * utils.c
3 *
4 * Copyright (c) 2004, K A Fraser
5 */
7 #include <Python.h>
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include <sys/ioctl.h>
12 #include <sys/types.h>
13 #include <sys/wait.h>
14 #include <sys/stat.h>
15 #include <sys/socket.h>
16 #include <sys/mman.h>
17 #include <sys/poll.h>
18 #include <sys/sysmacros.h>
19 #include <netinet/in.h>
20 #include <fcntl.h>
21 #include <unistd.h>
22 #include <errno.h>
23 #include <signal.h>
24 #include <xc.h>
26 #include <hypervisor-if.h>
27 #include <io/domain_controller.h>
29 #include <asm-xen/proc_cmd.h>
31 #define XENPKG "xen.lowlevel.xu"
33 /* Needed for Python versions earlier than 2.3. */
34 #ifndef PyMODINIT_FUNC
35 #define PyMODINIT_FUNC DL_EXPORT(void)
36 #endif
38 /* NB. The following should be kept in sync with the kernel's evtchn driver. */
39 #define EVTCHN_DEV_NAME "/dev/xen/evtchn"
40 #define EVTCHN_DEV_MAJOR 10
41 #define EVTCHN_DEV_MINOR 201
42 /* /dev/xen/evtchn ioctls: */
43 /* EVTCHN_RESET: Clear and reinit the event buffer. Clear error condition. */
44 #define EVTCHN_RESET _IO('E', 1)
45 /* EVTCHN_BIND: Bind to teh specified event-channel port. */
46 #define EVTCHN_BIND _IO('E', 2)
47 /* EVTCHN_UNBIND: Unbind from the specified event-channel port. */
48 #define EVTCHN_UNBIND _IO('E', 3)
50 /* Size of a machine page frame. */
51 #define PAGE_SIZE 4096
53 #if defined(__i386__)
54 #define rmb() __asm__ __volatile__ ( "lock; addl $0,0(%%esp)" : : : "memory" )
55 #define wmb() __asm__ __volatile__ ( "" : : : "memory" )
56 #else
57 #error "Define barriers"
58 #endif
61 /* Set the close-on-exec flag on a file descriptor. Doesn't currently bother
62 * to check for errors. */
63 static void set_cloexec(int fd)
64 {
65 int flags = fcntl(fd, F_GETFD, 0);
67 if ( flags < 0 )
68 return;
70 flags |= FD_CLOEXEC;
71 fcntl(fd, F_SETFD, flags);
72 }
74 /*
75 * *********************** NOTIFIER ***********************
76 */
78 typedef struct {
79 PyObject_HEAD;
80 int evtchn_fd;
81 } xu_notifier_object;
83 static PyObject *xu_notifier_read(PyObject *self, PyObject *args)
84 {
85 xu_notifier_object *xun = (xu_notifier_object *)self;
86 u16 v;
87 int bytes;
89 if ( !PyArg_ParseTuple(args, "") )
90 return NULL;
92 while ( (bytes = read(xun->evtchn_fd, &v, sizeof(v))) == -1 )
93 {
94 if ( errno == EINTR )
95 continue;
96 if ( errno == EAGAIN )
97 goto none;
98 return PyErr_SetFromErrno(PyExc_IOError);
99 }
101 if ( bytes == sizeof(v) )
102 return PyInt_FromLong(v);
104 none:
105 Py_INCREF(Py_None);
106 return Py_None;
107 }
109 static PyObject *xu_notifier_unmask(PyObject *self, PyObject *args)
110 {
111 xu_notifier_object *xun = (xu_notifier_object *)self;
112 u16 v;
113 int idx;
115 if ( !PyArg_ParseTuple(args, "i", &idx) )
116 return NULL;
118 v = (u16)idx;
120 (void)write(xun->evtchn_fd, &v, sizeof(v));
122 Py_INCREF(Py_None);
123 return Py_None;
124 }
126 static PyObject *xu_notifier_bind(PyObject *self, PyObject *args)
127 {
128 xu_notifier_object *xun = (xu_notifier_object *)self;
129 int idx;
131 if ( !PyArg_ParseTuple(args, "i", &idx) )
132 return NULL;
134 if ( ioctl(xun->evtchn_fd, EVTCHN_BIND, idx) != 0 )
135 return PyErr_SetFromErrno(PyExc_IOError);
137 Py_INCREF(Py_None);
138 return Py_None;
139 }
141 static PyObject *xu_notifier_unbind(PyObject *self, PyObject *args)
142 {
143 xu_notifier_object *xun = (xu_notifier_object *)self;
144 int idx;
146 if ( !PyArg_ParseTuple(args, "i", &idx) )
147 return NULL;
149 if ( ioctl(xun->evtchn_fd, EVTCHN_UNBIND, idx) != 0 )
150 return PyErr_SetFromErrno(PyExc_IOError);
152 Py_INCREF(Py_None);
153 return Py_None;
154 }
156 static PyObject *xu_notifier_fileno(PyObject *self, PyObject *args)
157 {
158 xu_notifier_object *xun = (xu_notifier_object *)self;
159 return PyInt_FromLong(xun->evtchn_fd);
160 }
162 static PyMethodDef xu_notifier_methods[] = {
163 { "read",
164 (PyCFunction)xu_notifier_read,
165 METH_VARARGS,
166 "Read a @port with pending notifications.\n" },
168 { "unmask",
169 (PyCFunction)xu_notifier_unmask,
170 METH_VARARGS,
171 "Unmask notifications for a @port.\n" },
173 { "bind",
174 (PyCFunction)xu_notifier_bind,
175 METH_VARARGS,
176 "Get notifications for a @port.\n" },
178 { "unbind",
179 (PyCFunction)xu_notifier_unbind,
180 METH_VARARGS,
181 "No longer get notifications for a @port.\n" },
183 { "fileno",
184 (PyCFunction)xu_notifier_fileno,
185 METH_VARARGS,
186 "Return the file descriptor for the notification channel.\n" },
188 { NULL, NULL, 0, NULL }
189 };
191 staticforward PyTypeObject xu_notifier_type;
193 static PyObject *xu_notifier_new(PyObject *self, PyObject *args)
194 {
195 xu_notifier_object *xun;
196 struct stat st;
198 if ( !PyArg_ParseTuple(args, "") )
199 return NULL;
201 xun = PyObject_New(xu_notifier_object, &xu_notifier_type);
203 /* Make sure any existing device file links to correct device. */
204 if ( (lstat(EVTCHN_DEV_NAME, &st) != 0) ||
205 !S_ISCHR(st.st_mode) ||
206 (st.st_rdev != makedev(EVTCHN_DEV_MAJOR, EVTCHN_DEV_MINOR)) )
207 (void)unlink(EVTCHN_DEV_NAME);
209 reopen:
210 xun->evtchn_fd = open(EVTCHN_DEV_NAME, O_NONBLOCK|O_RDWR);
211 if ( xun->evtchn_fd == -1 )
212 {
213 if ( (errno == ENOENT) &&
214 ((mkdir("/dev/xen", 0755) == 0) || (errno == EEXIST)) &&
215 (mknod(EVTCHN_DEV_NAME, S_IFCHR|0600,
216 makedev(EVTCHN_DEV_MAJOR,EVTCHN_DEV_MINOR)) == 0) )
217 goto reopen;
218 PyObject_Del((PyObject *)xun);
219 return PyErr_SetFromErrno(PyExc_IOError);
220 }
221 set_cloexec(xun->evtchn_fd);
223 return (PyObject *)xun;
224 }
226 static PyObject *xu_notifier_getattr(PyObject *obj, char *name)
227 {
228 return Py_FindMethod(xu_notifier_methods, obj, name);
229 }
231 static void xu_notifier_dealloc(PyObject *self)
232 {
233 xu_notifier_object *xun = (xu_notifier_object *)self;
234 (void)close(xun->evtchn_fd);
235 PyObject_Del(self);
236 }
238 static PyTypeObject xu_notifier_type = {
239 PyObject_HEAD_INIT(&PyType_Type)
240 0,
241 "notifier",
242 sizeof(xu_notifier_object),
243 0,
244 xu_notifier_dealloc, /* tp_dealloc */
245 NULL, /* tp_print */
246 xu_notifier_getattr, /* tp_getattr */
247 NULL, /* tp_setattr */
248 NULL, /* tp_compare */
249 NULL, /* tp_repr */
250 NULL, /* tp_as_number */
251 NULL, /* tp_as_sequence */
252 NULL, /* tp_as_mapping */
253 NULL /* tp_hash */
254 };
258 /*
259 * *********************** MESSAGE ***********************
260 */
262 #define TYPE(_x,_y) (((_x)<<8)|(_y))
263 #define P2C(_struct, _field, _ctype) \
264 do { \
265 PyObject *obj; \
266 if ( (obj = PyDict_GetItemString(payload, #_field)) != NULL ) \
267 { \
268 if ( PyInt_Check(obj) ) \
269 { \
270 ((_struct *)&xum->msg.msg[0])->_field = \
271 (_ctype)PyInt_AsLong(obj); \
272 dict_items_parsed++; \
273 } \
274 else if ( PyLong_Check(obj) ) \
275 { \
276 ((_struct *)&xum->msg.msg[0])->_field = \
277 (_ctype)PyLong_AsUnsignedLongLong(obj); \
278 dict_items_parsed++; \
279 } \
280 } \
281 xum->msg.length = sizeof(_struct); \
282 } while ( 0 )
283 #define C2P(_struct, _field, _pytype, _ctype) \
284 do { \
285 PyObject *obj = Py ## _pytype ## _From ## _ctype \
286 (((_struct *)&xum->msg.msg[0])->_field); \
287 if ( dict == NULL ) dict = PyDict_New(); \
288 PyDict_SetItemString(dict, #_field, obj); \
289 } while ( 0 )
291 typedef struct {
292 PyObject_HEAD;
293 control_msg_t msg;
294 } xu_message_object;
296 static PyObject *xu_message_append_payload(PyObject *self, PyObject *args)
297 {
298 xu_message_object *xum = (xu_message_object *)self;
299 char *str;
300 int len;
302 if ( !PyArg_ParseTuple(args, "s#", &str, &len) )
303 return NULL;
305 if ( (len + xum->msg.length) > sizeof(xum->msg.msg) )
306 {
307 PyErr_SetString(PyExc_RuntimeError, "out of space in control message");
308 return NULL;
309 }
311 memcpy(&xum->msg.msg[xum->msg.length], str, len);
312 xum->msg.length += len;
314 Py_INCREF(Py_None);
315 return Py_None;
316 }
318 static PyObject *xu_message_set_response_fields(PyObject *self, PyObject *args)
319 {
320 xu_message_object *xum = (xu_message_object *)self;
321 PyObject *payload;
322 int dict_items_parsed = 0;
324 if ( !PyArg_ParseTuple(args, "O", &payload) )
325 return NULL;
327 if ( !PyDict_Check(payload) )
328 {
329 PyErr_SetString(PyExc_TypeError, "payload is not a dictionary");
330 return NULL;
331 }
333 switch ( TYPE(xum->msg.type, xum->msg.subtype) )
334 {
335 case TYPE(CMSG_BLKIF_FE, CMSG_BLKIF_FE_DRIVER_STATUS):
336 P2C(blkif_fe_driver_status_t, max_handle, u32);
337 break;
338 case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_DRIVER_STATUS):
339 P2C(netif_fe_driver_status_t, max_handle, u32);
340 break;
341 }
343 if ( dict_items_parsed != PyDict_Size(payload) )
344 {
345 PyErr_SetString(PyExc_TypeError, "payload contains bad items");
346 return NULL;
347 }
349 Py_INCREF(Py_None);
350 return Py_None;
351 }
353 static PyObject *xu_message_get_payload(PyObject *self, PyObject *args)
354 {
355 xu_message_object *xum = (xu_message_object *)self;
356 PyObject *dict = NULL;
358 if ( !PyArg_ParseTuple(args, "") )
359 return NULL;
361 switch ( TYPE(xum->msg.type, xum->msg.subtype) )
362 {
363 case TYPE(CMSG_BLKIF_FE, CMSG_BLKIF_FE_INTERFACE_STATUS):
364 C2P(blkif_fe_interface_status_t, handle, Int, Long);
365 C2P(blkif_fe_interface_status_t, status, Int, Long);
366 C2P(blkif_fe_interface_status_t, evtchn, Int, Long);
367 return dict;
368 case TYPE(CMSG_BLKIF_FE, CMSG_BLKIF_FE_DRIVER_STATUS):
369 C2P(blkif_fe_driver_status_t, status, Int, Long);
370 return dict;
371 case TYPE(CMSG_BLKIF_FE, CMSG_BLKIF_FE_INTERFACE_CONNECT):
372 C2P(blkif_fe_interface_connect_t, handle, Int, Long);
373 C2P(blkif_fe_interface_connect_t, shmem_frame, Int, Long);
374 return dict;
375 case TYPE(CMSG_BLKIF_FE, CMSG_BLKIF_FE_INTERFACE_DISCONNECT):
376 C2P(blkif_fe_interface_disconnect_t, handle, Int, Long);
377 return dict;
378 case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_CREATE):
379 C2P(blkif_be_create_t, domid, Int, Long);
380 C2P(blkif_be_create_t, blkif_handle, Int, Long);
381 C2P(blkif_be_create_t, status, Int, Long);
382 return dict;
383 case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_DESTROY):
384 C2P(blkif_be_destroy_t, domid, Int, Long);
385 C2P(blkif_be_destroy_t, blkif_handle, Int, Long);
386 C2P(blkif_be_destroy_t, status, Int, Long);
387 return dict;
388 case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_CONNECT):
389 C2P(blkif_be_connect_t, domid, Int, Long);
390 C2P(blkif_be_connect_t, blkif_handle, Int, Long);
391 C2P(blkif_be_connect_t, shmem_frame, Int, Long);
392 C2P(blkif_be_connect_t, evtchn, Int, Long);
393 C2P(blkif_be_connect_t, status, Int, Long);
394 return dict;
395 case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_DISCONNECT):
396 C2P(blkif_be_disconnect_t, domid, Int, Long);
397 C2P(blkif_be_disconnect_t, blkif_handle, Int, Long);
398 C2P(blkif_be_disconnect_t, status, Int, Long);
399 return dict;
400 case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_CREATE):
401 C2P(blkif_be_vbd_create_t, domid, Int, Long);
402 C2P(blkif_be_vbd_create_t, blkif_handle, Int, Long);
403 C2P(blkif_be_vbd_create_t, vdevice, Int, Long);
404 C2P(blkif_be_vbd_create_t, readonly, Int, Long);
405 C2P(blkif_be_vbd_create_t, status, Int, Long);
406 return dict;
407 case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_DESTROY):
408 C2P(blkif_be_vbd_destroy_t, domid, Int, Long);
409 C2P(blkif_be_vbd_destroy_t, blkif_handle, Int, Long);
410 C2P(blkif_be_vbd_destroy_t, vdevice, Int, Long);
411 C2P(blkif_be_vbd_destroy_t, status, Int, Long);
412 return dict;
413 case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_GROW):
414 C2P(blkif_be_vbd_grow_t, domid, Int, Long);
415 C2P(blkif_be_vbd_grow_t, blkif_handle, Int, Long);
416 C2P(blkif_be_vbd_grow_t, vdevice, Int, Long);
417 C2P(blkif_be_vbd_grow_t, extent.sector_start,
418 Long, UnsignedLongLong);
419 C2P(blkif_be_vbd_grow_t, extent.sector_length,
420 Long, UnsignedLongLong);
421 C2P(blkif_be_vbd_grow_t, extent.device, Int, Long);
422 C2P(blkif_be_vbd_grow_t, status, Int, Long);
423 return dict;
424 case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_SHRINK):
425 C2P(blkif_be_vbd_shrink_t, domid, Int, Long);
426 C2P(blkif_be_vbd_shrink_t, blkif_handle, Int, Long);
427 C2P(blkif_be_vbd_shrink_t, vdevice, Int, Long);
428 C2P(blkif_be_vbd_shrink_t, status, Int, Long);
429 return dict;
430 case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_DRIVER_STATUS):
431 C2P(blkif_be_driver_status_t, status, Int, Long);
432 return dict;
433 case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_INTERFACE_STATUS):
434 C2P(netif_fe_interface_status_t, handle, Int, Long);
435 C2P(netif_fe_interface_status_t, status, Int, Long);
436 C2P(netif_fe_interface_status_t, evtchn, Int, Long);
437 C2P(netif_fe_interface_status_t, mac[0], Int, Long);
438 C2P(netif_fe_interface_status_t, mac[1], Int, Long);
439 C2P(netif_fe_interface_status_t, mac[2], Int, Long);
440 C2P(netif_fe_interface_status_t, mac[3], Int, Long);
441 C2P(netif_fe_interface_status_t, mac[4], Int, Long);
442 C2P(netif_fe_interface_status_t, mac[5], Int, Long);
443 return dict;
444 case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_DRIVER_STATUS):
445 C2P(netif_fe_driver_status_t, status, Int, Long);
446 C2P(netif_fe_driver_status_t, max_handle, Int, Long);
447 return dict;
448 case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_INTERFACE_CONNECT):
449 C2P(netif_fe_interface_connect_t, handle, Int, Long);
450 C2P(netif_fe_interface_connect_t, tx_shmem_frame, Int, Long);
451 C2P(netif_fe_interface_connect_t, rx_shmem_frame, Int, Long);
452 return dict;
453 case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_INTERFACE_DISCONNECT):
454 C2P(netif_fe_interface_disconnect_t, handle, Int, Long);
455 return dict;
456 case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_CREATE):
457 C2P(netif_be_create_t, domid, Int, Long);
458 C2P(netif_be_create_t, netif_handle, Int, Long);
459 C2P(netif_be_create_t, status, Int, Long);
460 return dict;
461 case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_DESTROY):
462 C2P(netif_be_destroy_t, domid, Int, Long);
463 C2P(netif_be_destroy_t, netif_handle, Int, Long);
464 C2P(netif_be_destroy_t, status, Int, Long);
465 return dict;
466 case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_CONNECT):
467 C2P(netif_be_connect_t, domid, Int, Long);
468 C2P(netif_be_connect_t, netif_handle, Int, Long);
469 C2P(netif_be_connect_t, tx_shmem_frame, Int, Long);
470 C2P(netif_be_connect_t, rx_shmem_frame, Int, Long);
471 C2P(netif_be_connect_t, evtchn, Int, Long);
472 C2P(netif_be_connect_t, status, Int, Long);
473 return dict;
474 case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_DISCONNECT):
475 C2P(netif_be_disconnect_t, domid, Int, Long);
476 C2P(netif_be_disconnect_t, netif_handle, Int, Long);
477 C2P(netif_be_disconnect_t, status, Int, Long);
478 return dict;
479 case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_DRIVER_STATUS):
480 C2P(netif_be_driver_status_t, status, Int, Long);
481 return dict;
482 case TYPE(CMSG_MEM_REQUEST, CMSG_MEM_REQUEST_SET):
483 C2P(mem_request_t, target, Int, Long);
484 C2P(mem_request_t, status, Int, Long);
485 return dict;
486 }
488 return PyString_FromStringAndSize(xum->msg.msg, xum->msg.length);
489 }
491 static PyObject *xu_message_get_header(PyObject *self, PyObject *args)
492 {
493 xu_message_object *xum = (xu_message_object *)self;
495 if ( !PyArg_ParseTuple(args, "") )
496 return NULL;
498 return Py_BuildValue("{s:i,s:i,s:i}",
499 "type", xum->msg.type,
500 "subtype", xum->msg.subtype,
501 "id", xum->msg.id);
502 }
504 static PyMethodDef xu_message_methods[] = {
505 { "append_payload",
506 (PyCFunction)xu_message_append_payload,
507 METH_VARARGS,
508 "Append @str to the message payload.\n" },
510 { "set_response_fields",
511 (PyCFunction)xu_message_set_response_fields,
512 METH_VARARGS,
513 "Fill in the response fields in a message that was passed to us.\n" },
515 { "get_payload",
516 (PyCFunction)xu_message_get_payload,
517 METH_VARARGS,
518 "Return the message payload in string form.\n" },
520 { "get_header",
521 (PyCFunction)xu_message_get_header,
522 METH_VARARGS,
523 "Returns a dictionary of values for @type, @subtype, and @id.\n" },
525 { NULL, NULL, 0, NULL }
526 };
528 staticforward PyTypeObject xu_message_type;
530 static PyObject *xu_message_new(PyObject *self, PyObject *args)
531 {
532 xu_message_object *xum;
533 int type, subtype, id, dict_items_parsed = 0;
534 PyObject *payload = NULL;
536 if ( !PyArg_ParseTuple(args, "iii|O", &type, &subtype, &id, &payload) )
537 return NULL;
539 xum = PyObject_New(xu_message_object, &xu_message_type);
541 xum->msg.type = type;
542 xum->msg.subtype = subtype;
543 xum->msg.id = id;
544 xum->msg.length = 0;
546 if ( payload == NULL )
547 return (PyObject *)xum;
549 if ( !PyDict_Check(payload) )
550 {
551 PyErr_SetString(PyExc_TypeError, "payload is not a dictionary");
552 PyObject_Del((PyObject *)xum);
553 return NULL;
554 }
556 switch ( TYPE(type, subtype) )
557 {
558 case TYPE(CMSG_BLKIF_FE, CMSG_BLKIF_FE_INTERFACE_STATUS):
559 P2C(blkif_fe_interface_status_t, handle, u32);
560 P2C(blkif_fe_interface_status_t, status, u32);
561 P2C(blkif_fe_interface_status_t, evtchn, u16);
562 P2C(blkif_fe_interface_status_t, domid, u16);
563 break;
564 case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_CREATE):
565 P2C(blkif_be_create_t, domid, u32);
566 P2C(blkif_be_create_t, blkif_handle, u32);
567 break;
568 case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_DESTROY):
569 P2C(blkif_be_destroy_t, domid, u32);
570 P2C(blkif_be_destroy_t, blkif_handle, u32);
571 break;
572 case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_CONNECT):
573 P2C(blkif_be_connect_t, domid, u32);
574 P2C(blkif_be_connect_t, blkif_handle, u32);
575 P2C(blkif_be_connect_t, shmem_frame, memory_t);
576 P2C(blkif_be_connect_t, evtchn, u16);
577 break;
578 case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_DISCONNECT):
579 P2C(blkif_be_disconnect_t, domid, u32);
580 P2C(blkif_be_disconnect_t, blkif_handle, u32);
581 break;
582 case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_CREATE):
583 P2C(blkif_be_vbd_create_t, domid, u32);
584 P2C(blkif_be_vbd_create_t, blkif_handle, u32);
585 P2C(blkif_be_vbd_create_t, vdevice, blkif_vdev_t);
586 P2C(blkif_be_vbd_create_t, readonly, u16);
587 break;
588 case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_DESTROY):
589 P2C(blkif_be_vbd_destroy_t, domid, u32);
590 P2C(blkif_be_vbd_destroy_t, blkif_handle, u32);
591 P2C(blkif_be_vbd_destroy_t, vdevice, blkif_vdev_t);
592 break;
593 case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_GROW):
594 P2C(blkif_be_vbd_grow_t, domid, u32);
595 P2C(blkif_be_vbd_grow_t, blkif_handle, u32);
596 P2C(blkif_be_vbd_grow_t, vdevice, blkif_vdev_t);
597 P2C(blkif_be_vbd_grow_t, extent.sector_start, blkif_sector_t);
598 P2C(blkif_be_vbd_grow_t, extent.sector_length, blkif_sector_t);
599 P2C(blkif_be_vbd_grow_t, extent.device, blkif_pdev_t);
600 break;
601 case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_SHRINK):
602 P2C(blkif_be_vbd_shrink_t, domid, u32);
603 P2C(blkif_be_vbd_shrink_t, blkif_handle, u32);
604 P2C(blkif_be_vbd_shrink_t, vdevice, blkif_vdev_t);
605 break;
606 case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_INTERFACE_STATUS):
607 P2C(netif_fe_interface_status_t, handle, u32);
608 P2C(netif_fe_interface_status_t, status, u32);
609 P2C(netif_fe_interface_status_t, evtchn, u16);
610 P2C(netif_fe_interface_status_t, domid, u16);
611 P2C(netif_fe_interface_status_t, mac[0], u8);
612 P2C(netif_fe_interface_status_t, mac[1], u8);
613 P2C(netif_fe_interface_status_t, mac[2], u8);
614 P2C(netif_fe_interface_status_t, mac[3], u8);
615 P2C(netif_fe_interface_status_t, mac[4], u8);
616 P2C(netif_fe_interface_status_t, mac[5], u8);
617 break;
618 case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_CREATE):
619 P2C(netif_be_create_t, domid, u32);
620 P2C(netif_be_create_t, netif_handle, u32);
621 P2C(netif_be_create_t, mac[0], u8);
622 P2C(netif_be_create_t, mac[1], u8);
623 P2C(netif_be_create_t, mac[2], u8);
624 P2C(netif_be_create_t, mac[3], u8);
625 P2C(netif_be_create_t, mac[4], u8);
626 P2C(netif_be_create_t, mac[5], u8);
627 break;
628 case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_DESTROY):
629 P2C(netif_be_destroy_t, domid, u32);
630 P2C(netif_be_destroy_t, netif_handle, u32);
631 break;
632 case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_CONNECT):
633 P2C(netif_be_connect_t, domid, u32);
634 P2C(netif_be_connect_t, netif_handle, u32);
635 P2C(netif_be_connect_t, tx_shmem_frame, memory_t);
636 P2C(netif_be_connect_t, rx_shmem_frame, memory_t);
637 P2C(netif_be_connect_t, evtchn, u16);
638 break;
639 case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_DISCONNECT):
640 P2C(netif_be_disconnect_t, domid, u32);
641 P2C(netif_be_disconnect_t, netif_handle, u32);
642 break;
643 case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_DRIVER_STATUS):
644 P2C(netif_fe_driver_status_t, status, u32);
645 P2C(netif_fe_driver_status_t, max_handle, u32);
646 break;
647 case TYPE(CMSG_MEM_REQUEST, CMSG_MEM_REQUEST_SET):
648 P2C(mem_request_t, target, u32);
649 P2C(mem_request_t, status, u32);
650 break;
651 }
653 if ( dict_items_parsed != PyDict_Size(payload) )
654 {
655 PyErr_SetString(PyExc_TypeError, "payload contains bad items");
656 PyObject_Del((PyObject *)xum);
657 return NULL;
658 }
660 return (PyObject *)xum;
661 }
663 static PyObject *xu_message_getattr(PyObject *obj, char *name)
664 {
665 xu_message_object *xum;
666 if ( strcmp(name, "MAX_PAYLOAD") == 0 )
667 return PyInt_FromLong(sizeof(xum->msg.msg));
668 return Py_FindMethod(xu_message_methods, obj, name);
669 }
671 static void xu_message_dealloc(PyObject *self)
672 {
673 PyObject_Del(self);
674 }
676 static PyTypeObject xu_message_type = {
677 PyObject_HEAD_INIT(&PyType_Type)
678 0,
679 "message",
680 sizeof(xu_message_object),
681 0,
682 xu_message_dealloc, /* tp_dealloc */
683 NULL, /* tp_print */
684 xu_message_getattr, /* tp_getattr */
685 NULL, /* tp_setattr */
686 NULL, /* tp_compare */
687 NULL, /* tp_repr */
688 NULL, /* tp_as_number */
689 NULL, /* tp_as_sequence */
690 NULL, /* tp_as_mapping */
691 NULL /* tp_hash */
692 };
696 /*
697 * *********************** PORT ***********************
698 */
700 static control_if_t *map_control_interface(int fd, unsigned long pfn,
701 u32 dom)
702 {
703 char *vaddr = xc_map_foreign_range( fd, dom, PAGE_SIZE,
704 PROT_READ|PROT_WRITE, pfn );
705 if ( vaddr == NULL )
706 return NULL;
707 return (control_if_t *)(vaddr + 2048);
708 }
709 static void unmap_control_interface(int fd, control_if_t *c)
710 {
711 char *vaddr = (char *)c - 2048;
712 (void)munmap(vaddr, PAGE_SIZE);
713 }
715 typedef struct xu_port_object {
716 PyObject_HEAD;
717 int xc_handle;
718 int connected;
719 u32 remote_dom;
720 int local_port, remote_port;
721 control_if_t *interface;
722 CONTROL_RING_IDX tx_req_cons, tx_resp_prod;
723 CONTROL_RING_IDX rx_req_prod, rx_resp_cons;
724 } xu_port_object;
726 static PyObject *port_error;
728 static PyObject *xu_port_notify(PyObject *self, PyObject *args)
729 {
730 xu_port_object *xup = (xu_port_object *)self;
732 if ( !PyArg_ParseTuple(args, "") )
733 return NULL;
735 (void)xc_evtchn_send(xup->xc_handle, xup->local_port);
737 Py_INCREF(Py_None);
738 return Py_None;
739 }
741 static PyObject *xu_port_read_request(PyObject *self, PyObject *args)
742 {
743 xu_port_object *xup = (xu_port_object *)self;
744 xu_message_object *xum;
745 CONTROL_RING_IDX c = xup->tx_req_cons;
746 control_if_t *cif = xup->interface;
747 control_msg_t *cmsg;
749 if ( !PyArg_ParseTuple(args, "") )
750 return NULL;
752 if ( (c == cif->tx_req_prod) ||
753 ((c - xup->tx_resp_prod) == CONTROL_RING_SIZE) )
754 {
755 PyErr_SetString(port_error, "no request to read");
756 return NULL;
757 }
759 /* Need to ensure we see the request, despite seeing the index update.*/
760 rmb();
762 cmsg = &cif->tx_ring[MASK_CONTROL_IDX(c)];
763 xum = PyObject_New(xu_message_object, &xu_message_type);
764 memcpy(&xum->msg, cmsg, sizeof(*cmsg));
765 if ( xum->msg.length > sizeof(xum->msg.msg) )
766 xum->msg.length = sizeof(xum->msg.msg);
767 xup->tx_req_cons++;
768 return (PyObject *)xum;
769 }
771 static PyObject *xu_port_write_request(PyObject *self, PyObject *args)
772 {
773 xu_port_object *xup = (xu_port_object *)self;
774 xu_message_object *xum;
775 CONTROL_RING_IDX p = xup->rx_req_prod;
776 control_if_t *cif = xup->interface;
777 control_msg_t *cmsg;
779 if ( !PyArg_ParseTuple(args, "O", (PyObject **)&xum) )
780 return NULL;
782 if ( !PyObject_TypeCheck((PyObject *)xum, &xu_message_type) )
783 {
784 PyErr_SetString(PyExc_TypeError, "expected a " XENPKG ".message");
785 return NULL;
786 }
788 if ( ((p - xup->rx_resp_cons) == CONTROL_RING_SIZE) )
789 {
790 PyErr_SetString(port_error, "no space to write request");
791 return NULL;
792 }
794 cmsg = &cif->rx_ring[MASK_CONTROL_IDX(p)];
795 memcpy(cmsg, &xum->msg, sizeof(*cmsg));
797 wmb();
798 xup->rx_req_prod = cif->rx_req_prod = p + 1;
800 Py_INCREF(Py_None);
801 return Py_None;
802 }
804 static PyObject *xu_port_read_response(PyObject *self, PyObject *args)
805 {
806 xu_port_object *xup = (xu_port_object *)self;
807 xu_message_object *xum;
808 CONTROL_RING_IDX c = xup->rx_resp_cons;
809 control_if_t *cif = xup->interface;
810 control_msg_t *cmsg;
812 if ( !PyArg_ParseTuple(args, "") )
813 return NULL;
815 if ( (c == cif->rx_resp_prod) || (c == xup->rx_req_prod) )
816 {
817 PyErr_SetString(port_error, "no response to read");
818 return NULL;
819 }
821 /* Need to ensure we see the response, despite seeing the index update.*/
822 rmb();
824 cmsg = &cif->rx_ring[MASK_CONTROL_IDX(c)];
825 xum = PyObject_New(xu_message_object, &xu_message_type);
826 memcpy(&xum->msg, cmsg, sizeof(*cmsg));
827 if ( xum->msg.length > sizeof(xum->msg.msg) )
828 xum->msg.length = sizeof(xum->msg.msg);
829 xup->rx_resp_cons++;
830 return (PyObject *)xum;
831 }
833 static PyObject *xu_port_write_response(PyObject *self, PyObject *args)
834 {
835 xu_port_object *xup = (xu_port_object *)self;
836 xu_message_object *xum;
837 CONTROL_RING_IDX p = xup->tx_resp_prod;
838 control_if_t *cif = xup->interface;
839 control_msg_t *cmsg;
841 if ( !PyArg_ParseTuple(args, "O", (PyObject **)&xum) )
842 return NULL;
844 if ( !PyObject_TypeCheck((PyObject *)xum, &xu_message_type) )
845 {
846 PyErr_SetString(PyExc_TypeError, "expected a " XENPKG ".message");
847 return NULL;
848 }
850 if ( p == xup->tx_req_cons )
851 {
852 PyErr_SetString(port_error, "no space to write response");
853 return NULL;
854 }
856 cmsg = &cif->tx_ring[MASK_CONTROL_IDX(p)];
857 memcpy(cmsg, &xum->msg, sizeof(*cmsg));
859 wmb();
860 xup->tx_resp_prod = cif->tx_resp_prod = p + 1;
862 Py_INCREF(Py_None);
863 return Py_None;
864 }
866 static PyObject *xu_port_request_to_read(PyObject *self, PyObject *args)
867 {
868 xu_port_object *xup = (xu_port_object *)self;
869 CONTROL_RING_IDX c = xup->tx_req_cons;
870 control_if_t *cif = xup->interface;
872 if ( !PyArg_ParseTuple(args, "") )
873 return NULL;
875 if ( (c == cif->tx_req_prod) ||
876 ((c - xup->tx_resp_prod) == CONTROL_RING_SIZE) )
877 return PyInt_FromLong(0);
879 return PyInt_FromLong(1);
880 }
882 static PyObject *xu_port_space_to_write_request(PyObject *self, PyObject *args)
883 {
884 xu_port_object *xup = (xu_port_object *)self;
885 CONTROL_RING_IDX p = xup->rx_req_prod;
887 if ( !PyArg_ParseTuple(args, "") )
888 return NULL;
890 if ( ((p - xup->rx_resp_cons) == CONTROL_RING_SIZE) )
891 return PyInt_FromLong(0);
893 return PyInt_FromLong(1);
894 }
896 static PyObject *xu_port_response_to_read(PyObject *self, PyObject *args)
897 {
898 xu_port_object *xup = (xu_port_object *)self;
899 CONTROL_RING_IDX c = xup->rx_resp_cons;
900 control_if_t *cif = xup->interface;
902 if ( !PyArg_ParseTuple(args, "") )
903 return NULL;
905 if ( (c == cif->rx_resp_prod) || (c == xup->rx_req_prod) )
906 return PyInt_FromLong(0);
908 return PyInt_FromLong(1);
909 }
911 static PyObject *xu_port_space_to_write_response(
912 PyObject *self, PyObject *args)
913 {
914 xu_port_object *xup = (xu_port_object *)self;
915 CONTROL_RING_IDX p = xup->tx_resp_prod;
917 if ( !PyArg_ParseTuple(args, "") )
918 return NULL;
920 if ( p == xup->tx_req_cons )
921 return PyInt_FromLong(0);
923 return PyInt_FromLong(1);
924 }
926 static int __xu_port_connect(xu_port_object *xup)
927 {
928 xc_dominfo_t info;
930 if ( xup->connected )
931 {
932 return 0;
933 }
935 if ( (xc_domain_getinfo(xup->xc_handle, xup->remote_dom, 1, &info) != 1) ||
936 (info.domid != xup->remote_dom) )
937 {
938 PyErr_SetString(port_error, "Failed to obtain domain status");
939 return -1;
940 }
942 xup->interface =
943 map_control_interface(xup->xc_handle, info.shared_info_frame,
944 xup->remote_dom);
946 if ( xup->interface == NULL )
947 {
948 PyErr_SetString(port_error, "Failed to map domain control interface");
949 return -1;
950 }
952 /* Synchronise ring indexes. */
953 xup->tx_resp_prod = xup->interface->tx_resp_prod;
954 xup->tx_req_cons = xup->interface->tx_resp_prod;
955 xup->rx_req_prod = xup->interface->rx_req_prod;
956 xup->rx_resp_cons = xup->interface->rx_resp_prod;
958 xup->connected = 1;
960 return 0;
961 }
963 static void __xu_port_disconnect(xu_port_object *xup)
964 {
965 if ( xup->connected )
966 unmap_control_interface(xup->xc_handle, xup->interface);
967 xup->connected = 0;
968 }
970 static PyObject *xu_port_connect(PyObject *self, PyObject *args)
971 {
972 xu_port_object *xup = (xu_port_object *)self;
974 if ( !PyArg_ParseTuple(args, "") )
975 return NULL;
977 if ( __xu_port_connect(xup) != 0 )
978 return NULL;
980 Py_INCREF(Py_None);
981 return Py_None;
982 }
984 static PyObject *xu_port_disconnect(PyObject *self, PyObject *args)
985 {
986 xu_port_object *xup = (xu_port_object *)self;
988 if ( !PyArg_ParseTuple(args, "") )
989 return NULL;
991 __xu_port_disconnect(xup);
993 Py_INCREF(Py_None);
994 return Py_None;
995 }
997 static PyMethodDef xu_port_methods[] = {
998 { "notify",
999 (PyCFunction)xu_port_notify,
1000 METH_VARARGS,
1001 "Send a notification to the remote end.\n" },
1003 { "read_request",
1004 (PyCFunction)xu_port_read_request,
1005 METH_VARARGS,
1006 "Read a request message from the control interface.\n" },
1008 { "write_request",
1009 (PyCFunction)xu_port_write_request,
1010 METH_VARARGS,
1011 "Write a request message to the control interface.\n" },
1013 { "read_response",
1014 (PyCFunction)xu_port_read_response,
1015 METH_VARARGS,
1016 "Read a response message from the control interface.\n" },
1018 { "write_response",
1019 (PyCFunction)xu_port_write_response,
1020 METH_VARARGS,
1021 "Write a response message to the control interface.\n" },
1023 { "request_to_read",
1024 (PyCFunction)xu_port_request_to_read,
1025 METH_VARARGS,
1026 "Returns TRUE if there is a request message to read.\n" },
1028 { "space_to_write_request",
1029 (PyCFunction)xu_port_space_to_write_request,
1030 METH_VARARGS,
1031 "Returns TRUE if there is space to write a request message.\n" },
1033 { "response_to_read",
1034 (PyCFunction)xu_port_response_to_read,
1035 METH_VARARGS,
1036 "Returns TRUE if there is a response message to read.\n" },
1038 { "space_to_write_response",
1039 (PyCFunction)xu_port_space_to_write_response,
1040 METH_VARARGS,
1041 "Returns TRUE if there is space to write a response message.\n" },
1043 { "connect",
1044 (PyCFunction)xu_port_connect,
1045 METH_VARARGS,
1046 "Synchronously connect to remote domain.\n" },
1048 { "disconnect",
1049 (PyCFunction)xu_port_disconnect,
1050 METH_VARARGS,
1051 "Synchronously disconnect from remote domain.\n" },
1053 { NULL, NULL, 0, NULL }
1054 };
1056 staticforward PyTypeObject xu_port_type;
1058 static PyObject *xu_port_new(PyObject *self, PyObject *args)
1060 xu_port_object *xup;
1061 u32 dom;
1062 int port1 = 0, port2 = 0;
1064 if ( !PyArg_ParseTuple(args, "i", &dom) )
1065 return NULL;
1067 xup = PyObject_New(xu_port_object, &xu_port_type);
1069 xup->connected = 0;
1070 xup->remote_dom = dom;
1072 if ( (xup->xc_handle = xc_interface_open()) == -1 )
1074 PyErr_SetString(port_error, "Could not open Xen control interface");
1075 goto fail1;
1078 if ( dom == 0 )
1080 /*
1081 * The control-interface event channel for DOM0 is already set up.
1082 * We use an ioctl to discover the port at our end of the channel.
1083 */
1084 port1 = ioctl(xup->xc_handle, IOCTL_PRIVCMD_INITDOMAIN_EVTCHN, NULL);
1085 port2 = -1; /* We don't need the remote end of the DOM0 link. */
1086 if ( port1 < 0 )
1088 PyErr_SetString(port_error, "Could not open channel to DOM0");
1089 goto fail2;
1092 else if ( xc_evtchn_bind_interdomain(xup->xc_handle,
1093 DOMID_SELF, dom,
1094 &port1, &port2) != 0 )
1096 PyErr_SetString(port_error, "Could not open channel to domain");
1097 goto fail2;
1100 xup->local_port = port1;
1101 xup->remote_port = port2;
1103 if ( __xu_port_connect(xup) != 0 )
1104 goto fail3;
1106 return (PyObject *)xup;
1108 fail3:
1109 if ( dom != 0 )
1110 (void)xc_evtchn_close(xup->xc_handle, DOMID_SELF, port1);
1111 fail2:
1112 (void)xc_interface_close(xup->xc_handle);
1113 fail1:
1114 PyObject_Del((PyObject *)xup);
1115 return NULL;
1118 static PyObject *xu_port_getattr(PyObject *obj, char *name)
1120 xu_port_object *xup = (xu_port_object *)obj;
1121 if ( strcmp(name, "local_port") == 0 )
1122 return PyInt_FromLong(xup->local_port);
1123 if ( strcmp(name, "remote_port") == 0 )
1124 return PyInt_FromLong(xup->remote_port);
1125 if ( strcmp(name, "remote_dom") == 0 )
1126 return PyInt_FromLong(xup->remote_dom);
1127 return Py_FindMethod(xu_port_methods, obj, name);
1130 static void xu_port_dealloc(PyObject *self)
1132 xu_port_object *xup = (xu_port_object *)self;
1133 __xu_port_disconnect(xup);
1134 if ( xup->remote_dom != 0 )
1135 (void)xc_evtchn_close(xup->xc_handle, DOMID_SELF, xup->local_port);
1136 (void)xc_interface_close(xup->xc_handle);
1137 PyObject_Del(self);
1140 static PyTypeObject xu_port_type = {
1141 PyObject_HEAD_INIT(&PyType_Type)
1142 0,
1143 "port",
1144 sizeof(xu_port_object),
1145 0,
1146 xu_port_dealloc, /* tp_dealloc */
1147 NULL, /* tp_print */
1148 xu_port_getattr, /* tp_getattr */
1149 NULL, /* tp_setattr */
1150 NULL, /* tp_compare */
1151 NULL, /* tp_repr */
1152 NULL, /* tp_as_number */
1153 NULL, /* tp_as_sequence */
1154 NULL, /* tp_as_mapping */
1155 NULL /* tp_hash */
1156 };
1160 /*
1161 * *********************** BUFFER ***********************
1162 */
1164 #define BUFSZ 65536
1165 #define MASK_BUF_IDX(_i) ((_i)&(BUFSZ-1))
1166 typedef unsigned int BUF_IDX;
1168 typedef struct {
1169 PyObject_HEAD;
1170 char *buf;
1171 unsigned int prod, cons;
1172 } xu_buffer_object;
1174 static PyObject *__xu_buffer_peek(xu_buffer_object *xub, int max)
1176 PyObject *str1, *str2;
1177 int len1, len2, c = MASK_BUF_IDX(xub->cons);
1179 len1 = xub->prod - xub->cons;
1180 if ( len1 > (BUFSZ - c) ) /* clip to ring wrap */
1181 len1 = BUFSZ - c;
1182 if ( len1 > max ) /* clip to specified maximum */
1183 len1 = max;
1184 if ( len1 < 0 ) /* sanity */
1185 len1 = 0;
1187 if ( (str1 = PyString_FromStringAndSize(&xub->buf[c], len1)) == NULL )
1188 return NULL;
1190 if ( (len1 < (xub->prod - xub->cons)) && (len1 < max) )
1192 len2 = max - len1;
1193 if ( len2 > MASK_BUF_IDX(xub->prod) )
1194 len2 = MASK_BUF_IDX(xub->prod);
1195 if ( len2 > 0 )
1197 str2 = PyString_FromStringAndSize(&xub->buf[0], len2);
1198 if ( str2 == NULL )
1199 return NULL;
1200 PyString_ConcatAndDel(&str1, str2);
1201 if ( str1 == NULL )
1202 return NULL;
1206 return str1;
1209 static PyObject *xu_buffer_peek(PyObject *self, PyObject *args)
1211 xu_buffer_object *xub = (xu_buffer_object *)self;
1212 int max = 1024;
1214 if ( !PyArg_ParseTuple(args, "|i", &max) )
1215 return NULL;
1217 return __xu_buffer_peek(xub, max);
1220 static PyObject *xu_buffer_read(PyObject *self, PyObject *args)
1222 xu_buffer_object *xub = (xu_buffer_object *)self;
1223 PyObject *str;
1224 int max = 1024;
1226 if ( !PyArg_ParseTuple(args, "|i", &max) )
1227 return NULL;
1229 if ( (str = __xu_buffer_peek(xub, max)) != NULL )
1230 xub->cons += PyString_Size(str);
1232 return str;
1235 static PyObject *xu_buffer_discard(PyObject *self, PyObject *args)
1237 xu_buffer_object *xub = (xu_buffer_object *)self;
1238 int max, len;
1240 if ( !PyArg_ParseTuple(args, "i", &max) )
1241 return NULL;
1243 len = xub->prod - xub->cons;
1244 if ( len > max )
1245 len = max;
1246 if ( len < 0 )
1247 len = 0;
1249 xub->cons += len;
1251 return PyInt_FromLong(len);
1254 static PyObject *xu_buffer_write(PyObject *self, PyObject *args)
1256 xu_buffer_object *xub = (xu_buffer_object *)self;
1257 char *str;
1258 int len, len1, len2;
1260 if ( !PyArg_ParseTuple(args, "s#", &str, &len) )
1261 return NULL;
1263 len1 = len;
1264 if ( len1 > (BUFSZ - MASK_BUF_IDX(xub->prod)) )
1265 len1 = BUFSZ - MASK_BUF_IDX(xub->prod);
1266 if ( len1 > (BUFSZ - (xub->prod - xub->cons)) )
1267 len1 = BUFSZ - (xub->prod - xub->cons);
1269 if ( len1 == 0 )
1270 return PyInt_FromLong(0);
1272 memcpy(&xub->buf[MASK_BUF_IDX(xub->prod)], &str[0], len1);
1273 xub->prod += len1;
1275 if ( len1 < len )
1277 len2 = len - len1;
1278 if ( len2 > (BUFSZ - MASK_BUF_IDX(xub->prod)) )
1279 len2 = BUFSZ - MASK_BUF_IDX(xub->prod);
1280 if ( len2 > (BUFSZ - (xub->prod - xub->cons)) )
1281 len2 = BUFSZ - (xub->prod - xub->cons);
1282 if ( len2 != 0 )
1284 memcpy(&xub->buf[MASK_BUF_IDX(xub->prod)], &str[len1], len2);
1285 xub->prod += len2;
1286 return PyInt_FromLong(len1 + len2);
1290 return PyInt_FromLong(len1);
1293 static PyObject *xu_buffer_empty(PyObject *self, PyObject *args)
1295 xu_buffer_object *xub = (xu_buffer_object *)self;
1297 if ( !PyArg_ParseTuple(args, "") )
1298 return NULL;
1300 if ( xub->cons == xub->prod )
1301 return PyInt_FromLong(1);
1303 return PyInt_FromLong(0);
1306 static PyObject *xu_buffer_full(PyObject *self, PyObject *args)
1308 xu_buffer_object *xub = (xu_buffer_object *)self;
1310 if ( !PyArg_ParseTuple(args, "") )
1311 return NULL;
1313 if ( (xub->prod - xub->cons) == BUFSZ )
1314 return PyInt_FromLong(1);
1316 return PyInt_FromLong(0);
1319 static PyMethodDef xu_buffer_methods[] = {
1320 { "peek",
1321 (PyCFunction)xu_buffer_peek,
1322 METH_VARARGS,
1323 "Peek up to @max bytes from the buffer. Returns a string.\n" },
1325 { "read",
1326 (PyCFunction)xu_buffer_read,
1327 METH_VARARGS,
1328 "Read up to @max bytes from the buffer. Returns a string.\n" },
1330 { "discard",
1331 (PyCFunction)xu_buffer_discard,
1332 METH_VARARGS,
1333 "Discard up to @max bytes from the buffer. Returns number of bytes.\n" },
1335 { "write",
1336 (PyCFunction)xu_buffer_write,
1337 METH_VARARGS,
1338 "Write @string into buffer. Return number of bytes written.\n" },
1340 { "empty",
1341 (PyCFunction)xu_buffer_empty,
1342 METH_VARARGS,
1343 "Return TRUE if the buffer is empty.\n" },
1345 { "full",
1346 (PyCFunction)xu_buffer_full,
1347 METH_VARARGS,
1348 "Return TRUE if the buffer is full.\n" },
1350 { NULL, NULL, 0, NULL }
1351 };
1353 staticforward PyTypeObject xu_buffer_type;
1355 static PyObject *xu_buffer_new(PyObject *self, PyObject *args)
1357 xu_buffer_object *xub;
1359 if ( !PyArg_ParseTuple(args, "") )
1360 return NULL;
1362 xub = PyObject_New(xu_buffer_object, &xu_buffer_type);
1364 if ( (xub->buf = malloc(BUFSZ)) == NULL )
1366 PyObject_Del((PyObject *)xub);
1367 return NULL;
1370 xub->prod = xub->cons = 0;
1372 return (PyObject *)xub;
1375 static PyObject *xu_buffer_getattr(PyObject *obj, char *name)
1377 return Py_FindMethod(xu_buffer_methods, obj, name);
1380 static void xu_buffer_dealloc(PyObject *self)
1382 xu_buffer_object *xub = (xu_buffer_object *)self;
1383 free(xub->buf);
1384 PyObject_Del(self);
1387 static PyTypeObject xu_buffer_type = {
1388 PyObject_HEAD_INIT(&PyType_Type)
1389 0,
1390 "buffer",
1391 sizeof(xu_buffer_object),
1392 0,
1393 xu_buffer_dealloc, /* tp_dealloc */
1394 NULL, /* tp_print */
1395 xu_buffer_getattr, /* tp_getattr */
1396 NULL, /* tp_setattr */
1397 NULL, /* tp_compare */
1398 NULL, /* tp_repr */
1399 NULL, /* tp_as_number */
1400 NULL, /* tp_as_sequence */
1401 NULL, /* tp_as_mapping */
1402 NULL /* tp_hash */
1403 };
1407 /*
1408 * *********************** MODULE WRAPPER ***********************
1409 */
1411 static void handle_child_death(int dummy)
1413 while ( waitpid(-1, NULL, WNOHANG) > 0 )
1414 continue;
1417 static PyObject *xu_autoreap(PyObject *self, PyObject *args)
1419 struct sigaction sa;
1421 if ( !PyArg_ParseTuple(args, "") )
1422 return NULL;
1424 memset(&sa, 0, sizeof(sa));
1425 sa.sa_handler = handle_child_death;
1426 sigemptyset(&sa.sa_mask);
1427 sa.sa_flags = SA_NOCLDSTOP | SA_RESTART;
1428 (void)sigaction(SIGCHLD, &sa, NULL);
1430 Py_INCREF(Py_None);
1431 return Py_None;
1434 static PyMethodDef xu_methods[] = {
1435 { "notifier", xu_notifier_new, METH_VARARGS,
1436 "Create a new notifier." },
1437 { "message", xu_message_new, METH_VARARGS,
1438 "Create a new communications message." },
1439 { "port", xu_port_new, METH_VARARGS,
1440 "Create a new communications port." },
1441 { "buffer", xu_buffer_new, METH_VARARGS,
1442 "Create a new ring buffer." },
1443 { "autoreap", xu_autoreap, METH_VARARGS,
1444 "Ensure that zombie children are automatically reaped by the OS." },
1445 { NULL, NULL, 0, NULL }
1446 };
1448 PyMODINIT_FUNC initxu(void)
1450 PyObject *m, *d;
1452 m = Py_InitModule(XENPKG, xu_methods);
1454 d = PyModule_GetDict(m);
1455 port_error = PyErr_NewException(XENPKG ".PortError", NULL, NULL);
1456 PyDict_SetItemString(d, "PortError", port_error);
1458 /* KAF: This ensures that we get debug output in a timely manner. */
1459 setbuf(stdout, NULL);
1460 setbuf(stderr, NULL);