/* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
/*
 *  tickcount - a Python extension to provide access to the tick counter
 *  Copyright (C) 2006  Canonical Ltd
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License as published by the Free Software Foundation; either
 *  version 2.1 of the License, or (at your option) any later version.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
 *  USA
 */

#include <Python.h>

static const char tickcount_doc[] =
"tickcount() -> int\n"
"Return the value of the current thread's tick counter.\n"
"\n"
"By multiplying the return value by sys.getcheckinterval(), you can\n"
"get an estimate of the number of instructions executed.\n";

static PyObject*
tickcount(PyObject *self)
{
    PyThreadState *tstate;

    tstate = PyThreadState_Get();
    return PyInt_FromLong(tstate->tick_counter);
}

static const char difference_doc[] =
"difference(oldcount, newcount) -> int\n"
"Return the difference between two tick counts.\n"
"\n"
"The thread's tick count is stored as a C int.  In a long running\n"
"program, it is conceivable that the counter could overflow.  By using\n"
"this function rather than simple subtraction, the overflow will be\n"
"automatically corrected.\n";

static PyObject *
difference(PyObject *self, PyObject *args)
{
    long old, new, diff;

    if (!PyArg_ParseTuple(args, "ll:difference", &old, &new))
        return NULL;

    /* adjust for wrap around */
    diff = new - old;
    if (diff < 0)
        diff += UINT_MAX;
    return PyInt_FromLong(diff);
}


static const char module_doc[] =
"Provide access to the interpreter tick counter.\n"
"\n"
"As the Python interpreter executes code, it increments a 'tick\n"
"counter'.  This counter is incremented every $checkinterval\n"
"instructions.\n"
"\n"
"By taking the difference between two tick counts and multiplying the\n"
"result by check interval (returned by sys.getcheckinterval) you can\n"
"get an estimate of the number of instructions executed in the thread\n"
"over that interval.\n";


static PyMethodDef tickcount_methods[] = {
    {"tickcount", (PyCFunction)tickcount, METH_NOARGS,
     (char *)tickcount_doc},
    {"difference", (PyCFunction)difference, METH_VARARGS,
     (char *)difference_doc},
    {NULL, NULL, 0}
};

/* module entry-point (module-initialization) function */
void
inittickcount(void)
{
    PyObject *m;

    /* Create the module and add the functions */
    m = Py_InitModule3("tickcount", tickcount_methods,
                       (char *)module_doc);
}
