Where & how to deallocate resources in Python C extension

fredbasset1000 at gmail.com fredbasset1000 at gmail.com
Mon Feb 2 18:03:18 EST 2009


Hi,

I've written a C extension, see code below, to provide a Python
interface to a hardware watchdog timer.  As part of the initialization
it makes some calls to mmap, I am wondering should I be making
balanced calls to munmap in some kind of de-init function?  Do Python
extensions have d'tors?

Thanks for any help,
Fred

----------------------------------------------------------------------------------------------
#include <Python.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <inttypes.h>
#include <errno.h>

static const uint8_t WD_PAT_VALUE = 0x05; // hard coded value to
indicate a pat to the watchdog

static uint8_t* wdt_control = NULL;
static uint8_t* wdt_feed = NULL;

/*!
    \brief Initialize the watchdog timer and start it.

    \param[in] int timeout_period, value to pass to timeout register
0x00 - 0x07, see table above.
    \return void
*/
static PyObject* init(PyObject *self, PyObject *args) {
    int period;
    int fd;

    if (!PyArg_Parse(args, "(i)", &period)) {
        PyErr_SetString(PyExc_TypeError, "single integer argument
expected");
        return NULL;
    }
    if (period <= 0x00 || period >= 0x07) {
        PyErr_SetString(PyExc_ValueError, "watchdog reg. value out of
range (0x00 to 0x07 only)");
        return NULL;
    }

    fd = open("/dev/mem", O_RDWR | O_SYNC);
    if (fd == -1) {
        PyErr_SetString(PyExc_SystemError, strerror(errno));
        return NULL;
    }
    wdt_control = mmap(0, getpagesize(), PROT_READ|PROT_WRITE,
MAP_SHARED, fd, 0x23800000);
    if (wdt_control == MAP_FAILED) {
        PyErr_SetString(PyExc_SystemError, strerror(errno));
        return NULL;
    }

    wdt_feed = mmap(0, getpagesize(), PROT_READ|PROT_WRITE,
MAP_SHARED, fd, 0x23C00000);
    if (wdt_feed == MAP_FAILED) {
        PyErr_SetString(PyExc_SystemError, strerror(errno));
        return NULL;
    }

    *wdt_feed = WD_PAT_VALUE;   // must first pat the w.d. before
setting period
    *wdt_control = period;

    Py_INCREF(Py_None);
    return Py_None;
}

/*!
    \brief Pat the watchdog timer once.
    Always call init() before calling this function.

    \return void
*/
static PyObject* pat(PyObject *self, PyObject *args)
{
    if (!PyArg_Parse(args, "( )")) { // verify no args passed
        return NULL;
    }

    if (wdt_feed != NULL) {
        *wdt_feed = WD_PAT_VALUE;
    }

    Py_INCREF(Py_None);
    return Py_None;
}

// method registration table
static struct PyMethodDef wdt_methods[] = {
    {"init", init, METH_VARARGS},
    {"pat", pat, METH_VARARGS},
    {NULL, NULL}
};

// module initializer, called on first import
void initwdtmodule() {
    (void) Py_InitModule("wdtmodule", wdt_methods);
}



More information about the Python-list mailing list