/*
 *  Python extension for using Mac OS X realtime threads.
 *  Copyright (C) 2004  Andreas Junghans <aj@lucid-cake.net>
 *
 *  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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#include <Python.h>
#include <mach/mach_init.h>
#include <mach/thread_act.h>
#include <sys/sysctl.h>

#define MODULE_NAME "realtime"
#define MODULE_PREFIX MODULE_NAME "."

#define CHAR_BUFFER_SIZE 256
//static char char_buffer[CHAR_BUFFER_SIZE];
#define ADD_STRING_CONSTANT(m, c) \
    if (CFStringGetCString(c, char_buffer, CHAR_BUFFER_SIZE, kCFStringEncodingASCII)) \
    { \
        PyModule_AddStringConstant(m, #c, char_buffer); \
    }
#define ADD_INT_CONSTANT(m, c) \
    PyModule_AddIntConstant(m, #c, c);
#define INIT_TYPE(dict, name, typeObject) \
    PyType_Ready(typeObject); \
    PyDict_SetItemString(dict, name, (PyObject*) typeObject);


// Test method for error handling.
static PyObject* errorTest(PyObject* self, PyObject* args)
{
    PyErr_SetString(PyExc_OSError, "an error test");
    return NULL;
}

// Boosts the priority of the current thread.
static PyObject* boostpriority(PyObject* self, PyObject* args)
{
    // try to get ourselves realtime priority
    int mib[2] = {CTL_HW, HW_BUS_FREQ};
    int bus_speed;
    struct thread_time_constraint_policy ttcpolicy;
    size_t len = sizeof(bus_speed);
    if (sysctl(mib, 2, &bus_speed, &len, NULL, 0)) {
		PyErr_SetString(PyExc_OSError, "cannot determine the bus speed");
		return NULL;
    }
    ttcpolicy.period = bus_speed/160;
    ttcpolicy.computation = bus_speed/3300;
    ttcpolicy.constraint = bus_speed/2200;
    ttcpolicy.preemptible = 1;
    if (thread_policy_set(mach_thread_self(),
                          THREAD_TIME_CONSTRAINT_POLICY,
						  (int *)&ttcpolicy,
                          THREAD_TIME_CONSTRAINT_POLICY_COUNT) == KERN_SUCCESS) {
		Py_INCREF(Py_None);
		return Py_None;
	}
    PyErr_SetString(PyExc_OSError, "cannot boost the priority");
    return NULL;
}


static PyMethodDef RealtimeMethods[] = {
    {"errorTest", errorTest, METH_NOARGS, "Method for testing error handling, please ignore."},
    {"boostpriority", boostpriority, METH_VARARGS, "Boosts the priority of the current thread."},
	{NULL, NULL, 0, NULL}
};

void initrealtime() {
    PyObject *m, *dict;
    
    // initialize the module
	m = Py_InitModule(MODULE_NAME, RealtimeMethods);
    dict = PyModule_GetDict(m);
}
