ia64/xen-unstable

changeset 1180:9a2d0dca20c1

bitkeeper revision 1.795 (4054a3055ggg3MJTpSU1-ZFQRfQQ5g)

xend.py, setup.py:
new file
Many files:
Rewritten the Xen control daemon in Python, with C extensions for the low-level bits. All our Python libraries now throw exceptions on error rather than returning error codes --- this will require our higher-level scripts to be updated at some point.
author kaf24@scramble.cl.cam.ac.uk
date Sun Mar 14 18:23:01 2004 +0000 (2004-03-14)
parents 39a4998c88fc
children fe871cc66b5a
files .rootkeys tools/examples/xc_dom_create.py tools/xc/py/Makefile tools/xc/py/Xc.c tools/xc/py/XenoUtil.py tools/xend/Makefile tools/xend/setup.py tools/xend/xend.py tools/xend/xend_utils.c tools/xentrace/Makefile xenolinux-2.4.25-sparse/arch/xeno/drivers/console/console.c xenolinux-2.4.25-sparse/include/asm-xeno/control_if.h
line diff
     1.1 --- a/.rootkeys	Fri Mar 12 18:12:23 2004 +0000
     1.2 +++ b/.rootkeys	Sun Mar 14 18:23:01 2004 +0000
     1.3 @@ -89,6 +89,8 @@ 3fbd0a42l40lM0IICw2jXbQBVZSdZg tools/xc/
     1.4  3fbd4bd6GtGwZGxYUJPOheYIR7bPaA tools/xc/py/XenoUtil.py
     1.5  3fbd0a40yT6G3M9hMpaz5xTUdl0E4g tools/xc/py/setup.py
     1.6  40431ac64Hj4ixUnKmlugZKhXPFE_Q tools/xend/Makefile
     1.7 +4054a2fdkdATEnRw-U7AUlgu-6JiUA tools/xend/setup.py
     1.8 +4054a301VEag2GwrBrFBna5U1BGlLA tools/xend/xend.py
     1.9  40431ac8wrUEj-XM7B8smFtx_HA7lQ tools/xend/xend_utils.c
    1.10  403a3edbrr8RE34gkbR40zep98SXbg tools/xentrace/Makefile
    1.11  4050c413PhhLNAYk3TEwP37i_iLw9Q tools/xentrace/xentrace.8
     2.1 --- a/tools/examples/xc_dom_create.py	Fri Mar 12 18:12:23 2004 +0000
     2.2 +++ b/tools/examples/xc_dom_create.py	Sun Mar 14 18:23:01 2004 +0000
     2.3 @@ -237,9 +237,14 @@ def make_domain():
     2.4              xc.domain_destroy ( dom=id )
     2.5              sys.exit()
     2.6  
     2.7 -    ports = xc.evtchn_open( dom2=id )
     2.8 -    if not ports:
     2.9 +    cmsg = 'new_control_interface(dom='+str(id)+')'
    2.10 +    xend_response = XenoUtil.xend_control_message(cmsg)
    2.11 +    if not xend_response['success']:
    2.12          print "Error creating initial event channel"
    2.13 +        print "Error type: " + xend_response['error_type']
    2.14 +        if xend_response['error_type'] == 'exception':
    2.15 +            print "Exception type: " + xend_response['exception_type']
    2.16 +            print "Exception value: " + xend_response['exception_value']
    2.17          xc.domain_destroy ( dom=id )
    2.18          sys.exit()
    2.19  
    2.20 @@ -292,7 +297,7 @@ def make_domain():
    2.21          xc.domain_destroy ( dom=id )
    2.22          sys.exit()
    2.23  
    2.24 -    return (id, 9600+ports['port1'])
    2.25 +    return (id, xend_response['console_port'])
    2.26  # end of make_domain()
    2.27  
    2.28  def mkpidfile():
     3.1 --- a/tools/xc/py/Makefile	Fri Mar 12 18:12:23 2004 +0000
     3.2 +++ b/tools/xc/py/Makefile	Sun Mar 14 18:23:01 2004 +0000
     3.3 @@ -1,5 +1,5 @@
     3.4  
     3.5 -all: ../lib/libxc.so.1.3.0 ../lib/xc.h
     3.6 +all:
     3.7  	python setup.py build
     3.8  
     3.9  install: all
     4.1 --- a/tools/xc/py/Xc.c	Fri Mar 12 18:12:23 2004 +0000
     4.2 +++ b/tools/xc/py/Xc.c	Sun Mar 14 18:23:01 2004 +0000
     4.3 @@ -1,19 +1,13 @@
     4.4  /******************************************************************************
     4.5   * Xc.c
     4.6   * 
     4.7 - * Copyright (c) 2003, K A Fraser
     4.8 + * Copyright (c) 2003-2004, K A Fraser (University of Cambridge)
     4.9   */
    4.10  
    4.11  #include <Python.h>
    4.12  #include <xc.h>
    4.13  
    4.14 -#if 1
    4.15 -#define DPRINTF(_f, _a...)                  \
    4.16 -    fprintf(stderr, "%s:%s:%d:: " _f "\n" , \
    4.17 -            __FILE__ , __FUNCTION__ , __LINE__ , ## _a)
    4.18 -#else
    4.19 -#define DPRINTF(_f, _a...) ((void)0)
    4.20 -#endif
    4.21 +static PyObject *xc_error, *zero;
    4.22  
    4.23  typedef struct {
    4.24      PyObject_HEAD;
    4.25 @@ -39,13 +33,10 @@ static PyObject *pyxc_domain_create(PyOb
    4.26  
    4.27      if ( !PyArg_ParseTupleAndKeywords(args, kwds, "|is", kwd_list, 
    4.28                                        &mem_kb, &name) )
    4.29 -    {
    4.30 -        DPRINTF("could not parse parameter list.");
    4.31          return NULL;
    4.32 -    }
    4.33  
    4.34      if ( (ret = xc_domain_create(xc->xc_handle, mem_kb, name, &dom)) < 0 )
    4.35 -        return PyLong_FromLong(ret);
    4.36 +        return PyErr_SetFromErrno(xc_error);
    4.37  
    4.38      return PyLong_FromUnsignedLongLong(dom);
    4.39  }
    4.40 @@ -57,19 +48,17 @@ static PyObject *pyxc_domain_start(PyObj
    4.41      XcObject *xc = (XcObject *)self;
    4.42  
    4.43      u64 dom;
    4.44 -    int ret;
    4.45  
    4.46      static char *kwd_list[] = { "dom", NULL };
    4.47  
    4.48      if ( !PyArg_ParseTupleAndKeywords(args, kwds, "L", kwd_list, &dom) )
    4.49 -    {
    4.50 -        DPRINTF("could not parse parameter list.");
    4.51          return NULL;
    4.52 -    }
    4.53  
    4.54 -    ret = xc_domain_start(xc->xc_handle, dom);
    4.55 +    if ( xc_domain_start(xc->xc_handle, dom) != 0 )
    4.56 +        return PyErr_SetFromErrno(xc_error);
    4.57      
    4.58 -    return PyInt_FromLong(ret);
    4.59 +    Py_INCREF(zero);
    4.60 +    return zero;
    4.61  }
    4.62  
    4.63  static PyObject *pyxc_domain_stop(PyObject *self,
    4.64 @@ -79,19 +68,17 @@ static PyObject *pyxc_domain_stop(PyObje
    4.65      XcObject *xc = (XcObject *)self;
    4.66  
    4.67      u64 dom;
    4.68 -    int ret;
    4.69  
    4.70      static char *kwd_list[] = { "dom", NULL };
    4.71  
    4.72      if ( !PyArg_ParseTupleAndKeywords(args, kwds, "L", kwd_list, &dom) )
    4.73 -    {
    4.74 -        DPRINTF("could not parse parameter list.");
    4.75          return NULL;
    4.76 -    }
    4.77  
    4.78 -    ret = xc_domain_stop(xc->xc_handle, dom);
    4.79 +    if ( xc_domain_stop(xc->xc_handle, dom) != 0 )
    4.80 +        return PyErr_SetFromErrno(xc_error);
    4.81      
    4.82 -    return PyInt_FromLong(ret);
    4.83 +    Py_INCREF(zero);
    4.84 +    return zero;
    4.85  }
    4.86  
    4.87  static PyObject *pyxc_domain_destroy(PyObject *self,
    4.88 @@ -101,20 +88,19 @@ static PyObject *pyxc_domain_destroy(PyO
    4.89      XcObject *xc = (XcObject *)self;
    4.90  
    4.91      u64 dom;
    4.92 -    int force = 0, ret;
    4.93 +    int force = 0;
    4.94  
    4.95      static char *kwd_list[] = { "dom", "force", NULL };
    4.96  
    4.97      if ( !PyArg_ParseTupleAndKeywords(args, kwds, "L|i", kwd_list, 
    4.98                                        &dom, &force) )
    4.99 -    {
   4.100 -        DPRINTF("could not parse parameter list.");
   4.101          return NULL;
   4.102 -    }
   4.103  
   4.104 -    ret = xc_domain_destroy(xc->xc_handle, dom, force);
   4.105 +    if ( xc_domain_destroy(xc->xc_handle, dom, force) != 0 )
   4.106 +        return PyErr_SetFromErrno(xc_error);
   4.107      
   4.108 -    return PyInt_FromLong(ret);
   4.109 +    Py_INCREF(zero);
   4.110 +    return zero;
   4.111  }
   4.112  
   4.113  static PyObject *pyxc_domain_pincpu(PyObject *self,
   4.114 @@ -124,20 +110,19 @@ static PyObject *pyxc_domain_pincpu(PyOb
   4.115      XcObject *xc = (XcObject *)self;
   4.116  
   4.117      u64 dom;
   4.118 -    int cpu = -1, ret;
   4.119 +    int cpu = -1;
   4.120  
   4.121      static char *kwd_list[] = { "dom", "cpu", NULL };
   4.122  
   4.123      if ( !PyArg_ParseTupleAndKeywords(args, kwds, "L|i", kwd_list, 
   4.124                                        &dom, &cpu) )
   4.125 -    {
   4.126 -        DPRINTF("could not parse parameter list.");
   4.127          return NULL;
   4.128 -    }
   4.129  
   4.130 -    ret = xc_domain_pincpu(xc->xc_handle, dom, cpu);
   4.131 +    if ( xc_domain_pincpu(xc->xc_handle, dom, cpu) != 0 )
   4.132 +        return PyErr_SetFromErrno(xc_error);
   4.133      
   4.134 -    return PyInt_FromLong(ret);
   4.135 +    Py_INCREF(zero);
   4.136 +    return zero;
   4.137  }
   4.138  
   4.139  static PyObject *pyxc_domain_getinfo(PyObject *self,
   4.140 @@ -155,20 +140,12 @@ static PyObject *pyxc_domain_getinfo(PyO
   4.141      
   4.142      if ( !PyArg_ParseTupleAndKeywords(args, kwds, "|Li", kwd_list,
   4.143                                        &first_dom, &max_doms) )
   4.144 -    {
   4.145 -        DPRINTF("could not parse parameter list.");
   4.146          return NULL;
   4.147 -    }
   4.148  
   4.149      if ( (info = malloc(max_doms * sizeof(xc_dominfo_t))) == NULL )
   4.150 -    {
   4.151 -        DPRINTF("out of memory.");
   4.152 -        nr_doms = 0;
   4.153 -    }
   4.154 -    else
   4.155 -    {
   4.156 -        nr_doms = xc_domain_getinfo(xc->xc_handle, first_dom, max_doms, info);
   4.157 -    }
   4.158 +        return PyErr_NoMemory();
   4.159 +
   4.160 +    nr_doms = xc_domain_getinfo(xc->xc_handle, first_dom, max_doms, info);
   4.161      
   4.162      list = PyList_New(nr_doms);
   4.163      for ( i = 0 ; i < nr_doms; i++ )
   4.164 @@ -185,8 +162,7 @@ static PyObject *pyxc_domain_getinfo(PyO
   4.165                            "name",     info[i].name));
   4.166      }
   4.167  
   4.168 -    if ( info != NULL )
   4.169 -        free(info);
   4.170 +    free(info);
   4.171  
   4.172      return list;
   4.173  }
   4.174 @@ -199,20 +175,19 @@ static PyObject *pyxc_linux_save(PyObjec
   4.175  
   4.176      u64   dom;
   4.177      char *state_file;
   4.178 -    int   progress = 1, ret;
   4.179 +    int   progress = 1;
   4.180  
   4.181      static char *kwd_list[] = { "dom", "state_file", "progress", NULL };
   4.182  
   4.183      if ( !PyArg_ParseTupleAndKeywords(args, kwds, "Ls|i", kwd_list, 
   4.184                                        &dom, &state_file, &progress) )
   4.185 -    {
   4.186 -        DPRINTF("could not parse parameter list.");
   4.187          return NULL;
   4.188 -    }
   4.189  
   4.190 -    ret = xc_linux_save(xc->xc_handle, dom, state_file, progress);
   4.191 +    if ( xc_linux_save(xc->xc_handle, dom, state_file, progress) != 0 )
   4.192 +        return PyErr_SetFromErrno(xc_error);
   4.193      
   4.194 -    return PyInt_FromLong(ret);
   4.195 +    Py_INCREF(zero);
   4.196 +    return zero;
   4.197  }
   4.198  
   4.199  static PyObject *pyxc_linux_restore(PyObject *self,
   4.200 @@ -222,21 +197,17 @@ static PyObject *pyxc_linux_restore(PyOb
   4.201      XcObject *xc = (XcObject *)self;
   4.202  
   4.203      char        *state_file;
   4.204 -    int          progress = 1, ret;
   4.205 +    int          progress = 1;
   4.206      u64          dom;
   4.207  
   4.208      static char *kwd_list[] = { "state_file", "progress", NULL };
   4.209  
   4.210      if ( !PyArg_ParseTupleAndKeywords(args, kwds, "s|i", kwd_list, 
   4.211                                        &state_file, &progress) )
   4.212 -    {
   4.213 -        DPRINTF("could not parse parameter list.");
   4.214          return NULL;
   4.215 -    }
   4.216  
   4.217 -    ret = xc_linux_restore(xc->xc_handle, state_file, progress, &dom);
   4.218 -    if ( ret < 0 )
   4.219 -        return PyLong_FromLong(ret);
   4.220 +    if ( xc_linux_restore(xc->xc_handle, state_file, progress, &dom) != 0 )
   4.221 +        return PyErr_SetFromErrno(xc_error);
   4.222  
   4.223      return PyLong_FromUnsignedLongLong(dom);
   4.224  }
   4.225 @@ -249,20 +220,18 @@ static PyObject *pyxc_linux_build(PyObje
   4.226  
   4.227      u64   dom;
   4.228      char *image, *ramdisk = NULL, *cmdline = "";
   4.229 -    int   ret;
   4.230  
   4.231      static char *kwd_list[] = { "dom", "image", "ramdisk", "cmdline", NULL };
   4.232  
   4.233      if ( !PyArg_ParseTupleAndKeywords(args, kwds, "Ls|ss", kwd_list, 
   4.234                                        &dom, &image, &ramdisk, &cmdline) )
   4.235 -    {
   4.236 -        DPRINTF("could not parse parameter list.");
   4.237          return NULL;
   4.238 -    }
   4.239  
   4.240 -    ret = xc_linux_build(xc->xc_handle, dom, image, ramdisk, cmdline);
   4.241 +    if ( xc_linux_build(xc->xc_handle, dom, image, ramdisk, cmdline) != 0 )
   4.242 +        return PyErr_SetFromErrno(xc_error);
   4.243      
   4.244 -    return PyInt_FromLong(ret);
   4.245 +    Py_INCREF(zero);
   4.246 +    return zero;
   4.247  }
   4.248  
   4.249  static PyObject *pyxc_netbsd_build(PyObject *self,
   4.250 @@ -273,20 +242,18 @@ static PyObject *pyxc_netbsd_build(PyObj
   4.251  
   4.252      u64   dom;
   4.253      char *image, *ramdisk = NULL, *cmdline = "";
   4.254 -    int   ret;
   4.255  
   4.256      static char *kwd_list[] = { "dom", "image", "ramdisk", "cmdline", NULL };
   4.257  
   4.258      if ( !PyArg_ParseTupleAndKeywords(args, kwds, "Ls|ss", kwd_list, 
   4.259                                        &dom, &image, &ramdisk, &cmdline) )
   4.260 -    {
   4.261 -        DPRINTF("could not parse parameter list.");
   4.262          return NULL;
   4.263 -    }
   4.264  
   4.265 -    ret = xc_netbsd_build(xc->xc_handle, dom, image, cmdline);
   4.266 +    if ( xc_netbsd_build(xc->xc_handle, dom, image, cmdline) != 0 )
   4.267 +        return PyErr_SetFromErrno(xc_error);
   4.268      
   4.269 -    return PyInt_FromLong(ret);
   4.270 +    Py_INCREF(zero);
   4.271 +    return zero;
   4.272  }
   4.273  
   4.274  static PyObject *pyxc_bvtsched_global_set(PyObject *self,
   4.275 @@ -296,19 +263,17 @@ static PyObject *pyxc_bvtsched_global_se
   4.276      XcObject *xc = (XcObject *)self;
   4.277  
   4.278      unsigned long ctx_allow;
   4.279 -    int           ret;
   4.280  
   4.281      static char *kwd_list[] = { "ctx_allow", NULL };
   4.282  
   4.283      if ( !PyArg_ParseTupleAndKeywords(args, kwds, "l", kwd_list, &ctx_allow) )
   4.284 -    {
   4.285 -        DPRINTF("could not parse parameter list.");
   4.286          return NULL;
   4.287 -    }
   4.288  
   4.289 -    ret = xc_bvtsched_global_set(xc->xc_handle, ctx_allow);
   4.290 +    if ( xc_bvtsched_global_set(xc->xc_handle, ctx_allow) != 0 )
   4.291 +        return PyErr_SetFromErrno(xc_error);
   4.292      
   4.293 -    return PyInt_FromLong(ret);
   4.294 +    Py_INCREF(zero);
   4.295 +    return zero;
   4.296  }
   4.297  
   4.298  static PyObject *pyxc_bvtsched_domain_set(PyObject *self,
   4.299 @@ -319,22 +284,20 @@ static PyObject *pyxc_bvtsched_domain_se
   4.300  
   4.301      u64           dom;
   4.302      unsigned long mcuadv, warp, warpl, warpu;
   4.303 -    int           ret;
   4.304  
   4.305      static char *kwd_list[] = { "dom", "mcuadv", "warp", "warpl", 
   4.306                                  "warpu", NULL };
   4.307  
   4.308      if ( !PyArg_ParseTupleAndKeywords(args, kwds, "Lllll", kwd_list, 
   4.309                                        &dom, &mcuadv, &warp, &warpl, &warpu) )
   4.310 -    {
   4.311 -        DPRINTF("could not parse parameter list.");
   4.312          return NULL;
   4.313 -    }
   4.314  
   4.315 -    ret = xc_bvtsched_domain_set(xc->xc_handle, dom, mcuadv, 
   4.316 -                                 warp, warpl, warpu);
   4.317 +    if ( xc_bvtsched_domain_set(xc->xc_handle, dom, mcuadv, 
   4.318 +                                warp, warpl, warpu) != 0 )
   4.319 +        return PyErr_SetFromErrno(xc_error);
   4.320      
   4.321 -    return PyInt_FromLong(ret);
   4.322 +    Py_INCREF(zero);
   4.323 +    return zero;
   4.324  }
   4.325  
   4.326  static PyObject *pyxc_vif_scheduler_set(PyObject *self,
   4.327 @@ -346,7 +309,6 @@ static PyObject *pyxc_vif_scheduler_set(
   4.328      u64           dom;
   4.329      unsigned int  vif;
   4.330      xc_vif_sched_params_t sched = { 0, 0 };
   4.331 -    int           ret;
   4.332  
   4.333      static char *kwd_list[] = { "dom", "vif", "credit_bytes", 
   4.334                                  "credit_usecs", NULL };
   4.335 @@ -355,14 +317,13 @@ static PyObject *pyxc_vif_scheduler_set(
   4.336                                        &dom, &vif, 
   4.337                                        &sched.credit_bytes, 
   4.338                                        &sched.credit_usec) )
   4.339 -    {
   4.340 -        DPRINTF("could not parse parameter list.");
   4.341          return NULL;
   4.342 -    }
   4.343  
   4.344 -    ret = xc_vif_scheduler_set(xc->xc_handle, dom, vif, &sched);
   4.345 +    if ( xc_vif_scheduler_set(xc->xc_handle, dom, vif, &sched) != 0 )
   4.346 +        return PyErr_SetFromErrno(xc_error);
   4.347      
   4.348 -    return PyInt_FromLong(ret);
   4.349 +    Py_INCREF(zero);
   4.350 +    return zero;
   4.351  }
   4.352  
   4.353  static PyObject *pyxc_vif_scheduler_get(PyObject *self,
   4.354 @@ -370,32 +331,23 @@ static PyObject *pyxc_vif_scheduler_get(
   4.355                                          PyObject *kwds)
   4.356  {
   4.357      XcObject *xc = (XcObject *)self;
   4.358 -    PyObject *dict;
   4.359  
   4.360      u64           dom;
   4.361      unsigned int  vif;
   4.362      xc_vif_sched_params_t sched;
   4.363 -    int           ret;
   4.364  
   4.365      static char *kwd_list[] = { "dom", "vif", NULL };
   4.366  
   4.367      if ( !PyArg_ParseTupleAndKeywords(args, kwds, "Li", kwd_list, 
   4.368                                        &dom, &vif) )
   4.369 -    {
   4.370 -        DPRINTF("could not parse parameter list.");
   4.371          return NULL;
   4.372 -    }
   4.373 -
   4.374 -    ret = xc_vif_scheduler_get(xc->xc_handle, dom, vif, &sched);
   4.375  
   4.376 -    if ( ret < 0 )
   4.377 -        dict = Py_BuildValue("{}");
   4.378 -    else
   4.379 -        dict = Py_BuildValue("{s:l,s:l}", 
   4.380 -                             "credit_bytes", sched.credit_bytes,
   4.381 -                             "credit_usecs", sched.credit_usec);
   4.382 -    
   4.383 -    return dict;
   4.384 +    if ( xc_vif_scheduler_get(xc->xc_handle, dom, vif, &sched) != 0 )
   4.385 +        return PyErr_SetFromErrno(xc_error);
   4.386 +
   4.387 +    return Py_BuildValue("{s:l,s:l}", 
   4.388 +                         "credit_bytes", sched.credit_bytes,
   4.389 +                         "credit_usecs", sched.credit_usec);
   4.390  }
   4.391  
   4.392  static PyObject *pyxc_vif_stats_get(PyObject *self,
   4.393 @@ -403,34 +355,25 @@ static PyObject *pyxc_vif_stats_get(PyOb
   4.394                                      PyObject *kwds)
   4.395  {
   4.396      XcObject *xc = (XcObject *)self;
   4.397 -    PyObject *dict;
   4.398  
   4.399      u64            dom;
   4.400      unsigned int   vif;
   4.401      xc_vif_stats_t stats;
   4.402 -    int            ret;
   4.403  
   4.404      static char *kwd_list[] = { "dom", "vif", NULL };
   4.405  
   4.406      if ( !PyArg_ParseTupleAndKeywords(args, kwds, "Li", kwd_list, 
   4.407                                        &dom, &vif) )
   4.408 -    {
   4.409 -        DPRINTF("could not parse parameter list.");
   4.410          return NULL;
   4.411 -    }
   4.412  
   4.413 -    ret = xc_vif_stats_get(xc->xc_handle, dom, vif, &stats);
   4.414 +    if ( xc_vif_stats_get(xc->xc_handle, dom, vif, &stats) != 0 )
   4.415 +        return PyErr_SetFromErrno(xc_error);
   4.416  
   4.417 -    if ( ret < 0 )
   4.418 -        dict = Py_BuildValue("{}");
   4.419 -    else
   4.420 -        dict = Py_BuildValue("{s:L,s:L,s:L,s:L}", 
   4.421 -                             "tx_bytes", stats.tx_bytes,
   4.422 -                             "tx_packets", stats.tx_pkts,
   4.423 -                             "rx_bytes", stats.rx_bytes,
   4.424 -                             "rx_packets", stats.rx_pkts);
   4.425 -    
   4.426 -    return dict;
   4.427 +    return Py_BuildValue("{s:L,s:L,s:L,s:L}", 
   4.428 +                         "tx_bytes", stats.tx_bytes,
   4.429 +                         "tx_packets", stats.tx_pkts,
   4.430 +                         "rx_bytes", stats.rx_bytes,
   4.431 +                         "rx_packets", stats.rx_pkts);
   4.432  }
   4.433  
   4.434  static PyObject *pyxc_vbd_create(PyObject *self,
   4.435 @@ -441,20 +384,19 @@ static PyObject *pyxc_vbd_create(PyObjec
   4.436  
   4.437      u64          dom;
   4.438      unsigned int vbd;
   4.439 -    int          writeable, ret;
   4.440 +    int          writeable;
   4.441  
   4.442      static char *kwd_list[] = { "dom", "vbd", "writeable", NULL };
   4.443  
   4.444      if ( !PyArg_ParseTupleAndKeywords(args, kwds, "Lii", kwd_list, 
   4.445                                        &dom, &vbd, &writeable) )
   4.446 -    {
   4.447 -        DPRINTF("could not parse parameter list.");
   4.448          return NULL;
   4.449 -    }
   4.450  
   4.451 -    ret = xc_vbd_create(xc->xc_handle, dom, vbd, writeable);
   4.452 -    
   4.453 -    return PyInt_FromLong(ret);
   4.454 +    if ( xc_vbd_create(xc->xc_handle, dom, vbd, writeable) != 0 )
   4.455 +        return PyErr_SetFromErrno(xc_error);
   4.456 +
   4.457 +    Py_INCREF(zero);
   4.458 +    return zero;
   4.459  }
   4.460  
   4.461  static PyObject *pyxc_vbd_destroy(PyObject *self,
   4.462 @@ -465,20 +407,18 @@ static PyObject *pyxc_vbd_destroy(PyObje
   4.463  
   4.464      u64          dom;
   4.465      unsigned int vbd;
   4.466 -    int          ret;
   4.467  
   4.468      static char *kwd_list[] = { "dom", "vbd", NULL };
   4.469  
   4.470      if ( !PyArg_ParseTupleAndKeywords(args, kwds, "Li", kwd_list, 
   4.471                                        &dom, &vbd) )
   4.472 -    {
   4.473 -        DPRINTF("could not parse parameter list.");
   4.474          return NULL;
   4.475 -    }
   4.476  
   4.477 -    ret = xc_vbd_destroy(xc->xc_handle, dom, vbd);
   4.478 -    
   4.479 -    return PyInt_FromLong(ret);
   4.480 +    if ( xc_vbd_destroy(xc->xc_handle, dom, vbd) != 0 )
   4.481 +        return PyErr_SetFromErrno(xc_error);
   4.482 +
   4.483 +    Py_INCREF(zero);
   4.484 +    return zero;
   4.485  }
   4.486  
   4.487  static PyObject *pyxc_vbd_grow(PyObject *self,
   4.488 @@ -490,7 +430,6 @@ static PyObject *pyxc_vbd_grow(PyObject 
   4.489      u64            dom;
   4.490      unsigned int   vbd;
   4.491      xc_vbdextent_t extent;
   4.492 -    int            ret;
   4.493  
   4.494      static char *kwd_list[] = { "dom", "vbd", "device", 
   4.495                                  "start_sector", "nr_sectors", NULL };
   4.496 @@ -500,14 +439,13 @@ static PyObject *pyxc_vbd_grow(PyObject 
   4.497                                        &extent.real_device, 
   4.498                                        &extent.start_sector, 
   4.499                                        &extent.nr_sectors) )
   4.500 -    {
   4.501 -        DPRINTF("could not parse parameter list.");
   4.502          return NULL;
   4.503 -    }
   4.504  
   4.505 -    ret = xc_vbd_grow(xc->xc_handle, dom, vbd, &extent);
   4.506 -    
   4.507 -    return PyInt_FromLong(ret);
   4.508 +    if ( xc_vbd_grow(xc->xc_handle, dom, vbd, &extent) != 0 )
   4.509 +        return PyErr_SetFromErrno(xc_error);
   4.510 +
   4.511 +    Py_INCREF(zero);
   4.512 +    return zero;
   4.513  }
   4.514  
   4.515  static PyObject *pyxc_vbd_shrink(PyObject *self,
   4.516 @@ -518,20 +456,18 @@ static PyObject *pyxc_vbd_shrink(PyObjec
   4.517  
   4.518      u64          dom;
   4.519      unsigned int vbd;
   4.520 -    int          ret;
   4.521  
   4.522      static char *kwd_list[] = { "dom", "vbd", NULL };
   4.523  
   4.524      if ( !PyArg_ParseTupleAndKeywords(args, kwds, "Li", kwd_list, 
   4.525                                        &dom, &vbd) )
   4.526 -    {
   4.527 -        DPRINTF("could not parse parameter list.");
   4.528          return NULL;
   4.529 -    }
   4.530  
   4.531 -    ret = xc_vbd_shrink(xc->xc_handle, dom, vbd);
   4.532 -    
   4.533 -    return PyInt_FromLong(ret);
   4.534 +    if ( xc_vbd_shrink(xc->xc_handle, dom, vbd) != 0 )
   4.535 +        return PyErr_SetFromErrno(xc_error);
   4.536 +
   4.537 +    Py_INCREF(zero);
   4.538 +    return zero;
   4.539  }
   4.540  
   4.541  static PyObject *pyxc_vbd_setextents(PyObject *self,
   4.542 @@ -544,44 +480,38 @@ static PyObject *pyxc_vbd_setextents(PyO
   4.543      u64             dom;
   4.544      unsigned int    vbd;
   4.545      xc_vbdextent_t *extents = NULL;
   4.546 -    int             ret, i, nr_extents;
   4.547 +    int             i, nr_extents;
   4.548  
   4.549      static char *kwd_list[] = { "dom", "vbd", "extents", NULL };
   4.550  
   4.551      if ( !PyArg_ParseTupleAndKeywords(args, kwds, "LiO", kwd_list, 
   4.552                                        &dom, &vbd, &list) )
   4.553 +        return NULL;
   4.554 +
   4.555 +    if ( !PyList_Check(list) )
   4.556      {
   4.557 -        DPRINTF("could not parse parameter list.");
   4.558 -        goto fail;
   4.559 +        PyErr_SetString(PyExc_TypeError, "parameter 'extents' is not a list");
   4.560 +        return NULL;
   4.561      }
   4.562  
   4.563 -    if ( (nr_extents = PyList_Size(list)) < 0 )
   4.564 +    if ( (nr_extents = PyList_Size(list)) != 0 )
   4.565      {
   4.566 -        DPRINTF("parameter 'extents' is not a list.");
   4.567 -        goto fail;
   4.568 -    }
   4.569 -
   4.570 -    if ( nr_extents != 0 )
   4.571 -    {
   4.572 -        extents = malloc(nr_extents * sizeof(xc_vbdextent_t));
   4.573 -        if ( extents == NULL )
   4.574 -        {
   4.575 -            DPRINTF("out of memory.");
   4.576 -            goto fail;
   4.577 -        }
   4.578 +        if ( (extents = malloc(nr_extents * sizeof(xc_vbdextent_t))) == NULL )
   4.579 +            return PyErr_NoMemory();
   4.580  
   4.581          for ( i = 0; i < nr_extents; i++ )
   4.582          {
   4.583              dict = PyList_GetItem(list, i);
   4.584              if ( !PyDict_Check(dict) )
   4.585              {
   4.586 -                DPRINTF("extent %d -- extent is not a dictionary.", i);
   4.587 +                PyErr_SetString(PyExc_TypeError, "extent is not a dictionary");
   4.588                  goto fail;
   4.589              }
   4.590  
   4.591              if ( (obj = PyDict_GetItemString(dict, "device")) == NULL )
   4.592              {
   4.593 -                DPRINTF("extent %d -- 'device' is not in the dictionary.", i);
   4.594 +                PyErr_SetString(PyExc_TypeError,
   4.595 +                                "'device' is not in the dictionary");
   4.596                  goto fail;
   4.597              }
   4.598              if ( PyInt_Check(obj) )
   4.599 @@ -594,14 +524,15 @@ static PyObject *pyxc_vbd_setextents(PyO
   4.600              }
   4.601              else
   4.602              {
   4.603 -                DPRINTF("extent %d -- 'device' is not an int or long.", i);
   4.604 +                PyErr_SetString(PyExc_TypeError,
   4.605 +                                "'device' is not an int or long");
   4.606                  goto fail;
   4.607              }
   4.608  
   4.609              if ( (obj = PyDict_GetItemString(dict, "start_sector")) == NULL )
   4.610              {
   4.611 -                DPRINTF("extent %d -- 'start_sector' is not "
   4.612 -                        "in the dictionary.", i);
   4.613 +                PyErr_SetString(PyExc_TypeError,
   4.614 +                                "'start_sector' is not in the dictionary");
   4.615                  goto fail;
   4.616              }
   4.617              if ( PyInt_Check(obj) )
   4.618 @@ -614,15 +545,15 @@ static PyObject *pyxc_vbd_setextents(PyO
   4.619              }
   4.620              else
   4.621              {
   4.622 -                DPRINTF("extent %d -- 'start_sector' is not "
   4.623 -                        "an int or long.", i);
   4.624 +                PyErr_SetString(PyExc_TypeError,
   4.625 +                                "'start_sector' is not an int or long");
   4.626                  goto fail;
   4.627              }
   4.628  
   4.629              if ( (obj = PyDict_GetItemString(dict, "nr_sectors")) == NULL )
   4.630              {
   4.631 -                DPRINTF("extent %d -- 'nr_sectors' is not "
   4.632 -                        "in the dictionary.", i);
   4.633 +                PyErr_SetString(PyExc_TypeError,
   4.634 +                                "'nr_sectors' is not in the dictionary");
   4.635                  goto fail;
   4.636              }
   4.637              if ( PyInt_Check(obj) )
   4.638 @@ -635,19 +566,24 @@ static PyObject *pyxc_vbd_setextents(PyO
   4.639              }
   4.640              else
   4.641              {
   4.642 -                DPRINTF("extent %d -- 'nr_sectors' is not "
   4.643 -                        "an int or long.", i);
   4.644 +                PyErr_SetString(PyExc_TypeError,
   4.645 +                                "'nr_sectors' is not an int or long");
   4.646                  goto fail;
   4.647              }
   4.648          }
   4.649      }
   4.650  
   4.651 -    ret = xc_vbd_setextents(xc->xc_handle, dom, vbd, nr_extents, extents);
   4.652 -    
   4.653 +    if ( xc_vbd_setextents(xc->xc_handle, dom, vbd, nr_extents, extents) != 0 )
   4.654 +    {
   4.655 +        PyErr_SetFromErrno(xc_error);
   4.656 +        goto fail;
   4.657 +    }
   4.658 +
   4.659      if ( extents != NULL )
   4.660          free(extents);
   4.661      
   4.662 -    return PyInt_FromLong(ret);
   4.663 +    Py_INCREF(zero);
   4.664 +    return zero;
   4.665  
   4.666   fail:
   4.667      if ( extents != NULL )
   4.668 @@ -666,51 +602,38 @@ static PyObject *pyxc_vbd_getextents(PyO
   4.669      u64             dom;
   4.670      unsigned int    vbd;
   4.671      xc_vbdextent_t *extents;
   4.672 -    int             i, nr_extents, max_extents;
   4.673 +    int             i, nr_extents;
   4.674  
   4.675      static char *kwd_list[] = { "dom", "vbd", NULL };
   4.676  
   4.677      if ( !PyArg_ParseTupleAndKeywords(args, kwds, "Li", kwd_list, 
   4.678                                        &dom, &vbd) )
   4.679 -    {
   4.680 -        DPRINTF("could not parse parameter list.");
   4.681          return NULL;
   4.682 -    }
   4.683  
   4.684 -    extents = malloc(MAX_EXTENTS * sizeof(xc_vbdextent_t));
   4.685 -    if ( extents == NULL )
   4.686 -    {
   4.687 -        DPRINTF("out of memory.");
   4.688 -        max_extents = 0;
   4.689 -    }
   4.690 -    else
   4.691 -    {
   4.692 -        max_extents = MAX_EXTENTS;
   4.693 -    }
   4.694 +    if ( (extents = malloc(MAX_EXTENTS * sizeof(xc_vbdextent_t))) == NULL )
   4.695 +        return PyErr_NoMemory();
   4.696  
   4.697 -    nr_extents = xc_vbd_getextents(xc->xc_handle, dom, vbd, max_extents,
   4.698 +    nr_extents = xc_vbd_getextents(xc->xc_handle, dom, vbd, MAX_EXTENTS,
   4.699                                     extents, NULL);
   4.700      
   4.701 -    if ( nr_extents <= 0 )
   4.702 -    {
   4.703 -        list = PyList_New(0);
   4.704 -    }
   4.705 -    else
   4.706 +    if ( nr_extents < 0 )
   4.707      {
   4.708 -        list = PyList_New(nr_extents);
   4.709 -        for ( i = 0; i < nr_extents; i++ )
   4.710 -        {
   4.711 -            PyList_SetItem(
   4.712 -                list, i, 
   4.713 -                Py_BuildValue("{s:i,s:L,s:L}",
   4.714 -                              "device",       extents[i].real_device,
   4.715 -                              "start_sector", extents[i].start_sector,
   4.716 -                              "nr_sectors",   extents[i].nr_sectors));
   4.717 -        }
   4.718 +        free(extents);
   4.719 +        return PyErr_SetFromErrno(xc_error);
   4.720      }
   4.721  
   4.722 -    if ( extents != NULL )
   4.723 -        free(extents);
   4.724 +    list = PyList_New(nr_extents);
   4.725 +    for ( i = 0; i < nr_extents; i++ )
   4.726 +    {
   4.727 +        PyList_SetItem(
   4.728 +            list, i, 
   4.729 +            Py_BuildValue("{s:i,s:L,s:L}",
   4.730 +                          "device",       extents[i].real_device,
   4.731 +                          "start_sector", extents[i].start_sector,
   4.732 +                          "nr_sectors",   extents[i].nr_sectors));
   4.733 +    }
   4.734 +
   4.735 +    free(extents);
   4.736      
   4.737      return list;
   4.738  }
   4.739 @@ -731,20 +654,15 @@ static PyObject *pyxc_vbd_probe(PyObject
   4.740  
   4.741      if ( !PyArg_ParseTupleAndKeywords(args, kwds, "|Li", kwd_list, 
   4.742                                        &dom, &max_vbds) )
   4.743 -    {
   4.744 -        DPRINTF("could not parse parameter list.");
   4.745          return NULL;
   4.746 -    }
   4.747 +
   4.748 +    if ( (info = malloc(max_vbds * sizeof(xc_vbd_t))) == NULL )
   4.749 +        return PyErr_NoMemory();
   4.750  
   4.751 -    info = malloc(max_vbds * sizeof(xc_vbd_t));
   4.752 -    if ( info == NULL )
   4.753 +    if ( (nr_vbds = xc_vbd_probe(xc->xc_handle, dom, max_vbds, info)) < 0 )
   4.754      {
   4.755 -        DPRINTF("out of memory.");
   4.756 -        nr_vbds = 0;
   4.757 -    }
   4.758 -    else
   4.759 -    {
   4.760 -        nr_vbds = xc_vbd_probe(xc->xc_handle, dom, max_vbds, info);
   4.761 +        free(info);
   4.762 +        return PyErr_SetFromErrno(xc_error);
   4.763      }
   4.764  
   4.765      list = PyList_New(nr_vbds);
   4.766 @@ -759,8 +677,7 @@ static PyObject *pyxc_vbd_probe(PyObject
   4.767                            "nr_sectors", info[i].nr_sectors));
   4.768      }
   4.769  
   4.770 -    if ( info != NULL )
   4.771 -        free(info);
   4.772 +    free(info);
   4.773  
   4.774      return list;
   4.775  }
   4.776 @@ -770,30 +687,22 @@ static PyObject *pyxc_evtchn_open(PyObje
   4.777                                    PyObject *kwds)
   4.778  {
   4.779      XcObject *xc = (XcObject *)self;
   4.780 -    PyObject *dict;
   4.781  
   4.782      u64 dom1 = DOMID_SELF, dom2 = DOMID_SELF;
   4.783 -    int port1, port2, ret;
   4.784 +    int port1, port2;
   4.785  
   4.786      static char *kwd_list[] = { "dom1", "dom2", NULL };
   4.787  
   4.788      if ( !PyArg_ParseTupleAndKeywords(args, kwds, "|LL", kwd_list, 
   4.789                                        &dom1, &dom2) )
   4.790 -    {
   4.791 -        DPRINTF("could not parse parameter list.");
   4.792          return NULL;
   4.793 -    }
   4.794 -
   4.795 -    ret = xc_evtchn_open(xc->xc_handle, dom1, dom2, &port1, &port2);
   4.796  
   4.797 -    if ( ret < 0 )
   4.798 -        dict = Py_BuildValue("{}");
   4.799 -    else
   4.800 -        dict = Py_BuildValue("{s:i,s:i}", 
   4.801 -                             "port1", port1,
   4.802 -                             "port2", port2);
   4.803 -    
   4.804 -    return dict;
   4.805 +    if ( xc_evtchn_open(xc->xc_handle, dom1, dom2, &port1, &port2) != 0 )
   4.806 +        return PyErr_SetFromErrno(xc_error);
   4.807 +
   4.808 +    return Py_BuildValue("{s:i,s:i}", 
   4.809 +                         "port1", port1,
   4.810 +                         "port2", port2);
   4.811  }
   4.812  
   4.813  static PyObject *pyxc_evtchn_close(PyObject *self,
   4.814 @@ -803,20 +712,19 @@ static PyObject *pyxc_evtchn_close(PyObj
   4.815      XcObject *xc = (XcObject *)self;
   4.816  
   4.817      u64 dom = DOMID_SELF;
   4.818 -    int port, ret;
   4.819 +    int port;
   4.820  
   4.821      static char *kwd_list[] = { "port", "dom", NULL };
   4.822  
   4.823      if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i|L", kwd_list, 
   4.824                                        &port, &dom) )
   4.825 -    {
   4.826 -        DPRINTF("could not parse parameter list.");
   4.827          return NULL;
   4.828 -    }
   4.829  
   4.830 -    ret = xc_evtchn_close(xc->xc_handle, dom, port);
   4.831 +    if ( xc_evtchn_close(xc->xc_handle, dom, port) != 0 )
   4.832 +        return PyErr_SetFromErrno(xc_error);
   4.833  
   4.834 -    return PyInt_FromLong(ret);
   4.835 +    Py_INCREF(zero);
   4.836 +    return zero;
   4.837  }
   4.838  
   4.839  static PyObject *pyxc_evtchn_send(PyObject *self,
   4.840 @@ -825,19 +733,18 @@ static PyObject *pyxc_evtchn_send(PyObje
   4.841  {
   4.842      XcObject *xc = (XcObject *)self;
   4.843  
   4.844 -    int port, ret;
   4.845 +    int port;
   4.846  
   4.847      static char *kwd_list[] = { "port", NULL };
   4.848  
   4.849      if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i", kwd_list, &port) )
   4.850 -    {
   4.851 -        DPRINTF("could not parse parameter list.");
   4.852          return NULL;
   4.853 -    }
   4.854  
   4.855 -    ret = xc_evtchn_send(xc->xc_handle, port);
   4.856 +    if ( xc_evtchn_send(xc->xc_handle, port) != 0 )
   4.857 +        return PyErr_SetFromErrno(xc_error);
   4.858  
   4.859 -    return PyInt_FromLong(ret);
   4.860 +    Py_INCREF(zero);
   4.861 +    return zero;
   4.862  }
   4.863  
   4.864  static PyObject *pyxc_evtchn_status(PyObject *self,
   4.865 @@ -854,39 +761,31 @@ static PyObject *pyxc_evtchn_status(PyOb
   4.866  
   4.867      if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i|L", kwd_list, 
   4.868                                        &port1, &dom1) )
   4.869 -    {
   4.870 -        DPRINTF("could not parse parameter list.");
   4.871          return NULL;
   4.872 -    }
   4.873  
   4.874      ret = xc_evtchn_status(xc->xc_handle, dom1, port1, &dom2, &port2, &status);
   4.875 +    if ( ret != 0 )
   4.876 +        return PyErr_SetFromErrno(xc_error);
   4.877  
   4.878 -    if ( ret < 0 )
   4.879 -    {
   4.880 -        dict = Py_BuildValue("{}");
   4.881 -    }
   4.882 -    else
   4.883 +    switch ( status )
   4.884      {
   4.885 -        switch ( status )
   4.886 -        {
   4.887 -        case EVTCHNSTAT_closed:
   4.888 -            dict = Py_BuildValue("{s:s}", 
   4.889 -                                 "status", "closed");
   4.890 -            break;
   4.891 -        case EVTCHNSTAT_disconnected:
   4.892 -            dict = Py_BuildValue("{s:s}", 
   4.893 -                                 "status", "disconnected");
   4.894 -            break;
   4.895 -        case EVTCHNSTAT_connected:
   4.896 -            dict = Py_BuildValue("{s:s,s:L,s:i}", 
   4.897 -                                 "status", "connected",
   4.898 -                                 "dom", dom2,
   4.899 -                                 "port", port2);
   4.900 -            break;
   4.901 -        default:
   4.902 -            dict = Py_BuildValue("{}");
   4.903 -            break;
   4.904 -        }
   4.905 +    case EVTCHNSTAT_closed:
   4.906 +        dict = Py_BuildValue("{s:s}", 
   4.907 +                             "status", "closed");
   4.908 +        break;
   4.909 +    case EVTCHNSTAT_disconnected:
   4.910 +        dict = Py_BuildValue("{s:s}", 
   4.911 +                             "status", "disconnected");
   4.912 +        break;
   4.913 +    case EVTCHNSTAT_connected:
   4.914 +        dict = Py_BuildValue("{s:s,s:L,s:i}", 
   4.915 +                             "status", "connected",
   4.916 +                             "dom", dom2,
   4.917 +                             "port", port2);
   4.918 +        break;
   4.919 +    default:
   4.920 +        dict = Py_BuildValue("{}");
   4.921 +        break;
   4.922      }
   4.923      
   4.924      return dict;
   4.925 @@ -904,15 +803,15 @@ static PyObject *pyxc_physdev_pci_access
   4.926  
   4.927      if ( !PyArg_ParseTupleAndKeywords(args, kwds, "Liiii", kwd_list, 
   4.928                                        &dom, &bus, &dev, &func, &enable) )
   4.929 -    {
   4.930 -        DPRINTF("could not parse parameter list.");
   4.931          return NULL;
   4.932 -    }
   4.933  
   4.934      ret = xc_physdev_pci_access_modify(
   4.935          xc->xc_handle, dom, bus, dev, func, enable);
   4.936 -    
   4.937 -    return PyInt_FromLong(ret);
   4.938 +    if ( ret != 0 )
   4.939 +        return PyErr_SetFromErrno(xc_error);
   4.940 +
   4.941 +    Py_INCREF(zero);
   4.942 +    return zero;
   4.943  }
   4.944  
   4.945  static PyObject *pyxc_readconsolering(PyObject *self,
   4.946 @@ -928,14 +827,13 @@ static PyObject *pyxc_readconsolering(Py
   4.947      static char *kwd_list[] = { "clear", NULL };
   4.948  
   4.949      if ( !PyArg_ParseTupleAndKeywords(args, kwds, "|i", kwd_list, &clear) )
   4.950 -    {
   4.951 -        DPRINTF("could not parse parameter list.");
   4.952          return NULL;
   4.953 -    }
   4.954  
   4.955      ret = xc_readconsolering(xc->xc_handle, str, sizeof(str), clear);
   4.956 +    if ( ret < 0 )
   4.957 +        return PyErr_SetFromErrno(xc_error);
   4.958  
   4.959 -    return PyString_FromStringAndSize(str, (ret < 0) ? 0 : ret);
   4.960 +    return PyString_FromStringAndSize(str, ret);
   4.961  }
   4.962  
   4.963  static PyObject *pyxc_physinfo(PyObject *self,
   4.964 @@ -943,26 +841,20 @@ static PyObject *pyxc_physinfo(PyObject 
   4.965  			       PyObject *kwds)
   4.966  {
   4.967      XcObject *xc = (XcObject *)self;
   4.968 -    PyObject *ret_obj;
   4.969 -    int xc_ret;
   4.970      xc_physinfo_t info;
   4.971      
   4.972 -    if ( (xc_ret = xc_physinfo(xc->xc_handle, &info)) == 0 )
   4.973 -    {
   4.974 -        ret_obj = Py_BuildValue("{s:i,s:i,s:l,s:l,s:l}",
   4.975 -                                "ht_per_core", info.ht_per_core,
   4.976 -                                "cores",       info.cores,
   4.977 -                                "total_pages", info.total_pages,
   4.978 -                                "free_pages",  info.free_pages,
   4.979 -                                "cpu_khz",     info.cpu_khz);
   4.980 -    }
   4.981 -    else
   4.982 -    {
   4.983 -        Py_INCREF(Py_None);
   4.984 -        ret_obj = Py_None;
   4.985 -    }
   4.986 -    
   4.987 -    return ret_obj;
   4.988 +    if ( !PyArg_ParseTuple(args, "") )
   4.989 +        return NULL;
   4.990 +
   4.991 +    if ( xc_physinfo(xc->xc_handle, &info) != 0 )
   4.992 +        return PyErr_SetFromErrno(xc_error);
   4.993 +
   4.994 +    return Py_BuildValue("{s:i,s:i,s:l,s:l,s:l}",
   4.995 +                         "ht_per_core", info.ht_per_core,
   4.996 +                         "cores",       info.cores,
   4.997 +                         "total_pages", info.total_pages,
   4.998 +                         "free_pages",  info.free_pages,
   4.999 +                         "cpu_khz",     info.cpu_khz);
  4.1000  }
  4.1001  
  4.1002  static PyMethodDef pyxc_methods[] = {
  4.1003 @@ -1305,7 +1197,15 @@ static PyMethodDef PyXc_methods[] = {
  4.1004      { NULL, NULL, 0, NULL }
  4.1005  };
  4.1006  
  4.1007 -DL_EXPORT(void) initXc(void)
  4.1008 +PyMODINIT_FUNC initXc(void)
  4.1009  {
  4.1010 -    Py_InitModule("Xc", PyXc_methods);
  4.1011 +    PyObject *m, *d;
  4.1012 +
  4.1013 +    m = Py_InitModule("Xc", PyXc_methods);
  4.1014 +
  4.1015 +    d = PyModule_GetDict(m);
  4.1016 +    xc_error = PyErr_NewException("Xc.error", NULL, NULL);
  4.1017 +    PyDict_SetItemString(d, "error", xc_error);
  4.1018 +
  4.1019 +    zero = PyInt_FromLong(0);
  4.1020  }
     5.1 --- a/tools/xc/py/XenoUtil.py	Fri Mar 12 18:12:23 2004 +0000
     5.2 +++ b/tools/xc/py/XenoUtil.py	Sun Mar 14 18:23:01 2004 +0000
     5.3 @@ -1,4 +1,4 @@
     5.4 -import string, re, os, sys
     5.5 +import os, re, socket, string, sys, tempfile
     5.6  
     5.7  ##### Module variables
     5.8  
     5.9 @@ -184,6 +184,27 @@ def lookup_disk_uname( uname ):
    5.10      return segments
    5.11  
    5.12  
    5.13 +##### Management of the Xen control daemon
    5.14 +##### (c) Keir Fraser, University of Cambridge
    5.15 +
    5.16 +def xend_control_message( message ):
    5.17 +    """Takes a textual control message and sends it to the 'xend' Xen
    5.18 +    control daemon. Returns a dictionary containing the daemon's multi-part
    5.19 +    response."""
    5.20 +    tmpdir = tempfile.mkdtemp()
    5.21 +    try:
    5.22 +        ctl = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM, 0)
    5.23 +        ctl.bind(tmpdir+'/sock')
    5.24 +        ctl.sendto(message, '/var/run/xend/management_sock')
    5.25 +        data, addr = ctl.recvfrom(2048)
    5.26 +        ctl.close()
    5.27 +    finally:
    5.28 +        if os.path.exists(tmpdir+'/sock'):
    5.29 +            os.unlink(tmpdir+'/sock')
    5.30 +        if os.path.exists(tmpdir):
    5.31 +            os.rmdir(tmpdir)    
    5.32 +    return eval(data)
    5.33 +
    5.34  
    5.35  ##### VD Management-related functions
    5.36  
     6.1 --- a/tools/xend/Makefile	Fri Mar 12 18:12:23 2004 +0000
     6.2 +++ b/tools/xend/Makefile	Sun Mar 14 18:23:01 2004 +0000
     6.3 @@ -1,27 +1,24 @@
     6.4  
     6.5 -CC       = gcc
     6.6 -CFLAGS   = -Wall -O3 
     6.7 -CFLAGS  += -I../xc/lib -I../../xenolinux-sparse/include
     6.8 -
     6.9 -HDRS     = $(wildcard *.h)
    6.10 -OBJS     = $(patsubst %.c,%.o,$(wildcard *.c))
    6.11 -
    6.12 -BIN      = xend
    6.13 -
    6.14 -all: $(BIN)
    6.15 +all:
    6.16 +	python setup.py build
    6.17  
    6.18  install: all
    6.19 -	mkdir -p $(prefix)/usr/sbin
    6.20 -	cp $(BIN) $(prefix)/usr/sbin
    6.21 -	chmod 755 $(prefix)/usr/sbin/$(BIN)
    6.22 +	if [ "$(prefix)" = "" ]; then python setup.py install; \
    6.23 +	else python setup.py install --root "$(prefix)"; fi
    6.24 +	install --mode=755 xend.py $(prefix)/usr/sbin
    6.25 +	ln -sf xend.py $(prefix)/usr/sbin/xend
    6.26  
    6.27  dist: all
    6.28 -	mkdir -p ../../../install/sbin
    6.29 -	cp $(BIN) ../../../install/sbin
    6.30 -	chmod 755 ../../../install/sbin/$(BIN)
    6.31 +	mkdir -p ../../../../install/lib/python
    6.32 +	for i in `find . -name 'xend_utils.so'` ; do           \
    6.33 +		install --mode=755 $$i ../../../../install/lib/python/`basename $$i` ; \
    6.34 +	done
    6.35 +	python -c 'import py_compile, sys; py_compile.compile("XenoUtil.py")'
    6.36 +	install --mode=755 xend.py ../../../../install/sbin
    6.37 +	ln -sf xend.py ../../../../install/sbin/xend
    6.38  
    6.39  clean:
    6.40 -	$(RM) *.a *.so *.o *.rpm $(BIN)
    6.41 +	rm -rf build *.pyc *.pyo *.a *.so *.o *~ *.rpm 
    6.42  
    6.43  $(BIN): $(OBJS)
    6.44  	$(CC) -o $@ $^ -L../xc/lib -lxc
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/tools/xend/setup.py	Sun Mar 14 18:23:01 2004 +0000
     7.3 @@ -0,0 +1,11 @@
     7.4 +
     7.5 +from distutils.core import setup, Extension
     7.6 +
     7.7 +module = Extension("xend_utils",
     7.8 +                   include_dirs         = ["../xc/lib",
     7.9 +                                           "../../xenolinux-sparse/include"],
    7.10 +                   library_dirs         = ["../xc/lib"],
    7.11 +                   libraries            = ["xc"],
    7.12 +                   sources              = ["xend_utils.c"])
    7.13 +
    7.14 +setup(name = "xend_utils", version = "1.0", ext_modules = [module])
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/tools/xend/xend.py	Sun Mar 14 18:23:01 2004 +0000
     8.3 @@ -0,0 +1,454 @@
     8.4 +#!/usr/bin/env python
     8.5 +
     8.6 +
     8.7 +###########################################################
     8.8 +## xend.py -- Xen controller daemon
     8.9 +## Copyright (c) 2004, K A Fraser (University of Cambridge)
    8.10 +###########################################################
    8.11 +
    8.12 +
    8.13 +import errno, re, os, pwd, select, signal, socket, struct, sys, tempfile, time
    8.14 +import xend_utils, Xc
    8.15 +
    8.16 +
    8.17 +
    8.18 +# The following parameters could be placed in a configuration file.
    8.19 +PID  = '/var/run/xend.pid'
    8.20 +LOG  = '/var/log/xend.log'
    8.21 +USER = 'root'
    8.22 +CONTROL_DIR  = '/var/run/xend'
    8.23 +UNIX_SOCK    = 'management_sock' # relative to CONTROL_DIR
    8.24 +
    8.25 +
    8.26 +
    8.27 +##
    8.28 +## console_interface:
    8.29 +##  Each control interface owns an instance of this class, which manages
    8.30 +##  the current state of the console interface. Normally a console interface
    8.31 +##  will be one of two state:
    8.32 +##   LISTENING: listening for a connection on TCP port 'self.port'
    8.33 +##   CONNECTED: sending/receiving console data on TCP port 'self.port'
    8.34 +##
    8.35 +##  A dictionary of all active interfaces, indexed by TCP socket descriptor,
    8.36 +##  is accessible as 'console_interface.interface_list'.
    8.37 +##
    8.38 +##  NB. When a class instance is to be destroyed you *must* call the 'close'
    8.39 +##  method. Otherwise a stale reference will eb left in the interface list.
    8.40 +##
    8.41 +class console_interface:
    8.42 +
    8.43 +    # The various states that a console interface may be in.
    8.44 +    CLOSED    = 0 # No console activity
    8.45 +    LISTENING = 1 # Listening on port 'self.port'. Socket object 'self.sock'.
    8.46 +    CONNECTED = 2 # Active connection on 'self.port'. Socket obj 'self.sock'.
    8.47 +
    8.48 +
    8.49 +    # Dictionary of all active (non-closed) console interfaces.
    8.50 +    interface_list = {}
    8.51 +
    8.52 +
    8.53 +    # NB. 'key' is an opaque value that has no meaning in this class.
    8.54 +    def __init__(self, port, key):
    8.55 +        self.status = console_interface.CLOSED
    8.56 +        self.port   = port
    8.57 +        self.key    = key
    8.58 +
    8.59 +
    8.60 +    # Is this interface closed (inactive)?
    8.61 +    def closed(self):
    8.62 +        return self.status == console_interface.CLOSED
    8.63 +
    8.64 +
    8.65 +    # Is this interface listening?
    8.66 +    def listening(self):
    8.67 +        return self.status == console_interface.LISTENING
    8.68 +
    8.69 +
    8.70 +    # Is this interface active and connected?
    8.71 +    def connected(self):
    8.72 +        return self.status == console_interface.CONNECTED
    8.73 +
    8.74 +
    8.75 +    # Close the interface, if it is not closed already.
    8.76 +    def close(self):
    8.77 +        if not self.closed():
    8.78 +            del console_interface.interface_list[self.sock.fileno()]
    8.79 +            self.sock.close()
    8.80 +            del self.sock
    8.81 +            self.status = console_interface.CLOSED
    8.82 +
    8.83 +
    8.84 +    # Move the interface into the 'listening' state. Opens a new listening
    8.85 +    # socket and updates 'interface_list'.
    8.86 +    def listen(self):
    8.87 +        # Close old socket (if any), and create a fresh one.
    8.88 +        self.close()
    8.89 +        self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM, 0)
    8.90 +
    8.91 +        try:
    8.92 +            # Turn the new socket into a non-blocking listener.
    8.93 +            self.sock.setblocking(False)
    8.94 +            self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    8.95 +            self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_LINGER,
    8.96 +                                 struct.pack('ii', 0, 0))
    8.97 +            self.sock.bind(('', self.port))
    8.98 +            self.sock.listen(1)
    8.99 +
   8.100 +            # Announce the new status of thsi interface.
   8.101 +            self.status = console_interface.LISTENING
   8.102 +            console_interface.interface_list[self.sock.fileno()] = self
   8.103 +
   8.104 +        except:
   8.105 +            # In case of trouble ensure we get rid of dangling socket reference
   8.106 +            self.sock.close()
   8.107 +            del self.sock
   8.108 +            raise
   8.109 +
   8.110 +
   8.111 +    # Move a listening interface into the 'connected' state.
   8.112 +    def connect(self):
   8.113 +        # Pick up a new connection, if one is available.
   8.114 +        try:
   8.115 +            (sock, addr) = self.sock.accept()
   8.116 +        except:
   8.117 +            return 0
   8.118 +        sock.setblocking(False)
   8.119 +        sock.setsockopt(socket.SOL_SOCKET, socket.SO_LINGER,
   8.120 +                        struct.pack('ii', 0, 0))
   8.121 +
   8.122 +        # Close the listening socket.
   8.123 +        self.sock.close()
   8.124 +
   8.125 +        # Publish the new socket and the new interface state.
   8.126 +        self.sock = sock
   8.127 +        self.status = console_interface.CONNECTED
   8.128 +        console_interface.interface_list[self.sock.fileno()] = self
   8.129 +        return 1
   8.130 +
   8.131 +
   8.132 +
   8.133 +##
   8.134 +## new_control_interface:
   8.135 +##  Create a new control interface with the specified domain 'dom'.
   8.136 +##  The console port may also be specified; otehrwise a suitable port is
   8.137 +##  automatically allocated.
   8.138 +##
   8.139 +def new_control_interface(dom, console_port=-1):
   8.140 +    # Allocate an event channel. Clear pending notifications.
   8.141 +    port = xend_utils.port(dom)
   8.142 +    notifier.clear(port.local_port, notifier.NORMAL)
   8.143 +    notifier.clear(port.local_port, notifier.DISCONNECT)
   8.144 +    
   8.145 +    # If necessary, compute a suitable TCP port for console I/O.
   8.146 +    if console_port < 0:
   8.147 +        console_port = 9600 + port.local_port
   8.148 +
   8.149 +    # Create a listenign console interface.
   8.150 +    con_if = console_interface(console_port, port.local_port)
   8.151 +    con_if.listen()
   8.152 +
   8.153 +    # Add control state to the master list.
   8.154 +    control_list[port.local_port] = \
   8.155 +      (port, xend_utils.buffer(), xend_utils.buffer(), con_if)
   8.156 +
   8.157 +    # Construct the successful response to be returned to the requester.
   8.158 +    response = { 'success': True }
   8.159 +    response['local_port']   = port.local_port
   8.160 +    response['remote_port']  = port.remote_port
   8.161 +    response['console_port'] = console_port
   8.162 +    return response
   8.163 +
   8.164 +
   8.165 +        
   8.166 +def daemon_loop():
   8.167 +    global control_list, notifier
   8.168 +
   8.169 +    xc = Xc.new()
   8.170 +    control_list = {}
   8.171 +
   8.172 +    # Ignore writes to disconnected sockets. We clean up differently.
   8.173 +    signal.signal(signal.SIGPIPE, signal.SIG_IGN)
   8.174 +
   8.175 +    # Construct the management interface. This is a UNIX domain socket via
   8.176 +    # which we receive 'request' datagrams. Each request is a string that
   8.177 +    # can be eval'ed as a Python statement. Responses can be remotely eval'ed
   8.178 +    # by the requester to create a Python dictionary of result values.
   8.179 +    management_interface = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM, 0)
   8.180 +    if os.path.exists(CONTROL_DIR+'/'+UNIX_SOCK):
   8.181 +        os.unlink(CONTROL_DIR+'/'+UNIX_SOCK)
   8.182 +    management_interface.setblocking(False)
   8.183 +    management_interface.bind(CONTROL_DIR+'/'+UNIX_SOCK)
   8.184 +
   8.185 +    notifier = xend_utils.notifier()
   8.186 +
   8.187 +    ##
   8.188 +    ## MAIN LOOP
   8.189 +    ## 
   8.190 +    while 1:
   8.191 +
   8.192 +        # Construct a poll set. We wait on:
   8.193 +        #  1. Requests on the management interface.
   8.194 +        #  2. Incoming event-channel notifications.
   8.195 +        # Furthermore, for each active control interface:
   8.196 +        #  3. Incoming console data.
   8.197 +        #  4. Space for outgoing console data (if there is data to send).
   8.198 +        waitset = select.poll()
   8.199 +        waitset.register(management_interface, select.POLLIN)
   8.200 +        waitset.register(notifier, select.POLLIN)
   8.201 +        for idx, (port, rbuf, wbuf, con_if) in control_list.items():
   8.202 +            if not con_if.closed():
   8.203 +                pflags = select.POLLIN
   8.204 +                if not rbuf.empty() and con_if.connected():
   8.205 +                    pflags = select.POLLIN | select.POLLOUT
   8.206 +                waitset.register(con_if.sock.fileno(), pflags)
   8.207 +
   8.208 +        # Wait for something to do...
   8.209 +        fdset = waitset.poll()
   8.210 +        
   8.211 +        # Look for messages on the management interface.
   8.212 +        # These should consist of executable Python statements that call
   8.213 +        # well-known management functions (e.g., new_control_interface(dom=9)).
   8.214 +        try:
   8.215 +            data, addr = management_interface.recvfrom(2048)
   8.216 +        except socket.error, error:
   8.217 +            if error[0] != errno.EAGAIN:
   8.218 +                raise
   8.219 +        else:
   8.220 +            if addr:
   8.221 +                # Evaluate the request in an exception-trapping sandbox.
   8.222 +                try:
   8.223 +                    print "Mgmt_req[%s]: %s" % (addr, data)
   8.224 +                    response = str(eval(data))
   8.225 +
   8.226 +                except:
   8.227 +                    # Catch all exceptions and turn into an error response:
   8.228 +                    #  status:          False
   8.229 +                    #  error_type:      'exception'
   8.230 +                    #  exception_type:  name of exception type.
   8.231 +                    #  exception value: textual exception value.
   8.232 +                    exc_type, exc_val = sys.exc_info()[:2]
   8.233 +                    response = { 'success': False }
   8.234 +                    response['error_type'] = 'exception'
   8.235 +                    response['exception_type'] = str(exc_type)
   8.236 +                    response['exception_value'] = str(exc_val)
   8.237 +                    response = str(response)
   8.238 +
   8.239 +                # Try to send a response to the requester.
   8.240 +                try:
   8.241 +                    print "Mgmt_rsp[%s]: %s" % (addr, response)
   8.242 +                    management_interface.sendto(response, addr)
   8.243 +                except socket.error, error:
   8.244 +                    pass
   8.245 +                
   8.246 +        # Do work for every console interface that hit in the poll set.
   8.247 +        for (fd, events) in fdset:
   8.248 +            if not console_interface.interface_list.has_key(fd):
   8.249 +                continue
   8.250 +            con_if = console_interface.interface_list[fd]
   8.251 +
   8.252 +            # If the interface is listening, check for pending connections.
   8.253 +            if con_if.listening():
   8.254 +                con_if.connect()
   8.255 +
   8.256 +            # All done if the interface is not connected.
   8.257 +            if not con_if.connected():
   8.258 +                continue
   8.259 +            (port, rbuf, wbuf, con_if) = control_list[con_if.key]
   8.260 +
   8.261 +            # Send as much pending data as possible via the socket.
   8.262 +            while not rbuf.empty():
   8.263 +                try:
   8.264 +                    bytes = con_if.sock.send(rbuf.peek())
   8.265 +                    if bytes > 0:
   8.266 +                        rbuf.discard(bytes)
   8.267 +                except socket.error, error:
   8.268 +                    pass
   8.269 +
   8.270 +            # Read as much data as is available. Don't worry about
   8.271 +            # overflowing our buffer: it's more important to read the
   8.272 +            # incoming data stream and detect errors or closure of the
   8.273 +            # remote end in a timely manner.
   8.274 +            try:
   8.275 +                while 1:
   8.276 +                    data = con_if.sock.recv(2048)
   8.277 +                    # Return of zero means the remote end has disconnected.
   8.278 +                    # We therefore return the console interface to listening.
   8.279 +                    if not data:
   8.280 +                        con_if.listen()
   8.281 +                        break
   8.282 +                    wbuf.write(data)
   8.283 +            except socket.error, error:
   8.284 +                # Assume that most errors mean that the connection is dead.
   8.285 +                # In such cases we return the interface to 'listening' state.
   8.286 +                if error[0] != errno.EAGAIN:
   8.287 +                    print "Better return to listening"
   8.288 +                    con_if.listen()
   8.289 +                    print "New status: " + str(con_if.status)
   8.290 +
   8.291 +            # We may now have pending data to send via the relevant
   8.292 +            # inter-domain control interface. If so then we send all we can
   8.293 +            # and notify the remote end.
   8.294 +            work_done = False
   8.295 +            while not wbuf.empty() and port.space_to_write_request():
   8.296 +                msg = xend_utils.message(0, 0, 0)
   8.297 +                msg.append_payload(wbuf.read(msg.MAX_PAYLOAD))
   8.298 +                port.write_request(msg)
   8.299 +                work_done = True
   8.300 +            if work_done:
   8.301 +                port.notify()
   8.302 +
   8.303 +        # Process control-interface notifications from other guest OSes.
   8.304 +        while 1:            
   8.305 +            # Grab a notification, if there is one.
   8.306 +            notification = notifier.read()
   8.307 +            if not notification:
   8.308 +                break
   8.309 +            (idx, type) = notification
   8.310 +
   8.311 +            # If we pick up a disconnect notification then we do any necessary
   8.312 +            # cleanup, even if the event channel doesn't belong to us.
   8.313 +            # This is intended to prevent the event-channel port space from
   8.314 +            # getting clogged with stale connections.
   8.315 +            if type == notifier.DISCONNECT:
   8.316 +                ret = xc.evtchn_status(idx)
   8.317 +                if ret['status'] != 'connected':
   8.318 +                    notifier.clear(idx, notifier.NORMAL)
   8.319 +                    notifier.clear(idx, notifier.DISCONNECT)
   8.320 +                    if control_list.has_key(idx):
   8.321 +                        (port, rbuf, wbuf, con_if) =  control_list[idx]
   8.322 +                        con_if.close()
   8.323 +                        del control_list[idx], port, rbuf, wbuf, con_if
   8.324 +                    elif ret['status'] == 'disconnected':
   8.325 +                        # There's noone to do the closure for us...
   8.326 +                        xc.evtchn_close(idx)
   8.327 +
   8.328 +            # A standard notification: probably means there are messages to
   8.329 +            # read or that there is space to write messages.
   8.330 +            elif type == notifier.NORMAL and control_list.has_key(idx):
   8.331 +                (port, rbuf, wbuf, con_if) = control_list[idx]
   8.332 +                work_done = False
   8.333 +
   8.334 +                # We clear the notification before doing any work, to avoid
   8.335 +                # races.
   8.336 +                notifier.clear(idx, notifier.NORMAL)
   8.337 +
   8.338 +                # Read incoming requests. Currently assume that request
   8.339 +                # message always containb console data.
   8.340 +                while port.request_to_read():
   8.341 +                    msg = port.read_request()
   8.342 +                    rbuf.write(msg.get_payload())
   8.343 +                    port.write_response(msg)
   8.344 +                    work_done = True
   8.345 +
   8.346 +                # Incoming responses are currently thrown on the floor.
   8.347 +                while port.response_to_read():
   8.348 +                    msg = port.read_response()
   8.349 +                    work_done = True
   8.350 +
   8.351 +                # Send as much pending console data as there is room for.
   8.352 +                while not wbuf.empty() and port.space_to_write_request():
   8.353 +                    msg = xend_utils.message(0, 0, 0)
   8.354 +                    msg.append_payload(wbuf.read(msg.MAX_PAYLOAD))
   8.355 +                    port.write_request(msg)
   8.356 +                    work_done = True
   8.357 +
   8.358 +                # Finally, notify the remote end of any work that we did.
   8.359 +                if work_done:
   8.360 +                    port.notify()
   8.361 +
   8.362 +
   8.363 +
   8.364 +def cleanup_daemon(kill=False):
   8.365 +    # No cleanup to do if the PID file is empty.
   8.366 +    if not os.path.isfile(PID) or not os.path.getsize(PID):
   8.367 +        return 0
   8.368 +    # Read the PID of the previous invocation and search active process list.
   8.369 +    pid = open(PID, 'r').read()
   8.370 +    lines = os.popen('ps ' + pid + ' 2>/dev/null').readlines()
   8.371 +    for line in lines:
   8.372 +        if re.search('^ *' + pid + '.+xend', line):
   8.373 +            if not kill:
   8.374 +                print "Daemon is already running (PID %d)" % int(pid)
   8.375 +                return 1
   8.376 +            # Old daemon is still active: terminate it.
   8.377 +            os.kill(int(pid), 1)
   8.378 +    # Delete the, now stale, PID file.
   8.379 +    os.remove(PID)
   8.380 +    return 0
   8.381 +
   8.382 +
   8.383 +
   8.384 +def start_daemon():
   8.385 +    if cleanup_daemon(kill=False):
   8.386 +        return 1
   8.387 +
   8.388 +    if not os.path.exists(CONTROL_DIR):
   8.389 +        os.mkdir(CONTROL_DIR)
   8.390 +
   8.391 +    # Open log file. Truncate it if non-empty, and request line buffering.
   8.392 +    if os.path.isfile(LOG):
   8.393 +        os.rename(LOG, LOG+'.old')
   8.394 +    logfile = open(LOG, 'w+', 1)
   8.395 +
   8.396 +    # Detach from TTY.
   8.397 +    os.setsid()
   8.398 +
   8.399 +    # Set the UID.
   8.400 +    try:
   8.401 +        os.setuid(pwd.getpwnam(USER)[2])
   8.402 +    except KeyError, error:
   8.403 +        print "Error: no such user '%s'" % USER
   8.404 +        return 1
   8.405 +
   8.406 +    # Ensure that zombie children are automatically reaped.
   8.407 +    xend_utils.autoreap()
   8.408 +
   8.409 +    # Fork -- parent writes the PID file and exits.
   8.410 +    pid = os.fork()
   8.411 +    if pid:
   8.412 +        pidfile = open(PID, 'w')
   8.413 +        pidfile.write(str(pid))
   8.414 +        pidfile.close()
   8.415 +        return 0
   8.416 +
   8.417 +    # Close down standard file handles
   8.418 +    try:
   8.419 +        os.close(0) # stdin
   8.420 +        os.close(1) # stdout
   8.421 +        os.close(2) # stderr
   8.422 +    except:
   8.423 +        pass
   8.424 +
   8.425 +    # Redirect output to log file, then enter the main loop.
   8.426 +    sys.stdout = sys.stderr = logfile
   8.427 +    daemon_loop()
   8.428 +    return 0
   8.429 +
   8.430 +
   8.431 +
   8.432 +def stop_daemon():
   8.433 +    return cleanup_daemon(kill=True)
   8.434 +
   8.435 +
   8.436 +
   8.437 +def main():
   8.438 +    xend_utils.autoreap()
   8.439 +    if not sys.argv[1:]:
   8.440 +        print 'usage: %s {start|stop|restart}' % sys.argv[0]
   8.441 +    elif os.fork():
   8.442 +        pid, status = os.wait()
   8.443 +        return status >> 8
   8.444 +    elif sys.argv[1] == 'start':
   8.445 +        return start_daemon()
   8.446 +    elif sys.argv[1] == 'stop':
   8.447 +        return stop_daemon()
   8.448 +    elif sys.argv[1] == 'restart':
   8.449 +        return stop_daemon() or start_daemon()
   8.450 +    else:
   8.451 +        print 'not an option:', sys.argv[1]
   8.452 +    return 1
   8.453 +
   8.454 +
   8.455 +
   8.456 +if __name__ == '__main__':
   8.457 +    sys.exit(main())
     9.1 --- a/tools/xend/xend_utils.c	Fri Mar 12 18:12:23 2004 +0000
     9.2 +++ b/tools/xend/xend_utils.c	Sun Mar 14 18:23:01 2004 +0000
     9.3 @@ -1,16 +1,16 @@
     9.4  /******************************************************************************
     9.5 - * xend.c
     9.6 - * 
     9.7 - * The grand Xen daemon. For now it's just a virtual-console concentrator.
     9.8 + * xend_utils.c
     9.9   * 
    9.10   * Copyright (c) 2004, K A Fraser
    9.11   */
    9.12  
    9.13 +#include <Python.h>
    9.14  #include <stdio.h>
    9.15  #include <stdlib.h>
    9.16  #include <string.h>
    9.17  #include <sys/ioctl.h>
    9.18  #include <sys/types.h>
    9.19 +#include <sys/wait.h>
    9.20  #include <sys/stat.h>
    9.21  #include <sys/socket.h>
    9.22  #include <sys/mman.h>
    9.23 @@ -32,64 +32,302 @@
    9.24  #define PORTIDX_MASK    0x7fff   /* Strip subtype to obtain port index. */
    9.25  #define EVTCHN_RESET _IO('E', 1) /* Clear notification buffer. Clear errors. */
    9.26  
    9.27 -/* Error macros. */
    9.28 -#define ERROR(_f, _a...)     \
    9.29 -    fprintf ( stderr, "ERROR: " _f "\n" , ## _a );
    9.30 -#define SYS_ERROR(_f, _a...) \
    9.31 -    fprintf ( stderr, "ERROR: " _f " [errno=%d (%s)]\n" , \
    9.32 -              ## _a , errno , strerror(errno) );
    9.33 -#define HINT(_f, _a...)      \
    9.34 -    fprintf ( stderr, "Hint: " _f "\n" , ## _a );
    9.35 -#define ROOT_HINT() HINT("You must execute this daemon as root.")
    9.36 -#define DOM0_HINT() HINT("You must execute this daemon " \
    9.37 -                         "on a privileged Xenolinux instance (e.g., DOM0).")
    9.38 +/* Size of a machine page frame. */
    9.39 +#define PAGE_SIZE 4096
    9.40 +
    9.41 +
    9.42 +/*
    9.43 + * *********************** NOTIFIER ***********************
    9.44 + */
    9.45 +
    9.46 +typedef struct {
    9.47 +    PyObject_HEAD;
    9.48 +    int evtchn_fd;
    9.49 +} xu_notifier_object;
    9.50 +
    9.51 +static PyObject *xu_notifier_read(PyObject *self, PyObject *args)
    9.52 +{
    9.53 +    xu_notifier_object *xun = (xu_notifier_object *)self;
    9.54 +    u16 v;
    9.55 +    int bytes;
    9.56 +
    9.57 +    if ( !PyArg_ParseTuple(args, "") )
    9.58 +        return NULL;
    9.59 +    
    9.60 +    while ( (bytes = read(xun->evtchn_fd, &v, sizeof(v))) == -1 )
    9.61 +    {
    9.62 +        if ( errno == EINTR )
    9.63 +            continue;
    9.64 +        if ( errno == EAGAIN )
    9.65 +            goto none;
    9.66 +        return PyErr_SetFromErrno(PyExc_IOError);
    9.67 +    }
    9.68 +    
    9.69 +    if ( bytes == sizeof(v) )
    9.70 +        return Py_BuildValue("(i,i)", v&PORTIDX_MASK, v&~PORTIDX_MASK);
    9.71 +
    9.72 + none:
    9.73 +    Py_INCREF(Py_None);
    9.74 +    return Py_None;
    9.75 +}
    9.76 +
    9.77 +static PyObject *xu_notifier_clear(PyObject *self, PyObject *args)
    9.78 +{
    9.79 +    xu_notifier_object *xun = (xu_notifier_object *)self;
    9.80 +    u16 v;
    9.81 +    int idx, type;
    9.82 +
    9.83 +    if ( !PyArg_ParseTuple(args, "ii", &idx, &type) )
    9.84 +        return NULL;
    9.85 +    
    9.86 +    v = (u16)idx | (u16)type;
    9.87 +
    9.88 +    (void)write(xun->evtchn_fd, &v, sizeof(v));
    9.89 +
    9.90 +    Py_INCREF(Py_None);
    9.91 +    return Py_None;
    9.92 +}
    9.93 +
    9.94 +static PyObject *xu_notifier_fileno(PyObject *self, PyObject *args)
    9.95 +{
    9.96 +    xu_notifier_object *xun = (xu_notifier_object *)self;
    9.97 +    return PyInt_FromLong(xun->evtchn_fd);
    9.98 +}
    9.99 +
   9.100 +static PyMethodDef xu_notifier_methods[] = {
   9.101 +    { "read",
   9.102 +      (PyCFunction)xu_notifier_read,
   9.103 +      METH_VARARGS,
   9.104 +      "Read a (@port, @type) pair.\n" },
   9.105 +
   9.106 +    { "clear", 
   9.107 +      (PyCFunction)xu_notifier_clear,
   9.108 +      METH_VARARGS,
   9.109 +      "Clear a (@port, @type) pair.\n" },
   9.110  
   9.111 -#if 0
   9.112 -#define DPRINTF(_f, _a...)  \
   9.113 -    fprintf ( stdout, _f "\n" , ## _a );
   9.114 -#else
   9.115 -#define DPRINTF(_f, _a...) ((void)0)
   9.116 -#endif
   9.117 +    { "fileno", 
   9.118 +      (PyCFunction)xu_notifier_fileno,
   9.119 +      METH_VARARGS,
   9.120 +      "Return the file descriptor for the notification channel.\n" },
   9.121 +
   9.122 +    { NULL, NULL, 0, NULL }
   9.123 +};
   9.124 +
   9.125 +staticforward PyTypeObject xu_notifier_type;
   9.126 +
   9.127 +static PyObject *xu_notifier_new(PyObject *self, PyObject *args)
   9.128 +{
   9.129 +    xu_notifier_object *xun;
   9.130 +
   9.131 +    if ( !PyArg_ParseTuple(args, "") )
   9.132 +        return NULL;
   9.133 +
   9.134 +    xun = PyObject_New(xu_notifier_object, &xu_notifier_type);
   9.135 +
   9.136 +    xun->evtchn_fd = open(EVTCHN_DEV_NAME, O_NONBLOCK|O_RDWR);
   9.137 +    if ( xun->evtchn_fd == -1 )
   9.138 +    {
   9.139 +        PyObject_Del((PyObject *)xun);
   9.140 +        return PyErr_SetFromErrno(PyExc_IOError);
   9.141 +    }
   9.142 +
   9.143 +    return (PyObject *)xun;
   9.144 +}
   9.145  
   9.146 -/* Per-port Tx/Rx buffering. */
   9.147 -#define CONBUFSZ 65536
   9.148 -#define MASK_CONBUF_IDX(_i) ((_i)&(CONBUFSZ-1))
   9.149 +static PyObject *xu_notifier_getattr(PyObject *obj, char *name)
   9.150 +{
   9.151 +    if ( strcmp(name, "DISCONNECT") == 0 )
   9.152 +        return PyInt_FromLong(PORT_DISCONNECT);
   9.153 +    if ( strcmp(name, "NORMAL") == 0 )
   9.154 +        return PyInt_FromLong(PORT_NORMAL);
   9.155 +    return Py_FindMethod(xu_notifier_methods, obj, name);
   9.156 +}
   9.157 +
   9.158 +static void xu_notifier_dealloc(PyObject *self)
   9.159 +{
   9.160 +    xu_notifier_object *xun = (xu_notifier_object *)self;
   9.161 +    (void)close(xun->evtchn_fd);
   9.162 +    PyObject_Del(self);
   9.163 +}
   9.164 +
   9.165 +static PyTypeObject xu_notifier_type = {
   9.166 +    PyObject_HEAD_INIT(&PyType_Type)
   9.167 +    0,
   9.168 +    "notifier",
   9.169 +    sizeof(xu_notifier_object),
   9.170 +    0,
   9.171 +    xu_notifier_dealloc, /* tp_dealloc     */
   9.172 +    NULL,                /* tp_print       */
   9.173 +    xu_notifier_getattr, /* tp_getattr     */
   9.174 +    NULL,                /* tp_setattr     */
   9.175 +    NULL,                /* tp_compare     */
   9.176 +    NULL,                /* tp_repr        */
   9.177 +    NULL,                /* tp_as_number   */
   9.178 +    NULL,                /* tp_as_sequence */
   9.179 +    NULL,                /* tp_as_mapping  */
   9.180 +    NULL                 /* tp_hash        */
   9.181 +};
   9.182 +
   9.183 +
   9.184 +
   9.185 +/*
   9.186 + * *********************** MESSAGE ***********************
   9.187 + */
   9.188 +
   9.189 +typedef struct {
   9.190 +    PyObject_HEAD;
   9.191 +    control_msg_t msg;
   9.192 +} xu_message_object;
   9.193  
   9.194 -struct portinfo;
   9.195 -typedef struct portinfo {
   9.196 -    u64              dom;
   9.197 -    control_if_t    *interface;
   9.198 -    CONTROL_RING_IDX tx_req_cons, tx_resp_prod;
   9.199 -    CONTROL_RING_IDX rx_req_prod, rx_resp_cons;
   9.200 -    char            *tx_buf, *rx_buf;
   9.201 -    unsigned int     txp, txc, rxp, rxc;
   9.202 -#define CONSTAT_CLOSED    0
   9.203 -#define CONSTAT_LISTENING 1
   9.204 -#define CONSTAT_CONNECTED 2
   9.205 -    int              con_fd, con_status;
   9.206 -    struct portinfo **pprev, *next; /* links to other active ports */
   9.207 -} portinfo_t;
   9.208 +static PyObject *xu_message_append_payload(PyObject *self, PyObject *args)
   9.209 +{
   9.210 +    xu_message_object *xum = (xu_message_object *)self;
   9.211 +    char *str;
   9.212 +    int len;
   9.213 +
   9.214 +    if ( !PyArg_ParseTuple(args, "s#", &str, &len) )
   9.215 +        return NULL;
   9.216 +
   9.217 +    if ( (len + xum->msg.length) > sizeof(xum->msg.msg) )
   9.218 +    {
   9.219 +        PyErr_SetString(PyExc_RuntimeError, "out of space in control message");
   9.220 +        return NULL;
   9.221 +    }
   9.222 +
   9.223 +    memcpy(&xum->msg.msg[xum->msg.length], str, len);
   9.224 +    xum->msg.length += len;
   9.225 +
   9.226 +    Py_INCREF(Py_None);
   9.227 +    return Py_None;
   9.228 +}
   9.229 +
   9.230 +static PyObject *xu_message_get_payload(PyObject *self, PyObject *args)
   9.231 +{
   9.232 +    xu_message_object *xum = (xu_message_object *)self;
   9.233 +
   9.234 +    if ( !PyArg_ParseTuple(args, "") )
   9.235 +        return NULL;
   9.236 +
   9.237 +    return PyString_FromStringAndSize(xum->msg.msg, xum->msg.length);
   9.238 +}
   9.239 +
   9.240 +static PyObject *xu_message_set_header(PyObject *self, 
   9.241 +                                       PyObject *args, 
   9.242 +                                       PyObject *kwds)
   9.243 +{
   9.244 +    xu_message_object *xum = (xu_message_object *)self;
   9.245 +    int type = -1, subtype = -1, id = -1;
   9.246 +
   9.247 +    static char *kwd_list[] = { "type", "subtype", "id", NULL };
   9.248 +
   9.249 +    if ( !PyArg_ParseTupleAndKeywords(args, kwds, "|iii", kwd_list,
   9.250 +                                      &type, &subtype, &id) )
   9.251 +        return NULL;
   9.252 +
   9.253 +    if ( type != -1 )
   9.254 +        xum->msg.type = (u8)type;
   9.255 +    if ( subtype != -1 )
   9.256 +        xum->msg.subtype = (u8)subtype;
   9.257 +    if ( id != -1 )
   9.258 +        xum->msg.id = (u8)id;
   9.259 +
   9.260 +    Py_INCREF(Py_None);
   9.261 +    return Py_None;
   9.262 +}
   9.263 +
   9.264 +static PyObject *xu_message_get_header(PyObject *self, PyObject *args)
   9.265 +{
   9.266 +    xu_message_object *xum = (xu_message_object *)self;
   9.267 +
   9.268 +    if ( !PyArg_ParseTuple(args, "") )
   9.269 +        return NULL;
   9.270 +
   9.271 +    return Py_BuildValue("{s:i,s:i,s:i}",
   9.272 +                         "type",    xum->msg.type,
   9.273 +                         "subtype", xum->msg.subtype,
   9.274 +                         "id",      xum->msg.id);
   9.275 +}
   9.276 +
   9.277 +static PyMethodDef xu_message_methods[] = {
   9.278 +    { "append_payload", 
   9.279 +      (PyCFunction)xu_message_append_payload,
   9.280 +      METH_VARARGS,
   9.281 +      "Append @str to the message payload.\n" },
   9.282  
   9.283 -#define PORT(_pinfo) ((_pinfo)-portinfo)
   9.284 -#define TX_EMPTY(_pinfo) ((_pinfo)->txp == (_pinfo)->txc)
   9.285 -#define TX_FULL(_pinfo)  (((_pinfo)->txp - (_pinfo)->txc) == CONBUFSZ)
   9.286 -#define RX_EMPTY(_pinfo) ((_pinfo)->rxp == (_pinfo)->rxc)
   9.287 -#define RX_FULL(_pinfo)  (((_pinfo)->rxp - (_pinfo)->rxc) == CONBUFSZ)
   9.288 +    { "get_payload",
   9.289 +      (PyCFunction)xu_message_get_payload,
   9.290 +      METH_VARARGS,
   9.291 +      "Return the message payload in string form.\n" },
   9.292 +
   9.293 +    { "set_header",
   9.294 +      (PyCFunction)xu_message_set_header,
   9.295 +      METH_VARARGS | METH_KEYWORDS,
   9.296 +      "Accepts keywords @type, @subtype, and @id.\n" },
   9.297 +
   9.298 +    { "get_header",
   9.299 +      (PyCFunction)xu_message_get_header,
   9.300 +      METH_VARARGS,
   9.301 +      "Returns a dictionary of values for @type, @subtype, and @id.\n" },
   9.302  
   9.303 -static portinfo_t *active_head;   /* linked list of active ports */
   9.304 -static portinfo_t portinfo[1024]; /* array of all ports */    
   9.305 -static int xc_fd, evt_fd, mem_fd;
   9.306 +    { NULL, NULL, 0, NULL }
   9.307 +};
   9.308 +
   9.309 +staticforward PyTypeObject xu_message_type;
   9.310 +
   9.311 +static PyObject *xu_message_new(PyObject *self, PyObject *args)
   9.312 +{
   9.313 +    xu_message_object *xum;
   9.314 +    int type, subtype, id;
   9.315 +
   9.316 +    if ( !PyArg_ParseTuple(args, "iii", &type, &subtype, &id) )
   9.317 +        return NULL;
   9.318 +
   9.319 +    xum = PyObject_New(xu_message_object, &xu_message_type);
   9.320 +
   9.321 +    xum->msg.type    = type;
   9.322 +    xum->msg.subtype = subtype;
   9.323 +    xum->msg.id      = id;
   9.324 +    xum->msg.length  = 0;
   9.325  
   9.326 -#define PAGE_SIZE           4096 /* size of a machine page frame            */
   9.327 -#define BATCH_SIZE           512 /* maximum notifications to read at a time */
   9.328 +    return (PyObject *)xum;
   9.329 +}
   9.330 +
   9.331 +static PyObject *xu_message_getattr(PyObject *obj, char *name)
   9.332 +{
   9.333 +    xu_message_object *xum;
   9.334 +    if ( strcmp(name, "MAX_PAYLOAD") == 0 )
   9.335 +        return PyInt_FromLong(sizeof(xum->msg.msg));
   9.336 +    return Py_FindMethod(xu_message_methods, obj, name);
   9.337 +}
   9.338 +
   9.339 +static void xu_message_dealloc(PyObject *self)
   9.340 +{
   9.341 +    PyObject_Del(self);
   9.342 +}
   9.343  
   9.344 -static int make_consock_listener(portinfo_t *pinfo);
   9.345 -static int make_consock_connected(portinfo_t *pinfo);
   9.346 -static void make_consock_closed(portinfo_t *pinfo);
   9.347 -static void do_consock_read(portinfo_t *pinfo);
   9.348 -static void do_consock_write(portinfo_t *pinfo);
   9.349 -static int process_evtchn_reads(portinfo_t *pinfo);
   9.350 -static int process_evtchn_writes(portinfo_t *pinfo);
   9.351 +static PyTypeObject xu_message_type = {
   9.352 +    PyObject_HEAD_INIT(&PyType_Type)
   9.353 +    0,
   9.354 +    "message",
   9.355 +    sizeof(xu_message_object),
   9.356 +    0,
   9.357 +    xu_message_dealloc,   /* tp_dealloc     */
   9.358 +    NULL,                /* tp_print       */
   9.359 +    xu_message_getattr,   /* tp_getattr     */
   9.360 +    NULL,                /* tp_setattr     */
   9.361 +    NULL,                /* tp_compare     */
   9.362 +    NULL,                /* tp_repr        */
   9.363 +    NULL,                /* tp_as_number   */
   9.364 +    NULL,                /* tp_as_sequence */
   9.365 +    NULL,                /* tp_as_mapping  */
   9.366 +    NULL                 /* tp_hash        */
   9.367 +};
   9.368 +
   9.369 +
   9.370 +
   9.371 +/*
   9.372 + * *********************** PORT ***********************
   9.373 + */
   9.374  
   9.375  static control_if_t *map_control_interface(int fd, unsigned long pfn)
   9.376  {
   9.377 @@ -99,518 +337,670 @@ static control_if_t *map_control_interfa
   9.378          return NULL;
   9.379      return (control_if_t *)(vaddr + 2048);
   9.380  }
   9.381 -
   9.382  static void unmap_control_interface(int fd, control_if_t *c)
   9.383  {
   9.384      char *vaddr = (char *)c - 2048;
   9.385      (void)munmap(vaddr, PAGE_SIZE);
   9.386  }
   9.387  
   9.388 -/* Returns TRUE if the channel is open on exit. */
   9.389 -static int handle_channel_exception(unsigned int port)
   9.390 +typedef struct {
   9.391 +    PyObject_HEAD;
   9.392 +    int mem_fd;
   9.393 +    int xc_handle;
   9.394 +    u64 remote_dom;
   9.395 +    int local_port, remote_port;
   9.396 +    control_if_t    *interface;
   9.397 +    CONTROL_RING_IDX tx_req_cons, tx_resp_prod;
   9.398 +    CONTROL_RING_IDX rx_req_prod, rx_resp_cons;
   9.399 +} xu_port_object;
   9.400 +
   9.401 +static PyObject *port_error;
   9.402 +
   9.403 +static PyObject *xu_port_notify(PyObject *self, PyObject *args)
   9.404  {
   9.405 -    xc_dominfo_t info;
   9.406 -    unsigned int remote_port, status;
   9.407 -    u64          remote_dom;
   9.408 -    u16          wbuf;
   9.409 -    portinfo_t  *pinfo = &portinfo[port];
   9.410 +    xu_port_object *xup = (xu_port_object *)self;
   9.411 +
   9.412 +    if ( !PyArg_ParseTuple(args, "") )
   9.413 +        return NULL;
   9.414  
   9.415 -    if ( xc_evtchn_status(xc_fd, DOMID_SELF, port, 
   9.416 -                          &remote_dom, &remote_port, &status) != 0 )
   9.417 -    {
   9.418 -        SYS_ERROR("Unexpected failure when obtaining port-%d status.", port);
   9.419 -        exit(1);
   9.420 -    }
   9.421 -    
   9.422 -    if ( status != EVTCHNSTAT_connected )
   9.423 +    (void)xc_evtchn_send(xup->xc_handle, xup->local_port);
   9.424 +
   9.425 +    Py_INCREF(Py_None);
   9.426 +    return Py_None;
   9.427 +}
   9.428 +
   9.429 +static PyObject *xu_port_read_request(PyObject *self, PyObject *args)
   9.430 +{
   9.431 +    xu_port_object    *xup = (xu_port_object *)self;
   9.432 +    xu_message_object *xum;
   9.433 +    CONTROL_RING_IDX   c = xup->tx_req_cons;
   9.434 +    control_if_t      *cif = xup->interface;
   9.435 +    control_msg_t     *cmsg;
   9.436 +
   9.437 +    if ( !PyArg_ParseTuple(args, "") )
   9.438 +        return NULL;
   9.439 +
   9.440 +    if ( (c == cif->tx_req_prod) || 
   9.441 +         ((c - xup->tx_resp_prod) == CONTROL_RING_SIZE) )
   9.442      {
   9.443 -        DPRINTF("Port %d not connected: cleaning up.", port);
   9.444 -        if ( pinfo->interface != NULL )
   9.445 -        {
   9.446 -            unmap_control_interface(mem_fd, pinfo->interface);
   9.447 -            pinfo->interface = NULL;
   9.448 -            *(pinfo->pprev) = pinfo->next;
   9.449 -            if ( pinfo->next != NULL )
   9.450 -                pinfo->next->pprev = pinfo->pprev;
   9.451 -            make_consock_closed(pinfo);
   9.452 -            free(pinfo->tx_buf);
   9.453 -            free(pinfo->rx_buf);
   9.454 -            memset(pinfo, 0, sizeof(*pinfo));
   9.455 -        }
   9.456 -        /* Cleanup sanity: we'll be the grim reaper. */
   9.457 -        wbuf = port | PORT_NORMAL;
   9.458 -        (void)write(evt_fd, &wbuf, sizeof(wbuf));
   9.459 -        wbuf = port | PORT_DISCONNECT;
   9.460 -        (void)write(evt_fd, &wbuf, sizeof(wbuf));
   9.461 -        if ( status == EVTCHNSTAT_disconnected )
   9.462 -            (void)xc_evtchn_close(xc_fd, DOMID_SELF, port);
   9.463 -        return 0;
   9.464 +        PyErr_SetString(port_error, "no request to read");
   9.465 +        return NULL;
   9.466      }
   9.467  
   9.468 -    /* We only deal with initial ports (id == 0). */
   9.469 -    if ( remote_port != 0 )
   9.470 -        return 0;
   9.471 +    cmsg = &cif->tx_ring[MASK_CONTROL_IDX(c)];
   9.472 +    xum = PyObject_New(xu_message_object, &xu_message_type);
   9.473 +    memcpy(&xum->msg, cmsg, sizeof(*cmsg));
   9.474 +    if ( xum->msg.length > sizeof(xum->msg.msg) )
   9.475 +        xum->msg.length = sizeof(xum->msg.msg);
   9.476 +    xup->tx_req_cons++;
   9.477 +    return (PyObject *)xum;
   9.478 +}
   9.479  
   9.480 -    if ( pinfo->interface == NULL )
   9.481 +static PyObject *xu_port_write_request(PyObject *self, PyObject *args)
   9.482 +{
   9.483 +    xu_port_object    *xup = (xu_port_object *)self;
   9.484 +    xu_message_object *xum;
   9.485 +    CONTROL_RING_IDX   p = xup->rx_req_prod;
   9.486 +    control_if_t      *cif = xup->interface;
   9.487 +    control_msg_t     *cmsg;
   9.488 +
   9.489 +    if ( !PyArg_ParseTuple(args, "O", (PyObject **)&xum) )
   9.490 +        return NULL;
   9.491 +
   9.492 +    if ( !PyObject_TypeCheck((PyObject *)xum, &xu_message_type) )
   9.493      {
   9.494 -        DPRINTF("New control interface for DOM%llu on port %d.", 
   9.495 -                remote_dom, port);
   9.496 -        if ( xc_domain_getinfo(xc_fd, remote_dom, 1, &info) != 1 )
   9.497 -        {
   9.498 -            SYS_ERROR("Failed to obtain DOM%llu status.", remote_dom);
   9.499 -            exit(1);
   9.500 -        }
   9.501 -        memset(pinfo, 0, sizeof(*pinfo));
   9.502 -        pinfo->interface = 
   9.503 -            map_control_interface(mem_fd, info.shared_info_frame);
   9.504 -        pinfo->tx_buf = malloc(CONBUFSZ);
   9.505 -        pinfo->rx_buf = malloc(CONBUFSZ);
   9.506 -        pinfo->dom = remote_dom;
   9.507 -        pinfo->con_status = CONSTAT_CLOSED;
   9.508 -        if ( !make_consock_listener(pinfo) )
   9.509 -        {
   9.510 -            ERROR("Could not start console %d in listener status.",
   9.511 -                  PORT(pinfo));
   9.512 -            exit(1);
   9.513 -        }
   9.514 -        pinfo->pprev = &active_head;
   9.515 -        if ( (pinfo->next = active_head) != NULL )
   9.516 -            pinfo->next->pprev = &pinfo->next;
   9.517 -        active_head = pinfo;
   9.518 +        PyErr_SetString(PyExc_TypeError, "expected a xend_utils.message");
   9.519 +        return NULL;        
   9.520 +    }
   9.521 +
   9.522 +    if ( ((p - xup->rx_resp_cons) == CONTROL_RING_SIZE) )
   9.523 +    {
   9.524 +        PyErr_SetString(port_error, "no space to write request");
   9.525 +        return NULL;
   9.526      }
   9.527  
   9.528 -    return 1;
   9.529 -}
   9.530 +    cmsg = &cif->rx_ring[MASK_CONTROL_IDX(p)];
   9.531 +    memcpy(cmsg, &xum->msg, sizeof(*cmsg));
   9.532  
   9.533 -static void process_channel(unsigned int port)
   9.534 -{
   9.535 -    portinfo_t      *pinfo = &portinfo[port];
   9.536 -    u16              wbuf = port;
   9.537 +    xup->rx_req_prod = cif->rx_req_prod = p + 1;
   9.538  
   9.539 -    /* Acknowledge the notification. */
   9.540 -    (void)write(evt_fd, &wbuf, sizeof(wbuf));
   9.541 -
   9.542 -    /* Process requests; send notification if we updated either ring. */
   9.543 -    if ( process_evtchn_reads(pinfo) || process_evtchn_writes(pinfo) )
   9.544 -        (void)xc_evtchn_send(xc_fd, port);
   9.545 +    Py_INCREF(Py_None);
   9.546 +    return Py_None;
   9.547  }
   9.548  
   9.549 -int main(int argc, char **argv)
   9.550 +static PyObject *xu_port_read_response(PyObject *self, PyObject *args)
   9.551  {
   9.552 -    struct pollfd polls[1025]; /* one per port, plus /dev/xeno/evtchn */
   9.553 -    portinfo_t *pinfo;
   9.554 -    unsigned int batch, bytes, i, port, fd_idx;
   9.555 -    u16 buf[BATCH_SIZE];
   9.556 +    xu_port_object    *xup = (xu_port_object *)self;
   9.557 +    xu_message_object *xum;
   9.558 +    CONTROL_RING_IDX   c = xup->rx_resp_cons;
   9.559 +    control_if_t      *cif = xup->interface;
   9.560 +    control_msg_t     *cmsg;
   9.561 +
   9.562 +    if ( !PyArg_ParseTuple(args, "") )
   9.563 +        return NULL;
   9.564 +
   9.565 +    if ( (c == cif->rx_resp_prod) || (c == xup->rx_req_prod) )
   9.566 +    {
   9.567 +        PyErr_SetString(port_error, "no response to read");
   9.568 +        return NULL;
   9.569 +    }
   9.570  
   9.571 -    /* Ignore writes to disconnected sockets. We clear up later. */
   9.572 -    (void)signal(SIGPIPE, SIG_IGN);
   9.573 -    
   9.574 -    if ( (evt_fd = open(EVTCHN_DEV_NAME, O_NONBLOCK|O_RDWR)) == -1 )
   9.575 +    cmsg = &cif->rx_ring[MASK_CONTROL_IDX(c)];
   9.576 +    xum = PyObject_New(xu_message_object, &xu_message_type);
   9.577 +    memcpy(&xum->msg, cmsg, sizeof(*cmsg));
   9.578 +    if ( xum->msg.length > sizeof(xum->msg.msg) )
   9.579 +        xum->msg.length = sizeof(xum->msg.msg);
   9.580 +    xup->rx_resp_cons++;
   9.581 +    return (PyObject *)xum;
   9.582 +}
   9.583 +
   9.584 +static PyObject *xu_port_write_response(PyObject *self, PyObject *args)
   9.585 +{
   9.586 +    xu_port_object    *xup = (xu_port_object *)self;
   9.587 +    xu_message_object *xum;
   9.588 +    CONTROL_RING_IDX   p = xup->tx_resp_prod;
   9.589 +    control_if_t      *cif = xup->interface;
   9.590 +    control_msg_t     *cmsg;
   9.591 +
   9.592 +    if ( !PyArg_ParseTuple(args, "O", (PyObject **)&xum) )
   9.593 +        return NULL;
   9.594 +
   9.595 +    if ( !PyObject_TypeCheck((PyObject *)xum, &xu_message_type) )
   9.596      {
   9.597 -        SYS_ERROR("Could not open '%s'", EVTCHN_DEV_NAME);
   9.598 -        ROOT_HINT();
   9.599 -        HINT("On a non-devfs system you must run 'mknod %s c %d %d'.",
   9.600 -             EVTCHN_DEV_NAME, EVTCHN_DEV_MAJOR, EVTCHN_DEV_MINOR);
   9.601 -        exit(1);
   9.602 +        PyErr_SetString(PyExc_TypeError, "expected a xend_utils.message");
   9.603 +        return NULL;        
   9.604 +    }
   9.605 +
   9.606 +    if ( p == xup->tx_req_cons )
   9.607 +    {
   9.608 +        PyErr_SetString(port_error, "no space to write response");
   9.609 +        return NULL;
   9.610      }
   9.611  
   9.612 -    if ( (mem_fd = open("/dev/mem", O_RDWR)) == -1 )
   9.613 -    {
   9.614 -        SYS_ERROR("Could not open '/dev/mem'");
   9.615 -        ROOT_HINT();
   9.616 -        exit(1);
   9.617 -    }
   9.618 +    cmsg = &cif->tx_ring[MASK_CONTROL_IDX(p)];
   9.619 +    memcpy(cmsg, &xum->msg, sizeof(*cmsg));
   9.620 +
   9.621 +    xup->tx_resp_prod = cif->tx_resp_prod = p + 1;
   9.622 +
   9.623 +    Py_INCREF(Py_None);
   9.624 +    return Py_None;
   9.625 +}
   9.626 +
   9.627 +static PyObject *xu_port_request_to_read(PyObject *self, PyObject *args)
   9.628 +{
   9.629 +    xu_port_object    *xup = (xu_port_object *)self;
   9.630 +    CONTROL_RING_IDX   c = xup->tx_req_cons;
   9.631 +    control_if_t      *cif = xup->interface;
   9.632 +
   9.633 +    if ( !PyArg_ParseTuple(args, "") )
   9.634 +        return NULL;
   9.635 +
   9.636 +    if ( (c == cif->tx_req_prod) || 
   9.637 +         ((c - xup->tx_resp_prod) == CONTROL_RING_SIZE) )
   9.638 +        return PyInt_FromLong(0);
   9.639 +
   9.640 +    return PyInt_FromLong(1);
   9.641 +}
   9.642 +
   9.643 +static PyObject *xu_port_space_to_write_request(PyObject *self, PyObject *args)
   9.644 +{
   9.645 +    xu_port_object    *xup = (xu_port_object *)self;
   9.646 +    CONTROL_RING_IDX   p = xup->rx_req_prod;
   9.647 +
   9.648 +    if ( !PyArg_ParseTuple(args, "") )
   9.649 +        return NULL;
   9.650 +
   9.651 +    if ( ((p - xup->rx_resp_cons) == CONTROL_RING_SIZE) )
   9.652 +        return PyInt_FromLong(0);
   9.653 +
   9.654 +    return PyInt_FromLong(1);
   9.655 +}
   9.656 +
   9.657 +static PyObject *xu_port_response_to_read(PyObject *self, PyObject *args)
   9.658 +{
   9.659 +    xu_port_object    *xup = (xu_port_object *)self;
   9.660 +    CONTROL_RING_IDX   c = xup->rx_resp_cons;
   9.661 +    control_if_t      *cif = xup->interface;
   9.662 +
   9.663 +    if ( !PyArg_ParseTuple(args, "") )
   9.664 +        return NULL;
   9.665 +
   9.666 +    if ( (c == cif->rx_resp_prod) || (c == xup->rx_req_prod) )
   9.667 +        return PyInt_FromLong(0);
   9.668 +
   9.669 +    return PyInt_FromLong(1);
   9.670 +}
   9.671 +
   9.672 +static PyObject *xu_port_space_to_write_response(
   9.673 +    PyObject *self, PyObject *args)
   9.674 +{
   9.675 +    xu_port_object    *xup = (xu_port_object *)self;
   9.676 +    CONTROL_RING_IDX   p = xup->tx_resp_prod;
   9.677 +
   9.678 +    if ( !PyArg_ParseTuple(args, "") )
   9.679 +        return NULL;
   9.680 +
   9.681 +    if ( p == xup->tx_req_cons )
   9.682 +        return PyInt_FromLong(0);
   9.683  
   9.684 -    if ( (xc_fd = xc_interface_open()) == -1 )
   9.685 +    return PyInt_FromLong(1);
   9.686 +}
   9.687 +
   9.688 +static PyMethodDef xu_port_methods[] = {
   9.689 +    { "notify",
   9.690 +      (PyCFunction)xu_port_notify,
   9.691 +      METH_VARARGS,
   9.692 +      "Send a notification to the remote end.\n" },
   9.693 +
   9.694 +    { "read_request",
   9.695 +      (PyCFunction)xu_port_read_request,
   9.696 +      METH_VARARGS,
   9.697 +      "Read a request message from the control interface.\n" },
   9.698 +
   9.699 +    { "write_request",
   9.700 +      (PyCFunction)xu_port_write_request,
   9.701 +      METH_VARARGS,
   9.702 +      "Write a request message to the control interface.\n" },
   9.703 +
   9.704 +    { "read_response",
   9.705 +      (PyCFunction)xu_port_read_response,
   9.706 +      METH_VARARGS,
   9.707 +      "Read a response message from the control interface.\n" },
   9.708 +
   9.709 +    { "write_response",
   9.710 +      (PyCFunction)xu_port_write_response,
   9.711 +      METH_VARARGS,
   9.712 +      "Write a response message to the control interface.\n" },
   9.713 +
   9.714 +    { "request_to_read",
   9.715 +      (PyCFunction)xu_port_request_to_read,
   9.716 +      METH_VARARGS,
   9.717 +      "Returns TRUE if there is a request message to read.\n" },
   9.718 +
   9.719 +    { "space_to_write_request",
   9.720 +      (PyCFunction)xu_port_space_to_write_request,
   9.721 +      METH_VARARGS,
   9.722 +      "Returns TRUE if there is space to write a request message.\n" },
   9.723 +
   9.724 +    { "response_to_read",
   9.725 +      (PyCFunction)xu_port_response_to_read,
   9.726 +      METH_VARARGS,
   9.727 +      "Returns TRUE if there is a response message to read.\n" },
   9.728 +
   9.729 +    { "space_to_write_response",
   9.730 +      (PyCFunction)xu_port_space_to_write_response,
   9.731 +      METH_VARARGS,
   9.732 +      "Returns TRUE if there is space to write a response message.\n" },
   9.733 +
   9.734 +    { NULL, NULL, 0, NULL }
   9.735 +};
   9.736 +
   9.737 +staticforward PyTypeObject xu_port_type;
   9.738 +
   9.739 +static PyObject *xu_port_new(PyObject *self, PyObject *args)
   9.740 +{
   9.741 +    xu_port_object *xup;
   9.742 +    u64 dom;
   9.743 +    int port1, port2;
   9.744 +    xc_dominfo_t info;
   9.745 +
   9.746 +    if ( !PyArg_ParseTuple(args, "L", &dom) )
   9.747 +        return NULL;
   9.748 +
   9.749 +    xup = PyObject_New(xu_port_object, &xu_port_type);
   9.750 +
   9.751 +    if ( (xup->mem_fd = open("/dev/mem", O_RDWR)) == -1 )
   9.752      {
   9.753 -        SYS_ERROR("Could not open Xen control interface");
   9.754 -        ROOT_HINT();
   9.755 -        DOM0_HINT();
   9.756 -        exit(1);
   9.757 +        PyErr_SetString(port_error, "Could not open '/dev/mem'");
   9.758 +        goto fail1;
   9.759      }
   9.760  
   9.761 -    for ( ; ; )
   9.762 +    if ( (xup->xc_handle = xc_interface_open()) == -1 )
   9.763 +    {
   9.764 +        PyErr_SetString(port_error, "Could not open Xen control interface");
   9.765 +        goto fail2;
   9.766 +    }
   9.767 +
   9.768 +    if ( xc_evtchn_open(xup->xc_handle, DOMID_SELF, dom, &port1, &port2) != 0 )
   9.769 +    {
   9.770 +        PyErr_SetString(port_error, "Could not open channel to domain");
   9.771 +        goto fail3;
   9.772 +    }
   9.773 +
   9.774 +    if ( (xc_domain_getinfo(xup->xc_handle, dom, 1, &info) != 1) ||
   9.775 +         (info.domid != dom) )
   9.776 +    {
   9.777 +        PyErr_SetString(port_error, "Failed to obtain domain status");
   9.778 +        goto fail4;
   9.779 +    }
   9.780 +
   9.781 +    xup->interface = 
   9.782 +        map_control_interface(xup->mem_fd, info.shared_info_frame);
   9.783 +    if ( xup->interface == NULL )
   9.784      {
   9.785 -        polls[0].fd     = evt_fd;
   9.786 -        polls[0].events = POLLIN;
   9.787 +        PyErr_SetString(port_error, "Failed to map domain control interface");
   9.788 +        goto fail4;
   9.789 +    }
   9.790 +
   9.791 +    xup->tx_req_cons  = 0;
   9.792 +    xup->tx_resp_prod = 0;
   9.793 +    xup->rx_req_prod  = 0;
   9.794 +    xup->rx_resp_cons = 0;
   9.795 +    xup->remote_dom   = dom;
   9.796 +    xup->local_port   = port1;
   9.797 +    xup->remote_port  = port2;
   9.798 +
   9.799 +    return (PyObject *)xup;
   9.800 +
   9.801 +    
   9.802 + fail4:
   9.803 +    (void)xc_evtchn_close(xup->xc_handle, DOMID_SELF, port1);
   9.804 + fail3:
   9.805 +    (void)xc_interface_close(xup->xc_handle);
   9.806 + fail2:
   9.807 +    (void)close(xup->mem_fd);
   9.808 + fail1:
   9.809 +    PyObject_Del((PyObject *)xup);
   9.810 +    return NULL;        
   9.811 +}
   9.812 +
   9.813 +static PyObject *xu_port_getattr(PyObject *obj, char *name)
   9.814 +{
   9.815 +    xu_port_object *xup = (xu_port_object *)obj;
   9.816 +    if ( strcmp(name, "local_port") == 0 )
   9.817 +        return PyInt_FromLong(xup->local_port);
   9.818 +    if ( strcmp(name, "remote_port") == 0 )
   9.819 +        return PyInt_FromLong(xup->remote_port);
   9.820 +    if ( strcmp(name, "remote_dom") == 0 )
   9.821 +        return PyLong_FromUnsignedLongLong(xup->remote_dom);
   9.822 +    return Py_FindMethod(xu_port_methods, obj, name);
   9.823 +}
   9.824  
   9.825 -        fd_idx = 1;
   9.826 -        for ( pinfo = active_head; pinfo != NULL; pinfo = pinfo->next )
   9.827 -        {
   9.828 -            switch ( pinfo->con_status )
   9.829 -            {
   9.830 -            case CONSTAT_LISTENING:
   9.831 -                polls[fd_idx].fd     = pinfo->con_fd;
   9.832 -                polls[fd_idx].events = POLLIN;
   9.833 -                fd_idx++;
   9.834 -                break;
   9.835 -            case CONSTAT_CONNECTED:
   9.836 -                polls[fd_idx].fd     = pinfo->con_fd;
   9.837 -                polls[fd_idx].events = POLLIN | (RX_EMPTY(pinfo)?0:POLLOUT);
   9.838 -                fd_idx++;
   9.839 -                break;
   9.840 -            }
   9.841 -        }
   9.842 +static void xu_port_dealloc(PyObject *self)
   9.843 +{
   9.844 +    xu_port_object *xup = (xu_port_object *)self;
   9.845 +    unmap_control_interface(xup->mem_fd, xup->interface);
   9.846 +    (void)xc_evtchn_close(xup->xc_handle, DOMID_SELF, xup->local_port);
   9.847 +    (void)xc_interface_close(xup->xc_handle);
   9.848 +    (void)close(xup->mem_fd);
   9.849 +    PyObject_Del(self);
   9.850 +}
   9.851 +
   9.852 +static PyTypeObject xu_port_type = {
   9.853 +    PyObject_HEAD_INIT(&PyType_Type)
   9.854 +    0,
   9.855 +    "port",
   9.856 +    sizeof(xu_port_object),
   9.857 +    0,
   9.858 +    xu_port_dealloc,     /* tp_dealloc     */
   9.859 +    NULL,                /* tp_print       */
   9.860 +    xu_port_getattr,     /* tp_getattr     */
   9.861 +    NULL,                /* tp_setattr     */
   9.862 +    NULL,                /* tp_compare     */
   9.863 +    NULL,                /* tp_repr        */
   9.864 +    NULL,                /* tp_as_number   */
   9.865 +    NULL,                /* tp_as_sequence */
   9.866 +    NULL,                /* tp_as_mapping  */
   9.867 +    NULL                 /* tp_hash        */
   9.868 +};
   9.869 +
   9.870 +
   9.871  
   9.872 -        while ( poll(polls, fd_idx, -1) == -1 )
   9.873 -        {
   9.874 -            if ( errno == EINTR )
   9.875 -                continue;
   9.876 -            SYS_ERROR("Unexpected error from poll().");
   9.877 -            exit(1);
   9.878 -        }
   9.879 +/*
   9.880 + * *********************** BUFFER ***********************
   9.881 + */
   9.882 +
   9.883 +#define BUFSZ 65536
   9.884 +#define MASK_BUF_IDX(_i) ((_i)&(BUFSZ-1))
   9.885 +typedef unsigned int BUF_IDX;
   9.886 +
   9.887 +typedef struct {
   9.888 +    PyObject_HEAD;
   9.889 +    char        *buf;
   9.890 +    unsigned int prod, cons;
   9.891 +} xu_buffer_object;
   9.892  
   9.893 -        fd_idx = 1;
   9.894 -        for ( pinfo = active_head; pinfo != NULL; pinfo = pinfo->next )
   9.895 +static PyObject *__xu_buffer_peek(xu_buffer_object *xub, int max)
   9.896 +{
   9.897 +    PyObject *str1, *str2;
   9.898 +    int len1, len2, c = MASK_BUF_IDX(xub->cons);
   9.899 +
   9.900 +    len1 = xub->prod - xub->cons;
   9.901 +    if ( len1 > (BUFSZ - c) ) /* clip to ring wrap */
   9.902 +        len1 = BUFSZ - c;
   9.903 +    if ( len1 > max )         /* clip to specified maximum */
   9.904 +        len1 = max;
   9.905 +    if ( len1 < 0 )           /* sanity */
   9.906 +        len1 = 0;
   9.907 +
   9.908 +    if ( (str1 = PyString_FromStringAndSize(&xub->buf[c], len1)) == NULL )
   9.909 +        return NULL;
   9.910 +
   9.911 +    if ( (len1 < (xub->prod - xub->cons)) && (len1 < max) )
   9.912 +    {
   9.913 +        len2 = max - len1;
   9.914 +        if ( len2 > MASK_BUF_IDX(xub->prod) )
   9.915 +            len2 = MASK_BUF_IDX(xub->prod);
   9.916 +        if ( len2 > 0 )
   9.917          {
   9.918 -            switch ( pinfo->con_status )
   9.919 -            {
   9.920 -            case CONSTAT_LISTENING:
   9.921 -                if ( ((polls[fd_idx].revents & POLLIN) != 0) )
   9.922 -                    (void)make_consock_connected(pinfo);
   9.923 -                break;
   9.924 -            case CONSTAT_CONNECTED:
   9.925 -                if ( ((polls[fd_idx].revents & POLLOUT) != 0) )
   9.926 -                    do_consock_write(pinfo);
   9.927 -                if ( ((polls[fd_idx].revents & POLLIN) != 0) )
   9.928 -                    do_consock_read(pinfo);
   9.929 -                break;
   9.930 -            }
   9.931 -            fd_idx++;
   9.932 -        }
   9.933 -
   9.934 -        while ( (bytes = read(evt_fd, buf, sizeof(buf))) == -1 )
   9.935 -        {
   9.936 -            if ( errno == EINTR )
   9.937 -                continue;
   9.938 -            if ( errno == EAGAIN )
   9.939 -            {
   9.940 -                bytes = 0;
   9.941 -                break;
   9.942 -            }
   9.943 -            SYS_ERROR("Unexpected error while reading '%s'.", EVTCHN_DEV_NAME);
   9.944 -            exit(1);
   9.945 -        }
   9.946 -        
   9.947 -        if ( bytes == 0 )
   9.948 -            continue;
   9.949 -
   9.950 -        if ( (bytes & 1) != 0 )
   9.951 -        {
   9.952 -            ERROR("Bad read length (%d bytes) from '%s'.",
   9.953 -                  bytes, EVTCHN_DEV_NAME);
   9.954 -            exit(1);
   9.955 -        }
   9.956 -        
   9.957 -        batch = bytes / sizeof(u16);
   9.958 -        for ( i = 0; i < batch; i++ )
   9.959 -        {
   9.960 -            port = buf[i] & PORTIDX_MASK;
   9.961 -            
   9.962 -            if ( buf[i] & PORT_DISCONNECT )
   9.963 -            {
   9.964 -                DPRINTF("Disconnect on port %d.", port);
   9.965 -                (void)handle_channel_exception(port);
   9.966 -                continue;
   9.967 -            }
   9.968 -            
   9.969 -            if ( portinfo[port].interface == NULL )
   9.970 -            {
   9.971 -                DPRINTF("Unexpected notification on port %d.", port);
   9.972 -                if ( !handle_channel_exception(port) )
   9.973 -                    continue;
   9.974 -            }
   9.975 -            
   9.976 -            process_channel(port);
   9.977 +            str2 = PyString_FromStringAndSize(&xub->buf[0], len2);
   9.978 +            if ( str2 == NULL )
   9.979 +                return NULL;
   9.980 +            PyString_ConcatAndDel(&str1, str2);
   9.981 +            if ( str1 == NULL )
   9.982 +                return NULL;
   9.983          }
   9.984      }
   9.985  
   9.986 -    (void)xc_interface_close(xc_fd);
   9.987 -    (void)close(mem_fd);
   9.988 -    (void)close(evt_fd);
   9.989 +    return str1;
   9.990 +}
   9.991 +
   9.992 +static PyObject *xu_buffer_peek(PyObject *self, PyObject *args)
   9.993 +{
   9.994 +    xu_buffer_object *xub = (xu_buffer_object *)self;
   9.995 +    int max = 1024;
   9.996 +
   9.997 +    if ( !PyArg_ParseTuple(args, "|i", &max) )
   9.998 +        return NULL;
   9.999 +    
  9.1000 +    return __xu_buffer_peek(xub, max);
  9.1001 +}
  9.1002  
  9.1003 -    return 0;
  9.1004 +static PyObject *xu_buffer_read(PyObject *self, PyObject *args)
  9.1005 +{
  9.1006 +    xu_buffer_object *xub = (xu_buffer_object *)self;
  9.1007 +    PyObject *str;
  9.1008 +    int max = 1024;
  9.1009 +
  9.1010 +    if ( !PyArg_ParseTuple(args, "|i", &max) )
  9.1011 +        return NULL;
  9.1012 +
  9.1013 +    if ( (str = __xu_buffer_peek(xub, max)) != NULL )
  9.1014 +        xub->cons += PyString_Size(str);
  9.1015 +
  9.1016 +    return str;
  9.1017  }
  9.1018  
  9.1019 -
  9.1020 -/* Returns non-zero if console is listening on exit. */
  9.1021 -static int make_consock_listener(portinfo_t *pinfo)
  9.1022 +static PyObject *xu_buffer_discard(PyObject *self, PyObject *args)
  9.1023  {
  9.1024 -    int reuseaddr_flag = 1;
  9.1025 -    struct linger linger;
  9.1026 -    int tcp_port = 9600 + PORT(pinfo);
  9.1027 -    int fd, flags;
  9.1028 -    struct sockaddr_in sa;
  9.1029 +    xu_buffer_object *xub = (xu_buffer_object *)self;
  9.1030 +    int max, len;
  9.1031  
  9.1032 -    if ( pinfo->con_status == CONSTAT_LISTENING )
  9.1033 -        return 1;
  9.1034 -
  9.1035 -    if ( pinfo->con_status == CONSTAT_CONNECTED )
  9.1036 -    {
  9.1037 -        (void)close(pinfo->con_fd);
  9.1038 -        pinfo->con_status = CONSTAT_CLOSED;
  9.1039 -    }
  9.1040 -
  9.1041 -    if ( (fd = socket(AF_INET, SOCK_STREAM, 0)) == -1 )
  9.1042 -    {
  9.1043 -        SYS_ERROR("Could not create TCP socket.");
  9.1044 -        return 0;
  9.1045 -    }
  9.1046 +    if ( !PyArg_ParseTuple(args, "i", &max) )
  9.1047 +        return NULL;
  9.1048  
  9.1049 -    linger.l_onoff = 0;
  9.1050 -    if ( (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, 
  9.1051 -                     &reuseaddr_flag, sizeof(int)) != 0) ||
  9.1052 -         (setsockopt(fd, SOL_SOCKET, SO_LINGER, 
  9.1053 -                     &linger, sizeof(linger)) != 0) )
  9.1054 -    {
  9.1055 -        SYS_ERROR("Could not enable immediate reuse of socket port.");
  9.1056 -        close(fd);
  9.1057 -        return 0;
  9.1058 -    }
  9.1059 +    len = xub->prod - xub->cons;
  9.1060 +    if ( len > max )
  9.1061 +        len = max;
  9.1062 +    if ( len < 0 )
  9.1063 +        len = 0;
  9.1064  
  9.1065 -    sa.sin_family      = AF_INET;
  9.1066 -    sa.sin_addr.s_addr = htonl(INADDR_ANY);
  9.1067 -    sa.sin_port        = htons(tcp_port);
  9.1068 -    if ( bind(fd, (struct sockaddr *)&sa, sizeof(sa)) != 0 )
  9.1069 -    {
  9.1070 -        SYS_ERROR("Unable to bind to console port %d.", tcp_port);
  9.1071 -        close(fd);
  9.1072 -        return 0;
  9.1073 -    }
  9.1074 +    xub->cons += len;
  9.1075  
  9.1076 -    if ( listen(fd, 5) != 0 )
  9.1077 -    {
  9.1078 -        SYS_ERROR("Unable to listen on console port %d.", tcp_port);
  9.1079 -        close(fd);
  9.1080 -        return 0;
  9.1081 -    }
  9.1082 -
  9.1083 -    if ( ((flags = fcntl(fd, F_GETFL, 0)) < 0) ||
  9.1084 -         (fcntl(fd, F_SETFL, flags | O_NONBLOCK) < 0) )
  9.1085 -    {
  9.1086 -        SYS_ERROR("Unable to set non-blocking status for console listener.");
  9.1087 -        close(fd);
  9.1088 -        return 0;
  9.1089 -    }
  9.1090 -
  9.1091 -    pinfo->con_fd     = fd;
  9.1092 -    pinfo->con_status = CONSTAT_LISTENING;
  9.1093 -    return 1;
  9.1094 +    return PyInt_FromLong(len);
  9.1095  }
  9.1096  
  9.1097 -/* Returns non-zero if console is connected on exit. */
  9.1098 -static int make_consock_connected(portinfo_t *pinfo)
  9.1099 +static PyObject *xu_buffer_write(PyObject *self, PyObject *args)
  9.1100  {
  9.1101 -    int fd, flags, sa_len;
  9.1102 -    struct linger linger;
  9.1103 -    struct sockaddr_in sa;
  9.1104 -
  9.1105 -    if ( pinfo->con_status == CONSTAT_CONNECTED )
  9.1106 -        return 1;
  9.1107 -
  9.1108 -    if ( pinfo->con_status == CONSTAT_CLOSED )
  9.1109 -        return 0;
  9.1110 -
  9.1111 -    if ( (fd = accept(pinfo->con_fd, (struct sockaddr *)&sa, &sa_len)) == -1 )
  9.1112 -        return 0;
  9.1113 +    xu_buffer_object *xub = (xu_buffer_object *)self;
  9.1114 +    char *str;
  9.1115 +    int len, len1, len2;
  9.1116  
  9.1117 -    linger.l_onoff = 0;
  9.1118 -    if ( setsockopt(fd, SOL_SOCKET, SO_LINGER, 
  9.1119 -                    &linger, sizeof(linger)) != 0 )
  9.1120 -    {
  9.1121 -        SYS_ERROR("Could not enable immediate socket death.");
  9.1122 -        close(fd);
  9.1123 -        return 0;
  9.1124 -    }
  9.1125 +    if ( !PyArg_ParseTuple(args, "s#", &str, &len) )
  9.1126 +        return NULL;
  9.1127  
  9.1128 -    if ( ((flags = fcntl(fd, F_GETFL, 0)) < 0) ||
  9.1129 -         (fcntl(fd, F_SETFL, flags | O_NONBLOCK) < 0) )
  9.1130 -    {
  9.1131 -        SYS_ERROR("Unable to set non-blocking status on socket.");
  9.1132 -        close(fd);
  9.1133 -        return 0;
  9.1134 -    }
  9.1135 -
  9.1136 -    (void)close(pinfo->con_fd);
  9.1137 +    len1 = len;
  9.1138 +    if ( len1 > (BUFSZ - MASK_BUF_IDX(xub->prod)) )
  9.1139 +        len1 = BUFSZ - MASK_BUF_IDX(xub->prod);
  9.1140 +    if ( len1 > (BUFSZ - (xub->prod - xub->cons)) )
  9.1141 +        len1 = BUFSZ - (xub->prod - xub->cons);
  9.1142  
  9.1143 -    pinfo->con_fd     = fd;
  9.1144 -    pinfo->con_status = CONSTAT_CONNECTED;
  9.1145 -    return 1;
  9.1146 -}
  9.1147 -
  9.1148 +    if ( len1 == 0 )
  9.1149 +        return PyInt_FromLong(0);
  9.1150  
  9.1151 -static void make_consock_closed(portinfo_t *pinfo)
  9.1152 -{
  9.1153 -    if ( pinfo->con_status != CONSTAT_CLOSED )
  9.1154 -        (void)close(pinfo->con_fd);
  9.1155 -    pinfo->con_status = CONSTAT_CLOSED;
  9.1156 -}
  9.1157 -
  9.1158 +    memcpy(&xub->buf[MASK_BUF_IDX(xub->prod)], &str[0], len1);
  9.1159 +    xub->prod += len1;
  9.1160  
  9.1161 -static void do_consock_read(portinfo_t *pinfo)
  9.1162 -{
  9.1163 -    char buf[1024];
  9.1164 -    int  idx, bytes, rc, was_empty = TX_EMPTY(pinfo);
  9.1165 -
  9.1166 -    while ( (rc = read(pinfo->con_fd, &buf, sizeof(buf))) > 0 )
  9.1167 +    if ( len1 < len )
  9.1168      {
  9.1169 -        idx = 0;
  9.1170 -        while ( (rc != 0) && !TX_FULL(pinfo) )
  9.1171 +        len2 = len - len1;
  9.1172 +        if ( len2 > (BUFSZ - MASK_BUF_IDX(xub->prod)) )
  9.1173 +            len2 = BUFSZ - MASK_BUF_IDX(xub->prod);
  9.1174 +        if ( len2 > (BUFSZ - (xub->prod - xub->cons)) )
  9.1175 +            len2 = BUFSZ - (xub->prod - xub->cons);
  9.1176 +        if ( len2 != 0 )
  9.1177          {
  9.1178 -            bytes = rc;
  9.1179 -            /* Clip copy to ring-buffer wrap. */
  9.1180 -            if ( bytes > (CONBUFSZ - MASK_CONBUF_IDX(pinfo->txp)) )
  9.1181 -                bytes = CONBUFSZ - MASK_CONBUF_IDX(pinfo->txp);
  9.1182 -            /* Clip copy to ring-buffer overflow. */
  9.1183 -            if ( bytes > (CONBUFSZ - (pinfo->txp - pinfo->txc)) )
  9.1184 -                bytes = CONBUFSZ - (pinfo->txp - pinfo->txc);
  9.1185 -            memcpy(&pinfo->tx_buf[MASK_CONBUF_IDX(pinfo->txp)],
  9.1186 -                   &buf[idx], bytes);
  9.1187 -            pinfo->txp += bytes;
  9.1188 -            idx        += bytes;
  9.1189 -            rc         -= bytes;
  9.1190 +            memcpy(&xub->buf[MASK_BUF_IDX(xub->prod)], &str[len1], len2);
  9.1191 +            xub->prod += len2;
  9.1192 +            return PyInt_FromLong(len1 + len2);
  9.1193          }
  9.1194      }
  9.1195  
  9.1196 -    if ( (rc == 0) || (errno != EAGAIN) )
  9.1197 -    {
  9.1198 -        DPRINTF("Console client has disconnected.");
  9.1199 -        if ( !make_consock_listener(pinfo) )
  9.1200 -        {
  9.1201 -            ERROR("Could not revert console %d to listener status.",
  9.1202 -                  PORT(pinfo));
  9.1203 -            exit(1);
  9.1204 -        }
  9.1205 -    }
  9.1206 -
  9.1207 -    if ( was_empty && !TX_EMPTY(pinfo) )
  9.1208 -    {
  9.1209 -        /* There is now data to transmit to guest. Kickstart the pipeline. */
  9.1210 -        if ( process_evtchn_writes(pinfo) )
  9.1211 -            (void)xc_evtchn_send(xc_fd, PORT(pinfo));
  9.1212 -    }
  9.1213 +    return PyInt_FromLong(len1);
  9.1214  }
  9.1215  
  9.1216 -static void do_consock_write(portinfo_t *pinfo)
  9.1217 +static PyObject *xu_buffer_empty(PyObject *self, PyObject *args)
  9.1218  {
  9.1219 -    int bytes, rc;
  9.1220 +    xu_buffer_object *xub = (xu_buffer_object *)self;
  9.1221 +
  9.1222 +    if ( !PyArg_ParseTuple(args, "") )
  9.1223 +        return NULL;
  9.1224 +
  9.1225 +    if ( xub->cons == xub->prod )
  9.1226 +        return PyInt_FromLong(1);
  9.1227  
  9.1228 -    while ( !RX_EMPTY(pinfo) )
  9.1229 -    {
  9.1230 -        /* Clip transfer to ring-buffer wrap. */
  9.1231 -        bytes = CONBUFSZ - MASK_CONBUF_IDX(pinfo->rxc);
  9.1232 -        /* Clip transfer to ring-buffer overflow. */
  9.1233 -        if ( bytes > (pinfo->rxp - pinfo->rxc) )
  9.1234 -            bytes = pinfo->rxp - pinfo->rxc;
  9.1235 -        rc = write(pinfo->con_fd, 
  9.1236 -                   &pinfo->rx_buf[MASK_CONBUF_IDX(pinfo->rxc)], 
  9.1237 -                   bytes);
  9.1238 -        if ( rc <= 0 )
  9.1239 -            return; /* Nothing to do. Errors cleaned up in reader code. */
  9.1240 -        pinfo->rxc += rc;
  9.1241 -    }
  9.1242 +    return PyInt_FromLong(0);
  9.1243 +}
  9.1244 +
  9.1245 +static PyObject *xu_buffer_full(PyObject *self, PyObject *args)
  9.1246 +{
  9.1247 +    xu_buffer_object *xub = (xu_buffer_object *)self;
  9.1248 +
  9.1249 +    if ( !PyArg_ParseTuple(args, "") )
  9.1250 +        return NULL;
  9.1251 +
  9.1252 +    if ( (xub->prod - xub->cons) == BUFSZ )
  9.1253 +        return PyInt_FromLong(1);
  9.1254 +
  9.1255 +    return PyInt_FromLong(0);
  9.1256  }
  9.1257  
  9.1258 -static int process_evtchn_reads(portinfo_t *pinfo)
  9.1259 -{
  9.1260 -    CONTROL_RING_IDX c;
  9.1261 -    control_if_t    *cif = pinfo->interface;
  9.1262 -    control_msg_t   *cmsg;
  9.1263 -    unsigned int     clen, idx, len, bytes;
  9.1264 +static PyMethodDef xu_buffer_methods[] = {
  9.1265 +    { "peek", 
  9.1266 +      (PyCFunction)xu_buffer_peek,
  9.1267 +      METH_VARARGS,
  9.1268 +      "Peek up to @max bytes from the buffer. Returns a string.\n" },
  9.1269  
  9.1270 -    for ( c = pinfo->tx_req_cons; 
  9.1271 -          (c != cif->tx_req_prod) && 
  9.1272 -              ((c-pinfo->tx_resp_prod) != CONTROL_RING_SIZE);
  9.1273 -          c++ )
  9.1274 -    {
  9.1275 -        cmsg = &cif->tx_ring[MASK_CONTROL_IDX(c)];
  9.1276 +    { "read", 
  9.1277 +      (PyCFunction)xu_buffer_read,
  9.1278 +      METH_VARARGS,
  9.1279 +      "Read up to @max bytes from the buffer. Returns a string.\n" },
  9.1280  
  9.1281 -        if ( (clen = cmsg->length) > sizeof(cmsg->msg) )
  9.1282 -            clen = sizeof(cmsg->msg);
  9.1283 +    { "discard", 
  9.1284 +      (PyCFunction)xu_buffer_discard,
  9.1285 +      METH_VARARGS,
  9.1286 +      "Discard up to @max bytes from the buffer. Returns number of bytes.\n" },
  9.1287 +
  9.1288 +    { "write", 
  9.1289 +      (PyCFunction)xu_buffer_write,
  9.1290 +      METH_VARARGS,
  9.1291 +      "Write @string into buffer. Return number of bytes written.\n" },
  9.1292  
  9.1293 -        if ( (cmsg->cmd_type == CMD_CONSOLE) &&
  9.1294 -             (cmsg->cmd_subtype == CMD_CONSOLE_DATA) )
  9.1295 -        {
  9.1296 -            idx = 0;
  9.1297 -            len = cmsg->length;
  9.1298 -            while ( (len != 0) && !RX_FULL(pinfo) )
  9.1299 -            {
  9.1300 -                bytes = len;
  9.1301 -                /* Clip copy to ring-buffer wrap. */
  9.1302 -                if ( bytes > (CONBUFSZ - MASK_CONBUF_IDX(pinfo->rxp)) )
  9.1303 -                    bytes = CONBUFSZ - MASK_CONBUF_IDX(pinfo->rxp);
  9.1304 -                /* Clip copy to ring-buffer overflow. */
  9.1305 -                if ( bytes > (CONBUFSZ - (pinfo->rxp - pinfo->rxc)) )
  9.1306 -                    bytes = CONBUFSZ - (pinfo->rxp - pinfo->rxc);
  9.1307 -                memcpy(&pinfo->rx_buf[MASK_CONBUF_IDX(pinfo->rxp)],
  9.1308 -                       &cmsg->msg[idx], bytes);
  9.1309 -                pinfo->rxp += bytes;
  9.1310 -                idx += bytes;
  9.1311 -                len -= bytes;
  9.1312 -            }
  9.1313 -        }
  9.1314 +    { "empty", 
  9.1315 +      (PyCFunction)xu_buffer_empty,
  9.1316 +      METH_VARARGS,
  9.1317 +      "Return TRUE if the buffer is empty.\n" },
  9.1318 +
  9.1319 +    { "full", 
  9.1320 +      (PyCFunction)xu_buffer_full,
  9.1321 +      METH_VARARGS,
  9.1322 +      "Return TRUE if the buffer is full.\n" },
  9.1323 +
  9.1324 +    { NULL, NULL, 0, NULL }
  9.1325 +};
  9.1326  
  9.1327 -        /* Prepare response. No payload; msg type and id same as request. */
  9.1328 -        cmsg->length = 0;
  9.1329 +staticforward PyTypeObject xu_buffer_type;
  9.1330 +
  9.1331 +static PyObject *xu_buffer_new(PyObject *self, PyObject *args)
  9.1332 +{
  9.1333 +    xu_buffer_object *xub;
  9.1334 +
  9.1335 +    if ( !PyArg_ParseTuple(args, "") )
  9.1336 +        return NULL;
  9.1337 +
  9.1338 +    xub = PyObject_New(xu_buffer_object, &xu_buffer_type);
  9.1339 +
  9.1340 +    if ( (xub->buf = malloc(BUFSZ)) == NULL )
  9.1341 +    {
  9.1342 +        PyObject_Del((PyObject *)xub);
  9.1343 +        return NULL;
  9.1344      }
  9.1345  
  9.1346 -    if ( c != pinfo->tx_req_cons )
  9.1347 -    {
  9.1348 -        /* Update private indexes. */
  9.1349 -        pinfo->tx_resp_prod = c;
  9.1350 -        pinfo->tx_req_cons  = c;
  9.1351 -        /* Queue responses and send a notification to the guest OS. */
  9.1352 -        cif->tx_resp_prod   = c;
  9.1353 -        return 1;
  9.1354 -    }
  9.1355 +    xub->prod = xub->cons = 0;
  9.1356 +
  9.1357 +    return (PyObject *)xub;
  9.1358 +}
  9.1359  
  9.1360 -    return 0;
  9.1361 +static PyObject *xu_buffer_getattr(PyObject *obj, char *name)
  9.1362 +{
  9.1363 +    return Py_FindMethod(xu_buffer_methods, obj, name);
  9.1364 +}
  9.1365 +
  9.1366 +static void xu_buffer_dealloc(PyObject *self)
  9.1367 +{
  9.1368 +    xu_buffer_object *xub = (xu_buffer_object *)self;
  9.1369 +    free(xub->buf);
  9.1370 +    PyObject_Del(self);
  9.1371  }
  9.1372  
  9.1373 -static int process_evtchn_writes(portinfo_t *pinfo)
  9.1374 -{
  9.1375 -    CONTROL_RING_IDX p, rx_resp_prod;
  9.1376 -    control_if_t    *cif = pinfo->interface;
  9.1377 -    control_msg_t   *cmsg;
  9.1378 -    unsigned int     bytes;
  9.1379 +static PyTypeObject xu_buffer_type = {
  9.1380 +    PyObject_HEAD_INIT(&PyType_Type)
  9.1381 +    0,
  9.1382 +    "buffer",
  9.1383 +    sizeof(xu_buffer_object),
  9.1384 +    0,
  9.1385 +    xu_buffer_dealloc,   /* tp_dealloc     */
  9.1386 +    NULL,                /* tp_print       */
  9.1387 +    xu_buffer_getattr,   /* tp_getattr     */
  9.1388 +    NULL,                /* tp_setattr     */
  9.1389 +    NULL,                /* tp_compare     */
  9.1390 +    NULL,                /* tp_repr        */
  9.1391 +    NULL,                /* tp_as_number   */
  9.1392 +    NULL,                /* tp_as_sequence */
  9.1393 +    NULL,                /* tp_as_mapping  */
  9.1394 +    NULL                 /* tp_hash        */
  9.1395 +};
  9.1396  
  9.1397 -    /* Validate the rx-response producer, an dupdate our consumer if okay. */
  9.1398 -    rx_resp_prod = cif->rx_resp_prod;
  9.1399 -    if ( (pinfo->rx_resp_cons != rx_resp_prod) &&
  9.1400 -         ((pinfo->rx_req_prod - rx_resp_prod) <= CONTROL_RING_SIZE) &&
  9.1401 -         ((rx_resp_prod - pinfo->rx_resp_cons) <= CONTROL_RING_SIZE) )
  9.1402 -        pinfo->rx_resp_cons = cif->rx_resp_prod;
  9.1403 +
  9.1404 +
  9.1405 +/*
  9.1406 + * *********************** MODULE WRAPPER ***********************
  9.1407 + */
  9.1408 +
  9.1409 +static void handle_child_death(int dummy)
  9.1410 +{
  9.1411 +    while ( waitpid(-1, NULL, WNOHANG) > 0 )
  9.1412 +        continue;
  9.1413 +}
  9.1414 +
  9.1415 +static PyObject *xu_autoreap(PyObject *self, PyObject *args)
  9.1416 +{
  9.1417 +    struct sigaction sa;
  9.1418  
  9.1419 -    for ( p = pinfo->rx_req_prod;
  9.1420 -          (p-pinfo->rx_resp_cons) != CONTROL_RING_SIZE;
  9.1421 -          p++ )
  9.1422 -    {
  9.1423 -        if ( TX_EMPTY(pinfo) )
  9.1424 -            break;
  9.1425 -        cmsg = &cif->rx_ring[MASK_CONTROL_IDX(p)];
  9.1426 -        bytes = sizeof(cmsg->msg);
  9.1427 -        /* Clip transfer to ring-buffer wrap. */
  9.1428 -        if ( bytes > (CONBUFSZ - MASK_CONBUF_IDX(pinfo->txc)) )
  9.1429 -            bytes = CONBUFSZ - MASK_CONBUF_IDX(pinfo->txc);
  9.1430 -        /* Clip transfer to ring-buffer overflow. */
  9.1431 -        if ( bytes > (pinfo->txp - pinfo->txc) )
  9.1432 -            bytes = pinfo->txp - pinfo->txc;
  9.1433 -        cmsg->cmd_type    = CMD_CONSOLE;
  9.1434 -        cmsg->cmd_subtype = CMD_CONSOLE_DATA;
  9.1435 -        cmsg->id          = 0xaa;
  9.1436 -        cmsg->length      = bytes;
  9.1437 -        memcpy(&cmsg->msg[0], 
  9.1438 -               &pinfo->tx_buf[MASK_CONBUF_IDX(pinfo->txc)], 
  9.1439 -               bytes);
  9.1440 -        pinfo->txc += bytes;
  9.1441 -    }
  9.1442 +    if ( !PyArg_ParseTuple(args, "") )
  9.1443 +        return NULL;
  9.1444 +
  9.1445 +    memset(&sa, 0, sizeof(sa));
  9.1446 +    sa.sa_handler = handle_child_death;
  9.1447 +    sigemptyset(&sa.sa_mask);
  9.1448 +    sa.sa_flags = SA_NOCLDSTOP | SA_RESTART;
  9.1449 +    (void)sigaction(SIGCHLD, &sa, NULL);
  9.1450 +
  9.1451 +    Py_INCREF(Py_None);
  9.1452 +    return Py_None;
  9.1453 +}
  9.1454  
  9.1455 -    if ( p != pinfo->rx_req_prod )
  9.1456 -    {
  9.1457 -        pinfo->rx_req_prod  = p;
  9.1458 -        cif->rx_req_prod    = p;
  9.1459 -        return 1;
  9.1460 -    }
  9.1461 +static PyMethodDef xu_methods[] = {
  9.1462 +    { "notifier", xu_notifier_new, METH_VARARGS, 
  9.1463 +      "Create a new notifier." },
  9.1464 +    { "message", xu_message_new, METH_VARARGS, 
  9.1465 +      "Create a new communications message." },
  9.1466 +    { "port", xu_port_new, METH_VARARGS, 
  9.1467 +      "Create a new communications port." },
  9.1468 +    { "buffer", xu_buffer_new, METH_VARARGS, 
  9.1469 +      "Create a new ring buffer." },
  9.1470 +    { "autoreap", xu_autoreap, METH_VARARGS,
  9.1471 +      "Ensure that zombie children are automatically reaped by the OS." },
  9.1472 +    { NULL, NULL, 0, NULL }
  9.1473 +};
  9.1474  
  9.1475 -    return 0;
  9.1476 +PyMODINIT_FUNC initxend_utils(void)
  9.1477 +{
  9.1478 +    PyObject *m, *d;
  9.1479 +
  9.1480 +    m = Py_InitModule("xend_utils", xu_methods);
  9.1481 +
  9.1482 +    d = PyModule_GetDict(m);
  9.1483 +    port_error = PyErr_NewException("xend_utils.PortError", NULL, NULL);
  9.1484 +    PyDict_SetItemString(d, "PortError", port_error);
  9.1485  }
    10.1 --- a/tools/xentrace/Makefile	Fri Mar 12 18:12:23 2004 +0000
    10.2 +++ b/tools/xentrace/Makefile	Sun Mar 14 18:23:01 2004 +0000
    10.3 @@ -14,18 +14,22 @@ MAN8     = $(wildcard *.8)
    10.4  all: $(BIN)
    10.5  
    10.6  install: all
    10.7 -	mkdir -p /usr/bin
    10.8 -	cp $(BIN) /usr/bin
    10.9 -	for i in $(BIN); do chmod 755 /usr/bin/$$i; done
   10.10 -	for i in $(MAN1); do cp $$i /usr/man/man1/$$i; done
   10.11 -	for i in $(MAN8); do cp $$i /usr/man/man8/$$i; done
   10.12 +	mkdir -p $(prefix)/usr/bin
   10.13 +	mkdir -p $(prefix)/usr/man/man1
   10.14 +	mkdir -p $(prefix)/usr/man/man8
   10.15 +	cp $(BIN) $(prefix)/usr/bin
   10.16 +	for i in $(BIN); do chmod 755 $(prefix)/usr/bin/$$i; done
   10.17 +	for i in $(MAN1); do cp $$i $(prefix)/usr/man/man1/$$i; done
   10.18 +	for i in $(MAN8); do cp $$i $(prefix)/usr/man/man8/$$i; done
   10.19  
   10.20  dist: all
   10.21  	mkdir -p ../../../install/bin
   10.22 +	mkdir -p ../../../install/man/man1
   10.23 +	mkdir -p ../../../install/man/man8
   10.24  	cp $(BIN) ../../../install/bin
   10.25 -	chmod 755 ../../../install/bin/$(BIN)
   10.26 -	cp $(SCRIPTS) ../../../install/bin
   10.27 -	for i in $(SCRIPTS); do chmod 755 ../../../install/bin/$i; done
   10.28 +	for i in $(BIN); do chmod 755 ../../../install/bin/$$i; done
   10.29 +	for i in $(MAN1); do cp $$i ../../../install/man/man1/$$i; done
   10.30 +	for i in $(MAN8); do cp $$i ../../../install/man/man8/$$i; done
   10.31  
   10.32  clean:
   10.33  	$(RM) *.a *.so *.o *.rpm $(BIN)
    11.1 --- a/xenolinux-2.4.25-sparse/arch/xeno/drivers/console/console.c	Fri Mar 12 18:12:23 2004 +0000
    11.2 +++ b/xenolinux-2.4.25-sparse/arch/xeno/drivers/console/console.c	Sun Mar 14 18:23:01 2004 +0000
    11.3 @@ -52,9 +52,9 @@ static void nonpriv_conwrite(const char 
    11.4  
    11.5          p = MASK_CONTROL_IDX(ctrl_if->tx_req_prod);
    11.6          
    11.7 -        ctrl_if->tx_ring[p].cmd_type    = CMD_CONSOLE;
    11.8 -        ctrl_if->tx_ring[p].cmd_subtype = CMD_CONSOLE_DATA;
    11.9 -        ctrl_if->tx_ring[p].id          = 0xaa;
   11.10 +        ctrl_if->tx_ring[p].type    = CMSG_CONSOLE;
   11.11 +        ctrl_if->tx_ring[p].subtype = CMSG_CONSOLE_DATA;
   11.12 +        ctrl_if->tx_ring[p].id      = 0xaa;
   11.13          src = dst = 0;
   11.14          while ( (src < count) && (dst < (sizeof(ctrl_if->tx_ring[p].msg)-1)) )
   11.15          {
   11.16 @@ -202,8 +202,8 @@ static void __do_console_io(void)
   11.17      for ( c = ctrl_if->rx_resp_prod; c != ctrl_if->rx_req_prod; c++ )
   11.18      {
   11.19          msg = &ctrl_if->rx_ring[MASK_CONTROL_IDX(c)];
   11.20 -        if ( (msg->cmd_type == CMD_CONSOLE) &&
   11.21 -             (msg->cmd_subtype == CMD_CONSOLE_DATA) )
   11.22 +        if ( (msg->type == CMSG_CONSOLE) &&
   11.23 +             (msg->subtype == CMSG_CONSOLE_DATA) )
   11.24          {
   11.25              for ( i = 0; i < msg->length; i++ )
   11.26                  tty_insert_flip_char(xeno_console_tty, msg->msg[i], 0);
   11.27 @@ -225,9 +225,9 @@ static void __do_console_io(void)
   11.28          if ( (wc == wp) && (x_char == 0) )
   11.29              break;
   11.30          msg = &ctrl_if->tx_ring[MASK_CONTROL_IDX(c)];
   11.31 -        msg->cmd_type    = CMD_CONSOLE;
   11.32 -        msg->cmd_subtype = CMD_CONSOLE_DATA;
   11.33 -        msg->id          = 0xaa;
   11.34 +        msg->type    = CMSG_CONSOLE;
   11.35 +        msg->subtype = CMSG_CONSOLE_DATA;
   11.36 +        msg->id      = 0xaa;
   11.37          len = 0;
   11.38          if ( x_char != 0 ) /* Handle XON/XOFF urgently. */
   11.39          {
    12.1 --- a/xenolinux-2.4.25-sparse/include/asm-xeno/control_if.h	Fri Mar 12 18:12:23 2004 +0000
    12.2 +++ b/xenolinux-2.4.25-sparse/include/asm-xeno/control_if.h	Sun Mar 14 18:23:01 2004 +0000
    12.3 @@ -8,11 +8,11 @@
    12.4  #define __CONTROL_IF_H__
    12.5  
    12.6  typedef struct {
    12.7 -    u8 cmd_type;     /* echoed in response */
    12.8 -    u8 cmd_subtype;  /* echoed in response */
    12.9 -    u8 id;           /* echoed in response */
   12.10 -    u8 length;       /* number of bytes in 'msg' */
   12.11 -    unsigned char msg[60]; /* command-specific message data */
   12.12 +    u8 type;     /* echoed in response */
   12.13 +    u8 subtype;  /* echoed in response */
   12.14 +    u8 id;       /* echoed in response */
   12.15 +    u8 length;   /* number of bytes in 'msg' */
   12.16 +    unsigned char msg[60]; /* type-specific message data */
   12.17  } control_msg_t;
   12.18  
   12.19  #define CONTROL_RING_SIZE 8
   12.20 @@ -26,7 +26,7 @@ typedef struct {
   12.21      CONTROL_RING_IDX rx_req_prod, rx_resp_prod;
   12.22  } control_if_t;
   12.23  
   12.24 -#define CMD_CONSOLE      0
   12.25 -#define CMD_CONSOLE_DATA 0
   12.26 +#define CMSG_CONSOLE      0
   12.27 +#define CMSG_CONSOLE_DATA 0
   12.28  
   12.29  #endif /* __CONTROL_IF_H__ */