diff --git a/src/backend/pyloader/ScriptAdapter.py b/src/backend/pyloader/ScriptAdapter.py index 9dd590a..d6a66d5 100644 --- a/src/backend/pyloader/ScriptAdapter.py +++ b/src/backend/pyloader/ScriptAdapter.py @@ -1,13 +1,6 @@ import mutex, thread import sgpem -## Var Global syncronization object -_g_mutex = mutex.mutex() - -## @var 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 # @@ -28,7 +21,13 @@ class ScriptAdapter : ## @var The event to pass to Policy.sort_queue() after the asynchronous call _event = None + + ## @var Synchronized return value you can read from C++ + # when a threaded function returns + _ret_val = None + ## Var Testable syncronization object + _g_mutex = mutex.mutex() ## @brief Constructor of ScriptAdapter # @@ -43,7 +42,7 @@ class ScriptAdapter : # # @param self The caller object def async_configure(self): - _g_mutex.lock(ScriptAdapter._wrap_configure, self ) + self._g_mutex.lock(ScriptAdapter._wrap_configure, self ) def _wrap_configure(self): thread.start_new_thread(ScriptAdapter._wrap_configure_callback, (self,)) @@ -51,7 +50,7 @@ class ScriptAdapter : def _wrap_configure_callback(self): # call configure method self._policy.configure() - _g_mutex.unlock() + self._g_mutex.unlock() ## @brief Asynchronously call Policy.sort_queue() @@ -63,7 +62,7 @@ class ScriptAdapter : # @param event The event to pass to sort_queue def async_sort_queue(self, event): self._event = event - _g_mutex.lock(ScriptAdapter._wrap_sort_queue, self) + self._g_mutex.lock(ScriptAdapter._wrap_sort_queue, self) def _wrap_sort_queue(self): thread.start_new_thread(ScriptAdapter._wrap_sort_queue_callback, @@ -73,7 +72,7 @@ class ScriptAdapter : # here we retrieve and pass the ready queue queue = sgpem.Scheduler.get_instance().get_ready_queue() self._policy.sort_queue(event, queue) - _g_mutex.unlock() + self._g_mutex.unlock() ## @brief Asynchronously call Policy.is_preemptive() @@ -86,19 +85,25 @@ class ScriptAdapter : thread.start_new_thread(ScriptAdapter._wrap_is_preemptive_callback, (self,)) def _wrap_is_preemptive_callback(self): - _ret_val = self._policy.is_preemptive() - _g_mutex.unlock() - + self._ret_val = self._policy.is_preemptive() + self._g_mutex.unlock() ## @brief Asynchronously call Policy.get_time_slice() # # @param self The caller object def async_get_time_slice(self): - _g_mutex.lock(ScriptAdapter._wrap_get_time_slice, self) + self._g_mutex.lock(ScriptAdapter._wrap_get_time_slice, self) def _wrap_get_time_slice(self): thread.start_new_thread(ScriptAdapter._wrap_get_time_slice_callback, (self,)) def _wrap_get_time_slice_callback(self): - _ret_val = self._policy.get_time_slice() - _g_mutex.unlock() + self._ret_val = self._policy.get_time_slice() + self._g_mutex.unlock() + + ## @brief Return the global shared variable with the methods' last return value + def get_return_value(self): + return self._ret_val + + def test_lock(self): + return self._g_mutex.test() diff --git a/src/backend/pyloader/python_policy.cc b/src/backend/pyloader/python_policy.cc index 017a616..4d412d4 100644 --- a/src/backend/pyloader/python_policy.cc +++ b/src/backend/pyloader/python_policy.cc @@ -31,8 +31,7 @@ using namespace std; // *strong* exception checking / handling! PythonPolicy::PythonPolicy(const char* name) - : _adapter(NULL), _adapter_dict(NULL), - _lock(NULL), _name(name) + : _adapter(NULL), _adapter_dict(NULL), _name(name) { PyObject* pLoadmeStr = PyString_FromString(name); PyObject* pUserPolicyModule = PyImport_Import(pLoadmeStr); @@ -56,18 +55,13 @@ PythonPolicy::PythonPolicy(const char* name) 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 + // We want to keep a reference to it 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"); @@ -136,8 +130,10 @@ PythonPolicy::is_pre_emptive() const throw(UserInterruptException) wait_unlock(); // Parse return value stored in global Python object - retval = PyDict_GetItemString(_adapter_dict, "_ret_val"); - return PyBool_Check(retval); + retval = PyObject_CallMethod(_adapter, "get_return_value", NULL); + bool ret = PyObject_IsTrue(retval); + Py_DECREF(retval); + return ret; } @@ -149,8 +145,10 @@ PythonPolicy::get_time_slice() const throw(UserInterruptException) { wait_unlock(); // Parse return value stored in global Python object - retval = PyDict_GetItemString(_adapter_dict, "_ret_val"); + retval = PyObject_CallMethod(_adapter, "get_return_value", NULL); long tmp = PyInt_AsLong(retval); + Py_DECREF(retval); + return tmp < 0 ? numeric_limits::max() : static_cast(tmp); } @@ -169,24 +167,24 @@ PythonPolicy::wait_unlock() const throw(UserInterruptException) usleep(WAIT_FOR); // hack'a'ton! magggggiccc nummmbeeerrrrrs!! Py_BLOCK_THREADS; - PyObject* retval = PyObject_CallMethod(_lock, "test", NULL); - still_locked = PyBool_Check(retval); + PyObject* retval = PyObject_CallMethod(_adapter, "test_lock", NULL); + assert(retval); + still_locked = PyObject_IsTrue(retval); Py_DECREF(retval); - if(i++ > WAIT_FOR*12) + if(i++ > 12) /* waits for WAIT_FOR * 12 microseconds == 3 secs */ { PyThreadState_Clear(_save); PyEval_RestoreThread(_save); //Py_UNBLOCK_THREADS; - + throw UserInterruptException("User-defined policy is " "taking too long to terminate."); } } while(still_locked); - // What we should really do here: /* do { enable python threads diff --git a/src/backend/pyloader/python_policy.hh b/src/backend/pyloader/python_policy.hh index 4c65f3a..5fcbdd9 100644 --- a/src/backend/pyloader/python_policy.hh +++ b/src/backend/pyloader/python_policy.hh @@ -82,7 +82,6 @@ namespace sgpem PyObject* _adapter; PyObject* _adapter_dict; - PyObject* _lock; Glib::ustring _name; }; diff --git a/src/builtin-policies/fcfs.py b/src/builtin-policies/fcfs.py index a1b04f4..3d4adaf 100644 --- a/src/builtin-policies/fcfs.py +++ b/src/builtin-policies/fcfs.py @@ -33,7 +33,7 @@ class fcfs(Policy) : return False def get_time_slice(self): - return -1 + return -2 def sort_queue(self, event, queue): cmpf = lambda a, b: \ diff --git a/src/simulation.cc b/src/simulation.cc index 71f905b..e0586f8 100644 --- a/src/simulation.cc +++ b/src/simulation.cc @@ -77,8 +77,17 @@ Simulation::run() throw(UserInterruptException) { History& h = History::get_instance(); - if (_state == state_stopped) - h.truncate_at(0); + switch(_state) + { + case state_running: + // FIXME: write out something, or just ignore user input? + return; + case state_stopped: + h.truncate_at(0); + break; + default: + break; + } _state = state_running; @@ -86,7 +95,7 @@ Simulation::run() throw(UserInterruptException) if (_mode) { -loop: + do { // chech for termination bool all_term = true; smart_ptr left = h.get_simulation_status_at(h.get_current_time()); @@ -101,8 +110,8 @@ loop: //by the last execution of upadate() if (all_term) { - _state = state_paused; - return; + _state = state_stopped; + return; // Exit from loop } try @@ -116,16 +125,15 @@ loop: } catch(UserInterruptException e) { - stop(); - - throw; + stop(); + throw; } //check the state if (_state == state_stopped || _state == state_paused) return; - goto loop; + } while(true); } //******* STEP by STEP