2006-02-23 12:29:25 +01:00
|
|
|
// src/backend/pyloader/python_policy.cc - Copyright 2005, 2006, University
|
2006-02-17 17:08:54 +01:00
|
|
|
// of Padova, dept. of Pure and Applied
|
|
|
|
// Mathematics
|
|
|
|
//
|
|
|
|
// This file is part of SGPEMv2.
|
|
|
|
//
|
|
|
|
// This is free software; you can redistribute it and/or modify
|
|
|
|
// it under the terms of the GNU General Public License as published by
|
|
|
|
// the Free Software Foundation; either version 2 of the License, or
|
|
|
|
// (at your option) any later version.
|
|
|
|
//
|
|
|
|
// SGPEMv2 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 General Public License for more details.
|
|
|
|
//
|
|
|
|
// You should have received a copy of the GNU General Public License
|
|
|
|
// along with SGPEMv2; if not, write to the Free Software
|
|
|
|
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
|
|
|
|
|
|
#include "python_policy.hh"
|
2006-02-23 11:12:27 +01:00
|
|
|
#include <iostream>
|
2006-02-22 16:16:08 +01:00
|
|
|
#include <unistd.h>
|
2006-02-17 17:08:54 +01:00
|
|
|
using namespace sgpem;
|
|
|
|
using namespace std;
|
|
|
|
|
2006-02-22 16:16:08 +01:00
|
|
|
// WARNING : this class needs extensive and above all
|
|
|
|
// *strong* exception checking / handling!
|
|
|
|
|
|
|
|
PythonPolicy::PythonPolicy(const char* name)
|
|
|
|
: _adapter(NULL), _adapter_dict(NULL),
|
|
|
|
_lock(NULL), _name(name)
|
|
|
|
{
|
|
|
|
PyObject* pLoadmeStr = PyString_FromString(name);
|
|
|
|
PyObject* pUserPolicyModule = PyImport_Import(pLoadmeStr);
|
|
|
|
Py_DECREF(pLoadmeStr);
|
|
|
|
|
|
|
|
if( !pUserPolicyModule )
|
|
|
|
{
|
|
|
|
PyErr_Print(); // Error in import
|
|
|
|
// FIXME : don't exit abruptly, but fall back gracefully
|
|
|
|
exit(-1);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Dictionary with defined ``symbols'' for .pyc file
|
|
|
|
PyObject* pUserPolicyDict = PyModule_GetDict(pUserPolicyModule);
|
|
|
|
assert(pUserPolicyDict);
|
|
|
|
|
|
|
|
// Loads ScriptAdapter module and get its dictionary
|
|
|
|
pLoadmeStr = PyString_FromString("ScriptAdapter");
|
|
|
|
PyObject* pScriptAdapterModule = PyImport_Import(pLoadmeStr);
|
|
|
|
Py_DECREF(pLoadmeStr);
|
|
|
|
assert(pScriptAdapterModule);
|
|
|
|
_adapter_dict = PyModule_GetDict(pScriptAdapterModule);
|
|
|
|
assert(_adapter_dict);
|
|
|
|
// We want to keep a reference to it even if we decref
|
|
|
|
// its containing module
|
|
|
|
Py_INCREF(_adapter_dict);
|
|
|
|
|
|
|
|
// Now takes the user-defined policy class from pUserPolicyDict
|
|
|
|
PyObject* pPolicyClass = PyDict_GetItemString(pUserPolicyDict, name);
|
|
|
|
assert(pPolicyClass); // FIXME needs stricter checking and exception throwing
|
|
|
|
|
|
|
|
// Save a reference to the global lock
|
|
|
|
_lock = PyDict_GetItemString(_adapter_dict, "_g_mutex");
|
|
|
|
assert(_lock);
|
|
|
|
|
|
|
|
// Creates a new object of type ScriptAdapter :
|
|
|
|
// takes init function from ScriptAdapter class
|
|
|
|
PyObject* pAdapterClass = PyDict_GetItemString(_adapter_dict, "ScriptAdapter");
|
|
|
|
PyObject* pAdapterCtorParam = PyTuple_New(1);
|
|
|
|
Py_INCREF(pPolicyClass); // PyTuple_SetItem steals a reference
|
|
|
|
PyTuple_SetItem(pAdapterCtorParam, 0, pPolicyClass);
|
|
|
|
_adapter = PyInstance_New(pAdapterClass, pAdapterCtorParam, NULL);
|
|
|
|
Py_DECREF(pAdapterCtorParam);
|
|
|
|
assert(_adapter);
|
|
|
|
|
|
|
|
Py_DECREF(pUserPolicyModule);
|
|
|
|
Py_DECREF(pScriptAdapterModule);
|
|
|
|
|
|
|
|
// And now, who's your daddy, huh?
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
PythonPolicy::~PythonPolicy()
|
2006-02-17 17:08:54 +01:00
|
|
|
{
|
2006-02-22 16:16:08 +01:00
|
|
|
if(_adapter) Py_DECREF(_adapter);
|
|
|
|
if(_adapter_dict) Py_DECREF(_adapter_dict);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
2006-02-23 12:29:25 +01:00
|
|
|
PythonPolicy::configure() throw(UserInterruptException)
|
2006-02-22 16:16:08 +01:00
|
|
|
{
|
|
|
|
PyObject* retval = PyObject_CallMethod(_adapter, "async_configure", NULL);
|
|
|
|
Py_DECREF(retval);
|
2006-02-23 12:29:25 +01:00
|
|
|
|
2006-02-22 16:16:08 +01:00
|
|
|
wait_unlock();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
2006-02-23 12:29:25 +01:00
|
|
|
PythonPolicy::sort_queue(Scheduler::event event) const throw(UserInterruptException)
|
2006-02-22 16:16:08 +01:00
|
|
|
{
|
|
|
|
PyObject* pEvent = PyInt_FromLong(event);
|
|
|
|
PyObject* pMethodName = PyString_FromString("async_sort_queue");
|
|
|
|
PyObject* retval = PyObject_CallMethodObjArgs(_adapter, pMethodName, pEvent, NULL);
|
2006-02-23 12:29:25 +01:00
|
|
|
|
|
|
|
// Do minimal debugging
|
2006-02-23 11:12:27 +01:00
|
|
|
if(!retval) PyErr_Print();
|
|
|
|
else Py_DECREF(retval);
|
2006-02-23 12:29:25 +01:00
|
|
|
|
2006-02-22 16:16:08 +01:00
|
|
|
Py_DECREF(pMethodName);
|
|
|
|
Py_DECREF(pEvent);
|
|
|
|
|
|
|
|
wait_unlock();
|
2006-02-17 17:08:54 +01:00
|
|
|
}
|
2006-02-19 23:36:24 +01:00
|
|
|
|
2006-02-22 16:16:08 +01:00
|
|
|
|
|
|
|
Glib::ustring
|
|
|
|
PythonPolicy::get_description() const
|
|
|
|
{
|
|
|
|
return _name;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool
|
2006-02-23 12:29:25 +01:00
|
|
|
PythonPolicy::is_pre_emptive() const throw(UserInterruptException)
|
|
|
|
{
|
2006-02-22 16:16:08 +01:00
|
|
|
PyObject* retval = PyObject_CallMethod(_adapter, "async_is_preemptive", NULL);
|
|
|
|
Py_DECREF(retval);
|
|
|
|
|
|
|
|
wait_unlock();
|
|
|
|
|
|
|
|
// Parse return value stored in global Python object
|
|
|
|
retval = PyDict_GetItemString(_adapter_dict, "_ret_val");
|
|
|
|
return static_cast<bool>(PyInt_AsLong(retval));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int
|
2006-02-23 12:29:25 +01:00
|
|
|
PythonPolicy::get_time_slice() const throw(UserInterruptException) {
|
2006-02-22 16:16:08 +01:00
|
|
|
PyObject* retval = PyObject_CallMethod(_adapter, "async_get_time_slice", NULL);
|
|
|
|
Py_DECREF(retval);
|
|
|
|
|
|
|
|
wait_unlock();
|
|
|
|
|
|
|
|
// Parse return value stored in global Python object
|
|
|
|
retval = PyDict_GetItemString(_adapter_dict, "_ret_val");
|
|
|
|
return static_cast<int>(PyInt_AsLong(retval));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
PythonPolicy::set_time_slice(const int&)
|
|
|
|
{
|
|
|
|
throw "The design is wrong, and I shouldn't be called.";
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
2006-02-23 12:29:25 +01:00
|
|
|
PythonPolicy::wait_unlock() const throw(UserInterruptException)
|
2006-02-22 16:16:08 +01:00
|
|
|
{
|
|
|
|
PyThreadState *_save;
|
|
|
|
Py_UNBLOCK_THREADS
|
2006-02-22 21:36:33 +01:00
|
|
|
sleep(2); // hack'a'ton! magggggiccc nummmbeeerrrrrs!!
|
2006-02-23 12:29:25 +01:00
|
|
|
Py_BLOCK_THREADS
|
|
|
|
|
|
|
|
// Now check if lock has been released, else
|
|
|
|
// throw an exception
|
|
|
|
PyObject* retval = PyObject_CallMethod(_lock, "test", NULL);
|
|
|
|
bool still_locked = static_cast<bool>(PyInt_AsLong(retval));
|
|
|
|
Py_DECREF(retval);
|
|
|
|
|
|
|
|
if(still_locked)
|
|
|
|
throw UserInterruptException("User-defined policy is taking too long to terminate.");
|
2006-02-22 16:16:08 +01:00
|
|
|
|
|
|
|
// What we should really do here:
|
|
|
|
/* do {
|
|
|
|
enable python threads
|
|
|
|
wait for some time...
|
|
|
|
disable python threads
|
|
|
|
...check if user asked for interruption, reading a
|
|
|
|
syncronized variable...
|
|
|
|
...if he has, break
|
|
|
|
...else:
|
|
|
|
if the global lock is set:
|
|
|
|
stay in this loop
|
|
|
|
else:
|
|
|
|
all's went okay, can exit loop
|
|
|
|
} */
|
|
|
|
|
|
|
|
}
|