Permalink
Browse files

Refactor Environment/cli.cpp around

  • Loading branch information...
1 parent 35b6a84 commit db6659b578f4e7d6682af9d3ecfff8ea855eede0 Evan Phoenix committed Dec 11, 2009
Showing with 168 additions and 169 deletions.
  1. +0 −13 vm/config_parser.cpp
  2. +0 −1 vm/config_parser.hpp
  3. +28 −75 vm/drivers/cli.cpp
  4. +114 −24 vm/environment.cpp
  5. +15 −2 vm/environment.hpp
  6. +0 −37 vm/vm.cpp
  7. +11 −17 vm/vm.hpp
View
@@ -38,19 +38,6 @@ namespace rubinius {
}
}
-
- void ConfigParser::process_argv(int argc, char** argv) {
- for(int i=1; i < argc; i++) {
- char* arg = argv[i];
- if(strncmp(arg, "-X", 2) == 0) {
- import_line(arg + 2);
- continue;
- }
-
- if(arg[0] != '-' || strcmp(arg, "--") == 0) return;
- }
- }
-
bool ConfigParser::load_file(std::string path) {
std::ifstream stream(path.c_str());
if(!stream) return false;
View
@@ -30,7 +30,6 @@ namespace rubinius {
virtual ~ConfigParser();
bool load_file(std::string path);
- void process_argv(int argc, char** argv);
Entry* parse_line(const char* line);
void import_line(const char* line);
void import_many(std::string string);
View
@@ -14,39 +14,7 @@
using namespace std;
using namespace rubinius;
-/* Loads the runtime kernel files. They're stored in /kernel.
- * These files consist of classes needed to bootstrap the kernel
- * and just get things started in general.
- *
- * @param root [String] The file root for /kernel. This expects to find
- * alpha.rbc (will compile if not there).
- * @param env [Environment&] The environment for Rubinius. It is the uber
- * manager for multiple VMs and process-Ruby interaction.
- */
-static void load_runtime_kernel(Environment& env, std::string root) {
- std::string dirs = root + "/index";
- std::ifstream stream(dirs.c_str());
- if(!stream) {
- std::cout << "It appears that " << root << "/index is missing.\n";
- exit(1);
- }
-
- // Load the ruby file to prepare for bootstrapping Ruby!
- // The bootstrapping for the VM is already done by the time we're here.
- env.run_file(root + "/alpha.rbc");
-
- while(!stream.eof()) {
- std::string line;
-
- stream >> line;
- stream.get(); // eat newline
-
- // skip empty lines
- if(line.size() == 0) continue;
-
- env.load_directory(root + "/" + line);
- }
-}
+static void check_directory(std::string root);
/* The main function here handles the CL arguments passed to it.
* It then boots the VM, runs the appropriate file (`loader`),
@@ -62,12 +30,9 @@ static void load_runtime_kernel(Environment& env, std::string root) {
* function does not deal with that subject.
*/
int main(int argc, char** argv) {
- Environment env;
+ Environment env(argc, argv);
env.setup_cpp_terminate();
- env.state->init_stack_size();
- env.state->set_stack_start(&env);
-
try {
if(const char* var = getenv("RBX_OPTIONS")) {
env.load_string(var);
@@ -77,47 +42,12 @@ int main(int argc, char** argv) {
env.load_conf(path);
}
- env.load_config_argv(argc, argv);
-
const char* runtime = getenv("RBX_RUNTIME");
- if(!runtime) {
- struct stat st;
-
- runtime = RBX_RUNTIME;
- if(stat(runtime, &st) == -1 || !S_ISDIR(st.st_mode)) {
-
- std::cerr << "ERROR: unable to find runtime directory" << std::endl;
- std::cerr << std::endl;
- std::cerr << "Rubinius was configured to find the runtime directory at:" << std::endl;
- std::cerr << std::endl << " " << runtime << std::endl;
- std::cerr << std::endl;
- std::cerr << "but that directory does not exist." << std::endl;
- std::cerr << std::endl;
- std::cerr << "Set the environment variable RBX_RUNTIME to the location" << std::endl;
- std::cerr << "of the directory with the compiled Rubinius kernel files." << std::endl;
- std::cerr << std::endl;
- std::cerr << "You may have configured Rubinius for a different install" << std::endl;
- std::cerr << "directory but you have not run \'rake install\' yet." << std::endl;
- std::cerr << std::endl;
-
- exit(1);
- }
- }
-
- std::string root = std::string(runtime);
-
- env.load_platform_conf(root);
- env.boot_vm();
- env.load_argv(argc, argv);
-
- load_runtime_kernel(env, std::string(root));
-
- std::string loader = root + "/loader.rbc";
+ if(!runtime) runtime = RBX_RUNTIME;
- env.enable_preemption();
- env.start_signals();
- env.run_file(loader);
+ check_directory(runtime);
+ env.run_from_filesystem(runtime);
} catch(Assertion *e) {
std::cout << "VM Assertion:" << std::endl;
@@ -173,3 +103,26 @@ int main(int argc, char** argv) {
env.halt();
return env.exit_code();
}
+
+static void check_directory(std::string runtime) {
+ struct stat st;
+
+ if(stat(runtime.c_str(), &st) == -1 || !S_ISDIR(st.st_mode)) {
+
+ std::cerr << "ERROR: unable to find runtime directory" << std::endl;
+ std::cerr << std::endl;
+ std::cerr << "Rubinius was configured to find the runtime directory at:" << std::endl;
+ std::cerr << std::endl << " " << runtime << std::endl;
+ std::cerr << std::endl;
+ std::cerr << "but that directory does not exist." << std::endl;
+ std::cerr << std::endl;
+ std::cerr << "Set the environment variable RBX_RUNTIME to the location" << std::endl;
+ std::cerr << "of the directory with the compiled Rubinius kernel files." << std::endl;
+ std::cerr << std::endl;
+ std::cerr << "You may have configured Rubinius for a different install" << std::endl;
+ std::cerr << "directory but you have not run \'rake install\' yet." << std::endl;
+ std::cerr << std::endl;
+
+ exit(1);
+ }
+}
View
@@ -39,35 +39,26 @@
namespace rubinius {
- Environment::Environment()
- : agent(0)
+ Environment::Environment(int argc, char** argv)
+ : argc_(argc)
+ , argv_(argv)
+ , agent(0)
{
#ifdef ENABLE_LLVM
assert(llvm::llvm_start_multithreaded() && "llvm doesn't support threading!");
#endif
shared = new SharedState(config, config_parser);
state = shared->new_vm();
+
+ VM::init_stack_size();
}
Environment::~Environment() {
VM::discard(state);
SharedState::discard(shared);
}
- void Environment::load_config_argv(int argc, char** argv) {
- config_parser.process_argv(argc, argv);
- config_parser.update_configuration(config);
-
- if(config.print_config > 1) {
- std::cout << "========= Configuration =========\n";
- config.print(true);
- std::cout << "=================================\n";
- } else if(config.print_config) {
- config.print();
- }
- }
-
void cpp_exception_bug() {
std::cerr << "[BUG] Uncaught C++ internal exception\n";
std::cerr << "So sorry, it appears that you've encountered an internal\n";
@@ -83,8 +74,44 @@ namespace rubinius {
std::set_terminate(cpp_exception_bug);
}
+ // Trampoline to call scheduler_loop()
+ static void* __thread_tramp__(void* arg) {
+ Environment* env = static_cast<Environment*>(arg);
+ env->scheduler_loop();
+ return NULL;
+ }
+
+ // Runs forever, telling the VM to reschedule threads ever 10 milliseconds
+ void Environment::scheduler_loop() {
+ // First off, we don't want this thread ever receiving a signal.
+ sigset_t mask;
+ sigfillset(&mask);
+ if(pthread_sigmask(SIG_SETMASK, &mask, NULL) != 0) {
+ abort();
+ }
+
+ struct timespec requested;
+ struct timespec actual;
+
+ requested.tv_sec = 0;
+ requested.tv_nsec = 10000000; // 10 milliseconds
+
+ Interrupts& interrupts = shared->interrupts;
+
+ for(;;) {
+ nanosleep(&requested, &actual);
+ if(interrupts.enable_preempt) {
+ interrupts.set_timer();
+ }
+ }
+ }
+
+ // Create the preemption thread and call scheduler_loop() in the new thread
void Environment::enable_preemption() {
- state->setup_preemption();
+ if(pthread_create(&preemption_thread_, NULL, __thread_tramp__, this) != 0) {
+ std::cerr << "Unable to create preemption thread!\n";
+ exit(1);
+ }
}
static void null_func(int sig) {}
@@ -216,12 +243,33 @@ namespace rubinius {
process_xflags = false;
}
- if(!process_xflags || strncmp(arg, "-X", 2) != 0) {
+ if(process_xflags && strncmp(arg, "-X", 2) == 0) {
+ config_parser.import_line(arg + 2);
+ } else {
ary->set(state, which_arg++, String::create(state, arg)->taint(state));
}
}
state->set_const("ARGV", ary);
+
+ // Now finish up with the config
+ //
+ // Respect -Xint
+ if(config.jit_force_off) {
+ config.jit_enabled.set("no");
+ }
+
+ if(config.qa_port > 0) start_agent(config.qa_port);
+
+ config_parser.update_configuration(config);
+
+ if(config.print_config > 1) {
+ std::cout << "========= Configuration =========\n";
+ config.print(true);
+ std::cout << "=================================\n";
+ } else if(config.print_config) {
+ config.print();
+ }
}
void Environment::load_directory(std::string dir) {
@@ -269,13 +317,6 @@ namespace rubinius {
}
void Environment::boot_vm() {
- if(config.qa_port > 0) start_agent(config.qa_port);
-
- // Respect -Xint
- if(config.jit_force_off) {
- config.jit_enabled.set("no");
- }
-
state->initialize();
state->boot();
@@ -357,4 +398,53 @@ namespace rubinius {
if(config.qa_verbose) agent->set_verbose();
agent->run();
}
+
+ /* Loads the runtime kernel files. They're stored in /kernel.
+ * These files consist of classes needed to bootstrap the kernel
+ * and just get things started in general.
+ *
+ * @param root [String] The file root for /kernel. This expects to find
+ * alpha.rbc (will compile if not there).
+ * @param env [Environment&] The environment for Rubinius. It is the uber
+ * manager for multiple VMs and process-Ruby interaction.
+ */
+ void Environment::load_kernel(std::string root) {
+ std::string dirs = root + "/index";
+ std::ifstream stream(dirs.c_str());
+ if(!stream) {
+ std::cerr << "It appears that " << root << "/index is missing.\n";
+ exit(1);
+ }
+
+ // Load the ruby file to prepare for bootstrapping Ruby!
+ // The bootstrapping for the VM is already done by the time we're here.
+ run_file(root + "/alpha.rbc");
+
+ while(!stream.eof()) {
+ std::string line;
+
+ stream >> line;
+ stream.get(); // eat newline
+
+ // skip empty lines
+ if(line.size() == 0) continue;
+
+ load_directory(root + "/" + line);
+ }
+ }
+
+ void Environment::run_from_filesystem(std::string root) {
+ int i = 0;
+ state->set_stack_start(&i);
+
+ load_platform_conf(root);
+ boot_vm();
+ load_argv(argc_, argv_);
+
+ load_kernel(root);
+
+ enable_preemption();
+ start_signals();
+ run_file(root + "/loader.rbc");
+ }
}
View
@@ -14,6 +14,12 @@ namespace rubinius {
class QueryAgent;
class Environment {
+ // The thread used to trigger preemptive thread switching
+ pthread_t preemption_thread_;
+
+ int argc_;
+ char** argv_;
+
public:
SharedState* shared;
VM* state;
@@ -23,20 +29,27 @@ namespace rubinius {
Configuration config;
public:
- Environment();
+ Environment(int argc, char** argv);
~Environment();
void setup_cpp_terminate();
void load_config_argv(int argc, char** argv);
void load_argv(int argc, char** argv);
+ void load_kernel(std::string root);
void load_directory(std::string dir);
void load_platform_conf(std::string dir);
void load_conf(std::string path);
void load_string(std::string str);
void run_file(std::string path);
- void enable_preemption();
+ void run_from_filesystem(std::string root);
void boot_vm();
+
+ void enable_preemption();
+ // Run in a seperate thread to provide preemptive thread
+ // scheduling.
+ void scheduler_loop();
+
void halt();
int exit_code();
void start_signals();
Oops, something went wrong.

0 comments on commit db6659b

Please sign in to comment.