Added:
/branches/gcc-linux/build/incls/_preemption.cpp.incl
/branches/gcc-linux/vm/runtime/preemption.cpp
/branches/gcc-linux/vm/runtime/preemption.hpp
Modified:
/branches/gcc-linux/build/Dependencies
/branches/gcc-linux/build/includeDB.current
/branches/gcc-linux/build.win32/strongtalk/strongtalk.vcproj
/branches/gcc-linux/build.win32/strongtalk.ncb
/branches/gcc-linux/build.win32/strongtalk.suo
/branches/gcc-linux/test/strongtalkrc
/branches/gcc-linux/vm/compiler/scope.cpp
/branches/gcc-linux/vm/deps/includeDB
/branches/gcc-linux/vm/interpreter/interpreter.cpp
/branches/gcc-linux/vm/interpreter/prettyPrinter.cpp
/branches/gcc-linux/vm/oops/byteArrayOop.cpp
/branches/gcc-linux/vm/oops/klass.cpp
/branches/gcc-linux/vm/prims/dll.cpp
/branches/gcc-linux/vm/prims/generatedPrimitives.cpp
/branches/gcc-linux/vm/runtime/debug.hpp
/branches/gcc-linux/vm/runtime/init.cpp
/branches/gcc-linux/vm/runtime/os_darwin.cpp
/branches/gcc-linux/vm/runtime/os_linux.cpp
/branches/gcc-linux/vm/runtime/os_nt.cpp
/branches/gcc-linux/vm/runtime/process.cpp
/branches/gcc-linux/vm/runtime/process.hpp
=======================================
--- /dev/null
+++ /branches/gcc-linux/build/incls/_preemption.cpp.incl Thu Dec 31
11:09:51 2009
@@ -0,0 +1,2 @@
+# include "task.hpp"
+# include "preemption.hpp"
=======================================
--- /dev/null
+++ /branches/gcc-linux/vm/runtime/preemption.cpp Thu Dec 31 11:09:51 2009
@@ -0,0 +1,12 @@
+# include "incls/_precompiled.incl"
+# include "incls/_preemption.cpp.incl"
+
+void ProcessPreemptionTask::task() {
+ if (EnableProcessPreemption)
+ DeltaProcess::preempt_active();
+}
+
+void preemption_init() {
+ ProcessPreemptionTask* task = new ProcessPreemptionTask;
+ task->enroll();
+}
=======================================
--- /dev/null
+++ /branches/gcc-linux/vm/runtime/preemption.hpp Thu Dec 31 11:09:51 2009
@@ -0,0 +1,6 @@
+class ProcessPreemptionTask : public PeriodicTask {
+public:
+ ProcessPreemptionTask() : PeriodicTask(1) {};
+ void task();
+};
+
=======================================
--- /branches/gcc-linux/build/Dependencies Thu Dec 31 11:02:48 2009
+++ /branches/gcc-linux/build/Dependencies Thu Dec 31 11:09:51 2009
@@ -87,6 +87,7 @@
oopFactory.obj \
os.obj \
ostream.obj \
+preemption.obj \
prettyPrinter.obj \
prim.obj \
printlayout.obj \
@@ -448,6 +449,9 @@
ostream.obj ostream.i: \
$(VM_PATH)ostream.cpp $(VM_PATH)_ostream.cpp.incl $(VM_PATH)_precompiled
+preemption.obj preemption.i: \
+ $(VM_PATH)preemption.cpp $(VM_PATH)_preemption.cpp.incl
$(VM_PATH)_precompiled $(VM_PATH)task.hpp $(VM_PATH)preemption.hpp
+
prettyPrinter.obj prettyPrinter.i: \
$(VM_PATH)prettyPrinter.cpp $(VM_PATH)_prettyPrinter.cpp.incl
$(VM_PATH)_precompiled $(VM_PATH)prettyPrinter.hpp
$(VM_PATH)tempDecoder.hpp $(VM_PATH)dByteArrayOop.hpp
=======================================
--- /branches/gcc-linux/build/includeDB.current Thu Dec 31 11:02:48 2009
+++ /branches/gcc-linux/build/includeDB.current Thu Dec 31 11:09:51 2009
@@ -988,6 +988,11 @@
ostream.hpp allocation.hpp
+preemption.hpp task.hpp
+
+preemption.cpp preemption.hpp
+preemption.cpp process.hpp
+
preserve.hpp process.hpp
preserve.hpp top.hpp
preserve.hpp universe.inline.hpp
=======================================
--- /branches/gcc-linux/build.win32/strongtalk/strongtalk.vcproj Sun Aug 9
17:16:11 2009
+++ /branches/gcc-linux/build.win32/strongtalk/strongtalk.vcproj Thu Dec 31
11:09:51 2009
@@ -853,6 +853,10 @@
<File
RelativePath="..\..\build\incls\_precompiled.incl"
>
+ </File>
+ <File
+ RelativePath="..\..\build\incls\_preemption.cpp.incl"
+ >
</File>
<File
RelativePath="..\..\build\incls\_preg.cpp.incl"
@@ -1601,6 +1605,10 @@
<File
RelativePath="..\..\vm\code\pcDesc.hpp"
>
+ </File>
+ <File
+ RelativePath="..\..\vm\runtime\preemption.hpp"
+ >
</File>
<File
RelativePath="..\..\vm\compiler\preg.hpp"
@@ -3373,6 +3381,10 @@
UsePrecompiledHeader="2"
/>
</FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\vm\runtime\preemption.cpp"
+ >
</File>
<File
RelativePath="..\..\vm\compiler\preg.cpp"
=======================================
--- /branches/gcc-linux/build.win32/strongtalk.ncb Mon Dec 28 10:50:00 2009
+++ /branches/gcc-linux/build.win32/strongtalk.ncb Thu Dec 31 11:09:51 2009
File is too large to display a diff.
=======================================
--- /branches/gcc-linux/build.win32/strongtalk.suo Mon Dec 28 10:50:00 2009
+++ /branches/gcc-linux/build.win32/strongtalk.suo Thu Dec 31 11:09:51 2009
Binary file, no diff available.
=======================================
--- /branches/gcc-linux/test/strongtalkrc Mon Dec 28 10:47:15 2009
+++ /branches/gcc-linux/test/strongtalkrc Thu Dec 31 11:09:51 2009
@@ -1,7 +1,7 @@
#+BreakAtWarning
+UseRecompilation
-UseInliningDatabase
-+EnableTasks
+-EnableTasks
-CompilerDebug
-PrintDebugInfo
-PrintInlining
=======================================
--- /branches/gcc-linux/vm/compiler/scope.cpp Sun Jun 7 11:33:29 2009
+++ /branches/gcc-linux/vm/compiler/scope.cpp Thu Dec 31 11:09:51 2009
@@ -812,6 +812,7 @@
void print_selector_cr(symbolOop selector) {
char buffer[100];
int length = selector->length();
+ assert(length < 100, "selector longer than 99 characters - buffer
overrun");
strncpy(buffer, selector->chars(), length);
buffer[length] = '\0';
std->print_cr("%s", buffer);
=======================================
--- /branches/gcc-linux/vm/deps/includeDB Thu Dec 31 11:02:48 2009
+++ /branches/gcc-linux/vm/deps/includeDB Thu Dec 31 11:09:51 2009
@@ -988,6 +988,11 @@
ostream.hpp allocation.hpp
+preemption.hpp task.hpp
+
+preemption.cpp preemption.hpp
+preemption.cpp process.hpp
+
preserve.hpp process.hpp
preserve.hpp top.hpp
preserve.hpp universe.inline.hpp
=======================================
--- /branches/gcc-linux/vm/interpreter/interpreter.cpp Tue Dec 29 18:48:47
2009
+++ /branches/gcc-linux/vm/interpreter/interpreter.cpp Thu Dec 31 11:09:51
2009
@@ -2126,12 +2126,8 @@
extern "C" char* block_entry_point = NULL; // for interpreter_asm.asm
(remove if not used anymore)
extern "C" char* active_stack_limit(); // address of
pointer to the current process' stack limit
-extern "C" void check_stack_overflow() {
- if (!DeltaProcess::active()->is_scheduler())
- DeltaProcess::active()->suspend(stack_overflow);
- else
- fatal("Stack overflow in scheduler");
-}
+extern "C" void check_stack_overflow();
+
void InterpreterGenerator::generate_method_entry_code() {
// This generates the code sequence called to activate methodOop execution.
// It is usually called via the call_method() macro, which saves the old
@@ -2234,7 +2230,12 @@
masm->jmp(start_setup);
masm->bind(handle_stack_overflow);
+ masm->pushl(eax);
masm->call_C((char*)&check_stack_overflow,
relocInfo::external_word_type);
+ masm->popl(eax);
+ restore_esi();
+ restore_ebx();
+ load_ebx();
masm->jmp(continue_from_stack_overflow);
}
=======================================
--- /branches/gcc-linux/vm/interpreter/prettyPrinter.cpp Sun Nov 15
17:53:07 2009
+++ /branches/gcc-linux/vm/interpreter/prettyPrinter.cpp Thu Dec 31
11:09:51 2009
@@ -429,6 +429,7 @@
char num[10];
output->newline();
output->print("#");
+ assert(frame_index <= 999999999, "frame index too large for buffer -
buffer overrun");
sprintf(num, "%d", frame_index);
output->print(num);
output->print(", receiver \"");
=======================================
--- /branches/gcc-linux/vm/oops/byteArrayOop.cpp Sat Sep 19 09:18:27 2009
+++ /branches/gcc-linux/vm/oops/byteArrayOop.cpp Thu Dec 31 11:09:51 2009
@@ -100,7 +100,7 @@
// %not optimized
int len = length();
bool is_truncated = false;
- if (len > max_length) {
+ if (len >= max_length) {
len = max_length - 1;
is_truncated = true;
}
=======================================
--- /branches/gcc-linux/vm/oops/klass.cpp Sat Oct 17 07:54:56 2009
+++ /branches/gcc-linux/vm/oops/klass.cpp Thu Dec 31 11:09:51 2009
@@ -379,33 +379,26 @@
}
char* Klass::delta_name() {
- char buffer[100];
+ bool meta = false;
int offset =
as_klassOop()->blueprint()->lookup_inst_var(oopFactory::new_symbol("name"));
symbolOop name = NULL;
if (offset >= 0) {
name = symbolOop(as_klassOop()->raw_at(offset));
if (!name->is_symbol()) name = NULL;
}
- if (name != NULL) {
- strncpy(buffer, name->chars(), name->length());
- buffer[name->length()] = '\0';
- } else {
- bool meta;
+ if (name == NULL) {
name = Universe::find_global_key_for(as_klassOop(), &meta);
- if (name) {
- strncpy(buffer, name->chars(), name->length());
- if (meta) {
- strcpy(buffer + name->length(), " class");
- buffer[name->length() + 6] = '\0';
- } else
- buffer[name->length()] = '\0';
- } else {
- return NULL;
- }
- }
- int length = strlen(buffer);
- char* toReturn = NEW_RESOURCE_ARRAY(char, length + 1);
- strcpy(toReturn, buffer);
+ if (!name) return NULL;
+ }
+
+ int length = name->length() + (meta ? 7 : 1);
+ char* toReturn = NEW_RESOURCE_ARRAY(char, length);
+ strncpy(toReturn, name->chars(), name->length());
+
+ if (meta)
+ strcpy(toReturn + name->length(), " class");
+ toReturn[length-1] = '\0';
+
return toReturn;
}
=======================================
--- /branches/gcc-linux/vm/prims/dll.cpp Sun Jun 7 11:33:29 2009
+++ /branches/gcc-linux/vm/prims/dll.cpp Thu Dec 31 11:09:51 2009
@@ -87,14 +87,14 @@
dll_func DLLs::lookup(symbolOop name, DLL* library) {
char buffer[200];
- name->copy_null_terminated(buffer, 200);
+ assert(!name->copy_null_terminated(buffer, 200), "DLL function name
longer than 200 chars - truncated");
return os::dll_lookup(buffer, library);
}
DLL* DLLs::load(symbolOop name) {
char buffer[200];
- name->copy_null_terminated(buffer, 200);
+ assert(!name->copy_null_terminated(buffer, 200), "DLL library name
longer than 200 chars - truncated");
return os::dll_load(buffer);
}
=======================================
--- /branches/gcc-linux/vm/prims/generatedPrimitives.cpp Sun Jun 7
15:02:00 2009
+++ /branches/gcc-linux/vm/prims/generatedPrimitives.cpp Thu Dec 31
11:09:51 2009
@@ -221,6 +221,7 @@
char* GeneratedPrimitives::patch(char* name, char* entry_point, int
argument) {
char formated_name[100];
+ assert(strlen(name) < 100, "primitive name longer the 100 characters -
buffer overrun");
sprintf(formated_name, name, argument);
primitives::patch(formated_name, entry_point);
return entry_point;
=======================================
--- /branches/gcc-linux/vm/runtime/debug.hpp Thu Dec 31 11:02:48 2009
+++ /branches/gcc-linux/vm/runtime/debug.hpp Thu Dec 31 11:09:51 2009
@@ -106,6 +106,7 @@
\
develop(UseTimers , true , "Tells whether the
VM should use timers (only used at startup)" ) \
develop(SweeperUseTimer , true , "Tells whether the
sweeper should use timer interrupts or compile events" ) \
+ develop(EnableProcessPreemption , false, "Enables or disables
preemption of running Smalltalk processes" ) \
\
/* transition
*/
\
develop(HasActivationClass , true, "Transition
variable: tell whether the system has an activation class" ) \
=======================================
--- /branches/gcc-linux/vm/runtime/init.cpp Sun Aug 9 17:16:11 2009
+++ /branches/gcc-linux/vm/runtime/init.cpp Thu Dec 31 11:09:51 2009
@@ -48,6 +48,7 @@
template(sweeper_init) \
template(fprofiler_init) \
template(systemAverage_init) \
+ template(preemption_init) \
template(generatedPrimitives_init_after_interpreter) \
=======================================
--- /branches/gcc-linux/vm/runtime/os_darwin.cpp Sat Dec 19 12:40:34 2009
+++ /branches/gcc-linux/vm/runtime/os_darwin.cpp Thu Dec 31 11:09:51 2009
@@ -640,8 +640,8 @@
void real_time_tick(int delay_time);
void* watcherMain(void* ignored) {
- const struct timespec delay = { 0, 10 * 1000 * 1000 };
- const int delay_interval = 10; // Delay 10 ms
+ const struct timespec delay = { 0, 1 * 1000 * 1000 };
+ const int delay_interval = 1; // Delay 1 ms
while(1) {
int status = nanosleep(&delay, NULL);
if (!status) return 0;
=======================================
--- /branches/gcc-linux/vm/runtime/os_linux.cpp Sun Aug 9 17:16:11 2009
+++ /branches/gcc-linux/vm/runtime/os_linux.cpp Thu Dec 31 11:09:51 2009
@@ -601,8 +601,8 @@
void real_time_tick(int delay_time);
void* watcherMain(void* ignored) {
- const struct timespec delay = { 0, 10 * 1000 * 1000 };
- const int delay_interval = 10; // Delay 10 ms
+ const struct timespec delay = { 0, 1 * 1000 * 1000 };
+ const int delay_interval = 1; // Delay 1 ms
while(1) {
int status = nanosleep(&delay, NULL);
if (!status) return 0;
=======================================
--- /branches/gcc-linux/vm/runtime/os_nt.cpp Thu Dec 31 11:02:48 2009
+++ /branches/gcc-linux/vm/runtime/os_nt.cpp Thu Dec 31 11:09:51 2009
@@ -512,7 +512,7 @@
// timer interrupts.
DWORD WINAPI WatcherMain(LPVOID lpvParam) {
- const int delay_interval = 10; // Delay 10 ms
+ const int delay_interval = 1; // Delay 1 ms
while(1) {
Sleep(delay_interval);
real_time_tick(delay_interval);
=======================================
--- /branches/gcc-linux/vm/runtime/process.cpp Tue Dec 29 18:48:47 2009
+++ /branches/gcc-linux/vm/runtime/process.cpp Thu Dec 31 11:09:51 2009
@@ -290,7 +290,8 @@
}
}
-bool DeltaProcess::stepping = false;
+bool DeltaProcess::stepping = false;
+
VMProcess* VMProcess::_vm_process = NULL;
VM_Operation* VMProcess::_vm_operation = NULL;
@@ -300,16 +301,17 @@
return (char*) &DeltaProcess::_active_stack_limit;
}
-Process* Process::_current_process = NULL;
-DeltaProcess* DeltaProcess::_active_delta_process = NULL;
-char* DeltaProcess::_active_stack_limit = NULL;
-DeltaProcess* DeltaProcess::_scheduler_process = NULL;
-bool DeltaProcess::_is_idle = false;
-
-volatile bool DeltaProcess::_process_has_terminated = false;
-ProcessState DeltaProcess::_state_of_terminated_process = initialized;
-
-Event* DeltaProcess::_async_dll_completion_event = NULL;
+Process* Process::_current_process = NULL;
+DeltaProcess* DeltaProcess::_active_delta_process = NULL;
+volatile char* DeltaProcess::_active_stack_limit = NULL;
+DeltaProcess* DeltaProcess::_scheduler_process = NULL;
+bool DeltaProcess::_is_idle = false;
+volatile bool DeltaProcess::_interrupt = false;
+
+volatile bool DeltaProcess::_process_has_terminated = false;
+ProcessState DeltaProcess::_state_of_terminated_process = initialized;
+
+Event* DeltaProcess::_async_dll_completion_event = NULL;
void DeltaProcess::transfer(ProcessState reason, DeltaProcess* target) {
// change time_stamp for target
@@ -513,8 +515,31 @@
frame result((oop*)sp, fp, pc);
return result;
}
-
-
+static int interruptions = 0;
+void DeltaProcess::check_stack_overflow() {
+ bool isInterrupted = false;
+ if (EnableProcessPreemption) {
+ ThreadCritical tc;
+ isInterrupted = _interrupt;
+ _interrupt = false;
+ }
+ if (isInterrupted) {
+ assert(EnableProcessPreemption, "Should not be interrupted unless
preemption enabled");
+ //interruptions++;
+ _active_stack_limit = active()->_stack_limit;
+ //if (interruptions % 1000 == 0)
+ // warning("Interruptions: %d", interruptions);
+ if (DeltaProcess::active()->is_scheduler())
+ return;
+ active()->suspend(yielded);
+ } else if (!active()->is_scheduler())
+ active()->suspend(stack_overflow);
+ else
+ fatal("Stack overflow in scheduler");
+}
+extern "C" void check_stack_overflow() {
+ DeltaProcess::check_stack_overflow();
+}
DeltaProcess::~DeltaProcess() {
processObj()->set_process(NULL);
if (Processes::includes(this)) {
@@ -522,6 +547,12 @@
}
}
+void DeltaProcess::preempt_active() {
+ assert(EnableProcessPreemption, "Should preempt active process when
preemption not enabled");
+ ThreadCritical tc;
+ _interrupt = true;
+ _active_stack_limit = (char*)0x7fffffff;
+}
void DeltaProcess::print() {
processObj()->print_value();
std->print(" ");
=======================================
--- /branches/gcc-linux/vm/runtime/process.hpp Tue Dec 29 18:48:47 2009
+++ /branches/gcc-linux/vm/runtime/process.hpp Thu Dec 31 11:09:51 2009
@@ -173,6 +173,7 @@
};
extern "C" char* active_stack_limit();
+extern "C" void check_stack_overflow();
class DeltaProcess: public Process {
private:
@@ -371,10 +372,11 @@
// Static operations
private:
- static DeltaProcess* _active_delta_process;
- static DeltaProcess* _scheduler_process;
- static bool _is_idle;
- static char* _active_stack_limit;
+ static DeltaProcess* _active_delta_process;
+ static DeltaProcess* _scheduler_process;
+ static bool _is_idle;
+ static volatile char* _active_stack_limit;
+ static volatile bool _interrupt;
// The launch function for a new thread
static int launch_delta(DeltaProcess* process);
@@ -419,7 +421,7 @@
private:
static volatile bool _process_has_terminated;
static ProcessState _state_of_terminated_process;
-
+ static void check_stack_overflow();
public:
// Called whenever a async dll call completes
static void async_dll_call_completed();
@@ -427,6 +429,7 @@
// Waits for a completed async call or timeout.
// Returns whether the timer expired.
static bool wait_for_async_dll(int timeout_in_ms);
+ static void preempt_active();
private:
// Event for waking up the process scheduler when a
// async dll completes
@@ -434,6 +437,7 @@
friend class VMProcess; // to allow access to _process_has_terminated
friend class InterpreterGenerator;
friend char* active_stack_limit();
+ friend void check_stack_overflow();
};