direct-io.hg

view tools/python/xen/lowlevel/xu/xu.c @ 2821:724449a888fe

bitkeeper revision 1.1159.1.332 (41874e954CLIDA2J3phVFD2RnzVTpA)

Clean up public XenLinux header files. Now accessible from userspace as
#include <xen/linux...>
Got rid of the linux-xen-sparse symlink as it's no longer needed.
author kaf24@freefall.cl.cam.ac.uk
date Tue Nov 02 09:08:37 2004 +0000 (2004-11-02)
parents 3f929065a1d1
children 8a60d9e79b3c aeaa8b6b072d
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 <xen/xen.h>
27 #include <xen/io/domain_controller.h>
28 #include <xen/linux/privcmd.h>
30 #define XENPKG "xen.lowlevel.xu"
32 /* Needed for Python versions earlier than 2.3. */
33 #ifndef PyMODINIT_FUNC
34 #define PyMODINIT_FUNC DL_EXPORT(void)
35 #endif
37 /* NB. The following should be kept in sync with the kernel's evtchn driver. */
38 #define EVTCHN_DEV_NAME "/dev/xen/evtchn"
39 #define EVTCHN_DEV_MAJOR 10
40 #define EVTCHN_DEV_MINOR 201
41 /* /dev/xen/evtchn ioctls: */
42 /* EVTCHN_RESET: Clear and reinit the event buffer. Clear error condition. */
43 #define EVTCHN_RESET _IO('E', 1)
44 /* EVTCHN_BIND: Bind to teh specified event-channel port. */
45 #define EVTCHN_BIND _IO('E', 2)
46 /* EVTCHN_UNBIND: Unbind from the specified event-channel port. */
47 #define EVTCHN_UNBIND _IO('E', 3)
49 /* Size of a machine page frame. */
50 #define PAGE_SIZE 4096
52 #if defined(__i386__)
53 #define rmb() __asm__ __volatile__ ( "lock; addl $0,0(%%esp)" : : : "memory" )
54 #define wmb() __asm__ __volatile__ ( "" : : : "memory" )
55 #else
56 #error "Define barriers"
57 #endif
60 /* Set the close-on-exec flag on a file descriptor. Doesn't currently bother
61 * to check for errors. */
62 static void set_cloexec(int fd)
63 {
64 int flags = fcntl(fd, F_GETFD, 0);
66 if ( flags < 0 )
67 return;
69 flags |= FD_CLOEXEC;
70 fcntl(fd, F_SETFD, flags);
71 }
73 /*
74 * *********************** NOTIFIER ***********************
75 */
77 typedef struct {
78 PyObject_HEAD;
79 int evtchn_fd;
80 } xu_notifier_object;
82 static PyObject *xu_notifier_read(PyObject *self, PyObject *args)
83 {
84 xu_notifier_object *xun = (xu_notifier_object *)self;
85 u16 v;
86 int bytes;
88 if ( !PyArg_ParseTuple(args, "") )
89 return NULL;
91 while ( (bytes = read(xun->evtchn_fd, &v, sizeof(v))) == -1 )
92 {
93 if ( errno == EINTR )
94 continue;
95 if ( errno == EAGAIN )
96 goto none;
97 return PyErr_SetFromErrno(PyExc_IOError);
98 }
100 if ( bytes == sizeof(v) )
101 return PyInt_FromLong(v);
103 none:
104 Py_INCREF(Py_None);
105 return Py_None;
106 }
108 static PyObject *xu_notifier_unmask(PyObject *self, PyObject *args)
109 {
110 xu_notifier_object *xun = (xu_notifier_object *)self;
111 u16 v;
112 int idx;
114 if ( !PyArg_ParseTuple(args, "i", &idx) )
115 return NULL;
117 v = (u16)idx;
119 (void)write(xun->evtchn_fd, &v, sizeof(v));
121 Py_INCREF(Py_None);
122 return Py_None;
123 }
125 static PyObject *xu_notifier_bind(PyObject *self, PyObject *args)
126 {
127 xu_notifier_object *xun = (xu_notifier_object *)self;
128 int idx;
130 if ( !PyArg_ParseTuple(args, "i", &idx) )
131 return NULL;
133 if ( ioctl(xun->evtchn_fd, EVTCHN_BIND, idx) != 0 )
134 return PyErr_SetFromErrno(PyExc_IOError);
136 Py_INCREF(Py_None);
137 return Py_None;
138 }
140 static PyObject *xu_notifier_unbind(PyObject *self, PyObject *args)
141 {
142 xu_notifier_object *xun = (xu_notifier_object *)self;
143 int idx;
145 if ( !PyArg_ParseTuple(args, "i", &idx) )
146 return NULL;
148 if ( ioctl(xun->evtchn_fd, EVTCHN_UNBIND, idx) != 0 )
149 return PyErr_SetFromErrno(PyExc_IOError);
151 Py_INCREF(Py_None);
152 return Py_None;
153 }
155 static PyObject *xu_notifier_fileno(PyObject *self, PyObject *args)
156 {
157 xu_notifier_object *xun = (xu_notifier_object *)self;
158 return PyInt_FromLong(xun->evtchn_fd);
159 }
161 static PyMethodDef xu_notifier_methods[] = {
162 { "read",
163 (PyCFunction)xu_notifier_read,
164 METH_VARARGS,
165 "Read a @port with pending notifications.\n" },
167 { "unmask",
168 (PyCFunction)xu_notifier_unmask,
169 METH_VARARGS,
170 "Unmask notifications for a @port.\n" },
172 { "bind",
173 (PyCFunction)xu_notifier_bind,
174 METH_VARARGS,
175 "Get notifications for a @port.\n" },
177 { "unbind",
178 (PyCFunction)xu_notifier_unbind,
179 METH_VARARGS,
180 "No longer get notifications for a @port.\n" },
182 { "fileno",
183 (PyCFunction)xu_notifier_fileno,
184 METH_VARARGS,
185 "Return the file descriptor for the notification channel.\n" },
187 { NULL, NULL, 0, NULL }
188 };
190 staticforward PyTypeObject xu_notifier_type;
192 static PyObject *xu_notifier_new(PyObject *self, PyObject *args)
193 {
194 xu_notifier_object *xun;
195 struct stat st;
197 if ( !PyArg_ParseTuple(args, "") )
198 return NULL;
200 xun = PyObject_New(xu_notifier_object, &xu_notifier_type);
202 /* Make sure any existing device file links to correct device. */
203 if ( (lstat(EVTCHN_DEV_NAME, &st) != 0) ||
204 !S_ISCHR(st.st_mode) ||
205 (st.st_rdev != makedev(EVTCHN_DEV_MAJOR, EVTCHN_DEV_MINOR)) )
206 (void)unlink(EVTCHN_DEV_NAME);
208 reopen:
209 xun->evtchn_fd = open(EVTCHN_DEV_NAME, O_NONBLOCK|O_RDWR);
210 if ( xun->evtchn_fd == -1 )
211 {
212 if ( (errno == ENOENT) &&
213 ((mkdir("/dev/xen", 0755) == 0) || (errno == EEXIST)) &&
214 (mknod(EVTCHN_DEV_NAME, S_IFCHR|0600,
215 makedev(EVTCHN_DEV_MAJOR,EVTCHN_DEV_MINOR)) == 0) )
216 goto reopen;
217 PyObject_Del((PyObject *)xun);
218 return PyErr_SetFromErrno(PyExc_IOError);
219 }
220 set_cloexec(xun->evtchn_fd);
222 return (PyObject *)xun;
223 }
225 static PyObject *xu_notifier_getattr(PyObject *obj, char *name)
226 {
227 return Py_FindMethod(xu_notifier_methods, obj, name);
228 }
230 static void xu_notifier_dealloc(PyObject *self)
231 {
232 xu_notifier_object *xun = (xu_notifier_object *)self;
233 (void)close(xun->evtchn_fd);
234 PyObject_Del(self);
235 }
237 static PyTypeObject xu_notifier_type = {
238 PyObject_HEAD_INIT(&PyType_Type)
239 0,
240 "notifier",
241 sizeof(xu_notifier_object),
242 0,
243 xu_notifier_dealloc, /* tp_dealloc */
244 NULL, /* tp_print */
245 xu_notifier_getattr, /* tp_getattr */
246 NULL, /* tp_setattr */
247 NULL, /* tp_compare */
248 NULL, /* tp_repr */
249 NULL, /* tp_as_number */
250 NULL, /* tp_as_sequence */
251 NULL, /* tp_as_mapping */
252 NULL /* tp_hash */
253 };
257 /*
258 * *********************** MESSAGE ***********************
259 */
261 #define TYPE(_x,_y) (((_x)<<8)|(_y))
262 #define P2C(_struct, _field, _ctype) \
263 do { \
264 PyObject *obj; \
265 if ( (obj = PyDict_GetItemString(payload, #_field)) != NULL ) \
266 { \
267 if ( PyInt_Check(obj) ) \
268 { \
269 ((_struct *)&xum->msg.msg[0])->_field = \
270 (_ctype)PyInt_AsLong(obj); \
271 dict_items_parsed++; \
272 } \
273 else if ( PyLong_Check(obj) ) \
274 { \
275 ((_struct *)&xum->msg.msg[0])->_field = \
276 (_ctype)PyLong_AsUnsignedLongLong(obj); \
277 dict_items_parsed++; \
278 } \
279 } \
280 xum->msg.length = sizeof(_struct); \
281 } while ( 0 )
282 #define C2P(_struct, _field, _pytype, _ctype) \
283 do { \
284 PyObject *obj = Py ## _pytype ## _From ## _ctype \
285 (((_struct *)&xum->msg.msg[0])->_field); \
286 if ( dict == NULL ) dict = PyDict_New(); \
287 PyDict_SetItemString(dict, #_field, obj); \
288 } while ( 0 )
290 typedef struct {
291 PyObject_HEAD;
292 control_msg_t msg;
293 } xu_message_object;
295 static PyObject *xu_message_append_payload(PyObject *self, PyObject *args)
296 {
297 xu_message_object *xum = (xu_message_object *)self;
298 char *str;
299 int len;
301 if ( !PyArg_ParseTuple(args, "s#", &str, &len) )
302 return NULL;
304 if ( (len + xum->msg.length) > sizeof(xum->msg.msg) )
305 {
306 PyErr_SetString(PyExc_RuntimeError, "out of space in control message");
307 return NULL;
308 }
310 memcpy(&xum->msg.msg[xum->msg.length], str, len);
311 xum->msg.length += len;
313 Py_INCREF(Py_None);
314 return Py_None;
315 }
317 static PyObject *xu_message_set_response_fields(PyObject *self, PyObject *args)
318 {
319 xu_message_object *xum = (xu_message_object *)self;
320 PyObject *payload;
321 int dict_items_parsed = 0;
323 if ( !PyArg_ParseTuple(args, "O", &payload) )
324 return NULL;
326 if ( !PyDict_Check(payload) )
327 {
328 PyErr_SetString(PyExc_TypeError, "payload is not a dictionary");
329 return NULL;
330 }
332 switch ( TYPE(xum->msg.type, xum->msg.subtype) )
333 {
334 case TYPE(CMSG_BLKIF_FE, CMSG_BLKIF_FE_DRIVER_STATUS):
335 P2C(blkif_fe_driver_status_t, max_handle, u32);
336 break;
337 case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_DRIVER_STATUS):
338 P2C(netif_fe_driver_status_t, max_handle, u32);
339 break;
340 }
342 if ( dict_items_parsed != PyDict_Size(payload) )
343 {
344 PyErr_SetString(PyExc_TypeError, "payload contains bad items");
345 return NULL;
346 }
348 Py_INCREF(Py_None);
349 return Py_None;
350 }
352 static PyObject *xu_message_get_payload(PyObject *self, PyObject *args)
353 {
354 xu_message_object *xum = (xu_message_object *)self;
355 PyObject *dict = NULL;
357 if ( !PyArg_ParseTuple(args, "") )
358 return NULL;
360 switch ( TYPE(xum->msg.type, xum->msg.subtype) )
361 {
362 case TYPE(CMSG_BLKIF_FE, CMSG_BLKIF_FE_INTERFACE_STATUS):
363 C2P(blkif_fe_interface_status_t, handle, Int, Long);
364 C2P(blkif_fe_interface_status_t, status, Int, Long);
365 C2P(blkif_fe_interface_status_t, evtchn, Int, Long);
366 return dict;
367 case TYPE(CMSG_BLKIF_FE, CMSG_BLKIF_FE_DRIVER_STATUS):
368 C2P(blkif_fe_driver_status_t, status, Int, Long);
369 return dict;
370 case TYPE(CMSG_BLKIF_FE, CMSG_BLKIF_FE_INTERFACE_CONNECT):
371 C2P(blkif_fe_interface_connect_t, handle, Int, Long);
372 C2P(blkif_fe_interface_connect_t, shmem_frame, Int, Long);
373 return dict;
374 case TYPE(CMSG_BLKIF_FE, CMSG_BLKIF_FE_INTERFACE_DISCONNECT):
375 C2P(blkif_fe_interface_disconnect_t, handle, Int, Long);
376 return dict;
377 case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_CREATE):
378 C2P(blkif_be_create_t, domid, Int, Long);
379 C2P(blkif_be_create_t, blkif_handle, Int, Long);
380 C2P(blkif_be_create_t, status, Int, Long);
381 return dict;
382 case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_DESTROY):
383 C2P(blkif_be_destroy_t, domid, Int, Long);
384 C2P(blkif_be_destroy_t, blkif_handle, Int, Long);
385 C2P(blkif_be_destroy_t, status, Int, Long);
386 return dict;
387 case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_CONNECT):
388 C2P(blkif_be_connect_t, domid, Int, Long);
389 C2P(blkif_be_connect_t, blkif_handle, Int, Long);
390 C2P(blkif_be_connect_t, shmem_frame, Int, Long);
391 C2P(blkif_be_connect_t, evtchn, Int, Long);
392 C2P(blkif_be_connect_t, status, Int, Long);
393 return dict;
394 case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_DISCONNECT):
395 C2P(blkif_be_disconnect_t, domid, Int, Long);
396 C2P(blkif_be_disconnect_t, blkif_handle, Int, Long);
397 C2P(blkif_be_disconnect_t, status, Int, Long);
398 return dict;
399 case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_CREATE):
400 C2P(blkif_be_vbd_create_t, domid, Int, Long);
401 C2P(blkif_be_vbd_create_t, blkif_handle, Int, Long);
402 C2P(blkif_be_vbd_create_t, vdevice, Int, Long);
403 C2P(blkif_be_vbd_create_t, readonly, Int, Long);
404 C2P(blkif_be_vbd_create_t, status, Int, Long);
405 return dict;
406 case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_DESTROY):
407 C2P(blkif_be_vbd_destroy_t, domid, Int, Long);
408 C2P(blkif_be_vbd_destroy_t, blkif_handle, Int, Long);
409 C2P(blkif_be_vbd_destroy_t, vdevice, Int, Long);
410 C2P(blkif_be_vbd_destroy_t, status, Int, Long);
411 return dict;
412 case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_GROW):
413 C2P(blkif_be_vbd_grow_t, domid, Int, Long);
414 C2P(blkif_be_vbd_grow_t, blkif_handle, Int, Long);
415 C2P(blkif_be_vbd_grow_t, vdevice, Int, Long);
416 C2P(blkif_be_vbd_grow_t, extent.sector_start,
417 Long, UnsignedLongLong);
418 C2P(blkif_be_vbd_grow_t, extent.sector_length,
419 Long, UnsignedLongLong);
420 C2P(blkif_be_vbd_grow_t, extent.device, Int, Long);
421 C2P(blkif_be_vbd_grow_t, status, Int, Long);
422 return dict;
423 case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_SHRINK):
424 C2P(blkif_be_vbd_shrink_t, domid, Int, Long);
425 C2P(blkif_be_vbd_shrink_t, blkif_handle, Int, Long);
426 C2P(blkif_be_vbd_shrink_t, vdevice, Int, Long);
427 C2P(blkif_be_vbd_shrink_t, status, Int, Long);
428 return dict;
429 case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_DRIVER_STATUS):
430 C2P(blkif_be_driver_status_t, status, Int, Long);
431 return dict;
432 case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_INTERFACE_STATUS):
433 C2P(netif_fe_interface_status_t, handle, Int, Long);
434 C2P(netif_fe_interface_status_t, status, Int, Long);
435 C2P(netif_fe_interface_status_t, evtchn, Int, Long);
436 C2P(netif_fe_interface_status_t, mac[0], Int, Long);
437 C2P(netif_fe_interface_status_t, mac[1], Int, Long);
438 C2P(netif_fe_interface_status_t, mac[2], Int, Long);
439 C2P(netif_fe_interface_status_t, mac[3], Int, Long);
440 C2P(netif_fe_interface_status_t, mac[4], Int, Long);
441 C2P(netif_fe_interface_status_t, mac[5], Int, Long);
442 return dict;
443 case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_DRIVER_STATUS):
444 C2P(netif_fe_driver_status_t, status, Int, Long);
445 C2P(netif_fe_driver_status_t, max_handle, Int, Long);
446 return dict;
447 case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_INTERFACE_CONNECT):
448 C2P(netif_fe_interface_connect_t, handle, Int, Long);
449 C2P(netif_fe_interface_connect_t, tx_shmem_frame, Int, Long);
450 C2P(netif_fe_interface_connect_t, rx_shmem_frame, Int, Long);
451 return dict;
452 case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_INTERFACE_DISCONNECT):
453 C2P(netif_fe_interface_disconnect_t, handle, Int, Long);
454 return dict;
455 case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_CREATE):
456 C2P(netif_be_create_t, domid, Int, Long);
457 C2P(netif_be_create_t, netif_handle, Int, Long);
458 C2P(netif_be_create_t, status, Int, Long);
459 return dict;
460 case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_DESTROY):
461 C2P(netif_be_destroy_t, domid, Int, Long);
462 C2P(netif_be_destroy_t, netif_handle, Int, Long);
463 C2P(netif_be_destroy_t, status, Int, Long);
464 return dict;
465 case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_CONNECT):
466 C2P(netif_be_connect_t, domid, Int, Long);
467 C2P(netif_be_connect_t, netif_handle, Int, Long);
468 C2P(netif_be_connect_t, tx_shmem_frame, Int, Long);
469 C2P(netif_be_connect_t, rx_shmem_frame, Int, Long);
470 C2P(netif_be_connect_t, evtchn, Int, Long);
471 C2P(netif_be_connect_t, status, Int, Long);
472 return dict;
473 case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_DISCONNECT):
474 C2P(netif_be_disconnect_t, domid, Int, Long);
475 C2P(netif_be_disconnect_t, netif_handle, Int, Long);
476 C2P(netif_be_disconnect_t, status, Int, Long);
477 return dict;
478 case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_DRIVER_STATUS):
479 C2P(netif_be_driver_status_t, status, Int, Long);
480 return dict;
481 case TYPE(CMSG_MEM_REQUEST, CMSG_MEM_REQUEST_SET):
482 C2P(mem_request_t, target, Int, Long);
483 C2P(mem_request_t, status, Int, Long);
484 return dict;
485 }
487 return PyString_FromStringAndSize(xum->msg.msg, xum->msg.length);
488 }
490 static PyObject *xu_message_get_header(PyObject *self, PyObject *args)
491 {
492 xu_message_object *xum = (xu_message_object *)self;
494 if ( !PyArg_ParseTuple(args, "") )
495 return NULL;
497 return Py_BuildValue("{s:i,s:i,s:i}",
498 "type", xum->msg.type,
499 "subtype", xum->msg.subtype,
500 "id", xum->msg.id);
501 }
503 static PyMethodDef xu_message_methods[] = {
504 { "append_payload",
505 (PyCFunction)xu_message_append_payload,
506 METH_VARARGS,
507 "Append @str to the message payload.\n" },
509 { "set_response_fields",
510 (PyCFunction)xu_message_set_response_fields,
511 METH_VARARGS,
512 "Fill in the response fields in a message that was passed to us.\n" },
514 { "get_payload",
515 (PyCFunction)xu_message_get_payload,
516 METH_VARARGS,
517 "Return the message payload in string form.\n" },
519 { "get_header",
520 (PyCFunction)xu_message_get_header,
521 METH_VARARGS,
522 "Returns a dictionary of values for @type, @subtype, and @id.\n" },
524 { NULL, NULL, 0, NULL }
525 };
527 staticforward PyTypeObject xu_message_type;
529 static PyObject *xu_message_new(PyObject *self, PyObject *args)
530 {
531 xu_message_object *xum;
532 int type, subtype, id, dict_items_parsed = 0;
533 PyObject *payload = NULL;
535 if ( !PyArg_ParseTuple(args, "iii|O", &type, &subtype, &id, &payload) )
536 return NULL;
538 xum = PyObject_New(xu_message_object, &xu_message_type);
540 xum->msg.type = type;
541 xum->msg.subtype = subtype;
542 xum->msg.id = id;
543 xum->msg.length = 0;
545 if ( payload == NULL )
546 return (PyObject *)xum;
548 if ( !PyDict_Check(payload) )
549 {
550 PyErr_SetString(PyExc_TypeError, "payload is not a dictionary");
551 PyObject_Del((PyObject *)xum);
552 return NULL;
553 }
555 switch ( TYPE(type, subtype) )
556 {
557 case TYPE(CMSG_BLKIF_FE, CMSG_BLKIF_FE_INTERFACE_STATUS):
558 P2C(blkif_fe_interface_status_t, handle, u32);
559 P2C(blkif_fe_interface_status_t, status, u32);
560 P2C(blkif_fe_interface_status_t, evtchn, u16);
561 P2C(blkif_fe_interface_status_t, domid, u16);
562 break;
563 case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_CREATE):
564 P2C(blkif_be_create_t, domid, u32);
565 P2C(blkif_be_create_t, blkif_handle, u32);
566 break;
567 case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_DESTROY):
568 P2C(blkif_be_destroy_t, domid, u32);
569 P2C(blkif_be_destroy_t, blkif_handle, u32);
570 break;
571 case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_CONNECT):
572 P2C(blkif_be_connect_t, domid, u32);
573 P2C(blkif_be_connect_t, blkif_handle, u32);
574 P2C(blkif_be_connect_t, shmem_frame, memory_t);
575 P2C(blkif_be_connect_t, evtchn, u16);
576 break;
577 case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_DISCONNECT):
578 P2C(blkif_be_disconnect_t, domid, u32);
579 P2C(blkif_be_disconnect_t, blkif_handle, u32);
580 break;
581 case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_CREATE):
582 P2C(blkif_be_vbd_create_t, domid, u32);
583 P2C(blkif_be_vbd_create_t, blkif_handle, u32);
584 P2C(blkif_be_vbd_create_t, vdevice, blkif_vdev_t);
585 P2C(blkif_be_vbd_create_t, readonly, u16);
586 break;
587 case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_DESTROY):
588 P2C(blkif_be_vbd_destroy_t, domid, u32);
589 P2C(blkif_be_vbd_destroy_t, blkif_handle, u32);
590 P2C(blkif_be_vbd_destroy_t, vdevice, blkif_vdev_t);
591 break;
592 case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_GROW):
593 P2C(blkif_be_vbd_grow_t, domid, u32);
594 P2C(blkif_be_vbd_grow_t, blkif_handle, u32);
595 P2C(blkif_be_vbd_grow_t, vdevice, blkif_vdev_t);
596 P2C(blkif_be_vbd_grow_t, extent.sector_start, blkif_sector_t);
597 P2C(blkif_be_vbd_grow_t, extent.sector_length, blkif_sector_t);
598 P2C(blkif_be_vbd_grow_t, extent.device, blkif_pdev_t);
599 break;
600 case TYPE(CMSG_BLKIF_BE, CMSG_BLKIF_BE_VBD_SHRINK):
601 P2C(blkif_be_vbd_shrink_t, domid, u32);
602 P2C(blkif_be_vbd_shrink_t, blkif_handle, u32);
603 P2C(blkif_be_vbd_shrink_t, vdevice, blkif_vdev_t);
604 break;
605 case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_INTERFACE_STATUS):
606 P2C(netif_fe_interface_status_t, handle, u32);
607 P2C(netif_fe_interface_status_t, status, u32);
608 P2C(netif_fe_interface_status_t, evtchn, u16);
609 P2C(netif_fe_interface_status_t, domid, u16);
610 P2C(netif_fe_interface_status_t, mac[0], u8);
611 P2C(netif_fe_interface_status_t, mac[1], u8);
612 P2C(netif_fe_interface_status_t, mac[2], u8);
613 P2C(netif_fe_interface_status_t, mac[3], u8);
614 P2C(netif_fe_interface_status_t, mac[4], u8);
615 P2C(netif_fe_interface_status_t, mac[5], u8);
616 break;
617 case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_CREATE):
618 P2C(netif_be_create_t, domid, u32);
619 P2C(netif_be_create_t, netif_handle, u32);
620 P2C(netif_be_create_t, mac[0], u8);
621 P2C(netif_be_create_t, mac[1], u8);
622 P2C(netif_be_create_t, mac[2], u8);
623 P2C(netif_be_create_t, mac[3], u8);
624 P2C(netif_be_create_t, mac[4], u8);
625 P2C(netif_be_create_t, mac[5], u8);
626 break;
627 case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_DESTROY):
628 P2C(netif_be_destroy_t, domid, u32);
629 P2C(netif_be_destroy_t, netif_handle, u32);
630 break;
631 case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_CONNECT):
632 P2C(netif_be_connect_t, domid, u32);
633 P2C(netif_be_connect_t, netif_handle, u32);
634 P2C(netif_be_connect_t, tx_shmem_frame, memory_t);
635 P2C(netif_be_connect_t, rx_shmem_frame, memory_t);
636 P2C(netif_be_connect_t, evtchn, u16);
637 break;
638 case TYPE(CMSG_NETIF_BE, CMSG_NETIF_BE_DISCONNECT):
639 P2C(netif_be_disconnect_t, domid, u32);
640 P2C(netif_be_disconnect_t, netif_handle, u32);
641 break;
642 case TYPE(CMSG_NETIF_FE, CMSG_NETIF_FE_DRIVER_STATUS):
643 P2C(netif_fe_driver_status_t, status, u32);
644 P2C(netif_fe_driver_status_t, max_handle, u32);
645 break;
646 case TYPE(CMSG_MEM_REQUEST, CMSG_MEM_REQUEST_SET):
647 P2C(mem_request_t, target, u32);
648 P2C(mem_request_t, status, u32);
649 break;
650 }
652 if ( dict_items_parsed != PyDict_Size(payload) )
653 {
654 PyErr_SetString(PyExc_TypeError, "payload contains bad items");
655 PyObject_Del((PyObject *)xum);
656 return NULL;
657 }
659 return (PyObject *)xum;
660 }
662 static PyObject *xu_message_getattr(PyObject *obj, char *name)
663 {
664 xu_message_object *xum;
665 if ( strcmp(name, "MAX_PAYLOAD") == 0 )
666 return PyInt_FromLong(sizeof(xum->msg.msg));
667 return Py_FindMethod(xu_message_methods, obj, name);
668 }
670 static void xu_message_dealloc(PyObject *self)
671 {
672 PyObject_Del(self);
673 }
675 static PyTypeObject xu_message_type = {
676 PyObject_HEAD_INIT(&PyType_Type)
677 0,
678 "message",
679 sizeof(xu_message_object),
680 0,
681 xu_message_dealloc, /* tp_dealloc */
682 NULL, /* tp_print */
683 xu_message_getattr, /* tp_getattr */
684 NULL, /* tp_setattr */
685 NULL, /* tp_compare */
686 NULL, /* tp_repr */
687 NULL, /* tp_as_number */
688 NULL, /* tp_as_sequence */
689 NULL, /* tp_as_mapping */
690 NULL /* tp_hash */
691 };
695 /*
696 * *********************** PORT ***********************
697 */
699 static control_if_t *map_control_interface(int fd, unsigned long pfn,
700 u32 dom)
701 {
702 char *vaddr = xc_map_foreign_range( fd, dom, PAGE_SIZE,
703 PROT_READ|PROT_WRITE, pfn );
704 if ( vaddr == NULL )
705 return NULL;
706 return (control_if_t *)(vaddr + 2048);
707 }
708 static void unmap_control_interface(int fd, control_if_t *c)
709 {
710 char *vaddr = (char *)c - 2048;
711 (void)munmap(vaddr, PAGE_SIZE);
712 }
714 typedef struct xu_port_object {
715 PyObject_HEAD;
716 int xc_handle;
717 int connected;
718 u32 remote_dom;
719 int local_port, remote_port;
720 control_if_t *interface;
721 CONTROL_RING_IDX tx_req_cons, tx_resp_prod;
722 CONTROL_RING_IDX rx_req_prod, rx_resp_cons;
723 } xu_port_object;
725 static PyObject *port_error;
727 static PyObject *xu_port_notify(PyObject *self, PyObject *args)
728 {
729 xu_port_object *xup = (xu_port_object *)self;
731 if ( !PyArg_ParseTuple(args, "") )
732 return NULL;
734 (void)xc_evtchn_send(xup->xc_handle, xup->local_port);
736 Py_INCREF(Py_None);
737 return Py_None;
738 }
740 static PyObject *xu_port_read_request(PyObject *self, PyObject *args)
741 {
742 xu_port_object *xup = (xu_port_object *)self;
743 xu_message_object *xum;
744 CONTROL_RING_IDX c = xup->tx_req_cons;
745 control_if_t *cif = xup->interface;
746 control_msg_t *cmsg;
748 if ( !PyArg_ParseTuple(args, "") )
749 return NULL;
751 if ( (c == cif->tx_req_prod) ||
752 ((c - xup->tx_resp_prod) == CONTROL_RING_SIZE) )
753 {
754 PyErr_SetString(port_error, "no request to read");
755 return NULL;
756 }
758 /* Need to ensure we see the request, despite seeing the index update.*/
759 rmb();
761 cmsg = &cif->tx_ring[MASK_CONTROL_IDX(c)];
762 xum = PyObject_New(xu_message_object, &xu_message_type);
763 memcpy(&xum->msg, cmsg, sizeof(*cmsg));
764 if ( xum->msg.length > sizeof(xum->msg.msg) )
765 xum->msg.length = sizeof(xum->msg.msg);
766 xup->tx_req_cons++;
767 return (PyObject *)xum;
768 }
770 static PyObject *xu_port_write_request(PyObject *self, PyObject *args)
771 {
772 xu_port_object *xup = (xu_port_object *)self;
773 xu_message_object *xum;
774 CONTROL_RING_IDX p = xup->rx_req_prod;
775 control_if_t *cif = xup->interface;
776 control_msg_t *cmsg;
778 if ( !PyArg_ParseTuple(args, "O", (PyObject **)&xum) )
779 return NULL;
781 if ( !PyObject_TypeCheck((PyObject *)xum, &xu_message_type) )
782 {
783 PyErr_SetString(PyExc_TypeError, "expected a " XENPKG ".message");
784 return NULL;
785 }
787 if ( ((p - xup->rx_resp_cons) == CONTROL_RING_SIZE) )
788 {
789 PyErr_SetString(port_error, "no space to write request");
790 return NULL;
791 }
793 cmsg = &cif->rx_ring[MASK_CONTROL_IDX(p)];
794 memcpy(cmsg, &xum->msg, sizeof(*cmsg));
796 wmb();
797 xup->rx_req_prod = cif->rx_req_prod = p + 1;
799 Py_INCREF(Py_None);
800 return Py_None;
801 }
803 static PyObject *xu_port_read_response(PyObject *self, PyObject *args)
804 {
805 xu_port_object *xup = (xu_port_object *)self;
806 xu_message_object *xum;
807 CONTROL_RING_IDX c = xup->rx_resp_cons;
808 control_if_t *cif = xup->interface;
809 control_msg_t *cmsg;
811 if ( !PyArg_ParseTuple(args, "") )
812 return NULL;
814 if ( (c == cif->rx_resp_prod) || (c == xup->rx_req_prod) )
815 {
816 PyErr_SetString(port_error, "no response to read");
817 return NULL;
818 }
820 /* Need to ensure we see the response, despite seeing the index update.*/
821 rmb();
823 cmsg = &cif->rx_ring[MASK_CONTROL_IDX(c)];
824 xum = PyObject_New(xu_message_object, &xu_message_type);
825 memcpy(&xum->msg, cmsg, sizeof(*cmsg));
826 if ( xum->msg.length > sizeof(xum->msg.msg) )
827 xum->msg.length = sizeof(xum->msg.msg);
828 xup->rx_resp_cons++;
829 return (PyObject *)xum;
830 }
832 static PyObject *xu_port_write_response(PyObject *self, PyObject *args)
833 {
834 xu_port_object *xup = (xu_port_object *)self;
835 xu_message_object *xum;
836 CONTROL_RING_IDX p = xup->tx_resp_prod;
837 control_if_t *cif = xup->interface;
838 control_msg_t *cmsg;
840 if ( !PyArg_ParseTuple(args, "O", (PyObject **)&xum) )
841 return NULL;
843 if ( !PyObject_TypeCheck((PyObject *)xum, &xu_message_type) )
844 {
845 PyErr_SetString(PyExc_TypeError, "expected a " XENPKG ".message");
846 return NULL;
847 }
849 if ( p == xup->tx_req_cons )
850 {
851 PyErr_SetString(port_error, "no space to write response");
852 return NULL;
853 }
855 cmsg = &cif->tx_ring[MASK_CONTROL_IDX(p)];
856 memcpy(cmsg, &xum->msg, sizeof(*cmsg));
858 wmb();
859 xup->tx_resp_prod = cif->tx_resp_prod = p + 1;
861 Py_INCREF(Py_None);
862 return Py_None;
863 }
865 static PyObject *xu_port_request_to_read(PyObject *self, PyObject *args)
866 {
867 xu_port_object *xup = (xu_port_object *)self;
868 CONTROL_RING_IDX c = xup->tx_req_cons;
869 control_if_t *cif = xup->interface;
871 if ( !PyArg_ParseTuple(args, "") )
872 return NULL;
874 if ( (c == cif->tx_req_prod) ||
875 ((c - xup->tx_resp_prod) == CONTROL_RING_SIZE) )
876 return PyInt_FromLong(0);
878 return PyInt_FromLong(1);
879 }
881 static PyObject *xu_port_space_to_write_request(PyObject *self, PyObject *args)
882 {
883 xu_port_object *xup = (xu_port_object *)self;
884 CONTROL_RING_IDX p = xup->rx_req_prod;
886 if ( !PyArg_ParseTuple(args, "") )
887 return NULL;
889 if ( ((p - xup->rx_resp_cons) == CONTROL_RING_SIZE) )
890 return PyInt_FromLong(0);
892 return PyInt_FromLong(1);
893 }
895 static PyObject *xu_port_response_to_read(PyObject *self, PyObject *args)
896 {
897 xu_port_object *xup = (xu_port_object *)self;
898 CONTROL_RING_IDX c = xup->rx_resp_cons;
899 control_if_t *cif = xup->interface;
901 if ( !PyArg_ParseTuple(args, "") )
902 return NULL;
904 if ( (c == cif->rx_resp_prod) || (c == xup->rx_req_prod) )
905 return PyInt_FromLong(0);
907 return PyInt_FromLong(1);
908 }
910 static PyObject *xu_port_space_to_write_response(
911 PyObject *self, PyObject *args)
912 {
913 xu_port_object *xup = (xu_port_object *)self;
914 CONTROL_RING_IDX p = xup->tx_resp_prod;
916 if ( !PyArg_ParseTuple(args, "") )
917 return NULL;
919 if ( p == xup->tx_req_cons )
920 return PyInt_FromLong(0);
922 return PyInt_FromLong(1);
923 }
925 static int __xu_port_connect(xu_port_object *xup)
926 {
927 xc_dominfo_t info;
929 if ( xup->connected )
930 {
931 return 0;
932 }
934 if ( (xc_domain_getinfo(xup->xc_handle, xup->remote_dom, 1, &info) != 1) ||
935 (info.domid != xup->remote_dom) )
936 {
937 PyErr_SetString(port_error, "Failed to obtain domain status");
938 return -1;
939 }
941 xup->interface =
942 map_control_interface(xup->xc_handle, info.shared_info_frame,
943 xup->remote_dom);
945 if ( xup->interface == NULL )
946 {
947 PyErr_SetString(port_error, "Failed to map domain control interface");
948 return -1;
949 }
951 /* Synchronise ring indexes. */
952 xup->tx_resp_prod = xup->interface->tx_resp_prod;
953 xup->tx_req_cons = xup->interface->tx_resp_prod;
954 xup->rx_req_prod = xup->interface->rx_req_prod;
955 xup->rx_resp_cons = xup->interface->rx_resp_prod;
957 xup->connected = 1;
959 return 0;
960 }
962 static void __xu_port_disconnect(xu_port_object *xup)
963 {
964 if ( xup->connected )
965 unmap_control_interface(xup->xc_handle, xup->interface);
966 xup->connected = 0;
967 }
969 static PyObject *xu_port_connect(PyObject *self, PyObject *args)
970 {
971 xu_port_object *xup = (xu_port_object *)self;
973 if ( !PyArg_ParseTuple(args, "") )
974 return NULL;
976 if ( __xu_port_connect(xup) != 0 )
977 return NULL;
979 Py_INCREF(Py_None);
980 return Py_None;
981 }
983 static PyObject *xu_port_disconnect(PyObject *self, PyObject *args)
984 {
985 xu_port_object *xup = (xu_port_object *)self;
987 if ( !PyArg_ParseTuple(args, "") )
988 return NULL;
990 __xu_port_disconnect(xup);
992 Py_INCREF(Py_None);
993 return Py_None;
994 }
996 static PyMethodDef xu_port_methods[] = {
997 { "notify",
998 (PyCFunction)xu_port_notify,
999 METH_VARARGS,
1000 "Send a notification to the remote end.\n" },
1002 { "read_request",
1003 (PyCFunction)xu_port_read_request,
1004 METH_VARARGS,
1005 "Read a request message from the control interface.\n" },
1007 { "write_request",
1008 (PyCFunction)xu_port_write_request,
1009 METH_VARARGS,
1010 "Write a request message to the control interface.\n" },
1012 { "read_response",
1013 (PyCFunction)xu_port_read_response,
1014 METH_VARARGS,
1015 "Read a response message from the control interface.\n" },
1017 { "write_response",
1018 (PyCFunction)xu_port_write_response,
1019 METH_VARARGS,
1020 "Write a response message to the control interface.\n" },
1022 { "request_to_read",
1023 (PyCFunction)xu_port_request_to_read,
1024 METH_VARARGS,
1025 "Returns TRUE if there is a request message to read.\n" },
1027 { "space_to_write_request",
1028 (PyCFunction)xu_port_space_to_write_request,
1029 METH_VARARGS,
1030 "Returns TRUE if there is space to write a request message.\n" },
1032 { "response_to_read",
1033 (PyCFunction)xu_port_response_to_read,
1034 METH_VARARGS,
1035 "Returns TRUE if there is a response message to read.\n" },
1037 { "space_to_write_response",
1038 (PyCFunction)xu_port_space_to_write_response,
1039 METH_VARARGS,
1040 "Returns TRUE if there is space to write a response message.\n" },
1042 { "connect",
1043 (PyCFunction)xu_port_connect,
1044 METH_VARARGS,
1045 "Synchronously connect to remote domain.\n" },
1047 { "disconnect",
1048 (PyCFunction)xu_port_disconnect,
1049 METH_VARARGS,
1050 "Synchronously disconnect from remote domain.\n" },
1052 { NULL, NULL, 0, NULL }
1053 };
1055 staticforward PyTypeObject xu_port_type;
1057 static PyObject *xu_port_new(PyObject *self, PyObject *args)
1059 xu_port_object *xup;
1060 u32 dom;
1061 int port1 = 0, port2 = 0;
1063 if ( !PyArg_ParseTuple(args, "i|ii", &dom, &port1, &port2) )
1064 return NULL;
1066 xup = PyObject_New(xu_port_object, &xu_port_type);
1068 xup->connected = 0;
1069 xup->remote_dom = dom;
1071 if ( (xup->xc_handle = xc_interface_open()) == -1 )
1073 PyErr_SetString(port_error, "Could not open Xen control interface");
1074 goto fail1;
1077 if ( dom == 0 )
1079 /*
1080 * The control-interface event channel for DOM0 is already set up.
1081 * We use an ioctl to discover the port at our end of the channel.
1082 */
1083 port1 = ioctl(xup->xc_handle, IOCTL_PRIVCMD_INITDOMAIN_EVTCHN, NULL);
1084 port2 = -1; /* We don't need the remote end of the DOM0 link. */
1085 if ( port1 < 0 )
1087 PyErr_SetString(port_error, "Could not open channel to DOM0");
1088 goto fail2;
1091 else if ( xc_evtchn_bind_interdomain(xup->xc_handle,
1092 DOMID_SELF, dom,
1093 &port1, &port2) != 0 )
1095 PyErr_SetString(port_error, "Could not open channel to domain");
1096 goto fail2;
1099 xup->local_port = port1;
1100 xup->remote_port = port2;
1102 if ( __xu_port_connect(xup) != 0 )
1103 goto fail3;
1105 return (PyObject *)xup;
1107 fail3:
1108 if ( dom != 0 )
1109 (void)xc_evtchn_close(xup->xc_handle, DOMID_SELF, port1);
1110 fail2:
1111 (void)xc_interface_close(xup->xc_handle);
1112 fail1:
1113 PyObject_Del((PyObject *)xup);
1114 return NULL;
1117 static PyObject *xu_port_getattr(PyObject *obj, char *name)
1119 xu_port_object *xup = (xu_port_object *)obj;
1120 if ( strcmp(name, "local_port") == 0 )
1121 return PyInt_FromLong(xup->local_port);
1122 if ( strcmp(name, "remote_port") == 0 )
1123 return PyInt_FromLong(xup->remote_port);
1124 if ( strcmp(name, "remote_dom") == 0 )
1125 return PyInt_FromLong(xup->remote_dom);
1126 return Py_FindMethod(xu_port_methods, obj, name);
1129 static void xu_port_dealloc(PyObject *self)
1131 xu_port_object *xup = (xu_port_object *)self;
1132 __xu_port_disconnect(xup);
1133 if ( xup->remote_dom != 0 )
1134 (void)xc_evtchn_close(xup->xc_handle, DOMID_SELF, xup->local_port);
1135 (void)xc_interface_close(xup->xc_handle);
1136 PyObject_Del(self);
1139 static PyTypeObject xu_port_type = {
1140 PyObject_HEAD_INIT(&PyType_Type)
1141 0,
1142 "port",
1143 sizeof(xu_port_object),
1144 0,
1145 xu_port_dealloc, /* tp_dealloc */
1146 NULL, /* tp_print */
1147 xu_port_getattr, /* tp_getattr */
1148 NULL, /* tp_setattr */
1149 NULL, /* tp_compare */
1150 NULL, /* tp_repr */
1151 NULL, /* tp_as_number */
1152 NULL, /* tp_as_sequence */
1153 NULL, /* tp_as_mapping */
1154 NULL /* tp_hash */
1155 };
1159 /*
1160 * *********************** BUFFER ***********************
1161 */
1163 #define BUFSZ 65536
1164 #define MASK_BUF_IDX(_i) ((_i)&(BUFSZ-1))
1165 typedef unsigned int BUF_IDX;
1167 typedef struct {
1168 PyObject_HEAD;
1169 char *buf;
1170 unsigned int prod, cons;
1171 } xu_buffer_object;
1173 static PyObject *__xu_buffer_peek(xu_buffer_object *xub, int max)
1175 PyObject *str1, *str2;
1176 int len1, len2, c = MASK_BUF_IDX(xub->cons);
1178 len1 = xub->prod - xub->cons;
1179 if ( len1 > (BUFSZ - c) ) /* clip to ring wrap */
1180 len1 = BUFSZ - c;
1181 if ( len1 > max ) /* clip to specified maximum */
1182 len1 = max;
1183 if ( len1 < 0 ) /* sanity */
1184 len1 = 0;
1186 if ( (str1 = PyString_FromStringAndSize(&xub->buf[c], len1)) == NULL )
1187 return NULL;
1189 if ( (len1 < (xub->prod - xub->cons)) && (len1 < max) )
1191 len2 = max - len1;
1192 if ( len2 > MASK_BUF_IDX(xub->prod) )
1193 len2 = MASK_BUF_IDX(xub->prod);
1194 if ( len2 > 0 )
1196 str2 = PyString_FromStringAndSize(&xub->buf[0], len2);
1197 if ( str2 == NULL )
1198 return NULL;
1199 PyString_ConcatAndDel(&str1, str2);
1200 if ( str1 == NULL )
1201 return NULL;
1205 return str1;
1208 static PyObject *xu_buffer_peek(PyObject *self, PyObject *args)
1210 xu_buffer_object *xub = (xu_buffer_object *)self;
1211 int max = 1024;
1213 if ( !PyArg_ParseTuple(args, "|i", &max) )
1214 return NULL;
1216 return __xu_buffer_peek(xub, max);
1219 static PyObject *xu_buffer_read(PyObject *self, PyObject *args)
1221 xu_buffer_object *xub = (xu_buffer_object *)self;
1222 PyObject *str;
1223 int max = 1024;
1225 if ( !PyArg_ParseTuple(args, "|i", &max) )
1226 return NULL;
1228 if ( (str = __xu_buffer_peek(xub, max)) != NULL )
1229 xub->cons += PyString_Size(str);
1231 return str;
1234 static PyObject *xu_buffer_discard(PyObject *self, PyObject *args)
1236 xu_buffer_object *xub = (xu_buffer_object *)self;
1237 int max, len;
1239 if ( !PyArg_ParseTuple(args, "i", &max) )
1240 return NULL;
1242 len = xub->prod - xub->cons;
1243 if ( len > max )
1244 len = max;
1245 if ( len < 0 )
1246 len = 0;
1248 xub->cons += len;
1250 return PyInt_FromLong(len);
1253 static PyObject *xu_buffer_write(PyObject *self, PyObject *args)
1255 xu_buffer_object *xub = (xu_buffer_object *)self;
1256 char *str;
1257 int len, len1, len2;
1259 if ( !PyArg_ParseTuple(args, "s#", &str, &len) )
1260 return NULL;
1262 len1 = len;
1263 if ( len1 > (BUFSZ - MASK_BUF_IDX(xub->prod)) )
1264 len1 = BUFSZ - MASK_BUF_IDX(xub->prod);
1265 if ( len1 > (BUFSZ - (xub->prod - xub->cons)) )
1266 len1 = BUFSZ - (xub->prod - xub->cons);
1268 if ( len1 == 0 )
1269 return PyInt_FromLong(0);
1271 memcpy(&xub->buf[MASK_BUF_IDX(xub->prod)], &str[0], len1);
1272 xub->prod += len1;
1274 if ( len1 < len )
1276 len2 = len - len1;
1277 if ( len2 > (BUFSZ - MASK_BUF_IDX(xub->prod)) )
1278 len2 = BUFSZ - MASK_BUF_IDX(xub->prod);
1279 if ( len2 > (BUFSZ - (xub->prod - xub->cons)) )
1280 len2 = BUFSZ - (xub->prod - xub->cons);
1281 if ( len2 != 0 )
1283 memcpy(&xub->buf[MASK_BUF_IDX(xub->prod)], &str[len1], len2);
1284 xub->prod += len2;
1285 return PyInt_FromLong(len1 + len2);
1289 return PyInt_FromLong(len1);
1292 static PyObject *xu_buffer_empty(PyObject *self, PyObject *args)
1294 xu_buffer_object *xub = (xu_buffer_object *)self;
1296 if ( !PyArg_ParseTuple(args, "") )
1297 return NULL;
1299 if ( xub->cons == xub->prod )
1300 return PyInt_FromLong(1);
1302 return PyInt_FromLong(0);
1305 static PyObject *xu_buffer_full(PyObject *self, PyObject *args)
1307 xu_buffer_object *xub = (xu_buffer_object *)self;
1309 if ( !PyArg_ParseTuple(args, "") )
1310 return NULL;
1312 if ( (xub->prod - xub->cons) == BUFSZ )
1313 return PyInt_FromLong(1);
1315 return PyInt_FromLong(0);
1318 static PyMethodDef xu_buffer_methods[] = {
1319 { "peek",
1320 (PyCFunction)xu_buffer_peek,
1321 METH_VARARGS,
1322 "Peek up to @max bytes from the buffer. Returns a string.\n" },
1324 { "read",
1325 (PyCFunction)xu_buffer_read,
1326 METH_VARARGS,
1327 "Read up to @max bytes from the buffer. Returns a string.\n" },
1329 { "discard",
1330 (PyCFunction)xu_buffer_discard,
1331 METH_VARARGS,
1332 "Discard up to @max bytes from the buffer. Returns number of bytes.\n" },
1334 { "write",
1335 (PyCFunction)xu_buffer_write,
1336 METH_VARARGS,
1337 "Write @string into buffer. Return number of bytes written.\n" },
1339 { "empty",
1340 (PyCFunction)xu_buffer_empty,
1341 METH_VARARGS,
1342 "Return TRUE if the buffer is empty.\n" },
1344 { "full",
1345 (PyCFunction)xu_buffer_full,
1346 METH_VARARGS,
1347 "Return TRUE if the buffer is full.\n" },
1349 { NULL, NULL, 0, NULL }
1350 };
1352 staticforward PyTypeObject xu_buffer_type;
1354 static PyObject *xu_buffer_new(PyObject *self, PyObject *args)
1356 xu_buffer_object *xub;
1358 if ( !PyArg_ParseTuple(args, "") )
1359 return NULL;
1361 xub = PyObject_New(xu_buffer_object, &xu_buffer_type);
1363 if ( (xub->buf = malloc(BUFSZ)) == NULL )
1365 PyObject_Del((PyObject *)xub);
1366 return NULL;
1369 xub->prod = xub->cons = 0;
1371 return (PyObject *)xub;
1374 static PyObject *xu_buffer_getattr(PyObject *obj, char *name)
1376 return Py_FindMethod(xu_buffer_methods, obj, name);
1379 static void xu_buffer_dealloc(PyObject *self)
1381 xu_buffer_object *xub = (xu_buffer_object *)self;
1382 free(xub->buf);
1383 PyObject_Del(self);
1386 static PyTypeObject xu_buffer_type = {
1387 PyObject_HEAD_INIT(&PyType_Type)
1388 0,
1389 "buffer",
1390 sizeof(xu_buffer_object),
1391 0,
1392 xu_buffer_dealloc, /* tp_dealloc */
1393 NULL, /* tp_print */
1394 xu_buffer_getattr, /* tp_getattr */
1395 NULL, /* tp_setattr */
1396 NULL, /* tp_compare */
1397 NULL, /* tp_repr */
1398 NULL, /* tp_as_number */
1399 NULL, /* tp_as_sequence */
1400 NULL, /* tp_as_mapping */
1401 NULL /* tp_hash */
1402 };
1406 /*
1407 * *********************** MODULE WRAPPER ***********************
1408 */
1410 static void handle_child_death(int dummy)
1412 while ( waitpid(-1, NULL, WNOHANG) > 0 )
1413 continue;
1416 static PyObject *xu_autoreap(PyObject *self, PyObject *args)
1418 struct sigaction sa;
1420 if ( !PyArg_ParseTuple(args, "") )
1421 return NULL;
1423 memset(&sa, 0, sizeof(sa));
1424 sa.sa_handler = handle_child_death;
1425 sigemptyset(&sa.sa_mask);
1426 sa.sa_flags = SA_NOCLDSTOP | SA_RESTART;
1427 (void)sigaction(SIGCHLD, &sa, NULL);
1429 Py_INCREF(Py_None);
1430 return Py_None;
1433 static PyMethodDef xu_methods[] = {
1434 { "notifier", xu_notifier_new, METH_VARARGS,
1435 "Create a new notifier." },
1436 { "message", xu_message_new, METH_VARARGS,
1437 "Create a new communications message." },
1438 { "port", xu_port_new, METH_VARARGS,
1439 "Create a new communications port." },
1440 { "buffer", xu_buffer_new, METH_VARARGS,
1441 "Create a new ring buffer." },
1442 { "autoreap", xu_autoreap, METH_VARARGS,
1443 "Ensure that zombie children are automatically reaped by the OS." },
1444 { NULL, NULL, 0, NULL }
1445 };
1447 PyMODINIT_FUNC initxu(void)
1449 PyObject *m, *d;
1451 m = Py_InitModule(XENPKG, xu_methods);
1453 d = PyModule_GetDict(m);
1454 port_error = PyErr_NewException(XENPKG ".PortError", NULL, NULL);
1455 PyDict_SetItemString(d, "PortError", port_error);
1457 /* KAF: This ensures that we get debug output in a timely manner. */
1458 setbuf(stdout, NULL);
1459 setbuf(stderr, NULL);