diff --git a/Makefile.am b/Makefile.am
index f3f53d5..4f8867b 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -153,6 +153,7 @@ src_backend_libbackend_la_SOURCES = \
src/backend/concrete_simulation.cc \
src/backend/cpu_policies_gatekeeper.cc \
src/backend/cpu_policy.cc \
+ src/backend/cpu_policy_exception.cc \
src/backend/cpu_policy_manager.cc \
src/backend/dynamic_process.cc \
src/backend/dynamic_request.cc \
@@ -203,6 +204,7 @@ pkginclude_HEADERS += \
config.h \
src/backend/cpu_policies_gatekeeper.hh \
src/backend/cpu_policy.hh \
+ src/backend/cpu_policy_exception.hh \
src/backend/cpu_policy_manager.hh \
src/backend/environment.hh \
src/backend/global_preferences.hh \
diff --git a/glade/add-process-dialog.glade b/glade/add-process-dialog.glade
index b3e4204..f699959 100644
--- a/glade/add-process-dialog.glade
+++ b/glade/add-process-dialog.glade
@@ -75,50 +75,6 @@
11
9
-
-
- True
- True
- True
- True
- 0
-
- True
- ●
- False
- 17
-
-
- 1
- 2
- 1
- 2
-
-
-
-
-
-
- True
- True
- True
- True
- 0
-
- True
- ●
- False
- 17
-
-
- 1
- 2
- 2
- 3
-
-
-
-
True
@@ -224,6 +180,48 @@
+
+
+
+ True
+ True
+ 1
+ 0
+ True
+ GTK_UPDATE_ALWAYS
+ False
+ False
+ 1 1 inf 1 10 10
+
+
+ 1
+ 2
+ 1
+ 2
+
+
+
+
+
+
+ True
+ True
+ 1
+ 0
+ True
+ GTK_UPDATE_ALWAYS
+ False
+ False
+ 0 0 inf 1 10 10
+
+
+ 1
+ 2
+ 2
+ 3
+
+
+
0
diff --git a/glade/add-request-dialog.glade b/glade/add-request-dialog.glade
index f5e255e..f1373b2 100644
--- a/glade/add-request-dialog.glade
+++ b/glade/add-request-dialog.glade
@@ -105,16 +105,16 @@
-
+
True
True
- True
- True
- 0
-
- True
- ●
- False
+ 1
+ 0
+ True
+ GTK_UPDATE_ALWAYS
+ False
+ False
+ 0 0 inf 1 10 10
0
@@ -225,27 +225,6 @@
-
-
- True
- True
- True
- True
- 0
-
- True
- ●
- False
-
-
- 1
- 2
- 1
- 2
-
-
-
-
True
@@ -261,6 +240,27 @@
fill
+
+
+
+ True
+ True
+ 1
+ 0
+ True
+ GTK_UPDATE_ALWAYS
+ False
+ False
+ 1 1 inf 1 10 10
+
+
+ 1
+ 2
+ 1
+ 2
+
+
+
0
diff --git a/glade/add-resource-dialog.glade b/glade/add-resource-dialog.glade
index c6dd96d..e39612c 100644
--- a/glade/add-resource-dialog.glade
+++ b/glade/add-resource-dialog.glade
@@ -163,7 +163,7 @@
GTK_UPDATE_ALWAYS
False
False
- 1 1 100 1 10 10
+ 1 1 inf 1 10 10
1
@@ -212,7 +212,7 @@
GTK_UPDATE_ALWAYS
False
False
- 1 0 100 1 10 10
+ 0 0 inf 1 10 10
1
diff --git a/glade/add-thread-dialog.glade b/glade/add-thread-dialog.glade
index e4fb4f3..7ce1313 100644
--- a/glade/add-thread-dialog.glade
+++ b/glade/add-thread-dialog.glade
@@ -153,28 +153,6 @@
-
-
- True
- True
- True
- True
- 0
-
- True
- ●
- False
- 17
-
-
- 1
- 2
- 3
- 4
-
-
-
-
True
@@ -203,28 +181,6 @@
-
-
- True
- True
- True
- True
- 0
-
- True
- ●
- False
- 17
-
-
- 1
- 2
- 2
- 3
-
-
-
-
True
@@ -254,16 +210,16 @@
-
+
True
True
- True
- True
- 0
-
- True
- ●
- False
+ 1
+ 0
+ True
+ GTK_UPDATE_ALWAYS
+ False
+ False
+ 1 1 inf 1 10 10
1
@@ -273,6 +229,48 @@
+
+
+
+ True
+ True
+ 1
+ 0
+ True
+ GTK_UPDATE_ALWAYS
+ False
+ False
+ 0 0 inf 1 10 10
+
+
+ 1
+ 2
+ 2
+ 3
+
+
+
+
+
+
+ True
+ True
+ 1
+ 0
+ True
+ GTK_UPDATE_ALWAYS
+ False
+ False
+ 0 0 inf 1 10 10
+
+
+ 1
+ 2
+ 3
+ 4
+
+
+
0
diff --git a/plugins/pyloader/src/ScriptAdapter.py b/plugins/pyloader/src/ScriptAdapter.py
index 03f0091..ed7a59c 100644
--- a/plugins/pyloader/src/ScriptAdapter.py
+++ b/plugins/pyloader/src/ScriptAdapter.py
@@ -1,4 +1,4 @@
-import mutex, thread
+import sys, mutex, thread
import sgpem
## @brief This is an adapter class which acts as a proxy
@@ -26,6 +26,8 @@ class ScriptAdapter :
## Var Testable syncronization object
_g_mutex = mutex.mutex()
+ _g_last_exception = None
+
## @brief Constructor of ScriptAdapter
#
# @param self The caller object
@@ -38,15 +40,19 @@ class ScriptAdapter :
#
# @param self The caller object
def async_configure(self):
- self._g_mutex.lock(ScriptAdapter._wrap_configure, self )
+ self._g_last_exception = None
+ self._g_mutex.lock(ScriptAdapter._wrap_configure, self )
def _wrap_configure(self):
thread.start_new_thread(ScriptAdapter._wrap_configure_callback, (self,))
def _wrap_configure_callback(self):
# call configure method
- self._policy.configure()
- self._g_mutex.unlock()
+ try:
+ self._policy.configure()
+ except:
+ self._g_last_exception = sys.exc_value
+ self._g_mutex.unlock()
## @brief Asynchronously call Policy.sort_queue()
@@ -56,6 +62,7 @@ class ScriptAdapter :
#
# @param self The caller object
def async_sort_queue(self):
+ self._g_last_exception = None
self._g_mutex.lock(ScriptAdapter._wrap_sort_queue, self)
def _wrap_sort_queue(self):
@@ -64,7 +71,11 @@ class ScriptAdapter :
def _wrap_sort_queue_callback(self):
# here we retrieve and pass the ready queue
queue = sgpem.Scheduler.get_instance().get_ready_queue()
- self._policy.sort_queue(queue)
+
+ try:
+ self._policy.sort_queue(queue)
+ except:
+ self._g_last_exception = sys.exc_value
self._g_mutex.unlock()
@@ -72,26 +83,34 @@ class ScriptAdapter :
#
# @param self The caller object
def async_is_preemptive(self):
+ self._g_last_exception = None
self._g_mutex.lock(ScriptAdapter._wrap_is_preemptive, self)
def _wrap_is_preemptive(self):
thread.start_new_thread(ScriptAdapter._wrap_is_preemptive_callback, (self,))
def _wrap_is_preemptive_callback(self):
- self._ret_val = self._policy.is_preemptive()
+ try:
+ self._ret_val = self._policy.is_preemptive()
+ except:
+ self._g_last_exception = sys.exc_value
self._g_mutex.unlock()
## @brief Asynchronously call Policy.get_time_slice()
#
# @param self The caller object
def async_get_time_slice(self):
+ self._g_last_exception = None
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):
- self._ret_val = self._policy.get_time_slice()
+ try:
+ self._ret_val = self._policy.get_time_slice()
+ except:
+ self._g_last_exception = sys.exc_value
self._g_mutex.unlock()
## @brief Return the global shared variable with the methods' last return value
@@ -100,3 +119,7 @@ class ScriptAdapter :
def mutex_test_lock(self):
return self._g_mutex.test()
+
+ def get_last_exception(self):
+ return self._g_last_exception
+
diff --git a/plugins/pyloader/src/python_cpu_policy.cc b/plugins/pyloader/src/python_cpu_policy.cc
index d9e86e9..fe40d47 100644
--- a/plugins/pyloader/src/python_cpu_policy.cc
+++ b/plugins/pyloader/src/python_cpu_policy.cc
@@ -40,7 +40,7 @@ PythonCPUPolicy::PythonCPUPolicy(const char* name) throw(MalformedPolicyExceptio
Py_DECREF(pLoadmeStr);
if (pUserCPUPolicyModule == NULL)
- throw MalformedPolicyException(get_exception_information().c_str());
+ throw MalformedPolicyException(get_exception_information());
// Dictionary with defined ``symbols'' for .pyc file
_upolicy_dict = PyModule_GetDict(pUserCPUPolicyModule);
@@ -70,7 +70,7 @@ PythonCPUPolicy::PythonCPUPolicy(const char* name) throw(MalformedPolicyExceptio
Py_DECREF(pScriptAdapterModule);
if (_adapter == NULL)
- throw MalformedPolicyException(get_exception_information().c_str());
+ throw MalformedPolicyException(get_exception_information());
// And now, who's your daddy, huh?
}
@@ -87,7 +87,7 @@ PythonCPUPolicy::~PythonCPUPolicy()
}
void
-PythonCPUPolicy::activate()
+PythonCPUPolicy::activate() throw(UserInterruptException, MalformedPolicyException)
{
// FIXME write the rest, taking away code from constructor
@@ -107,7 +107,7 @@ PythonCPUPolicy::deactivate()
void
-PythonCPUPolicy::configure() throw(UserInterruptException)
+PythonCPUPolicy::configure() throw(UserInterruptException, MalformedPolicyException)
{
PyObject* retval = PyObject_CallMethod(_adapter, "async_configure", NULL);
Py_DECREF(retval);
@@ -117,7 +117,7 @@ PythonCPUPolicy::configure() throw(UserInterruptException)
void
-PythonCPUPolicy::sort_queue() const throw(UserInterruptException)
+PythonCPUPolicy::sort_queue() const throw(UserInterruptException, MalformedPolicyException)
{
PyObject* retval = PyObject_CallMethod(_adapter, "async_sort_queue", NULL);
@@ -143,7 +143,7 @@ PythonCPUPolicy::get_name() const
}
bool
-PythonCPUPolicy::is_pre_emptive() const throw(UserInterruptException)
+PythonCPUPolicy::is_pre_emptive() const throw(UserInterruptException, MalformedPolicyException)
{
PyObject* retval = PyObject_CallMethod(_adapter, "async_is_preemptive", NULL);
Py_DECREF(retval);
@@ -160,7 +160,7 @@ PythonCPUPolicy::is_pre_emptive() const throw(UserInterruptException)
int
-PythonCPUPolicy::get_time_slice() const throw(UserInterruptException)
+PythonCPUPolicy::get_time_slice() const throw(UserInterruptException, MalformedPolicyException)
{
PyObject* retval = PyObject_CallMethod(_adapter, "async_get_time_slice", NULL);
@@ -181,7 +181,7 @@ PythonCPUPolicy::get_time_slice() const throw(UserInterruptException)
void
-PythonCPUPolicy::wait_unlock() const throw(UserInterruptException)
+PythonCPUPolicy::wait_unlock() const throw(UserInterruptException, MalformedPolicyException)
{
PyThreadState* _save;
int i = 0; // We give the sort_queue() three seconds max time, then...
@@ -198,7 +198,7 @@ PythonCPUPolicy::wait_unlock() const throw(UserInterruptException)
assert(retval);
still_locked = PyObject_IsTrue(retval);
Py_DECREF(retval);
-
+
if (i++ > 12) /* waits for WAIT_FOR * 12 microseconds == 3 secs */
{
PyThreadState_Clear(_save);
@@ -207,13 +207,37 @@ PythonCPUPolicy::wait_unlock() const throw(UserInterruptException)
Py_UNBLOCK_THREADS;
PyEval_RestoreThread(_save);
-
+ if(PyErr_Occurred() != NULL)
+ abort();
+
throw UserInterruptException(_("User-defined policy is "
"taking too long to terminate."));
}
}
while (still_locked);
+ // check if there were unhandled exception in the user-defined code
+
+ PyObject* pException = PyObject_CallMethod(_adapter, "get_last_exception", NULL);
+
+ if(pException != NULL)
+ {
+ if(pException != Py_None)
+ {
+ PyObject* pExceptStr = PyObject_Str(pException);
+
+ string msg = _("unhandled exception in user policy: ");
+ msg += PyString_AsString(pExceptStr);
+
+ Py_DECREF(pExceptStr);
+ Py_DECREF(pException);
+
+ throw MalformedPolicyException(msg);
+ }
+ else
+ Py_DECREF(pException);
+ }
+
// What we should really do here:
/* do {
enable python threads
@@ -260,6 +284,8 @@ PythonCPUPolicy::get_exception_information()
if (pValue != NULL) Py_DECREF(pValue);
if (pTraceback != NULL) Py_DECREF(pTraceback);
+ PyErr_Clear();
+
return msg;
}
diff --git a/plugins/pyloader/src/python_cpu_policy.hh b/plugins/pyloader/src/python_cpu_policy.hh
index 4c6f489..afb4cb8 100644
--- a/plugins/pyloader/src/python_cpu_policy.hh
+++ b/plugins/pyloader/src/python_cpu_policy.hh
@@ -51,12 +51,12 @@ namespace sgpem
/**
Calls the method \c async_configure
*/
- void configure() throw(UserInterruptException);
+ void configure() throw(UserInterruptException, MalformedPolicyException);
/**
Calls the method \c async_sort_queue
*/
- void sort_queue() const throw(UserInterruptException);
+ void sort_queue() const throw(UserInterruptException, MalformedPolicyException);
/**
\returns A textual description of this policy.
@@ -69,14 +69,14 @@ namespace sgpem
\returns \c TRUE if the policy is preemptive.
\returns \c FALSE if the policy is not preemptive.
*/
- bool is_pre_emptive() const throw(UserInterruptException);
+ bool is_pre_emptive() const throw(UserInterruptException, MalformedPolicyException);
/**
\returns The integer value of its time-slice.
*/
- int get_time_slice() const throw(UserInterruptException);
+ int get_time_slice() const throw(UserInterruptException, MalformedPolicyException);
- void activate();
+ void activate() throw(UserInterruptException, MalformedPolicyException);
void deactivate();
@@ -84,7 +84,7 @@ namespace sgpem
PythonCPUPolicy(const PythonCPUPolicy&);
PythonCPUPolicy& operator=(const PythonCPUPolicy&);
- void wait_unlock() const throw(UserInterruptException);
+ void wait_unlock() const throw(UserInterruptException, MalformedPolicyException);
static std::string get_exception_information();
PyObject* _upolicy_dict;
diff --git a/src/backend/cpu_policies_gatekeeper.cc b/src/backend/cpu_policies_gatekeeper.cc
index 56659b1..69a0834 100644
--- a/src/backend/cpu_policies_gatekeeper.cc
+++ b/src/backend/cpu_policies_gatekeeper.cc
@@ -101,8 +101,18 @@ CPUPoliciesGatekeeper::activate_policy(History *history, CPUPolicy* policy)
if (pos == end || pos->second != policy)
{
- _active_policies[history] = policy;
- _active_policies[history]->activate();
+ try
+ {
+ policy->activate();
+ _active_policies[history] = policy;
+ }
+ catch(UserInterruptException e)
+ {
+ //FIXME what to do here???
+ //probably throwing again a MalformedPolicyException
+ //maybe the best idea. or can we just fallback
+ //to the previous policy?
+ }
}
}
diff --git a/src/backend/cpu_policy.hh b/src/backend/cpu_policy.hh
index 636ee07..6660836 100644
--- a/src/backend/cpu_policy.hh
+++ b/src/backend/cpu_policy.hh
@@ -28,6 +28,7 @@
#include "policy_parameters.hh"
#include "user_interrupt_exception.hh"
+#include "malformed_policy_exception.hh"
namespace sgpem
{
@@ -50,7 +51,7 @@ namespace sgpem
Because it's a pure virtual method, must be re-implemented
in concrete derived classes.
*/
- virtual void configure() throw(UserInterruptException) = 0;
+ virtual void configure() throw(UserInterruptException, MalformedPolicyException) = 0;
/**
Sort the \ref ReadyQueue object that contain all the Schedulable objects
@@ -59,7 +60,7 @@ namespace sgpem
Because it's a pure virtual method, must be re-implemented
in concrete derived classes.
*/
- virtual void sort_queue() const throw(UserInterruptException) = 0;
+ virtual void sort_queue() const throw(UserInterruptException, MalformedPolicyException) = 0;
/**
Gets a string description of the policy.
@@ -79,7 +80,7 @@ namespace sgpem
in concrete derived classes.
\return True if this policy is preemptible.
*/
- virtual bool is_pre_emptive() const throw(UserInterruptException) = 0;
+ virtual bool is_pre_emptive() const throw(UserInterruptException, MalformedPolicyException) = 0;
/**
Gets the time quantum for the policy.
@@ -88,9 +89,9 @@ namespace sgpem
in concrete derived classes.
\return Time quantum for the policy.
*/
- virtual int get_time_slice() const throw(UserInterruptException) = 0;
+ virtual int get_time_slice() const throw(UserInterruptException, MalformedPolicyException) = 0;
- virtual void activate() = 0;
+ virtual void activate() throw(UserInterruptException, MalformedPolicyException) = 0;
virtual void deactivate() = 0;
diff --git a/src/backend/cpu_policy_exception.cc b/src/backend/cpu_policy_exception.cc
new file mode 100644
index 0000000..759abfd
--- /dev/null
+++ b/src/backend/cpu_policy_exception.cc
@@ -0,0 +1,31 @@
+// src/backend/cpu_policy_exception.cc - Copyright 2005, 2006, University
+// 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
+
+// Warning! This exception will be thrown across different libraries.
+// It could be necessary to do dynamic type-checking when
+// catching it (with typeinfo).
+
+#include "malformed_policy_exception.hh"
+using namespace sgpem;
+
+CPUPolicyException::CPUPolicyException(const std::string& msg)
+ : std::runtime_error(msg)
+{}
+
diff --git a/src/backend/cpu_policy_exception.hh b/src/backend/cpu_policy_exception.hh
new file mode 100644
index 0000000..b34f061
--- /dev/null
+++ b/src/backend/cpu_policy_exception.hh
@@ -0,0 +1,43 @@
+// src/backend/cpu_policy_exception.hh - Copyright 2005, 2006, University
+// 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
+
+// Warning! This exception will be thrown across different libraries.
+// It could be necessary to do dynamic type-checking when
+// catching it (with typeinfo).
+
+#ifndef CPU_POLICY_EXCEPTION
+#define CPU_POLICY_EXCEPTION 1
+
+#include "config.h"
+
+#include
+
+namespace sgpem
+{
+ class CPUPolicyException;
+
+ class SG_DLLEXPORT CPUPolicyException : public std::runtime_error
+ {
+ public:
+ explicit CPUPolicyException(const std::string& msg = "");
+ };
+} //~ namespace sgpem
+
+#endif
diff --git a/src/backend/malformed_policy_exception.cc b/src/backend/malformed_policy_exception.cc
index 2ed5369..2244548 100644
--- a/src/backend/malformed_policy_exception.cc
+++ b/src/backend/malformed_policy_exception.cc
@@ -25,8 +25,7 @@
#include "malformed_policy_exception.hh"
using namespace sgpem;
-MalformedPolicyException::MalformedPolicyException(const char* msg)
- : std::runtime_error(msg)
+MalformedPolicyException::MalformedPolicyException(const std::string& msg)
+ : CPUPolicyException(msg)
{}
-MalformedPolicyException::~MalformedPolicyException() throw() {}
diff --git a/src/backend/malformed_policy_exception.hh b/src/backend/malformed_policy_exception.hh
index 36e5fec..1f0e176 100644
--- a/src/backend/malformed_policy_exception.hh
+++ b/src/backend/malformed_policy_exception.hh
@@ -27,19 +27,16 @@
#include "config.h"
-#include
+#include "cpu_policy_exception.hh"
namespace sgpem
{
class MalformedPolicyException;
- class SG_DLLEXPORT MalformedPolicyException : public std::runtime_error
+ class SG_DLLEXPORT MalformedPolicyException : public CPUPolicyException
{
public:
- MalformedPolicyException(const char* msg = "");
- virtual ~MalformedPolicyException() throw ();
-
- private:
+ explicit MalformedPolicyException(const std::string& msg = "");
};
} //~ namespace sgpem
diff --git a/src/backend/null_policy_exception.cc b/src/backend/null_policy_exception.cc
index 8357c49..d12c286 100644
--- a/src/backend/null_policy_exception.cc
+++ b/src/backend/null_policy_exception.cc
@@ -29,4 +29,3 @@ NullPolicyException::NullPolicyException(const char* msg)
: std::runtime_error(msg)
{}
-NullPolicyException::~NullPolicyException() throw() {}
diff --git a/src/backend/null_policy_exception.hh b/src/backend/null_policy_exception.hh
index cfccec0..b0164f1 100644
--- a/src/backend/null_policy_exception.hh
+++ b/src/backend/null_policy_exception.hh
@@ -37,9 +37,6 @@ namespace sgpem
{
public:
NullPolicyException(const char* msg = "");
- virtual ~NullPolicyException() throw ();
-
- private:
};
} //~ namespace sgpem
diff --git a/src/backend/user_interrupt_exception.cc b/src/backend/user_interrupt_exception.cc
index 60230cc..87c7210 100644
--- a/src/backend/user_interrupt_exception.cc
+++ b/src/backend/user_interrupt_exception.cc
@@ -26,7 +26,6 @@
using namespace sgpem;
UserInterruptException::UserInterruptException(const char* msg)
- : std::runtime_error(msg)
+ : CPUPolicyException(msg)
{}
-UserInterruptException::~UserInterruptException() throw() {}
diff --git a/src/backend/user_interrupt_exception.hh b/src/backend/user_interrupt_exception.hh
index d3d21de..fccfc51 100644
--- a/src/backend/user_interrupt_exception.hh
+++ b/src/backend/user_interrupt_exception.hh
@@ -26,6 +26,7 @@
#define USER_INTERRUPT_EXCEPTION 1
#include "config.h"
+#include "cpu_policy_exception.hh"
#include
@@ -33,13 +34,10 @@ namespace sgpem
{
class UserInterruptException;
- class SG_DLLEXPORT UserInterruptException : public std::runtime_error
+ class SG_DLLEXPORT UserInterruptException : public CPUPolicyException
{
public:
- UserInterruptException(const char* msg = "");
- virtual ~UserInterruptException() throw ();
-
- private:
+ explicit UserInterruptException(const char* msg = "");
};
} //~ namespace sgpem