From 8f655f2f69b04d650fd4a683ccb3cd871cd2d23b Mon Sep 17 00:00:00 2001 From: tchernobog Date: Wed, 22 Feb 2006 15:16:08 +0000 Subject: [PATCH] - Finish implementing async setup for Python policies' access - Correct method names for the Python policy (design problem?) - Compiles, but can't run it on this machine. I'll test it later (and I expect quite a lot of SIGSEGVs). git-svn-id: svn://svn.gna.org/svn/sgpemv2/trunk@382 3ecf2c5c-341e-0410-92b4-d18e462d057c --- src/backend/dummy_policy.hh | 4 +- src/backend/policy.hh | 29 ++-- src/backend/pyloader/Policy.py | 2 +- src/backend/pyloader/ScriptAdapter.py | 21 +-- src/backend/pyloader/python_policy.cc | 151 +++++++++++++++++- src/backend/pyloader/python_policy.hh | 49 +++--- src/backend/pyloader/python_policy_manager.cc | 47 +----- src/builtin-policies/fcfs.py | 4 +- 8 files changed, 211 insertions(+), 96 deletions(-) diff --git a/src/backend/dummy_policy.hh b/src/backend/dummy_policy.hh index 7e34a79..4e2e51e 100644 --- a/src/backend/dummy_policy.hh +++ b/src/backend/dummy_policy.hh @@ -50,6 +50,4 @@ namespace sgpem }//~ namespace sgpem - - -#endif \ No newline at end of file +#endif diff --git a/src/backend/policy.hh b/src/backend/policy.hh index f72da51..f81764a 100644 --- a/src/backend/policy.hh +++ b/src/backend/policy.hh @@ -41,22 +41,21 @@ namespace sgpem class SG_DLLEXPORT Policy { public: - virtual ~Policy(); - - virtual void configure() = 0; - virtual void sort_queue(sgpem::Scheduler::event) const = 0; - int get_id() const; - virtual Glib::ustring get_description() const = 0; - virtual bool is_pre_emptive() const = 0; - virtual int get_time_slice() const = 0; - virtual void set_time_slice(const int&) = 0; - - PolicyParameters& get_parameters(); - - + virtual ~Policy(); + + virtual void configure() = 0; + virtual void sort_queue(sgpem::Scheduler::event) const = 0; + int get_id() const; + virtual Glib::ustring get_description() const = 0; + virtual bool is_pre_emptive() const = 0; + virtual int get_time_slice() const = 0; + virtual void set_time_slice(const int&) = 0; + + PolicyParameters& get_parameters(); + protected: - PolicyParameters _parameters; - int _id; + PolicyParameters _parameters; + int _id; }; }//~ namespace sgpem diff --git a/src/backend/pyloader/Policy.py b/src/backend/pyloader/Policy.py index af469a1..8f2a2ac 100644 --- a/src/backend/pyloader/Policy.py +++ b/src/backend/pyloader/Policy.py @@ -7,5 +7,5 @@ class Policy: configure = AbstractMethod('configure') sort_queue = AbstractMethod('sort_queue') is_preemptive = AbstractMethod('is_preemptive') - is_time_sliced = AbstractMethod('is_time_sliced') + get_time_slice = AbstractMethod('get_time_slice') diff --git a/src/backend/pyloader/ScriptAdapter.py b/src/backend/pyloader/ScriptAdapter.py index e9f45f2..0dbb632 100644 --- a/src/backend/pyloader/ScriptAdapter.py +++ b/src/backend/pyloader/ScriptAdapter.py @@ -3,6 +3,10 @@ import sgpem _g_mutex = mutex.mutex() +## @val Synchronized return value you can read from C++ +# when a threaded function returns +_ret_val = None + ## @brief This is an adapter class which acts as a proxy # for user-implemented policies # @@ -29,6 +33,7 @@ class ScriptAdapter : def _wrap_configure(self): thread.start_new_thread(ScriptAdapter._wrap_configure_callback, (self,)) + def _wrap_configure_callback(self): # call configure method self._policy.configure() @@ -53,17 +58,15 @@ class ScriptAdapter : thread.start_new_thread(ScriptAdapter._wrap_is_preemptible_callback, (self,)) def _wrap_is_preemptible_callback(self): - # FIXME : here we should return the call value - self._policy.is_preemptible() + _ret_val = self._policy.is_preemptible() _g_mutex.unlock() - def async_is_timesliced(self): - _g_mutex.lock(ScriptAdapter._wrap_is_timesliced, self) + def async_get_time_slice(self): + _g_mutex.lock(ScriptAdapter._wrap_get_time_slice, self) - def _wrap_is_timesliced(self): - thread.start_new_thread(ScriptAdapter._wrap_is_timesliced_callback, (self,)) + def _wrap_get_time_slice(self): + thread.start_new_thread(ScriptAdapter._wrap_get_time_slice_callback, (self,)) - def _wrap_is_timesliced_callback(self): - # FIXME : return value! - self._policy.is_timesliced() + def _wrap_get_time_slice_callback(self): + _ret_val = self._policy.get_time_slice() _g_mutex.unlock() diff --git a/src/backend/pyloader/python_policy.cc b/src/backend/pyloader/python_policy.cc index 43a22c5..ee07637 100644 --- a/src/backend/pyloader/python_policy.cc +++ b/src/backend/pyloader/python_policy.cc @@ -19,10 +19,159 @@ // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include "python_policy.hh" +#include using namespace sgpem; using namespace std; -PythonPolicy::PythonPolicy() +// 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() +{ + if(_adapter) Py_DECREF(_adapter); + if(_adapter_dict) Py_DECREF(_adapter_dict); +} + + +void +PythonPolicy::configure() +{ + PyObject* retval = PyObject_CallMethod(_adapter, "async_configure", NULL); + Py_DECREF(retval); + wait_unlock(); +} + + +void +PythonPolicy::sort_queue(Scheduler::event event) const +{ + PyObject* pEvent = PyInt_FromLong(event); + PyObject* pMethodName = PyString_FromString("async_sort_queue"); + PyObject* retval = PyObject_CallMethodObjArgs(_adapter, pMethodName, pEvent, NULL); + Py_DECREF(retval); + Py_DECREF(pMethodName); + Py_DECREF(pEvent); + + wait_unlock(); +} + + +Glib::ustring +PythonPolicy::get_description() const +{ + return _name; +} + + +bool +PythonPolicy::is_pre_emptive() const { + 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(PyInt_AsLong(retval)); +} + + +int +PythonPolicy::get_time_slice() const { + 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(PyInt_AsLong(retval)); +} + + +void +PythonPolicy::set_time_slice(const int&) +{ + throw "The design is wrong, and I shouldn't be called."; +} + + +void +PythonPolicy::wait_unlock() const +{ + PyThreadState *_save; + Py_UNBLOCK_THREADS + sleep(5); // hack'a'ton! magggggiccc nummmbeeerrrrrs!! + + // 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 + } */ + + Py_BLOCK_THREADS +} diff --git a/src/backend/pyloader/python_policy.hh b/src/backend/pyloader/python_policy.hh index 00c6e0e..d217156 100644 --- a/src/backend/pyloader/python_policy.hh +++ b/src/backend/pyloader/python_policy.hh @@ -32,28 +32,37 @@ namespace sgpem { + class PythonPolicy; + class PythonPolicyManager; - class PythonPolicy; - class PythonPolicyManager; + class SG_DLLEXPORT PythonPolicy : public Policy + { + public: + //only PythonPolicyManager can create a PythonPolicy object + friend class PythonPolicyManager; - class SG_DLLEXPORT PythonPolicy : public Policy - { - public: - //only PythonPolicyManager can create a PythonPolicy object - friend class PythonPolicyManager; - - void configure() {} - void sort_queue(sgpem::Scheduler::event) const {} - Glib::ustring get_description() const {} - bool is_pre_emptive() const {} - int get_time_slice() const {} - void set_time_slice(const int&) {} - - private: - PythonPolicy(); - PythonPolicy(const PythonPolicy&); - PythonPolicy& operator=(const PythonPolicy&); - }; + virtual ~PythonPolicy(); + + void configure(); + void sort_queue(Scheduler::event) const; + Glib::ustring get_description() const; + bool is_pre_emptive() const; + int get_time_slice() const; + void set_time_slice(const int&); + + private: + PythonPolicy(const char* name); + PythonPolicy(const PythonPolicy&); + PythonPolicy& operator=(const PythonPolicy&); + + void wait_unlock() const; + + PyObject* _adapter; + PyObject* _adapter_dict; + PyObject* _lock; + + Glib::ustring _name; + }; } diff --git a/src/backend/pyloader/python_policy_manager.cc b/src/backend/pyloader/python_policy_manager.cc index 5fb5e0f..d5b0d3a 100644 --- a/src/backend/pyloader/python_policy_manager.cc +++ b/src/backend/pyloader/python_policy_manager.cc @@ -76,50 +76,7 @@ PythonPolicyManager::init() // FIXME : Hardcoded policy name char* policy_name = "fcfs"; - PyObject* pLoadmeStr = PyString_FromString(policy_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); - PyObject* pScriptAdapterDict = PyModule_GetDict(pScriptAdapterModule); - assert(pScriptAdapterDict); - - // Now takes the user-defined policy class from pUserPolicyDict - PyObject* pPolicyClass = PyDict_GetItemString(pUserPolicyDict, policy_name); - assert(pPolicyClass); // FIXME needs stricter checking and exception throwing - - // Creates a new object of type ScriptAdapter : - // takes init function from ScriptAdapter class - PyObject* pAdapterClass = PyDict_GetItemString(pScriptAdapterDict, "ScriptAdapter"); - PyObject* pAdapterCtorParam = PyTuple_New(1); - Py_INCREF(pPolicyClass); // PyTuple_SetItem steals a reference - PyTuple_SetItem(pAdapterCtorParam, 0, pPolicyClass); - PyObject* pAdapterObject = PyInstance_New(pAdapterClass, pAdapterCtorParam, NULL); - - // try code - PyObject_CallMethod(pAdapterObject, "async_configure", NULL); - - PyThreadState *_save; - Py_UNBLOCK_THREADS - sleep(5); // hack'a'ton! magggggiccc nummmbeeerrrrrs!! - - Py_BLOCK_THREADS - - // And now, who's your daddy, huh? + PythonPolicy policy(policy_name); + policy.configure(); } diff --git a/src/builtin-policies/fcfs.py b/src/builtin-policies/fcfs.py index 480a051..8821025 100644 --- a/src/builtin-policies/fcfs.py +++ b/src/builtin-policies/fcfs.py @@ -23,8 +23,8 @@ class fcfs(Policy) : def is_preemptive(self): return False - def is_time_sliced(self): - return False + def get_time_slice(self): + return -1 def sort_queue(self, event, queue): # How am I supposed to sort that mess??