VIDEO: Added priority boost to thread performing SDL processing and updates

Reworked all priority adjustment code to leverage a new
sim_os_set_thread_priority API which is coded to use pthreads or OS
priority adjustment APIs as necessary.
This commit is contained in:
Mark Pizzolato 2016-06-11 09:52:33 -07:00
parent 3743d3d68a
commit a24aba69ae
9 changed files with 114 additions and 63 deletions

3
scp.c
View file

@ -7698,7 +7698,8 @@ if (double_quote_found && (!single_quote_found))
*tptr++ = quote; *tptr++ = quote;
while (size--) { while (size--) {
switch (*iptr) { switch (*iptr) {
case '\r': *tptr++ = '\\'; *tptr++ = 'r'; break; case '\r':
*tptr++ = '\\'; *tptr++ = 'r'; break;
case '\n': case '\n':
*tptr++ = '\\'; *tptr++ = 'n'; break; *tptr++ = '\\'; *tptr++ = 'n'; break;
case '\f': case '\f':

View file

@ -2156,17 +2156,13 @@ pthread_cond_t sim_console_startup_cond;
static void * static void *
_console_poll(void *arg) _console_poll(void *arg)
{ {
int sched_policy;
struct sched_param sched_priority;
int wait_count = 0; int wait_count = 0;
DEVICE *d; DEVICE *d;
/* Boost Priority for this I/O thread vs the CPU instruction execution /* Boost Priority for this I/O thread vs the CPU instruction execution
thread which, in general, won't be readily yielding the processor when thread which, in general, won't be readily yielding the processor when
this thread needs to run */ this thread needs to run */
pthread_getschedparam (pthread_self(), &sched_policy, &sched_priority); sim_os_set_thread_priority (PRIORITY_ABOVE_NORMAL);
++sched_priority.sched_priority;
pthread_setschedparam (pthread_self(), sched_policy, &sched_priority);
sim_debug (DBG_ASY, &sim_con_telnet, "_console_poll() - starting\n"); sim_debug (DBG_ASY, &sim_con_telnet, "_console_poll() - starting\n");
@ -2529,7 +2525,7 @@ if (sim_log) {
fflush (sim_log); fflush (sim_log);
_setmode (_fileno (sim_log), _O_BINARY); _setmode (_fileno (sim_log), _O_BINARY);
} }
SetThreadPriority (GetCurrentThread(), THREAD_PRIORITY_BELOW_NORMAL); sim_os_set_thread_priority (PRIORITY_BELOW_NORMAL);
return SCPE_OK; return SCPE_OK;
} }
@ -2539,7 +2535,7 @@ if (sim_log) {
fflush (sim_log); fflush (sim_log);
_setmode (_fileno (sim_log), _O_TEXT); _setmode (_fileno (sim_log), _O_TEXT);
} }
SetThreadPriority (GetCurrentThread(), THREAD_PRIORITY_NORMAL); sim_os_set_thread_priority (PRIORITY_NORMAL);
if ((std_input) && /* If Not Background process? */ if ((std_input) && /* If Not Background process? */
(std_input != INVALID_HANDLE_VALUE) && (std_input != INVALID_HANDLE_VALUE) &&
(!SetConsoleMode(std_input, saved_mode))) /* Restore Normal mode */ (!SetConsoleMode(std_input, saved_mode))) /* Restore Normal mode */
@ -2952,13 +2948,13 @@ if (ioctl (0, TIOCSETC, &runtchars) < 0)
return SCPE_TTIERR; return SCPE_TTIERR;
if (ioctl (0, TIOCSLTC, &runltchars) < 0) if (ioctl (0, TIOCSLTC, &runltchars) < 0)
return SCPE_TTIERR; return SCPE_TTIERR;
nice (10); /* lower priority */ sim_os_set_thread_priority (PRIORITY_BELOW_NORMAL)l /* lower priority */
return SCPE_OK; return SCPE_OK;
} }
static t_stat sim_os_ttcmd (void) static t_stat sim_os_ttcmd (void)
{ {
nice (-10); /* restore priority */ sim_os_set_thread_priority (PRIORITY_NORMAL); /* restore priority */
fcntl (0, F_SETFL, cmdfl); /* block mode */ fcntl (0, F_SETFL, cmdfl); /* block mode */
if (ioctl (0, TIOCSETP, &cmdtty) < 0) if (ioctl (0, TIOCSETP, &cmdtty) < 0)
return SCPE_TTIERR; return SCPE_TTIERR;
@ -3026,7 +3022,6 @@ return SCPE_OK;
#include <unistd.h> #include <unistd.h>
struct termios cmdtty, runtty; struct termios cmdtty, runtty;
static int prior_norm = 1;
static t_stat sim_os_ttinit (void) static t_stat sim_os_ttinit (void)
{ {
@ -3085,11 +3080,7 @@ runtty.c_cc[VINTR] = sim_int_char; /* in case changed */
#endif #endif
if (tcsetattr (0, TCSAFLUSH, &runtty) < 0) if (tcsetattr (0, TCSAFLUSH, &runtty) < 0)
return SCPE_TTIERR; return SCPE_TTIERR;
if (prior_norm) { /* at normal pri? */ sim_os_set_thread_priority (PRIORITY_BELOW_NORMAL); /* try to lower pri */
errno = 0;
(void)nice (10); /* try to lower pri */
prior_norm = errno; /* if no error, done */
}
return SCPE_OK; return SCPE_OK;
} }
@ -3097,11 +3088,7 @@ static t_stat sim_os_ttcmd (void)
{ {
if (!isatty (fileno (stdin))) /* skip if !tty */ if (!isatty (fileno (stdin))) /* skip if !tty */
return SCPE_OK; return SCPE_OK;
if (!prior_norm) { /* priority down? */ sim_os_set_thread_priority (PRIORITY_NORMAL); /* try to raise pri */
errno = 0;
(void)nice (-10); /* try to raise pri */
prior_norm = (errno == 0); /* if no error, done */
}
if (tcsetattr (0, TCSAFLUSH, &cmdtty) < 0) if (tcsetattr (0, TCSAFLUSH, &cmdtty) < 0)
return SCPE_TTIERR; return SCPE_TTIERR;
return SCPE_OK; return SCPE_OK;

View file

@ -162,16 +162,12 @@ static void *
_disk_io(void *arg) _disk_io(void *arg)
{ {
UNIT* volatile uptr = (UNIT*)arg; UNIT* volatile uptr = (UNIT*)arg;
int sched_policy;
struct sched_param sched_priority;
struct disk_context *ctx = (struct disk_context *)uptr->disk_ctx; struct disk_context *ctx = (struct disk_context *)uptr->disk_ctx;
/* Boost Priority for this I/O thread vs the CPU instruction execution /* Boost Priority for this I/O thread vs the CPU instruction execution
thread which in general won't be readily yielding the processor when thread which in general won't be readily yielding the processor when
this thread needs to run */ this thread needs to run */
pthread_getschedparam (pthread_self(), &sched_policy, &sched_priority); sim_os_set_thread_priority (PRIORITY_ABOVE_NORMAL);
++sched_priority.sched_priority;
pthread_setschedparam (pthread_self(), sched_policy, &sched_priority);
sim_debug (ctx->dbit, ctx->dptr, "_disk_io(unit=%d) starting\n", (int)(uptr-ctx->dptr->units)); sim_debug (ctx->dbit, ctx->dptr, "_disk_io(unit=%d) starting\n", (int)(uptr-ctx->dptr->units));

View file

@ -1689,8 +1689,6 @@ _eth_reader(void *arg)
{ {
ETH_DEV* volatile dev = (ETH_DEV*)arg; ETH_DEV* volatile dev = (ETH_DEV*)arg;
int status = 0; int status = 0;
int sched_policy;
struct sched_param sched_priority;
int sel_ret = 0; int sel_ret = 0;
int do_select = 0; int do_select = 0;
SOCKET select_fd = 0; SOCKET select_fd = 0;
@ -1721,9 +1719,7 @@ sim_debug(dev->dbit, dev->dptr, "Reader Thread Starting\n");
/* Boost Priority for this I/O thread vs the CPU instruction execution /* Boost Priority for this I/O thread vs the CPU instruction execution
thread which, in general, won't be readily yielding the processor thread which, in general, won't be readily yielding the processor
when this thread needs to run */ when this thread needs to run */
pthread_getschedparam (pthread_self(), &sched_policy, &sched_priority); sim_os_set_thread_priority (PRIORITY_ABOVE_NORMAL);
++sched_priority.sched_priority;
pthread_setschedparam (pthread_self(), sched_policy, &sched_priority);
while (dev->handle) { while (dev->handle) {
#if defined (_WIN32) #if defined (_WIN32)
@ -1880,15 +1876,11 @@ _eth_writer(void *arg)
{ {
ETH_DEV* volatile dev = (ETH_DEV*)arg; ETH_DEV* volatile dev = (ETH_DEV*)arg;
ETH_WRITE_REQUEST *request; ETH_WRITE_REQUEST *request;
int sched_policy;
struct sched_param sched_priority;
/* Boost Priority for this I/O thread vs the CPU instruction execution /* Boost Priority for this I/O thread vs the CPU instruction execution
thread which in general won't be readily yielding the processor when thread which in general won't be readily yielding the processor when
this thread needs to run */ this thread needs to run */
pthread_getschedparam (pthread_self(), &sched_policy, &sched_priority); sim_os_set_thread_priority (PRIORITY_ABOVE_NORMAL);
++sched_priority.sched_priority;
pthread_setschedparam (pthread_self(), sched_policy, &sched_priority);
sim_debug(dev->dbit, dev->dptr, "Writer Thread Starting\n"); sim_debug(dev->dbit, dev->dptr, "Writer Thread Starting\n");

View file

@ -216,16 +216,12 @@ static void *
_tape_io(void *arg) _tape_io(void *arg)
{ {
UNIT* volatile uptr = (UNIT*)arg; UNIT* volatile uptr = (UNIT*)arg;
int sched_policy;
struct sched_param sched_priority;
struct tape_context *ctx = (struct tape_context *)uptr->tape_ctx; struct tape_context *ctx = (struct tape_context *)uptr->tape_ctx;
/* Boost Priority for this I/O thread vs the CPU instruction execution /* Boost Priority for this I/O thread vs the CPU instruction execution
thread which in general won't be readily yielding the processor when thread which in general won't be readily yielding the processor when
this thread needs to run */ this thread needs to run */
pthread_getschedparam (pthread_self(), &sched_policy, &sched_priority); sim_os_set_thread_priority (PRIORITY_ABOVE_NORMAL);
++sched_priority.sched_priority;
pthread_setschedparam (pthread_self(), sched_policy, &sched_priority);
sim_debug (ctx->dbit, ctx->dptr, "_tape_io(unit=%d) starting\n", (int)(uptr-ctx->dptr->units)); sim_debug (ctx->dbit, ctx->dptr, "_tape_io(unit=%d) starting\n", (int)(uptr-ctx->dptr->units));

View file

@ -164,6 +164,59 @@ return sim_os_msec() - start_time;
#define SIM_IDLE_MS_SLEEP sim_os_ms_sleep #define SIM_IDLE_MS_SLEEP sim_os_ms_sleep
#endif #endif
/* Mark the need for the sim_os_set_thread_priority routine, */
/* allowing the feature and/or platform dependent code to provide it */
#define NEED_THREAD_PRIORITY
/* If we've got pthreads support then use pthreads mechanisms */
#if defined(USE_READER_THREAD)
#undef NEED_THREAD_PRIORITY
#if defined(_WIN32)
/* On Windows there are several potentially disjoint threading APIs */
/* in use (base win32 pthreads, libSDL provided threading, and direct */
/* calls to beginthreadex), so go directly to the Win32 threading APIs */
/* to manage thread priority */
t_stat sim_os_set_thread_priority (int below_normal_above)
{
const static int val[3] = {THREAD_PRIORITY_BELOW_NORMAL, THREAD_PRIORITY_NORMAL, THREAD_PRIORITY_ABOVE_NORMAL};
if ((below_normal_above < -1) || (below_normal_above > 1))
return SCPE_ARG;
SetThreadPriority (GetCurrentThread(), val[1 + below_normal_above]);
return SCPE_OK;
}
#else
/* Native pthreads priority implementation */
t_stat sim_os_set_thread_priority (int below_normal_above)
{
int sched_policy, min_prio, max_prio;
struct sched_param sched_priority;
if ((below_normal_above < -1) || (below_normal_above > 1))
return SCPE_ARG;
pthread_getschedparam (pthread_self(), &sched_policy, &sched_priority);
min_prio = sched_get_priority_min(sched_policy);
max_prio = sched_get_priority_max(sched_policy);
switch (below_normal_above) {
case PRIORITY_BELOW_NORMAL:
sched_priority.sched_priority = min_prio;
break;
case PRIORITY_NORMAL:
sched_priority.sched_priority = (max_prio + min_prio) / 2;
break;
case PRIORITY_ABOVE_NORMAL:
sched_priority.sched_priority = max_prio;
break;
}
pthread_setschedparam (pthread_self(), sched_policy, &sched_priority);
return SCPE_OK;
}
#endif
#endif /* defined(USE_READER_THREAD) */
/* OS-dependent timer and clock routines */ /* OS-dependent timer and clock routines */
/* VMS */ /* VMS */
@ -261,8 +314,6 @@ return 0;
/* Win32 routines */ /* Win32 routines */
#include <windows.h>
const t_bool rtc_avail = TRUE; const t_bool rtc_avail = TRUE;
uint32 sim_os_msec (void) uint32 sim_os_msec (void)
@ -494,6 +545,45 @@ treq.tv_nsec = (milliseconds % MILLIS_PER_SEC) * NANOS_PER_MILLI;
return sim_os_msec () - stime; return sim_os_msec () - stime;
} }
#if defined(NEED_THREAD_PRIORITY)
#undef NEED_THREAD_PRIORITY
#include <sys/time.h>
#include <sys/resource.h>
t_stat sim_os_set_thread_priority (int below_normal_above)
{
if ((below_normal_above < -1) || (below_normal_above > 1))
return SCPE_ARG;
errno = 0;
switch (below_normal_above) {
case PRIORITY_BELOW_NORMAL:
if ((getpriority (PRIO_PROCESS, 0) <= 0) && /* at or above normal pri? */
(errno == 0))
setpriority (PRIO_PROCESS, 0, 10);
break;
case PRIORITY_NORMAL:
if (getpriority (PRIO_PROCESS, 0) != 0) /* at or above normal pri? */
setpriority (PRIO_PROCESS, 0, 0);
break;
case PRIORITY_ABOVE_NORMAL:
if ((getpriority (PRIO_PROCESS, 0) <= 0) && /* at or above normal pri? */
(errno == 0))
setpriority (PRIO_PROCESS, 0, -10);
break;
}
return SCPE_OK;
}
#endif /* defined(NEED_THREAD_PRIORITY) */
#endif
/* If one hasn't been provided yet, then just stub it */
#if defined(NEED_THREAD_PRIORITY)
t_stat sim_os_set_thread_priority (int below_normal_above)
{
return SCPE_OK;
}
#endif #endif
/* diff = min - sub */ /* diff = min - sub */

View file

@ -136,6 +136,10 @@ t_stat sim_clock_coschedule_tmr (UNIT *uptr, int32 tmr, int32 interval);
t_stat sim_clock_coschedule_tmr_abs (UNIT *uptr, int32 tmr, int32 interval); t_stat sim_clock_coschedule_tmr_abs (UNIT *uptr, int32 tmr, int32 interval);
double sim_timer_inst_per_sec (void); double sim_timer_inst_per_sec (void);
t_bool sim_timer_idle_capable (uint32 *host_ms_sleep_1, uint32 *host_tick_ms); t_bool sim_timer_idle_capable (uint32 *host_ms_sleep_1, uint32 *host_tick_ms);
#define PRIORITY_BELOW_NORMAL -1
#define PRIORITY_NORMAL 0
#define PRIORITY_ABOVE_NORMAL 1
t_stat sim_os_set_thread_priority (int below_normal_above);
extern t_bool sim_idle_enab; /* idle enabled flag */ extern t_bool sim_idle_enab; /* idle enabled flag */
extern volatile t_bool sim_idle_wait; /* idle waiting flag */ extern volatile t_bool sim_idle_wait; /* idle waiting flag */

View file

@ -2960,8 +2960,6 @@ t_bool sim_tmxr_poll_running = FALSE;
static void * static void *
_tmxr_poll(void *arg) _tmxr_poll(void *arg)
{ {
int sched_policy;
struct sched_param sched_priority;
struct timeval timeout; struct timeval timeout;
int timeout_usec; int timeout_usec;
DEVICE *dptr = tmxr_open_devices[0]->dptr; DEVICE *dptr = tmxr_open_devices[0]->dptr;
@ -2973,9 +2971,7 @@ int wait_count = 0;
/* Boost Priority for this I/O thread vs the CPU instruction execution /* Boost Priority for this I/O thread vs the CPU instruction execution
thread which, in general, won't be readily yielding the processor when thread which, in general, won't be readily yielding the processor when
this thread needs to run */ this thread needs to run */
pthread_getschedparam (pthread_self(), &sched_policy, &sched_priority); sim_os_set_thread_priority (PRIORITY_ABOVE_NORMAL);
++sched_priority.sched_priority;
pthread_setschedparam (pthread_self(), sched_policy, &sched_priority);
sim_debug (TMXR_DBG_ASY, dptr, "_tmxr_poll() - starting\n"); sim_debug (TMXR_DBG_ASY, dptr, "_tmxr_poll() - starting\n");
@ -3180,8 +3176,6 @@ return NULL;
static void * static void *
_tmxr_serial_poll(void *arg) _tmxr_serial_poll(void *arg)
{ {
int sched_policy;
struct sched_param sched_priority;
int timeout_usec; int timeout_usec;
DEVICE *dptr = tmxr_open_devices[0]->dptr; DEVICE *dptr = tmxr_open_devices[0]->dptr;
UNIT **units = NULL; UNIT **units = NULL;
@ -3192,9 +3186,7 @@ int wait_count = 0;
/* Boost Priority for this I/O thread vs the CPU instruction execution /* Boost Priority for this I/O thread vs the CPU instruction execution
thread which, in general, won't be readily yielding the processor when thread which, in general, won't be readily yielding the processor when
this thread needs to run */ this thread needs to run */
pthread_getschedparam (pthread_self(), &sched_policy, &sched_priority); sim_os_set_thread_priority (PRIORITY_ABOVE_NORMAL);
++sched_priority.sched_priority;
pthread_setschedparam (pthread_self(), sched_policy, &sched_priority);
sim_debug (TMXR_DBG_ASY, dptr, "_tmxr_serial_poll() - starting\n"); sim_debug (TMXR_DBG_ASY, dptr, "_tmxr_serial_poll() - starting\n");
@ -3316,8 +3308,6 @@ static void *
_tmxr_serial_line_poll(void *arg) _tmxr_serial_line_poll(void *arg)
{ {
TMLN *lp = (TMLN *)arg; TMLN *lp = (TMLN *)arg;
int sched_policy;
struct sched_param sched_priority;
DEVICE *dptr = tmxr_open_devices[0]->dptr; DEVICE *dptr = tmxr_open_devices[0]->dptr;
UNIT *uptr = (lp->uptr ? lp->uptr : lp->mp->uptr); UNIT *uptr = (lp->uptr ? lp->uptr : lp->mp->uptr);
DEVICE *d = find_dev_from_unit(uptr); DEVICE *d = find_dev_from_unit(uptr);
@ -3326,9 +3316,7 @@ int wait_count = 0;
/* Boost Priority for this I/O thread vs the CPU instruction execution /* Boost Priority for this I/O thread vs the CPU instruction execution
thread which, in general, won't be readily yielding the processor when thread which, in general, won't be readily yielding the processor when
this thread needs to run */ this thread needs to run */
pthread_getschedparam (pthread_self(), &sched_policy, &sched_priority); sim_os_set_thread_priority (PRIORITY_ABOVE_NORMAL);
++sched_priority.sched_priority;
pthread_setschedparam (pthread_self(), sched_policy, &sched_priority);
sim_debug (TMXR_DBG_ASY, dptr, "_tmxr_serial_line_poll() - starting\n"); sim_debug (TMXR_DBG_ASY, dptr, "_tmxr_serial_line_poll() - starting\n");
@ -3398,8 +3386,6 @@ return NULL;
static void * static void *
_tmxr_serial_poll(void *arg) _tmxr_serial_poll(void *arg)
{ {
int sched_policy;
struct sched_param sched_priority;
int timeout_usec; int timeout_usec;
DEVICE *dptr = tmxr_open_devices[0]->dptr; DEVICE *dptr = tmxr_open_devices[0]->dptr;
TMLN **lines = NULL; TMLN **lines = NULL;
@ -3408,9 +3394,6 @@ pthread_t *threads = NULL;
/* Boost Priority for this I/O thread vs the CPU instruction execution /* Boost Priority for this I/O thread vs the CPU instruction execution
thread which, in general, won't be readily yielding the processor when thread which, in general, won't be readily yielding the processor when
this thread needs to run */ this thread needs to run */
pthread_getschedparam (pthread_self(), &sched_policy, &sched_priority);
++sched_priority.sched_priority;
pthread_setschedparam (pthread_self(), sched_policy, &sched_priority);
sim_debug (TMXR_DBG_ASY, dptr, "_tmxr_serial_poll() - starting\n"); sim_debug (TMXR_DBG_ASY, dptr, "_tmxr_serial_poll() - starting\n");

View file

@ -419,6 +419,8 @@ SDL_Init (SDL_INIT_VIDEO);
vid_main_thread_handle = SDL_CreateThread (main_thread , "simh-main", NULL); vid_main_thread_handle = SDL_CreateThread (main_thread , "simh-main", NULL);
#endif #endif
sim_os_set_thread_priority (PRIORITY_ABOVE_NORMAL);
vid_beep_setup (400, 660); vid_beep_setup (400, 660);
while (1) { while (1) {