00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #ifndef __GNUC__
00025
00026 #ifdef MICROSOFT
00027 #include <windows.h>
00028 #include <signal.h>
00029 #endif
00030
00031 #ifdef BORLAND
00032 #include <winbase.h>
00033 #endif
00034
00035 # include "incls/_os.cpp.incl"
00036
00037 static HANDLE main_process;
00038 static HANDLE main_thread;
00039 static int main_thread_id;
00040 static HANDLE watcher_thread;
00041
00042 static FILETIME process_creation_time;
00043 static FILETIME process_exit_time;
00044 static FILETIME process_user_time;
00045 static FILETIME process_kernel_time;
00046
00047 extern void intercept_for_single_step();
00048
00049 static inline double fileTimeAsDouble(FILETIME* time) {
00050 const double high = (double) ((unsigned int) ~0);
00051 const double split = 10000000.0;
00052 double result = (time->dwLowDateTime / split) +
00053 time->dwHighDateTime * (high/split);
00054 return result;
00055 }
00056
00057 int os::getenv(char* name,char* buffer,int len) {
00058 int result = GetEnvironmentVariable(name, buffer, len);
00059 return result != 0;
00060 }
00061
00062 bool os::move_file(char* from, char* to) {
00063 return MoveFileEx(from, to, MOVEFILE_REPLACE_EXISTING) ? true : false;
00064 }
00065
00066 bool os::check_directory(char* dir_name) {
00067 bool result = CreateDirectory(dir_name, NULL) ? true : false;
00068 if (!result) {
00069 int error = GetLastError();
00070 if (error == ERROR_ALREADY_EXISTS) return true;
00071 return false;
00072 }
00073 return true;
00074 }
00075
00076 void os::breakpoint() {
00077 DebugBreak();
00078 }
00079
00080 Thread* os::starting_thread(int* id_addr) {
00081 *id_addr = main_thread_id;
00082 return (Thread*) main_thread;
00083 }
00084
00085 Thread* os::create_thread(int main(void* parameter), void* parameter, int* id_addr) {
00086 HANDLE result = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) main, parameter, 0, (unsigned long*) id_addr);
00087 if (result == NULL) return NULL;
00088 return (Thread*) result;
00089 }
00090
00091 void os::terminate_thread(Thread* thread) {
00092 TerminateThread((HANDLE) thread, 0);
00093 CloseHandle((HANDLE) thread);
00094 }
00095
00096 void os::delete_event(Event* event) {
00097 CloseHandle((HANDLE) event);
00098 }
00099
00100 Event* os::create_event(bool initial_state) {
00101 HANDLE result = CreateEvent(NULL, TRUE, initial_state, NULL);
00102 if (result == NULL) fatal("CreateEvent failed");
00103 return (Event*) result;
00104 }
00105
00106 int os::updateTimes() {
00107 return GetProcessTimes(main_process,
00108 &process_creation_time,
00109 &process_exit_time,
00110 &process_kernel_time,
00111 &process_user_time);
00112 }
00113
00114 double os::userTime() {
00115 return fileTimeAsDouble(&process_user_time);
00116 }
00117
00118 double os::systemTime() {
00119 return fileTimeAsDouble(&process_kernel_time);
00120 }
00121
00122 double os::user_time_for(Thread* thread) {
00123 FILETIME creation_time;
00124 FILETIME exit_time;
00125 FILETIME user_time;
00126 FILETIME kernel_time;
00127 if (GetThreadTimes(main_process, &creation_time, &exit_time, &kernel_time, &user_time)) {
00128 return fileTimeAsDouble(&user_time);
00129 }
00130 return 0.0;
00131 }
00132
00133 double os::system_time_for(Thread* thread) {
00134 FILETIME creation_time;
00135 FILETIME exit_time;
00136 FILETIME user_time;
00137 FILETIME kernel_time;
00138 if (GetThreadTimes(main_process, &creation_time, &exit_time, &kernel_time, &user_time)) {
00139 return fileTimeAsDouble(&kernel_time);
00140 }
00141 return 0.0;
00142 }
00143
00144 static int has_performance_count = 0;
00145 static long_int initial_performance_count(0,0);
00146 static long_int performance_frequency(0,0);
00147
00148 long_int os::elapsed_counter() {
00149 LARGE_INTEGER count;
00150 QueryPerformanceCounter(&count);
00151 long_int current(count.LowPart, count.HighPart);
00152 return current;
00153 }
00154
00155 long_int os::elapsed_frequency() {
00156 return performance_frequency;
00157 }
00158
00159 static void initialze_performance_counter() {
00160 LARGE_INTEGER count;
00161 if (QueryPerformanceFrequency(&count)) {
00162 has_performance_count = 1;
00163 performance_frequency = long_int(count.LowPart, count.HighPart);
00164 QueryPerformanceCounter(&count);
00165 initial_performance_count = long_int(count.LowPart, count.HighPart);
00166 } else {
00167 has_performance_count = 0;
00168 }
00169 }
00170
00171 double os::elapsedTime() {
00172 if (!has_performance_count) return 0.0;
00173 LARGE_INTEGER current_count;
00174 QueryPerformanceCounter(¤t_count);
00175
00176 long_int current(current_count.LowPart, current_count.HighPart);
00177 double count = (current - initial_performance_count).as_double();
00178 double freq = performance_frequency.as_double();
00179
00180 return count/freq;
00181 }
00182
00183 double os::currentTime() {
00184 SYSTEMTIME s;
00185 FILETIME f;
00186 GetSystemTime(&s);
00187 SystemTimeToFileTime(&s, &f);
00188 return fileTimeAsDouble(&f);
00189 }
00190
00191 void os::fatalExit(int num) {
00192 FatalExit(num);
00193 }
00194
00195 dll_func os::dll_lookup(char* name, DLL* library) {
00196 dll_func result = (dll_func) GetProcAddress((HINSTANCE) library, name);
00197 return result;
00198 }
00199
00200 DLL* os::dll_load(char* name) {
00201 HINSTANCE lib = LoadLibrary(name);
00202 return (DLL*) lib;
00203 }
00204
00205 bool os::dll_unload(DLL* library) {
00206 return FreeLibrary((HINSTANCE) library) ? true : false;
00207 }
00208
00209 char* exception_name(int code) {
00210 switch(code) {
00211 case EXCEPTION_ACCESS_VIOLATION: return "Access violation";
00212 case EXCEPTION_DATATYPE_MISALIGNMENT: return "Data misaligned";
00213 case EXCEPTION_BREAKPOINT: return "Breakpoint";
00214 case EXCEPTION_SINGLE_STEP: return "Single step";
00215 case EXCEPTION_ARRAY_BOUNDS_EXCEEDED: return "Array bounds exceeded";
00216 case EXCEPTION_FLT_DENORMAL_OPERAND: return "Float denormal operand";
00217 case EXCEPTION_FLT_DIVIDE_BY_ZERO: return "Float divide by zero";
00218 case EXCEPTION_FLT_INEXACT_RESULT: return "Float inexact result";
00219 case EXCEPTION_FLT_INVALID_OPERATION: return "Float invalid operation";
00220 case EXCEPTION_FLT_OVERFLOW: return "Float overflow";
00221 case EXCEPTION_FLT_STACK_CHECK: return "Float stack check";
00222 case EXCEPTION_FLT_UNDERFLOW: return "Float underflow";
00223 case EXCEPTION_INT_DIVIDE_BY_ZERO: return "Integer divide by zero";
00224 case EXCEPTION_INT_OVERFLOW: return "Integer overflow";
00225 case EXCEPTION_PRIV_INSTRUCTION: return "Privileged instruction";
00226 case EXCEPTION_IN_PAGE_ERROR: return "In page error";
00227 case EXCEPTION_ILLEGAL_INSTRUCTION: return "Illegal Instruction";
00228 case EXCEPTION_STACK_OVERFLOW: return "Stack overflow";
00229 case EXCEPTION_GUARD_PAGE: return "Guard page";
00230 case EXCEPTION_NONCONTINUABLE_EXCEPTION: return "Noncontinuable exception";
00231 case EXCEPTION_INVALID_DISPOSITION: return "Invalid disposition";
00232 default: return "Unknown exception";
00233 }
00234 }
00235
00236 void trace_stack_at_exception(int* sp, int* fp, char* pc);
00237 void suspend_process_at_stack_overflow(int *sp, int* fp, char* pc);
00238
00239 LONG WINAPI topLevelExceptionFilter(struct _EXCEPTION_POINTERS* exceptionInfo) {
00240 int code = exceptionInfo->ExceptionRecord->ExceptionCode;
00241
00242 if (code == EXCEPTION_BREAKPOINT) {
00243
00244
00245
00246 return EXCEPTION_CONTINUE_SEARCH;
00247 }
00248
00249 lprintf("Exception caught \"%s\".\n", exception_name(code));
00250
00251 if (code == EXCEPTION_STACK_OVERFLOW) {
00252 lprintf(" Oops, we encounted a stack overflow.\n");
00253 lprintf(" You should check your program for infinite recursion!\n");
00254 suspend_process_at_stack_overflow(
00255 (int*) exceptionInfo->ContextRecord->Esp,
00256 (int*) exceptionInfo->ContextRecord->Ebp,
00257 (char*) exceptionInfo->ContextRecord->Eip);
00258 lprintf(" Coutinue execution ??????????????\n");
00259 } else {
00260
00261 report_vm_state();
00262 }
00263
00264 if (os::message_box("Exception caught", "Do you want a stack trace?")) {
00265 trace_stack_at_exception((int*) exceptionInfo->ContextRecord->Esp,
00266 (int*) exceptionInfo->ContextRecord->Ebp,
00267 (char*) exceptionInfo->ContextRecord->Eip);
00268 }
00269 return EXCEPTION_CONTINUE_SEARCH;
00270 }
00271
00272 HINSTANCE hInstance = NULL;
00273 HINSTANCE hPrevInstance = NULL;
00274 int nCmdShow = 0;
00275
00276 #ifdef _WINDOWS
00277 extern int __argc;
00278 extern char** __argv;
00279
00280 extern int my_main(int argc, char* argv[]);
00281
00282 int CALLBACK WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR cmdLine, int cmdShow) {
00283
00284 hInstance = hInst;
00285 hPrevInstance = hPrevInst;
00286 nCmdShow = cmdShow;
00287 return my_main(__argc, __argv);
00288 }
00289 #endif
00290
00291 void* os::get_hInstance() { return (void*) hInstance; }
00292 void* os::get_prevInstance() { return (void*) hPrevInstance; }
00293 int os::get_nCmdShow() { return nCmdShow; }
00294
00295 extern int bootstrapping;
00296 static CONTEXT context;
00297
00298 void os::timerStart() {}
00299
00300 void os::timerStop() {}
00301
00302 void os::timerPrintBuffer() {}
00303
00304
00305
00306 char* os::reserve_memory(int size) {
00307 return (char*) VirtualAlloc(NULL, size, MEM_RESERVE, PAGE_READWRITE);
00308 }
00309
00310 bool os::commit_memory(char* addr, int size) {
00311 bool result = VirtualAlloc(addr, size, MEM_COMMIT, PAGE_READWRITE) != NULL;
00312 if (!result) {
00313 int error = GetLastError();
00314 lprintf("commit_memory error %d 0x%lx\n", error, error);
00315 }
00316 return result;
00317 }
00318
00319 bool os::uncommit_memory(char* addr, int size) {
00320 return VirtualFree(addr, size, MEM_DECOMMIT) ? true : false;
00321 }
00322
00323 bool os::release_memory(char* addr, int size) {
00324 return VirtualFree(addr, 0, MEM_RELEASE) ? true : false;
00325 }
00326
00327 bool os::guard_memory(char* addr, int size) {
00328 DWORD old_status;
00329 return VirtualProtect(addr, size, PAGE_READWRITE | PAGE_GUARD, &old_status) ? true : false;
00330 }
00331
00332 void os::transfer(Thread* from_thread, Event* from_event, Thread* to_thread, Event* to_event) {
00333 ResetEvent((HANDLE) from_event);
00334 SetEvent((HANDLE) to_event);
00335 WaitForSingleObject((HANDLE) from_event, INFINITE);
00336 }
00337
00338 void os::transfer_and_continue(Thread* from_thread, Event* from_event, Thread* to_thread, Event* to_event) {
00339 ResetEvent((HANDLE) from_event);
00340 SetEvent((HANDLE) to_event);
00341 }
00342
00343 void os::suspend_thread(Thread* thread) {
00344 SuspendThread(thread);
00345 }
00346
00347 void os::resume_thread(Thread* thread) {
00348 ResumeThread(thread);
00349 }
00350
00351 void os::sleep(int ms) {
00352 Sleep(ms);
00353 }
00354
00355 void os::fetch_top_frame(Thread* thread, int** sp, int** fp, char** pc) {
00356 CONTEXT context;
00357 context.ContextFlags = CONTEXT_CONTROL;
00358 if (GetThreadContext(thread, &context)) {
00359 *sp = (int*) context.Esp;
00360 *fp = (int*) context.Ebp;
00361 *pc = (char*) context.Eip;
00362 } else {
00363 *sp = NULL;
00364 *fp = NULL;
00365 *pc = NULL;
00366 }
00367 }
00368
00369 int os::current_thread_id() {
00370 return GetCurrentThreadId();
00371 }
00372
00373 void os::wait_for_event(Event* event) {
00374 WaitForSingleObject((HANDLE) event, INFINITE);
00375 }
00376
00377 void os::reset_event(Event* event) {
00378 ResetEvent((HANDLE) event);
00379 }
00380
00381 void os::signal_event(Event* event) {
00382 SetEvent((HANDLE) event);
00383 }
00384
00385 bool os::wait_for_event_or_timer(Event* event, int timeout_in_ms) {
00386 return WAIT_TIMEOUT == WaitForSingleObject((HANDLE) event, timeout_in_ms);
00387 }
00388
00389 extern "C" bool WizardMode;
00390
00391 void process_settings_file(char* file_name, bool quiet);
00392
00393 static int number_of_ctrl_c = 0;
00394
00395 BOOL WINAPI HandlerRoutine(DWORD dwCtrlType) {
00396 if (CTRL_BREAK_EVENT == dwCtrlType) {
00397 lprintf("\n{receiving break}\n");
00398 intercept_for_single_step();
00399 } else {
00400 if (number_of_ctrl_c == 0) {
00401 lprintf("\n{reading .breakrc}");
00402 process_settings_file(".breakrc", false);
00403 } else {
00404 lprintf("\n{aborting}\n");
00405 _asm { int 3 }
00406 }
00407 number_of_ctrl_c++;
00408 }
00409 return TRUE;
00410 }
00411
00412 void real_time_tick(int delay_time);
00413
00414
00415
00416
00417 DWORD WINAPI WatcherMain(LPVOID lpvParam) {
00418 const int delay_interval = 10;
00419 while(1) {
00420 Sleep(delay_interval);
00421 real_time_tick(delay_interval);
00422 }
00423 return 0;
00424 }
00425
00426 int os::_vm_page_size = 0;
00427
00428 void os::initialize_system_info() {
00429 SYSTEM_INFO si;
00430 GetSystemInfo(&si);
00431 _vm_page_size = si.dwPageSize;
00432 initialze_performance_counter();
00433 }
00434
00435 int os::message_box(char* title, char* message) {
00436 int result = MessageBox(NULL, message, title,
00437 MB_YESNO | MB_ICONERROR | MB_SYSTEMMODAL | MB_DEFAULT_DESKTOP_ONLY);
00438 return result == IDYES;
00439 }
00440
00441 extern "C" bool EnableTasks;
00442
00443 LARGE_INTEGER counter;
00444
00445 CRITICAL_SECTION ThreadSection;
00446
00447 void ThreadCritical::intialize() { InitializeCriticalSection(&ThreadSection); }
00448 void ThreadCritical::release() { DeleteCriticalSection(&ThreadSection); }
00449
00450 ThreadCritical::ThreadCritical() {
00451 EnterCriticalSection(&ThreadSection);
00452 }
00453
00454 ThreadCritical::~ThreadCritical() {
00455 LeaveCriticalSection(&ThreadSection);
00456 }
00457
00458 void os_init() {
00459 ThreadCritical::intialize();
00460
00461 if (hInstance == NULL) {
00462 hInstance = GetModuleHandle(NULL);
00463 nCmdShow = SW_SHOWNORMAL;
00464 }
00465
00466 os::initialize_system_info();
00467
00468 SetConsoleCtrlHandler(&HandlerRoutine, TRUE);
00469
00470
00471 main_process = GetCurrentProcess();
00472 if (!DuplicateHandle(main_process, GetCurrentThread(), main_process,
00473 &main_thread, THREAD_ALL_ACCESS, FALSE, 0)) {
00474 fatal("DuplicateHandle failed\n");
00475 }
00476 main_thread_id = (int) GetCurrentThreadId();
00477
00478
00479 SetUnhandledExceptionFilter(topLevelExceptionFilter);
00480
00481
00482
00483 if (EnableTasks) {
00484 DWORD watcher_id;
00485 watcher_thread = CreateThread(NULL, 0, &WatcherMain, 0, 0, &watcher_id);
00486 SetThreadPriority(watcher_thread, THREAD_PRIORITY_HIGHEST);
00487 }
00488 }
00489
00490 void os_exit() {
00491 ThreadCritical::release();
00492 }
00493
00494 #endif