diff --git a/.gitattributes b/.gitattributes index 0f653413cdc..72159fd81ca 100644 --- a/.gitattributes +++ b/.gitattributes @@ -4417,6 +4417,8 @@ src/osd/sdl/texcopy.c svneol=native#text/plain src/osd/sdl/texsrc.h svneol=native#text/plain src/osd/sdl/video.c svneol=native#text/plain src/osd/sdl/video.h svneol=native#text/plain +src/osd/sdl/watchdog.c svneol=native#text/plain +src/osd/sdl/watchdog.h svneol=native#text/plain src/osd/sdl/window.c svneol=native#text/plain src/osd/sdl/window.h svneol=native#text/plain src/osd/windows/d3d8intf.c svneol=native#text/plain diff --git a/src/osd/sdl/osdsdl.h b/src/osd/sdl/osdsdl.h index 314fdcd430b..00e07ddc962 100644 --- a/src/osd/sdl/osdsdl.h +++ b/src/osd/sdl/osdsdl.h @@ -3,6 +3,8 @@ #include +#include "watchdog.h" + //============================================================ // Temporary SDL 1.3 defines //============================================================ @@ -74,6 +76,7 @@ #define SDLOPTION_KEYMAP_FILE "keymap_file" #define SDLOPTION_UIMODEKEY "uimodekey" #define SDLOPTION_OSLOG "oslog" +#define SDLOPTION_WATCHDOG "watchdog" #define SDLOPTION_SIXAXIS "sixaxis" #define SDLOPTION_JOYINDEX "joy_idx" @@ -162,6 +165,9 @@ public: private: static void osd_exit(running_machine &machine); + + watchdog *m_watchdog; + }; diff --git a/src/osd/sdl/sdl.mak b/src/osd/sdl/sdl.mak index f227e61f630..675b8ee1266 100644 --- a/src/osd/sdl/sdl.mak +++ b/src/osd/sdl/sdl.mak @@ -282,7 +282,8 @@ OSDOBJS = \ $(SDLOBJ)/video.o \ $(SDLOBJ)/drawsdl.o \ $(SDLOBJ)/window.o \ - $(SDLOBJ)/output.o + $(SDLOBJ)/output.o \ + $(SDLOBJ)/watchdog.o # Add SDL1.3 support ifdef SDL_INSTALL_ROOT diff --git a/src/osd/sdl/sdlmain.c b/src/osd/sdl/sdlmain.c index bac117baae0..c28a9a87abf 100644 --- a/src/osd/sdl/sdlmain.c +++ b/src/osd/sdl/sdlmain.c @@ -53,6 +53,8 @@ #include #endif +#include "watchdog.h" + //============================================================ // OPTIONS //============================================================ @@ -85,6 +87,7 @@ static const options_entry mame_sdl_options[] = // debugging options { NULL, NULL, OPTION_HEADER, "DEBUGGING OPTIONS" }, { SDLOPTION_OSLOG, "0", OPTION_BOOLEAN, "output error.log data to the system debugger" }, + { SDLOPTION_WATCHDOG ";wdog", "0", 0, "force the program to terminate if no updates within specified number of seconds" }, // performance options { NULL, NULL, OPTION_HEADER, "PERFORMANCE OPTIONS" }, @@ -369,6 +372,7 @@ static void output_oslog(running_machine &machine, const char *buffer) sdl_osd_interface::sdl_osd_interface() { + m_watchdog = NULL; } @@ -617,6 +621,15 @@ void sdl_osd_interface::init(running_machine &machine) if (options_get_bool(machine.options(), SDLOPTION_OSLOG)) machine.add_logerror_callback(output_oslog); + /* now setup watchdog */ + + int watchdog_timeout = options_get_int(machine.options(), SDLOPTION_WATCHDOG); + if (watchdog_timeout != 0) + { + m_watchdog = auto_alloc(&machine, watchdog); + m_watchdog->setTimeout(watchdog_timeout); + } + #if (SDL_VERSION_ATLEAST(1,3,0)) SDL_EventState(SDL_TEXTINPUT, SDL_TRUE); #else diff --git a/src/osd/sdl/sdlsync.h b/src/osd/sdl/sdlsync.h index 691497456a5..d581418460d 100644 --- a/src/osd/sdl/sdlsync.h +++ b/src/osd/sdl/sdlsync.h @@ -174,6 +174,18 @@ int osd_thread_cpu_affinity(osd_thread *thread, UINT32 mask); -----------------------------------------------------------------------------*/ void osd_thread_wait_free(osd_thread *thread); +/*----------------------------------------------------------------------------- + osd_process_kill: kill the current process + + Parameters: + + None. + + Return value: + + None. +-----------------------------------------------------------------------------*/ +void osd_process_kill(void); //============================================================ // Scalable Locks diff --git a/src/osd/sdl/sdlsync_ntc.c b/src/osd/sdl/sdlsync_ntc.c index 95297340a44..7eea5434429 100644 --- a/src/osd/sdl/sdlsync_ntc.c +++ b/src/osd/sdl/sdlsync_ntc.c @@ -512,3 +512,12 @@ void osd_thread_wait_free(osd_thread *thread) pthread_join(thread->thread, NULL); free(thread); } + +//============================================================ +// osd_process_kill +//============================================================ + +void osd_process_kill(void) +{ + kill(getpid(), SIGKILL); +} diff --git a/src/osd/sdl/sdlsync_tc.c b/src/osd/sdl/sdlsync_tc.c index 5d2e89135f2..425b0347f29 100644 --- a/src/osd/sdl/sdlsync_tc.c +++ b/src/osd/sdl/sdlsync_tc.c @@ -31,6 +31,7 @@ #include #include +#include #include typedef struct _hidden_mutex_t hidden_mutex_t; @@ -378,3 +379,11 @@ void osd_thread_wait_free(osd_thread *thread) free(thread); } +//============================================================ +// osd_process_kill +//============================================================ + +void osd_process_kill(void) +{ + kill(getpid(), SIGKILL); +} diff --git a/src/osd/sdl/sdlsync_win32.c b/src/osd/sdl/sdlsync_win32.c index cc89609b529..354d4c32b16 100644 --- a/src/osd/sdl/sdlsync_win32.c +++ b/src/osd/sdl/sdlsync_win32.c @@ -221,3 +221,11 @@ int osd_thread_cpu_affinity(osd_thread *thread, UINT32 mask) return TRUE; } +//============================================================ +// osd_process_kill +//============================================================ + +void osd_process_kill(void) +{ + TerminateProcess(GetCurrentProcess(), -1); +} diff --git a/src/osd/sdl/video.c b/src/osd/sdl/video.c index dee509ce874..79ffe86064c 100644 --- a/src/osd/sdl/video.c +++ b/src/osd/sdl/video.c @@ -333,6 +333,9 @@ void sdl_osd_interface::update(bool skip_redraw) { sdl_window_info *window; + if (m_watchdog != NULL) + m_watchdog->reset(); + // if we're not skipping this redraw, update all windows if (!skip_redraw) { diff --git a/src/osd/sdl/watchdog.c b/src/osd/sdl/watchdog.c new file mode 100644 index 00000000000..039a87639b6 --- /dev/null +++ b/src/osd/sdl/watchdog.c @@ -0,0 +1,64 @@ +//============================================================ +// +// watchdog.h - watchdog handling +// +// Copyright (c) 1996-2011, Nicola Salmoria and the MAME Team. +// Visit http://mamedev.org for licensing and usage restrictions. +// +// SDLMAME by Olivier Galibert and R. Belmont +// +//============================================================ + +#include "osdcomm.h" +#include "osdcore.h" +#include "osinline.h" + +#include "watchdog.h" + +static void *watchdog_thread(void *param) +{ + watchdog *thiz = (watchdog *) param; + + while (TRUE) + { + if (osd_event_wait(thiz->event(), thiz->getTimeout())) + { + if (thiz->do_exit()) + break; + else + { + osd_event_reset(thiz->event()); + continue; + } + } + else + { + fprintf(stderr, "Terminating due to watchdog timeout\n"); + + osd_process_kill(); + } + } + return NULL; +} + +watchdog::watchdog(void) +{ + m_do_exit = 0; + m_event = osd_event_alloc(1, 0); + m_thread = osd_thread_create(watchdog_thread, this); + m_timeout = 60 * osd_ticks_per_second(); +} + +watchdog::~watchdog(void) +{ + atomic_exchange32(&m_do_exit, 1); + osd_event_set(m_event); + osd_thread_wait_free(m_thread); + osd_event_free(m_event); +} + +void watchdog::setTimeout(int timeout) +{ + m_timeout = timeout * osd_ticks_per_second(); + this->reset(); +} diff --git a/src/osd/sdl/watchdog.h b/src/osd/sdl/watchdog.h new file mode 100644 index 00000000000..e1c762c7a8d --- /dev/null +++ b/src/osd/sdl/watchdog.h @@ -0,0 +1,35 @@ +#ifndef _watchdog_h_ +#define _watchdog_h_ +//============================================================ +// +// watchdog.h - watchdog handling +// +// Copyright (c) 1996-2011, Nicola Salmoria and the MAME Team. +// Visit http://mamedev.org for licensing and usage restrictions. +// +// SDLMAME by Olivier Galibert and R. Belmont +// +//============================================================ + +#include "sdlsync.h" + +class watchdog +{ +public: + watchdog(void); + ~watchdog(void); + + void reset() { osd_event_set(m_event); } + + osd_event * event(void) { return m_event; } + INT32 do_exit(void) { return m_do_exit; } + osd_ticks_t getTimeout(void) { return m_timeout; } + void setTimeout(int timeout); +private: + osd_event * m_event; + osd_thread * m_thread; + volatile INT32 m_do_exit; + + osd_ticks_t m_timeout; +}; +#endif