# HG changeset patch # User jcoomes # Date 1310418943 25200 # Node ID b0b8491925fe88c75c55f283ed1f7f7775a40289 # Parent 8a4fc299022942164613ab4e741a0cb170a4de15 7061212: use o/s low memory notification in embedded builds Reviewed-by: dholmes, never, jwilhelm, kvn diff -r 8a4fc2990229 -r b0b8491925fe src/os/linux/vm/os_linux.cpp --- a/src/os/linux/vm/os_linux.cpp Thu Jul 07 15:44:34 2011 -0700 +++ b/src/os/linux/vm/os_linux.cpp Mon Jul 11 14:15:43 2011 -0700 @@ -169,7 +169,35 @@ /* Used to protect dlsym() calls */ static pthread_mutex_t dl_mutex; -//////////////////////////////////////////////////////////////////////////////// +#ifdef JAVASE_EMBEDDED +class MemNotifyThread: public Thread { + friend class VMStructs; + public: + virtual void run(); + + private: + static MemNotifyThread* _memnotify_thread; + int _fd; + + public: + + // Constructor + MemNotifyThread(int fd); + + // Tester + bool is_memnotify_thread() const { return true; } + + // Printing + char* name() const { return (char*)"Linux MemNotify Thread"; } + + // Returns the single instance of the MemNotifyThread + static MemNotifyThread* memnotify_thread() { return _memnotify_thread; } + + // Create and start the single instance of MemNotifyThread + static void start(); +}; +#endif // JAVASE_EMBEDDED + // utility functions static int SR_initialize(); @@ -4245,7 +4273,16 @@ } // this is called at the end of vm_initialization -void os::init_3(void) { } +void os::init_3(void) +{ +#ifdef JAVASE_EMBEDDED + // Start the MemNotifyThread + if (LowMemoryProtection) { + MemNotifyThread::start(); + } + return; +#endif +} // Mark the polling page as unreadable void os::make_polling_page_unreadable(void) { @@ -5368,3 +5405,78 @@ return true; } + +#ifdef JAVASE_EMBEDDED +// +// A thread to watch the '/dev/mem_notify' device, which will tell us when the OS is running low on memory. +// +MemNotifyThread* MemNotifyThread::_memnotify_thread = NULL; + +// ctor +// +MemNotifyThread::MemNotifyThread(int fd): Thread() { + assert(memnotify_thread() == NULL, "we can only allocate one MemNotifyThread"); + _fd = fd; + + if (os::create_thread(this, os::os_thread)) { + _memnotify_thread = this; + os::set_priority(this, NearMaxPriority); + os::start_thread(this); + } +} + +// Where all the work gets done +// +void MemNotifyThread::run() { + assert(this == memnotify_thread(), "expected the singleton MemNotifyThread"); + + // Set up the select arguments + fd_set rfds; + if (_fd != -1) { + FD_ZERO(&rfds); + FD_SET(_fd, &rfds); + } + + // Now wait for the mem_notify device to wake up + while (1) { + // Wait for the mem_notify device to signal us.. + int rc = select(_fd+1, _fd != -1 ? &rfds : NULL, NULL, NULL, NULL); + if (rc == -1) { + perror("select!\n"); + break; + } else if (rc) { + //ssize_t free_before = os::available_memory(); + //tty->print ("Notified: Free: %dK \n",os::available_memory()/1024); + + // The kernel is telling us there is not much memory left... + // try to do something about that + + // If we are not already in a GC, try one. + if (!Universe::heap()->is_gc_active()) { + Universe::heap()->collect(GCCause::_allocation_failure); + + //ssize_t free_after = os::available_memory(); + //tty->print ("Post-Notify: Free: %dK\n",free_after/1024); + //tty->print ("GC freed: %dK\n", (free_after - free_before)/1024); + } + // We might want to do something like the following if we find the GC's are not helping... + // Universe::heap()->size_policy()->set_gc_time_limit_exceeded(true); + } + } +} + +// +// See if the /dev/mem_notify device exists, and if so, start a thread to monitor it. +// +void MemNotifyThread::start() { + int fd; + fd = open ("/dev/mem_notify", O_RDONLY, 0); + if (fd < 0) { + return; + } + + if (memnotify_thread() == NULL) { + new MemNotifyThread(fd); + } +} +#endif // JAVASE_EMBEDDED