os.cpp

Go to the documentation of this file.
00001 /* Copyright 1994 - 1996 LongView Technologies L.L.C. $Revision: 1.50 $ */
00002 /* Copyright (c) 2006, Sun Microsystems, Inc.
00003 All rights reserved.
00004 
00005 Redistribution and use in source and binary forms, with or without modification, are permitted provided that the 
00006 following conditions are met:
00007 
00008     * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
00009     * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following 
00010           disclaimer in the documentation and/or other materials provided with the distribution.
00011     * Neither the name of Sun Microsystems nor the names of its contributors may be used to endorse or promote products derived 
00012           from this software without specific prior written permission.
00013 
00014 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT 
00015 NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 
00016 THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
00017 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
00018 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 
00019 OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE
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(&current_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     // This exception is called when an assertion fails (__asm { int 3} is executed).
00244     // It is therefore imperative we continue the search hereby enabling 
00245     // spawning of a Just-in-time debugger.
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     // Do not report vm state when getting stack overflow 
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   // Save all parameters
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 // Virtual Memory
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 // The sole purpose of the watcher thread is simulating
00415 // timer interrupts.
00416 
00417 DWORD WINAPI WatcherMain(LPVOID lpvParam) {
00418   const int delay_interval = 10; // Delay 10 ms
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   // Initialize main_process and main_thread
00471   main_process = GetCurrentProcess();  // Remember main_process is a pseudo handle
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   // Setup Windows Exceptions
00479   SetUnhandledExceptionFilter(topLevelExceptionFilter);
00480 
00481   // Create the watcher thread
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 /* __GNUC__ */

Generated on Mon Oct 9 13:37:21 2006 for Strongtalk VM by  doxygen 1.4.7