diff --git a/scp.c b/scp.c index 15217d39..19be42e5 100644 --- a/scp.c +++ b/scp.c @@ -5952,7 +5952,6 @@ if (cptr && (*cptr != 0)) /* now eol? */ if (flag == sim_asynch_enabled) /* already set correctly? */ return SCPE_OK; sim_asynch_enabled = flag; -tmxr_change_async (); sim_timer_change_asynch (); if (1) { uint32 i, j; @@ -5991,9 +5990,6 @@ if (cptr && (*cptr != 0)) return SCPE_2MARG; #ifdef SIM_ASYNCH_IO fprintf (st, "Asynchronous I/O is %sabled, %s\n", (sim_asynch_enabled) ? "en" : "dis", AIO_QUEUE_MODE); -#if defined(SIM_ASYNCH_MUX) -fprintf (st, "Asynchronous Multiplexer support is available\n"); -#endif #if defined(SIM_ASYNCH_CLOCKS) fprintf (st, "Asynchronous Clock is %sabled\n", (sim_asynch_timer) ? "en" : "dis"); #endif @@ -6883,9 +6879,6 @@ if (flag) { #if defined (SIM_ASYNCH_IO) fprintf (st, "\n Asynchronous I/O support (%s)", AIO_QUEUE_MODE); #endif -#if defined (SIM_ASYNCH_MUX) - fprintf (st, "\n Asynchronous Multiplexer support"); -#endif #if defined (SIM_ASYNCH_CLOCKS) fprintf (st, "\n Asynchronous Clock support"); #endif @@ -12382,7 +12375,6 @@ do { } else sim_interval = noqueue_time = NOQUEUE_WAIT; - AIO_EVENT_BEGIN(uptr); if (uptr->usecs_remaining) { sim_debug (SIM_DBG_EVENT, &sim_scp_dev, "Requeueing %s after %.0f usecs\n", sim_uname (uptr), uptr->usecs_remaining); reason = sim_timer_activate_after (uptr, uptr->usecs_remaining); @@ -12394,7 +12386,6 @@ do { else reason = SCPE_OK; } - AIO_EVENT_COMPLETE(uptr, reason); if (sim_interval_catchup < -1) { sim_interval_catchup += sim_clock_queue->time; sim_time += sim_clock_queue->time; @@ -12599,7 +12590,6 @@ if ((uptr->cancel) && uptr->cancel (uptr)) return SCPE_OK; if (uptr->dynflags & UNIT_TMR_UNIT) sim_timer_cancel (uptr); -AIO_CANCEL(uptr); AIO_UPDATE_QUEUE; if (sim_clock_queue == QUEUE_LIST_END) return SCPE_OK; diff --git a/sim_console.c b/sim_console.c index ae29c6e8..ddde042f 100644 --- a/sim_console.c +++ b/sim_console.c @@ -210,7 +210,6 @@ UNIT sim_con_units[2] = {{ UDATA (&sim_con_poll_svc, UNIT_ATTABLE, 0)}}; /* cons #define DBG_XMT TMXR_DBG_XMT /* display Transmitted Data */ #define DBG_RCV TMXR_DBG_RCV /* display Received Data */ #define DBG_RET TMXR_DBG_RET /* display Returned Received Data */ -#define DBG_ASY TMXR_DBG_ASY /* asynchronous thread activity */ #define DBG_CON TMXR_DBG_CON /* display connection activity */ #define DBG_EXP 0x00000001 /* Expect match activity */ #define DBG_SND 0x00000002 /* Send (Inject) data activity */ @@ -220,7 +219,6 @@ static DEBTAB sim_con_debug[] = { {"XMT", DBG_XMT, "Transmitted Data"}, {"RCV", DBG_RCV, "Received Data"}, {"RET", DBG_RET, "Returned Received Data"}, - {"ASY", DBG_ASY, "asynchronous activity"}, {"CON", DBG_CON, "connection activity"}, {"EXP", DBG_EXP, "Expect match activity"}, {"SND", DBG_SND, "Send (Inject) data activity"}, @@ -3154,86 +3152,6 @@ return SCPE_OK; } -#if defined(SIM_ASYNCH_IO) && defined(SIM_ASYNCH_MUX) -extern pthread_mutex_t sim_tmxr_poll_lock; -extern pthread_cond_t sim_tmxr_poll_cond; -extern int32 sim_tmxr_poll_count; -extern t_bool sim_tmxr_poll_running; - -pthread_t sim_console_poll_thread; /* Keyboard Polling Thread Id */ -t_bool sim_console_poll_running = FALSE; -pthread_cond_t sim_console_startup_cond; - -static void * -_console_poll(void *arg) -{ -int wait_count = 0; -DEVICE *d; - -/* Boost Priority for this I/O thread vs the CPU instruction execution - thread which, in general, won't be readily yielding the processor when - this thread needs to run */ -sim_os_set_thread_priority (PRIORITY_ABOVE_NORMAL); - -sim_debug (DBG_ASY, &sim_con_telnet, "_console_poll() - starting\n"); - -pthread_mutex_lock (&sim_tmxr_poll_lock); -pthread_cond_signal (&sim_console_startup_cond); /* Signal we're ready to go */ -while (sim_asynch_enabled) { - - if (!sim_is_running) { - if (wait_count) { - sim_debug (DBG_ASY, d, "_console_poll() - Removing interest in %s. Other interest: %d\n", d->name, sim_con_ldsc.uptr->a_poll_waiter_count); - --sim_con_ldsc.uptr->a_poll_waiter_count; - --sim_tmxr_poll_count; - } - break; - } - - /* If we started something, let it finish before polling again */ - if (wait_count) { - sim_debug (DBG_ASY, &sim_con_telnet, "_console_poll() - waiting for %d units\n", wait_count); - pthread_cond_wait (&sim_tmxr_poll_cond, &sim_tmxr_poll_lock); - sim_debug (DBG_ASY, &sim_con_telnet, "_console_poll() - continuing with after wait\n"); - } - - pthread_mutex_unlock (&sim_tmxr_poll_lock); - wait_count = 0; - if (sim_os_poll_kbd_ready (1000)) { - sim_debug (DBG_ASY, &sim_con_telnet, "_console_poll() - Keyboard Data available\n"); - pthread_mutex_lock (&sim_tmxr_poll_lock); - ++wait_count; - if (!sim_con_ldsc.uptr->a_polling_now) { - sim_con_ldsc.uptr->a_polling_now = TRUE; - sim_con_ldsc.uptr->a_poll_waiter_count = 1; - d = find_dev_from_unit(sim_con_ldsc.uptr); - sim_debug (DBG_ASY, &sim_con_telnet, "_console_poll() - Activating %s\n", d->name); - pthread_mutex_unlock (&sim_tmxr_poll_lock); - _sim_activate (sim_con_ldsc.uptr, 0); - pthread_mutex_lock (&sim_tmxr_poll_lock); - } - else { - d = find_dev_from_unit(sim_con_ldsc.uptr); - sim_debug (DBG_ASY, &sim_con_telnet, "_console_poll() - Already Activated %s %d times\n", d->name, sim_con_ldsc.uptr->a_poll_waiter_count); - ++sim_con_ldsc.uptr->a_poll_waiter_count; - } - } - else - pthread_mutex_lock (&sim_tmxr_poll_lock); - - sim_tmxr_poll_count += wait_count; - } -pthread_mutex_unlock (&sim_tmxr_poll_lock); - -sim_debug (DBG_ASY, &sim_con_telnet, "_console_poll() - exiting\n"); - -return NULL; -} - - -#endif /* defined(SIM_ASYNCH_IO) && defined(SIM_ASYNCH_MUX) */ - - t_stat sim_ttinit (void) { sim_con_tmxr.ldsc->mp = &sim_con_tmxr; @@ -3244,52 +3162,13 @@ return sim_os_ttinit (); t_stat sim_ttrun (void) { -if (!sim_con_tmxr.ldsc->uptr) { /* If simulator didn't declare its input polling unit */ +if (!sim_con_tmxr.ldsc->uptr) /* If simulator didn't declare its input polling unit */ sim_con_unit.dynflags &= ~UNIT_TM_POLL; /* we can't poll asynchronously */ - sim_con_unit.dynflags |= TMUF_NOASYNCH; /* disable asynchronous behavior */ - } -else { -#if defined(SIM_ASYNCH_IO) && defined(SIM_ASYNCH_MUX) - if (sim_asynch_enabled) { - sim_con_tmxr.ldsc->uptr->dynflags |= UNIT_TM_POLL;/* flag console input device as a polling unit */ - sim_con_unit.dynflags |= UNIT_TM_POLL; /* flag as polling unit */ - } -#endif - } -#if defined(SIM_ASYNCH_IO) && defined(SIM_ASYNCH_MUX) -pthread_mutex_lock (&sim_tmxr_poll_lock); -if (sim_asynch_enabled) { - pthread_attr_t attr; - - pthread_cond_init (&sim_console_startup_cond, NULL); - pthread_attr_init (&attr); - pthread_attr_setscope (&attr, PTHREAD_SCOPE_SYSTEM); - pthread_create (&sim_console_poll_thread, &attr, _console_poll, NULL); - pthread_attr_destroy( &attr); - pthread_cond_wait (&sim_console_startup_cond, &sim_tmxr_poll_lock); /* Wait for thread to stabilize */ - pthread_cond_destroy (&sim_console_startup_cond); - sim_console_poll_running = TRUE; - } -pthread_mutex_unlock (&sim_tmxr_poll_lock); -#endif -tmxr_start_poll (); return sim_os_ttrun (); } t_stat sim_ttcmd (void) { -#if defined(SIM_ASYNCH_IO) && defined(SIM_ASYNCH_MUX) -pthread_mutex_lock (&sim_tmxr_poll_lock); -if (sim_console_poll_running) { - pthread_cond_signal (&sim_tmxr_poll_cond); - pthread_mutex_unlock (&sim_tmxr_poll_lock); - pthread_join (sim_console_poll_thread, NULL); - sim_console_poll_running = FALSE; - } -else - pthread_mutex_unlock (&sim_tmxr_poll_lock); -#endif -tmxr_stop_poll (); return sim_os_ttcmd (); } diff --git a/sim_defs.h b/sim_defs.h index 0b48e3f8..bedc3391 100644 --- a/sim_defs.h +++ b/sim_defs.h @@ -616,11 +616,6 @@ struct UNIT { UNIT *a_next; /* next asynch active */ int32 a_event_time; ACTIVATE_API a_activate_call; - /* Asynchronous Polling control */ - /* These fields should only be referenced when holding the sim_tmxr_poll_lock */ - t_bool a_polling_now; /* polling active flag */ - int32 a_poll_waiter_count; /* count of polling threads */ - /* waiting for this unit */ /* Asynchronous Timer control */ double a_due_time; /* due time for timer event */ double a_due_gtime; /* due time (in instructions) for timer event */ @@ -670,7 +665,7 @@ struct UNIT { /* These flags are only set dynamically */ #define UNIT_ATTMULT 0000001 /* Allow multiple attach commands */ -#define UNIT_TM_POLL 0000002 /* TMXR Polling unit */ +#define UNIT_TM_POLL 0000002 /* TMXR Polling unit (connect, transmit or receive) */ #define UNIT_NO_FIO 0000004 /* fileref is NOT a FILE * */ #define UNIT_DISK_CHK 0000010 /* disk data debug checking (sim_disk) */ #define UNIT_TMR_UNIT 0000200 /* Unit registered as a calibrated timer */ @@ -916,7 +911,7 @@ struct MEMFILE { #ifdef SIM_ASYNCH_IO #define UDATA(act,fl,cap) NULL,act,NULL,NULL,NULL,NULL,0,0,(fl),0,(cap),0,NULL,0,0,NULL,NULL,0,0,NULL,NULL,NULL,0,0,0,NULL,0,NULL,NULL,0,NULL,\ - NULL,NULL,NULL,0,NULL,0,0,0,0,0 + NULL,NULL,NULL,0,NULL,0,0,0 #else #define UDATA(act,fl,cap) NULL,act,NULL,NULL,NULL,NULL,0,0,(fl),0,(cap),0,NULL,0,0,NULL,NULL,0,0,NULL,NULL,NULL,0,0,0,NULL,0,NULL,NULL,0,NULL #endif @@ -1220,35 +1215,6 @@ extern int32 sim_asynch_inst_latency; #define AIO_UNLOCK \ pthread_mutex_unlock(&sim_asynch_lock) #define AIO_IS_ACTIVE(uptr) (((uptr)->a_is_active ? (uptr)->a_is_active (uptr) : FALSE) || ((uptr)->a_next)) -#if defined(SIM_ASYNCH_MUX) -#define AIO_CANCEL(uptr) \ - if (((uptr)->dynflags & UNIT_TM_POLL) && \ - !((uptr)->next) && !((uptr)->a_next)) { \ - (uptr)->a_polling_now = FALSE; \ - sim_tmxr_poll_count -= (uptr)->a_poll_waiter_count; \ - (uptr)->a_poll_waiter_count = 0; \ - } -#endif /* defined(SIM_ASYNCH_MUX) */ -#if !defined(AIO_CANCEL) -#define AIO_CANCEL(uptr) -#endif /* !defined(AIO_CANCEL) */ -#define AIO_EVENT_BEGIN(uptr) \ - do { \ - int __was_poll = uptr->dynflags & UNIT_TM_POLL -#define AIO_EVENT_COMPLETE(uptr, reason) \ - if (__was_poll) { \ - pthread_mutex_lock (&sim_tmxr_poll_lock); \ - uptr->a_polling_now = FALSE; \ - if (uptr->a_poll_waiter_count) { \ - sim_tmxr_poll_count -= uptr->a_poll_waiter_count; \ - uptr->a_poll_waiter_count = 0; \ - if (0 == sim_tmxr_poll_count) \ - pthread_cond_broadcast (&sim_tmxr_poll_cond); \ - } \ - pthread_mutex_unlock (&sim_tmxr_poll_lock); \ - } \ - AIO_UPDATE_QUEUE; \ - } while (0) #if defined(__DECC_VER) #include @@ -1388,10 +1354,7 @@ extern int32 sim_asynch_inst_latency; #define AIO_LOCK #define AIO_UNLOCK #define AIO_CLEANUP -#define AIO_EVENT_BEGIN(uptr) -#define AIO_EVENT_COMPLETE(uptr, reason) #define AIO_IS_ACTIVE(uptr) FALSE -#define AIO_CANCEL(uptr) #define AIO_SET_INTERRUPT_LATENCY(instpersec) #define AIO_TLS #endif /* SIM_ASYNCH_IO */ diff --git a/sim_tmxr.c b/sim_tmxr.c index 796a7a9a..ae6e1613 100644 --- a/sim_tmxr.c +++ b/sim_tmxr.c @@ -1087,9 +1087,6 @@ if (mp->last_poll_time == 0) { /* first poll initializa if (mp->poll_interval == 0) /* Assure reasonable polling interval */ mp->poll_interval = TMXR_DEFAULT_CONNECT_POLL_INTERVAL; - if (!(uptr->dynflags & TMUF_NOASYNCH)) /* if asynch not disabled */ - sim_cancel (uptr); - for (i=0; i < mp->lines; i++) { if (mp->ldsc[i].uptr) { mp->ldsc[i].uptr->tmxr = (void *)mp; /* Connect UNIT to TMXR */ @@ -1103,12 +1100,6 @@ if (mp->last_poll_time == 0) { /* first poll initializa } else mp->ldsc[i].o_uptr = uptr; /* default line output polling to primary poll unit */ - if (!(mp->uptr->dynflags & TMUF_NOASYNCH)) { /* if asynch not disabled */ - if (mp->ldsc[i].uptr) - sim_cancel (mp->ldsc[i].uptr); - if (mp->ldsc[i].o_uptr) - sim_cancel (mp->ldsc[i].o_uptr); - } } } @@ -2585,13 +2576,6 @@ for (i = 0; i < mp->lines; i++) { /* loop thru lines */ continue; nbytes = tmxr_send_buffered_data (lp); /* buffered bytes */ if (nbytes == 0) { /* buf empty? enab line */ -#if defined(SIM_ASYNCH_MUX) - UNIT *ruptr = lp->uptr ? lp->uptr : lp->mp->uptr; - if ((ruptr->dynflags & UNIT_TM_POLL) && - sim_asynch_enabled && - tmxr_rqln (lp)) - _sim_activate (ruptr, 0); -#endif if ((lp->xmte == 0) && ((lp->txbps == 0) || (lp->txnexttime <= sim_gtime_now))) @@ -3720,568 +3704,11 @@ return SCPE_OK; static TMXR **tmxr_open_devices = NULL; static int tmxr_open_device_count = 0; -#if defined(SIM_ASYNCH_MUX) -pthread_t sim_tmxr_poll_thread; /* Polling Thread Id */ -#if defined(_WIN32) || defined(VMS) -pthread_t sim_tmxr_serial_poll_thread; /* Serial Polling Thread Id */ -pthread_cond_t sim_tmxr_serial_startup_cond; -#endif -pthread_mutex_t sim_tmxr_poll_lock; -pthread_cond_t sim_tmxr_poll_cond; -pthread_cond_t sim_tmxr_startup_cond; -int32 sim_tmxr_poll_count = 0; -t_bool sim_tmxr_poll_running = FALSE; - -static void * -_tmxr_poll(void *arg) -{ -struct timeval timeout; -int timeout_usec; -DEVICE *dptr = tmxr_open_devices[0]->dptr; -UNIT **units = NULL; -UNIT **activated = NULL; -SOCKET *sockets = NULL; -int wait_count = 0; - -/* Boost Priority for this I/O thread vs the CPU instruction execution - thread which, in general, won't be readily yielding the processor when - this thread needs to run */ -sim_os_set_thread_priority (PRIORITY_ABOVE_NORMAL); - -sim_debug (TMXR_DBG_ASY, dptr, "_tmxr_poll() - starting\n"); - -units = (UNIT **)calloc(FD_SETSIZE, sizeof(*units)); -activated = (UNIT **)calloc(FD_SETSIZE, sizeof(*activated)); -sockets = (SOCKET *)calloc(FD_SETSIZE, sizeof(*sockets)); -timeout_usec = 1000000; -pthread_mutex_lock (&sim_tmxr_poll_lock); -pthread_cond_signal (&sim_tmxr_startup_cond); /* Signal we're ready to go */ -while (sim_asynch_enabled) { - int i, j, status, select_errno; - fd_set readfds, errorfds; - int socket_count; - SOCKET max_socket_fd; - TMXR *mp; - DEVICE *d; - - if ((tmxr_open_device_count == 0) || (!sim_is_running)) { - for (j=0; ja_poll_waiter_count); - --activated[j]->a_poll_waiter_count; - --sim_tmxr_poll_count; - } - break; - } - /* If we started something we should wait for, let it finish before polling again */ - if (wait_count) { - sim_debug (TMXR_DBG_ASY, dptr, "_tmxr_poll() - waiting for %d units\n", wait_count); - pthread_cond_wait (&sim_tmxr_poll_cond, &sim_tmxr_poll_lock); - sim_debug (TMXR_DBG_ASY, dptr, "_tmxr_poll() - continuing with timeout of %dms\n", timeout_usec/1000); - } - FD_ZERO (&readfds); - FD_ZERO (&errorfds); - for (i=max_socket_fd=socket_count=0; imaster) && (mp->uptr->dynflags&UNIT_TM_POLL)) { - units[socket_count] = mp->uptr; - sockets[socket_count] = mp->master; - FD_SET (mp->master, &readfds); - FD_SET (mp->master, &errorfds); - if (mp->master > max_socket_fd) - max_socket_fd = mp->master; - ++socket_count; - } - for (j=0; jlines; ++j) { - if (mp->ldsc[j].sock) { - units[socket_count] = mp->ldsc[j].uptr; - if (units[socket_count] == NULL) - units[socket_count] = mp->uptr; - sockets[socket_count] = mp->ldsc[j].sock; - FD_SET (mp->ldsc[j].sock, &readfds); - FD_SET (mp->ldsc[j].sock, &errorfds); - if (mp->ldsc[j].sock > max_socket_fd) - max_socket_fd = mp->ldsc[j].sock; - ++socket_count; - } -#if !defined(_WIN32) && !defined(VMS) - if (mp->ldsc[j].serport) { - units[socket_count] = mp->ldsc[j].uptr; - if (units[socket_count] == NULL) - units[socket_count] = mp->uptr; - sockets[socket_count] = mp->ldsc[j].serport; - FD_SET (mp->ldsc[j].serport, &readfds); - FD_SET (mp->ldsc[j].serport, &errorfds); - if (mp->ldsc[j].serport > max_socket_fd) - max_socket_fd = mp->ldsc[j].serport; - ++socket_count; - } -#endif - if (mp->ldsc[j].connecting) { - units[socket_count] = mp->uptr; - sockets[socket_count] = mp->ldsc[j].connecting; - FD_SET (mp->ldsc[j].connecting, &readfds); - FD_SET (mp->ldsc[j].connecting, &errorfds); - if (mp->ldsc[j].connecting > max_socket_fd) - max_socket_fd = mp->ldsc[j].connecting; - ++socket_count; - } - if (mp->ldsc[j].master) { - units[socket_count] = mp->uptr; - sockets[socket_count] = mp->ldsc[j].master; - FD_SET (mp->ldsc[j].master, &readfds); - FD_SET (mp->ldsc[j].master, &errorfds); - if (mp->ldsc[j].master > max_socket_fd) - max_socket_fd = mp->ldsc[j].master; - ++socket_count; - } - } - } - pthread_mutex_unlock (&sim_tmxr_poll_lock); - if (timeout_usec > 1000000) - timeout_usec = 1000000; - timeout.tv_sec = timeout_usec/1000000; - timeout.tv_usec = timeout_usec%1000000; - select_errno = 0; - if (socket_count == 0) { - sim_os_ms_sleep (timeout_usec/1000); - status = 0; - } - else - status = select (1+(int)max_socket_fd, &readfds, NULL, &errorfds, &timeout); - select_errno = errno; - wait_count=0; - pthread_mutex_lock (&sim_tmxr_poll_lock); - switch (status) { - case 0: /* timeout */ - for (i=max_socket_fd=socket_count=0; imaster) { - if (!mp->uptr->a_polling_now) { - mp->uptr->a_polling_now = TRUE; - mp->uptr->a_poll_waiter_count = 0; - d = find_dev_from_unit(mp->uptr); - sim_debug (TMXR_DBG_ASY, d, "_tmxr_poll() - Activating %s to poll connect\n", sim_uname(mp->uptr)); - pthread_mutex_unlock (&sim_tmxr_poll_lock); - _sim_activate (mp->uptr, 0); - pthread_mutex_lock (&sim_tmxr_poll_lock); - } - if (mp->txcount) { - timeout_usec = 10000; /* Wait 10ms next time (this gets doubled below) */ - mp->txcount = 0; - } - } - for (j=0; jlines; ++j) { - if ((mp->ldsc[j].conn) && (mp->ldsc[j].uptr)) { - if (tmxr_tqln(&mp->ldsc[j]) || tmxr_rqln (&mp->ldsc[j])) { - timeout_usec = 10000; /* Wait 10ms next time (this gets doubled below) */ - /* More than one socket can be associated with the - same unit. Make sure to only activate it one time */ - if (!mp->ldsc[j].uptr->a_polling_now) { - mp->ldsc[j].uptr->a_polling_now = TRUE; - mp->ldsc[j].uptr->a_poll_waiter_count = 0; - d = find_dev_from_unit(mp->ldsc[j].uptr); - sim_debug (TMXR_DBG_ASY, d, "_tmxr_poll() - Line %d Activating %s to poll data: %d/%d\n", - j, sim_uname(mp->ldsc[j].uptr), tmxr_tqln(&mp->ldsc[j]), tmxr_rqln (&mp->ldsc[j])); - pthread_mutex_unlock (&sim_tmxr_poll_lock); - _sim_activate (mp->ldsc[j].uptr, 0); - pthread_mutex_lock (&sim_tmxr_poll_lock); - } - } - } - } - } - sim_debug (TMXR_DBG_ASY, dptr, "_tmxr_poll() - Poll Timeout - %dms\n", timeout_usec/1000); - timeout_usec *= 2; /* Double timeout time */ - break; - case SOCKET_ERROR: - wait_count = 0; - if (select_errno == EINTR) - break; - sim_printf ("select() returned -1, errno=%d - %s\r\n", select_errno, strerror(select_errno)); - SIM_SCP_ABORT (""); - break; - default: - wait_count = 0; - for (i=0; ia_polling_now) { - activated[j]->a_polling_now = TRUE; - activated[j]->a_poll_waiter_count = 1; - d = find_dev_from_unit(activated[j]); - sim_debug (TMXR_DBG_ASY, d, "_tmxr_poll() - Activating for data %s\n", sim_uname(activated[j])); - pthread_mutex_unlock (&sim_tmxr_poll_lock); - _sim_activate (activated[j], 0); - pthread_mutex_lock (&sim_tmxr_poll_lock); - } - else { - d = find_dev_from_unit(activated[j]); - sim_debug (TMXR_DBG_ASY, d, "_tmxr_poll() - Already Activated %s%d %d times\n", sim_uname(activated[j]), activated[j]->a_poll_waiter_count); - ++activated[j]->a_poll_waiter_count; - } - } - } - } - if (wait_count) - timeout_usec = 10000; /* Wait 10ms next time */ - break; - } - sim_tmxr_poll_count += wait_count; - } -pthread_mutex_unlock (&sim_tmxr_poll_lock); -free(units); -free(activated); -free(sockets); - -sim_debug (TMXR_DBG_ASY, dptr, "_tmxr_poll() - exiting\n"); - -return NULL; -} - -#if defined(_WIN32) -static void * -_tmxr_serial_poll(void *arg) -{ -int timeout_usec; -DEVICE *dptr = tmxr_open_devices[0]->dptr; -UNIT **units = NULL; -UNIT **activated = NULL; -SERHANDLE *serports = NULL; -int wait_count = 0; - -/* Boost Priority for this I/O thread vs the CPU instruction execution - thread which, in general, won't be readily yielding the processor when - this thread needs to run */ -sim_os_set_thread_priority (PRIORITY_ABOVE_NORMAL); - -sim_debug (TMXR_DBG_ASY, dptr, "_tmxr_serial_poll() - starting\n"); - -units = (UNIT **)calloc(MAXIMUM_WAIT_OBJECTS, sizeof(*units)); -activated = (UNIT **)calloc(MAXIMUM_WAIT_OBJECTS, sizeof(*activated)); -serports = (SERHANDLE *)calloc(MAXIMUM_WAIT_OBJECTS, sizeof(*serports)); -timeout_usec = 1000000; -pthread_mutex_lock (&sim_tmxr_poll_lock); -pthread_cond_signal (&sim_tmxr_serial_startup_cond); /* Signal we're ready to go */ -while (sim_asynch_enabled) { - int i, j; - DWORD status; - int serport_count; - TMXR *mp; - DEVICE *d; - - if ((tmxr_open_device_count == 0) || (!sim_is_running)) { - for (j=0; ja_poll_waiter_count); - --activated[j]->a_poll_waiter_count; - --sim_tmxr_poll_count; - } - break; - } - /* If we started something we should wait for, let it finish before polling again */ - if (wait_count) { - sim_debug (TMXR_DBG_ASY, dptr, "_tmxr_serial_poll() - waiting for %d units\n", wait_count); - pthread_cond_wait (&sim_tmxr_poll_cond, &sim_tmxr_poll_lock); - sim_debug (TMXR_DBG_ASY, dptr, "_tmxr_serial_poll() - continuing with timeout of %dms\n", timeout_usec/1000); - } - for (i=serport_count=0; ilines; ++j) { - if (mp->ldsc[j].serport) { - units[serport_count] = mp->ldsc[j].uptr; - if (units[serport_count] == NULL) - units[serport_count] = mp->uptr; - serports[serport_count] = mp->ldsc[j].serport; - ++serport_count; - } - } - } - if (serport_count == 0) /* No open serial ports? */ - break; /* We're done */ - pthread_mutex_unlock (&sim_tmxr_poll_lock); - if (timeout_usec > 1000000) - timeout_usec = 1000000; - status = WaitForMultipleObjects (serport_count, serports, FALSE, timeout_usec/1000); - wait_count=0; - pthread_mutex_lock (&sim_tmxr_poll_lock); - switch (status) { - case WAIT_FAILED: - sim_printf ("WaitForMultipleObjects() Failed, LastError=%d\r\n", GetLastError()); - SIM_SCP_ABORT (""); - break; - case WAIT_TIMEOUT: - sim_debug (TMXR_DBG_ASY, dptr, "_tmxr_serial_poll() - Poll Timeout - %dms\n", timeout_usec/1000); - timeout_usec *= 2; /* Double timeout time */ - break; - default: - i = status - WAIT_OBJECT_0; - wait_count = 0; - j = wait_count; - activated[j] = units[i]; - ++wait_count; - if (!activated[j]->a_polling_now) { - activated[j]->a_polling_now = TRUE; - activated[j]->a_poll_waiter_count = 1; - d = find_dev_from_unit(activated[j]); - sim_debug (TMXR_DBG_ASY, d, "_tmxr_serial_poll() - Activating for data %s\n", sim_uname(activated[j])); - pthread_mutex_unlock (&sim_tmxr_poll_lock); - _sim_activate (activated[j], 0); - pthread_mutex_lock (&sim_tmxr_poll_lock); - } - else { - d = find_dev_from_unit(activated[j]); - sim_debug (TMXR_DBG_ASY, d, "_tmxr_serial_poll() - Already Activated %s%d %d times\n", sim_uname(activated[j]), activated[j]->a_poll_waiter_count); - ++activated[j]->a_poll_waiter_count; - } - if (wait_count) - timeout_usec = 10000; /* Wait 10ms next time */ - break; - } - sim_tmxr_poll_count += wait_count; - } -pthread_mutex_unlock (&sim_tmxr_poll_lock); -free(units); -free(activated); -free(serports); - -sim_debug (TMXR_DBG_ASY, dptr, "_tmxr_serial_poll() - exiting\n"); - -return NULL; -} -#endif /* _WIN32 */ - -#if defined(VMS) - -#include -#include -#include -#include -#include -#include -#include - -typedef struct { - unsigned short status; - unsigned short count; - unsigned int dev_status; } IOSB; - -#define MAXIMUM_WAIT_OBJECTS 64 /* Number of possible concurrently opened serial ports */ - -pthread_cond_t sim_serial_line_startup_cond; - - -static void * -_tmxr_serial_line_poll(void *arg) -{ -TMLN *lp = (TMLN *)arg; -DEVICE *dptr = tmxr_open_devices[0]->dptr; -UNIT *uptr = (lp->uptr ? lp->uptr : lp->mp->uptr); -DEVICE *d = find_dev_from_unit(uptr); -int wait_count = 0; - -/* Boost Priority for this I/O thread vs the CPU instruction execution - thread which, in general, won't be readily yielding the processor when - this thread needs to run */ -sim_os_set_thread_priority (PRIORITY_ABOVE_NORMAL); - -sim_debug (TMXR_DBG_ASY, dptr, "_tmxr_serial_line_poll() - starting\n"); - -pthread_mutex_lock (&sim_tmxr_poll_lock); -pthread_cond_signal (&sim_serial_line_startup_cond); /* Signal we're ready to go */ -while (sim_asynch_enabled) { - int i, j; - int serport_count; - TMXR *mp = lp->mp; - unsigned int status, term[2]; - unsigned char buf[4]; - IOSB iosb; - - if ((tmxr_open_device_count == 0) || (!sim_is_running)) { - if (wait_count) { - sim_debug (TMXR_DBG_ASY, d, "_tmxr_serial_line_poll() - Removing interest in %s. Other interest: %d\n", sim_uname(uptr), uptr->a_poll_waiter_count); - --uptr->a_poll_waiter_count; - --sim_tmxr_poll_count; - } - break; - } - /* If we started something we should wait for, let it finish before polling again */ - if (wait_count) { - sim_debug (TMXR_DBG_ASY, dptr, "_tmxr_serial_line_poll() - waiting for %d units\n", wait_count); - pthread_cond_wait (&sim_tmxr_poll_cond, &sim_tmxr_poll_lock); - sim_debug (TMXR_DBG_ASY, dptr, "_tmxr_serial_line_poll() - continuing with timeout of 1 sec\n"); - } - lp->a_active = TRUE; - pthread_mutex_unlock (&sim_tmxr_poll_lock); - term[0] = term[1] = 0; - status = sys$qiow (0, lp->serport, - IO$_READLBLK | IO$M_NOECHO | IO$M_NOFILTR | IO$M_TIMED | IO$M_TRMNOECHO, - &iosb, 0, 0, buf, 1, 1, term, 0, 0); - if (status != SS$_NORMAL) { - sim_printf ("_tmxr_serial_line_poll() - QIO Failed, Status=%d\r\n", status); - SIM_SCP_ABORT (""); - } - wait_count = 0; - sys$synch (0, &iosb); - pthread_mutex_lock (&sim_tmxr_poll_lock); - lp->a_active = FALSE; - if (iosb.count == 1) { - lp->a_buffered_character = buf[0] | SCPE_KFLAG; - wait_count = 1; - if (!uptr->a_polling_now) { - uptr->a_polling_now = TRUE; - uptr->a_poll_waiter_count = 1; - sim_debug (TMXR_DBG_ASY, d, "_tmxr_serial_line_poll() - Activating for data %s\n", sim_uname(uptr)); - pthread_mutex_unlock (&sim_tmxr_poll_lock); - _sim_activate (uptr, 0); - pthread_mutex_lock (&sim_tmxr_poll_lock); - } - else { - sim_debug (TMXR_DBG_ASY, d, "_tmxr_serial_line_poll() - Already Activated %s%d %d times\n", sim_uname(uptr), uptr->a_poll_waiter_count); - ++uptr->a_poll_waiter_count; - } - } - sim_tmxr_poll_count += wait_count; - } -pthread_mutex_unlock (&sim_tmxr_poll_lock); - -sim_debug (TMXR_DBG_ASY, dptr, "_tmxr_serial_line_poll() - exiting\n"); - -return NULL; -} - -static void * -_tmxr_serial_poll(void *arg) -{ -int timeout_usec; -DEVICE *dptr = tmxr_open_devices[0]->dptr; -TMLN **lines = NULL; -pthread_t *threads = NULL; - -/* Boost Priority for this I/O thread vs the CPU instruction execution - thread which, in general, won't be readily yielding the processor when - this thread needs to run */ - -sim_debug (TMXR_DBG_ASY, dptr, "_tmxr_serial_poll() - starting\n"); - -lines = (TMLN **)calloc(MAXIMUM_WAIT_OBJECTS, sizeof(*lines)); -threads = (pthread_t *)calloc(MAXIMUM_WAIT_OBJECTS, sizeof(*threads)); -pthread_mutex_lock (&sim_tmxr_poll_lock); -pthread_cond_signal (&sim_tmxr_serial_startup_cond); /* Signal we're ready to go */ -pthread_cond_init (&sim_serial_line_startup_cond, NULL); -while (sim_asynch_enabled) { - pthread_attr_t attr; - int i, j; - int serport_count; - TMXR *mp; - DEVICE *d; - - if ((tmxr_open_device_count == 0) || (!sim_is_running)) - break; - pthread_attr_init (&attr); - pthread_attr_setscope (&attr, PTHREAD_SCOPE_SYSTEM); - for (i=serport_count=0; ilines; ++j) { - if (mp->ldsc[j].serport) { - lines[serport_count] = &mp->ldsc[j]; - pthread_create (&threads[serport_count], &attr, _tmxr_serial_line_poll, (void *)&mp->ldsc[j]); - pthread_cond_wait (&sim_serial_line_startup_cond, &sim_tmxr_poll_lock); /* Wait for thread to stabilize */ - ++serport_count; - } - } - } - pthread_attr_destroy( &attr); - if (serport_count == 0) /* No open serial ports? */ - break; /* We're done */ - pthread_mutex_unlock (&sim_tmxr_poll_lock); - for (i=0; i 0) && - sim_asynch_enabled && - sim_is_running && - !sim_tmxr_poll_running) { - pthread_attr_t attr; - - pthread_cond_init (&sim_tmxr_startup_cond, NULL); - pthread_attr_init (&attr); - pthread_attr_setscope (&attr, PTHREAD_SCOPE_SYSTEM); - pthread_create (&sim_tmxr_poll_thread, &attr, _tmxr_poll, NULL); - pthread_attr_destroy( &attr); - pthread_cond_wait (&sim_tmxr_startup_cond, &sim_tmxr_poll_lock); /* Wait for thread to stabilize */ - pthread_cond_destroy (&sim_tmxr_startup_cond); - sim_tmxr_poll_running = TRUE; - } -pthread_mutex_unlock (&sim_tmxr_poll_lock); -#endif -return SCPE_OK; -} - -t_stat tmxr_stop_poll (void) -{ -#if defined(SIM_ASYNCH_MUX) -pthread_mutex_lock (&sim_tmxr_poll_lock); -if (sim_tmxr_poll_running) { - pthread_cond_signal (&sim_tmxr_poll_cond); - pthread_mutex_unlock (&sim_tmxr_poll_lock); - pthread_join (sim_tmxr_poll_thread, NULL); - sim_tmxr_poll_running = FALSE; - /* Transitioning from asynch mode so kick all polling units onto the event queue */ - if (tmxr_open_device_count) { - int i, j; - - for (i=0; iuptr) - _sim_activate (mp->uptr, 0); - for (j = 0; j < mp->lines; ++j) - if (mp->ldsc[j].uptr) - _sim_activate (mp->ldsc[j].uptr, 0); - } - } - } -else - pthread_mutex_unlock (&sim_tmxr_poll_lock); -#endif -return SCPE_OK; -} - static void tmxr_add_to_open_list (TMXR* mux) { int i; t_bool found = FALSE; -#if defined(SIM_ASYNCH_MUX) -pthread_mutex_lock (&sim_tmxr_poll_lock); -#endif for (i=0; ilines; i++) mux->ldsc[i].send.after = mux->ldsc[i].send.delay = 0; } -#if defined(SIM_ASYNCH_MUX) -pthread_mutex_unlock (&sim_tmxr_poll_lock); -if ((tmxr_open_device_count == 1) && (sim_asynch_enabled)) - tmxr_start_poll (); -#endif } static void _tmxr_remove_from_open_list (TMXR* mux) { int i, j; -#if defined(SIM_ASYNCH_MUX) -tmxr_stop_poll (); -pthread_mutex_lock (&sim_tmxr_poll_lock); -#endif for (i=0; ilines > 1) || (mp->ldsc[0].serport == 0))) uptr->dynflags = uptr->dynflags | UNIT_ATTMULT; /* allow multiple attach commands */ -#if defined(SIM_ASYNCH_MUX) -if (!async || (uptr->flags & TMUF_NOASYNCH)) /* if asynch disabled */ - uptr->dynflags |= TMUF_NOASYNCH; /* tag as no asynch */ -#else -uptr->dynflags |= TMUF_NOASYNCH; /* tag as no asynch */ -#endif uptr->dynflags |= UNIT_TM_POLL; /* tag as polling unit */ if (mp->dptr) { for (i=0; ilines; i++) { @@ -4759,7 +4156,7 @@ uptr->filename = NULL; uptr->tmxr = NULL; mp->last_poll_time = 0; uptr->flags &= ~(UNIT_ATT); /* not attached */ -uptr->dynflags &= ~(UNIT_TM_POLL|TMUF_NOASYNCH); /* no polling, not asynch disabled */ +uptr->dynflags &= ~UNIT_TM_POLL; /* no polling */ return SCPE_OK; } @@ -4822,17 +4219,8 @@ if (sooner != interval) { sim_debug (TIMER_DBG_MUX, &sim_timer_dev, "tmxr_activate() - scheduling %s after %d instructions rather than %d instructions\n", sim_uname (uptr), sooner, interval); return _sim_activate (uptr, sooner); /* Handle the busy case */ } -#if defined(SIM_ASYNCH_MUX) -if (!sim_asynch_enabled) { - sim_debug (TIMER_DBG_MUX, &sim_timer_dev, "tmxr_activate() - scheduling %s after %d instructions\n", sim_uname (uptr), interval); - return _sim_activate (uptr, interval); - } -sim_debug (TIMER_DBG_MUX, &sim_timer_dev, "tmxr_activate() - scheduling %s asynchronously instead of %d instructions\n", sim_uname (uptr), interval); -return SCPE_OK; -#else sim_debug (TIMER_DBG_MUX, &sim_timer_dev, "tmxr_activate() - scheduling %s after %d instructions\n", sim_uname (uptr), interval); return _sim_activate (uptr, interval); -#endif } t_stat tmxr_activate_abs (UNIT *uptr, int32 interval) @@ -4859,17 +4247,8 @@ if (sooner != 0x7FFFFFFF) { sim_debug (TIMER_DBG_MUX, &sim_timer_dev, "tmxr_activate_after() - scheduling %s after %d instructions rather than %u usecs\n", sim_uname (uptr), sooner, usecs_walltime); return _sim_activate (uptr, sooner); /* Handle the busy case directly */ } -#if defined(SIM_ASYNCH_MUX) -if (!sim_asynch_enabled) { - sim_debug (TIMER_DBG_MUX, &sim_timer_dev, "tmxr_activate_after() - scheduling %s after %u usecs\n", sim_uname (uptr), usecs_walltime); - return _sim_activate_after (uptr, (double)usecs_walltime); - } -sim_debug (TIMER_DBG_MUX, &sim_timer_dev, "tmxr_activate_after() - scheduling %s asynchronously instead of %u usecs\n", sim_uname (uptr), usecs_walltime); -return SCPE_OK; -#else sim_debug (TIMER_DBG_MUX, &sim_timer_dev, "tmxr_activate_after() - scheduling %s after %.0f usecs\n", sim_uname (uptr), (double)usecs_walltime); return _sim_activate_after (uptr, (double)usecs_walltime); -#endif } t_stat tmxr_activate_after_abs (UNIT *uptr, uint32 usecs_walltime) @@ -4906,16 +4285,8 @@ if (sooner != interval) { sim_debug (TIMER_DBG_MUX, &sim_timer_dev, "tmxr_clock_coschedule_tmr(tmr=%d) - scheduling %s after %d instructions rather than %d ticks (%d instructions)\n", tmr, sim_uname (uptr), sooner, ticks, interval); return _sim_activate (uptr, sooner); /* Handle the busy case directly */ } -#if defined(SIM_ASYNCH_MUX) -if (!sim_asynch_enabled) { - sim_debug (TIMER_DBG_MUX, &sim_timer_dev, "tmxr_clock_coschedule_tmr(tmr=%d) - coscheduling %s after interval %d ticks\n", tmr, sim_uname (uptr), ticks); - return sim_clock_coschedule (uptr, tmr, ticks); - } -return SCPE_OK; -#else sim_debug (TIMER_DBG_MUX, &sim_timer_dev, "tmxr_clock_coschedule_tmr(tmr=%d) - coscheduling %s after interval %d ticks\n", tmr, sim_uname (uptr), ticks); return sim_clock_coschedule_tmr (uptr, tmr, ticks); -#endif } t_stat tmxr_clock_coschedule_tmr_abs (UNIT *uptr, int32 tmr, int32 ticks) diff --git a/sim_tmxr.h b/sim_tmxr.h index 9202f2ab..f47eca7e 100644 --- a/sim_tmxr.h +++ b/sim_tmxr.h @@ -72,7 +72,7 @@ typedef struct SERPORT *SERHANDLE; #define TMXR_DBG_MDM 0x00800000 /* Debug Modem Signals */ #define TMXR_DBG_CFG 0x01000000 /* Debug Line Configuration Activities */ #define TMXR_DBG_CON 0x02000000 /* Debug Connection Activities */ -#define TMXR_DBG_ASY 0x04000000 /* Debug Asynchronous Activities */ +#define TMXR_DBG_ASY 0x04000000 /* Debug Asynchronous Activities - unused */ #define TMXR_DBG_TRC 0x08000000 /* Debug trace routine calls */ #define TMXR_DBG_PXMT 0x10000000 /* Debug Transmit Packet Data */ #define TMXR_DBG_PRCV 0x20000000 /* Debug Received Packet Data */ @@ -90,13 +90,6 @@ typedef struct SERPORT *SERHANDLE; #define TMXR_MDM_INCOMING (TMXR_MDM_DCD|TMXR_MDM_RNG|TMXR_MDM_CTS|TMXR_MDM_DSR) /* Settable Modem Bits */ #define TMXR_MDM_OUTGOING (TMXR_MDM_DTR|TMXR_MDM_RTS) /* Settable Modem Bits */ -/* Unit flags */ - -#define TMUF_V_NOASYNCH (UNIT_V_UF + 12) /* Asynch Disabled unit */ -#define TMUF_NOASYNCH (1u << TMUF_V_NOASYNCH) /* This flag can be defined */ - /* statically in a unit's flag field */ - /* This will disable the unit from */ - /* supporting asynchronmous mux behaviors */ /* Receive line speed limits */ #define TMLN_SPD_50_BPS 200000 /* usec per character */ @@ -258,7 +251,8 @@ int32 tmxr_send_buffered_data (TMLN *lp); t_stat tmxr_open_master (TMXR *mp, CONST char *cptr); t_stat tmxr_close_master (TMXR *mp); t_stat tmxr_connection_poll_interval (TMXR *mp, uint32 seconds); -t_stat tmxr_attach_ex (TMXR *mp, UNIT *uptr, CONST char *cptr, t_bool async); +t_stat tmxr_attach (TMXR *mp, UNIT *uptr, CONST char *cptr); +#define tmxr_attach_ex(mp, uptr, cptr, async) tmxr_attach (mp, uptr, cptr) t_stat tmxr_detach (TMXR *mp, UNIT *uptr); t_stat tmxr_attach_help(FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, const char *cptr); char *tmxr_line_attach_string(TMLN *lp); @@ -317,7 +311,6 @@ t_stat tmxr_clock_coschedule (UNIT *uptr, int32 interval); t_stat tmxr_clock_coschedule_abs (UNIT *uptr, int32 interval); t_stat tmxr_clock_coschedule_tmr (UNIT *uptr, int32 tmr, int32 ticks); t_stat tmxr_clock_coschedule_tmr_abs (UNIT *uptr, int32 tmr, int32 ticks); -t_stat tmxr_change_async (void); t_stat tmxr_locate_line_send (const char *dev_line, SEND **snd); t_stat tmxr_locate_line_expect (const char *dev_line, EXPECT **exp); t_stat tmxr_locate_line (const char *dev_line, TMLN **lp); @@ -326,8 +319,6 @@ const char *tmxr_expect_line_name (const EXPECT *exp); t_stat tmxr_startup (void); t_stat tmxr_shutdown (void); t_stat tmxr_sock_test (DEVICE *dptr, const char *cptr); -t_stat tmxr_start_poll (void); -t_stat tmxr_stop_poll (void); /* Framer support. These are a NOP if called on a non-framer line. */ void tmxr_start_framer (TMLN *line, int dmc_mode); void tmxr_stop_framer (TMLN *line); @@ -342,15 +333,6 @@ void _tmxr_debug (uint32 dbits, TMLN *lp, const char *msg, char *buf, int bufsiz #define tmxr_debug_connect_line(lp, msg) do {if (sim_deb && (lp)->mp && (lp)->mp->dptr && (TMXR_DBG_CON & (lp)->mp->dptr->dctrl)) sim_debug (TMXR_DBG_CON, (lp)->mp->dptr, "Ln%d:%s\n", (int)((lp)-(lp)->mp->ldsc), (msg)); } while (0) t_stat tmxr_add_debug (DEVICE *dptr); -#if defined(SIM_ASYNCH_MUX) && !defined(SIM_ASYNCH_IO) -#undef SIM_ASYNCH_MUX -#endif /* defined(SIM_ASYNCH_MUX) && !defined(SIM_ASYNCH_IO) */ - -#if defined(SIM_ASYNCH_MUX) -#define tmxr_attach(mp, uptr, cptr) tmxr_attach_ex(mp, uptr, cptr, TRUE) -#else -#define tmxr_attach(mp, uptr, cptr) tmxr_attach_ex(mp, uptr, cptr, FALSE) -#endif #if (!defined(NOT_MUX_USING_CODE)) #define sim_activate tmxr_activate #define sim_activate_abs tmxr_activate_abs