mirror of
https://github.com/simh/simh.git
synced 2026-01-11 23:52:58 +00:00
SCP: Fold up include files used by all simulators
- Add common system includes used in may places which are allowed and thus added directly in sim_defs.h. - Separate completely private system data structures and system APIs for use only by SCP library routines into sim_scp_private.h.
This commit is contained in:
parent
bdf28cf7f8
commit
194b313179
BIN
doc/simh.doc
BIN
doc/simh.doc
Binary file not shown.
22
scp.c
22
scp.c
@ -223,6 +223,7 @@
|
||||
#define IN_SCP_C 1 /* Include from scp.c */
|
||||
|
||||
#include "sim_defs.h"
|
||||
#include "sim_scp_private.h"
|
||||
#include "sim_rev.h"
|
||||
#include "sim_disk.h"
|
||||
#include "sim_tape.h"
|
||||
@ -233,14 +234,10 @@
|
||||
#include "sim_sock.h"
|
||||
#include "sim_frontpanel.h"
|
||||
#include <signal.h>
|
||||
#include <ctype.h>
|
||||
#include <time.h>
|
||||
#include <math.h>
|
||||
#if defined(_WIN32)
|
||||
#include <io.h>
|
||||
#include <fcntl.h>
|
||||
#endif
|
||||
#include <setjmp.h>
|
||||
|
||||
#if defined(SIM_HAVE_DLOPEN) /* Dynamic Readline support */
|
||||
#include <dlfcn.h>
|
||||
@ -437,7 +434,22 @@ if (sim_idle_wait) {
|
||||
pthread_cond_signal (&sim_asynch_wake);
|
||||
}
|
||||
}
|
||||
#else
|
||||
|
||||
void sim_aio_check_event (void)
|
||||
{
|
||||
if (0 > --sim_asynch_check) {
|
||||
AIO_UPDATE_QUEUE;
|
||||
sim_asynch_check = sim_asynch_inst_latency;
|
||||
}
|
||||
}
|
||||
|
||||
void sim_aio_set_interrupt_latency (int32 instpersec)
|
||||
{
|
||||
sim_asynch_inst_latency = (int32)((((double)(instpersec))*sim_asynch_latency)/1000000000);
|
||||
if (sim_asynch_inst_latency == 0)
|
||||
sim_asynch_inst_latency = 1;
|
||||
}
|
||||
#else /* !defined (SIM_ASYNCH_IO) */
|
||||
t_bool sim_asynch_enabled = FALSE;
|
||||
#endif
|
||||
|
||||
|
||||
4
scp.h
4
scp.h
@ -343,9 +343,13 @@ extern BRKTYPTAB *sim_brk_type_desc; /* type descriptions */
|
||||
extern const char *sim_prog_name; /* executable program name */
|
||||
extern FILE *stdnul;
|
||||
extern t_bool sim_asynch_enabled;
|
||||
extern int32 sim_asynch_latency;
|
||||
extern int32 sim_asynch_inst_latency;
|
||||
#if defined(SIM_ASYNCH_IO)
|
||||
int sim_aio_update_queue (void);
|
||||
void sim_aio_activate (ACTIVATE_API caller, UNIT *uptr, int32 event_time);
|
||||
void sim_aio_check_event (void);
|
||||
void sim_aio_set_interrupt_latency (int32 instpersec);
|
||||
#endif
|
||||
|
||||
/* VM interface */
|
||||
|
||||
@ -76,7 +76,6 @@
|
||||
*/
|
||||
|
||||
|
||||
#include <ctype.h>
|
||||
#include "sim_defs.h"
|
||||
#include "sim_card.h"
|
||||
|
||||
@ -1468,8 +1467,6 @@ fclose (f);
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
#include <setjmp.h>
|
||||
|
||||
t_stat sim_card_test (DEVICE *dptr, const char *cptr)
|
||||
{
|
||||
t_stat stat = SCPE_OK;
|
||||
|
||||
@ -128,11 +128,10 @@
|
||||
*/
|
||||
|
||||
#include "sim_defs.h"
|
||||
#include "sim_scp_private.h"
|
||||
#include "sim_tmxr.h"
|
||||
#include "sim_serial.h"
|
||||
#include "sim_timer.h"
|
||||
#include <ctype.h>
|
||||
#include <math.h>
|
||||
|
||||
#ifdef __HAIKU__
|
||||
#define nice(n) ({})
|
||||
|
||||
269
sim_defs.h
269
sim_defs.h
@ -125,6 +125,8 @@ extern int sim_vax_snprintf(char *buf, size_t buf_size, const char *fmt, ...);
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <ctype.h>
|
||||
#include <math.h>
|
||||
#include <setjmp.h>
|
||||
|
||||
#ifndef EXIT_FAILURE
|
||||
#define EXIT_FAILURE 1
|
||||
@ -133,25 +135,6 @@ extern int sim_vax_snprintf(char *buf, size_t buf_size, const char *fmt, ...);
|
||||
#define EXIT_SUCCESS 0
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <winsock2.h>
|
||||
#include <windows.h>
|
||||
#include <winerror.h>
|
||||
#undef PACKED /* avoid macro name collision */
|
||||
#undef ERROR /* avoid macro name collision */
|
||||
#undef MEM_MAPPED /* avoid macro name collision */
|
||||
#include <process.h>
|
||||
#endif
|
||||
|
||||
#ifdef USE_REGEX
|
||||
#undef USE_REGEX
|
||||
#endif
|
||||
#if defined(HAVE_PCRE_H)
|
||||
#include <pcre.h>
|
||||
#define USE_REGEX 1
|
||||
#endif
|
||||
|
||||
#if (defined (__MWERKS__) && defined (macintosh)) || defined(__DECC)
|
||||
#define __FUNCTION__ __FILE__
|
||||
#endif
|
||||
@ -824,55 +807,6 @@ struct BRKTYPTAB {
|
||||
};
|
||||
#define BRKTYPE(typ,descrip) {SWMASK(typ), descrip}
|
||||
|
||||
/* Expect rule */
|
||||
|
||||
struct EXPTAB {
|
||||
uint8 *match; /* match string */
|
||||
uint32 size; /* match string size */
|
||||
char *match_pattern; /* match pattern for format */
|
||||
int32 cnt; /* proceed count */
|
||||
uint32 after; /* delay before halting */
|
||||
int32 switches; /* flags */
|
||||
#define EXP_TYP_PERSIST (SWMASK ('P')) /* rule persists after match, default is once a rule matches, it is removed */
|
||||
#define EXP_TYP_CLEARALL (SWMASK ('C')) /* clear all rules after matching this rule, default is to once a rule matches, it is removed */
|
||||
#define EXP_TYP_REGEX (SWMASK ('R')) /* rule pattern is a regular expression */
|
||||
#define EXP_TYP_REGEX_I (SWMASK ('I')) /* regular expression pattern matching should be case independent */
|
||||
#define EXP_TYP_TIME (SWMASK ('T')) /* halt delay is in microseconds instead of instructions */
|
||||
#if defined(USE_REGEX)
|
||||
pcre *regex; /* compiled regular expression */
|
||||
int re_nsub; /* regular expression sub expression count */
|
||||
#endif
|
||||
char *act; /* action string */
|
||||
};
|
||||
|
||||
/* Expect Context */
|
||||
|
||||
struct EXPECT {
|
||||
DEVICE *dptr; /* Device (for Debug) */
|
||||
uint32 dbit; /* Debugging Bit */
|
||||
EXPTAB *rules; /* match rules */
|
||||
int32 size; /* count of match rules */
|
||||
uint8 *buf; /* buffer of output data which has produced */
|
||||
uint32 buf_ins; /* buffer insertion point for the next output data */
|
||||
uint32 buf_size; /* buffer size */
|
||||
uint32 buf_data; /* count of data in buffer */
|
||||
};
|
||||
|
||||
/* Send Context */
|
||||
|
||||
struct SEND {
|
||||
uint32 delay; /* instruction delay between sent data */
|
||||
#define SEND_DEFAULT_DELAY 1000 /* default delay instruction count */
|
||||
DEVICE *dptr; /* Device (for Debug) */
|
||||
uint32 dbit; /* Debugging Bit */
|
||||
uint32 after; /* instruction delay before sending any data */
|
||||
double next_time; /* execution time when next data can be sent */
|
||||
uint8 *buffer; /* buffer */
|
||||
size_t bufsize; /* buffer size */
|
||||
int32 insoff; /* insert offset */
|
||||
int32 extoff; /* extra offset */
|
||||
};
|
||||
|
||||
/* Debug table */
|
||||
|
||||
struct DEBTAB {
|
||||
@ -1160,204 +1094,13 @@ struct MEMFILE {
|
||||
SIM_SCP_ABORT (buf); \
|
||||
}
|
||||
|
||||
/* Asynch/Threaded I/O support */
|
||||
|
||||
#if defined (SIM_ASYNCH_IO)
|
||||
#include <pthread.h>
|
||||
|
||||
#define SIM_ASYNCH_CLOCKS 1
|
||||
|
||||
extern pthread_mutex_t sim_asynch_lock;
|
||||
extern pthread_cond_t sim_asynch_wake;
|
||||
extern pthread_mutex_t sim_timer_lock;
|
||||
extern pthread_cond_t sim_timer_wake;
|
||||
extern t_bool sim_timer_event_canceled;
|
||||
extern int32 sim_tmxr_poll_count;
|
||||
extern pthread_cond_t sim_tmxr_poll_cond;
|
||||
extern pthread_mutex_t sim_tmxr_poll_lock;
|
||||
extern pthread_t sim_asynch_main_threadid;
|
||||
extern UNIT * volatile sim_asynch_queue;
|
||||
extern volatile t_bool sim_idle_wait;
|
||||
extern int32 sim_asynch_check;
|
||||
extern int32 sim_asynch_latency;
|
||||
extern int32 sim_asynch_inst_latency;
|
||||
|
||||
/* Thread local storage */
|
||||
#if defined(thread_local)
|
||||
#define AIO_TLS thread_local
|
||||
#elif (__STDC_VERSION__ >= 201112) && !(defined(__STDC_NO_THREADS__))
|
||||
#define AIO_TLS _Thread_local
|
||||
#elif defined(__GNUC__) && !defined(__APPLE__) && !defined(__hpux) && !defined(__OpenBSD__) && !defined(_AIX)
|
||||
#define AIO_TLS __thread
|
||||
#elif defined(_MSC_VER)
|
||||
#define AIO_TLS __declspec(thread)
|
||||
#else
|
||||
/* Other compiler environment, then don't worry about thread local storage. */
|
||||
/* It is primarily used only used in debugging messages */
|
||||
#define AIO_TLS
|
||||
#endif
|
||||
#define AIO_QUEUE_CHECK(que, lock) \
|
||||
do { \
|
||||
UNIT *_cptr; \
|
||||
if (lock) \
|
||||
pthread_mutex_lock (lock); \
|
||||
for (_cptr = que; \
|
||||
(_cptr != QUEUE_LIST_END); \
|
||||
_cptr = _cptr->next) \
|
||||
if (!_cptr->next) \
|
||||
SIM_SCP_ABORT ("Queue Corruption detected"); \
|
||||
if (lock) \
|
||||
pthread_mutex_unlock (lock); \
|
||||
} while (0)
|
||||
#define AIO_MAIN_THREAD (pthread_equal ( pthread_self(), sim_asynch_main_threadid ))
|
||||
#define AIO_LOCK \
|
||||
pthread_mutex_lock(&sim_asynch_lock)
|
||||
#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(__DECC_VER)
|
||||
#include <builtins>
|
||||
#if defined(__IA64)
|
||||
#define USE_AIO_INTRINSICS 1
|
||||
#endif
|
||||
#endif
|
||||
#if defined(_WIN32) || defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4) || defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8)
|
||||
#define USE_AIO_INTRINSICS 1
|
||||
#endif
|
||||
/* Provide a way to test both Intrinsic and Lock based queue manipulations */
|
||||
/* when both are available on a particular platform */
|
||||
#if defined(DONT_USE_AIO_INTRINSICS) && defined(USE_AIO_INTRINSICS)
|
||||
#undef USE_AIO_INTRINSICS
|
||||
#endif
|
||||
#ifdef USE_AIO_INTRINSICS
|
||||
/* This approach uses intrinsics to manage access to the link list head */
|
||||
/* sim_asynch_queue. This implementation is a completely lock free design */
|
||||
/* which avoids the potential ABA issues. */
|
||||
#define AIO_QUEUE_MODE "Lock free asynchronous event queue"
|
||||
#define AIO_INIT \
|
||||
do { \
|
||||
sim_asynch_main_threadid = pthread_self(); \
|
||||
/* Empty list/list end uses the point value (void *)1. \
|
||||
This allows NULL in an entry's a_next pointer to \
|
||||
indicate that the entry is not currently in any list */ \
|
||||
sim_asynch_queue = QUEUE_LIST_END; \
|
||||
} while (0)
|
||||
#define AIO_CLEANUP \
|
||||
do { \
|
||||
pthread_mutex_destroy(&sim_asynch_lock); \
|
||||
pthread_cond_destroy(&sim_asynch_wake); \
|
||||
pthread_mutex_destroy(&sim_timer_lock); \
|
||||
pthread_cond_destroy(&sim_timer_wake); \
|
||||
pthread_mutex_destroy(&sim_tmxr_poll_lock); \
|
||||
pthread_cond_destroy(&sim_tmxr_poll_cond); \
|
||||
} while (0)
|
||||
#ifdef _WIN32
|
||||
#elif defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4) || defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8)
|
||||
#define InterlockedCompareExchangePointer(Destination, Exchange, Comparand) __sync_val_compare_and_swap(Destination, Comparand, Exchange)
|
||||
#elif defined(__DECC_VER)
|
||||
#define InterlockedCompareExchangePointer(Destination, Exchange, Comparand) (void *)((int32)_InterlockedCompareExchange64(Destination, Exchange, Comparand))
|
||||
#else
|
||||
#error "Implementation of function InterlockedCompareExchangePointer() is needed to build with USE_AIO_INTRINSICS"
|
||||
#endif
|
||||
#define AIO_ILOCK AIO_LOCK
|
||||
#define AIO_IUNLOCK AIO_UNLOCK
|
||||
#define AIO_QUEUE_VAL (UNIT *)(InterlockedCompareExchangePointer((void * volatile *)&sim_asynch_queue, (void *)sim_asynch_queue, NULL))
|
||||
#define AIO_QUEUE_SET(newval, oldval) (UNIT *)(InterlockedCompareExchangePointer((void * volatile *)&sim_asynch_queue, (void *)newval, oldval))
|
||||
#define AIO_UPDATE_QUEUE sim_aio_update_queue ()
|
||||
#define AIO_ACTIVATE(caller, uptr, event_time) \
|
||||
if (!pthread_equal ( pthread_self(), sim_asynch_main_threadid )) { \
|
||||
sim_aio_activate ((ACTIVATE_API)caller, uptr, event_time); \
|
||||
return SCPE_OK; \
|
||||
} else (void)0
|
||||
#else /* !USE_AIO_INTRINSICS */
|
||||
/* This approach uses a pthread mutex to manage access to the link list */
|
||||
/* head sim_asynch_queue. It will always work, but may be slower than the */
|
||||
/* lock free approach when using USE_AIO_INTRINSICS */
|
||||
#define AIO_QUEUE_MODE "Lock based asynchronous event queue"
|
||||
#define AIO_INIT \
|
||||
do { \
|
||||
pthread_mutexattr_t attr; \
|
||||
\
|
||||
pthread_mutexattr_init (&attr); \
|
||||
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); \
|
||||
pthread_mutex_init (&sim_asynch_lock, &attr); \
|
||||
pthread_mutexattr_destroy (&attr); \
|
||||
sim_asynch_main_threadid = pthread_self(); \
|
||||
/* Empty list/list end uses the point value (void *)1. \
|
||||
This allows NULL in an entry's a_next pointer to \
|
||||
indicate that the entry is not currently in any list */ \
|
||||
sim_asynch_queue = QUEUE_LIST_END; \
|
||||
} while (0)
|
||||
#define AIO_CLEANUP \
|
||||
do { \
|
||||
pthread_mutex_destroy(&sim_asynch_lock); \
|
||||
pthread_cond_destroy(&sim_asynch_wake); \
|
||||
pthread_mutex_destroy(&sim_timer_lock); \
|
||||
pthread_cond_destroy(&sim_timer_wake); \
|
||||
pthread_mutex_destroy(&sim_tmxr_poll_lock); \
|
||||
pthread_cond_destroy(&sim_tmxr_poll_cond); \
|
||||
} while (0)
|
||||
#define AIO_ILOCK AIO_LOCK
|
||||
#define AIO_IUNLOCK AIO_UNLOCK
|
||||
#define AIO_QUEUE_VAL sim_asynch_queue
|
||||
#define AIO_QUEUE_SET(newval, oldval) ((sim_asynch_queue = newval),oldval)
|
||||
#define AIO_UPDATE_QUEUE sim_aio_update_queue ()
|
||||
#define AIO_ACTIVATE(caller, uptr, event_time) \
|
||||
if (!pthread_equal ( pthread_self(), sim_asynch_main_threadid )) { \
|
||||
sim_debug (SIM_DBG_AIO_QUEUE, sim_dflt_dev, "Queueing Asynch event for %s after %d instructions\n", sim_uname(uptr), event_time);\
|
||||
AIO_LOCK; \
|
||||
if (uptr->a_next) { /* already queued? */ \
|
||||
uptr->a_activate_call = sim_activate_abs; \
|
||||
} else { \
|
||||
uptr->a_next = sim_asynch_queue; \
|
||||
uptr->a_event_time = event_time; \
|
||||
uptr->a_activate_call = (ACTIVATE_API)&caller; \
|
||||
sim_asynch_queue = uptr; \
|
||||
} \
|
||||
if (sim_idle_wait) { \
|
||||
if (sim_deb) { /* only while debug do lock/unlock overhead */ \
|
||||
AIO_UNLOCK; \
|
||||
sim_debug (TIMER_DBG_IDLE, &sim_timer_dev, "waking due to event on %s after %d instructions\n", sim_uname(uptr), event_time);\
|
||||
AIO_LOCK; \
|
||||
} \
|
||||
pthread_cond_signal (&sim_asynch_wake); \
|
||||
} \
|
||||
AIO_UNLOCK; \
|
||||
sim_asynch_check = 0; \
|
||||
return SCPE_OK; \
|
||||
} else (void)0
|
||||
#endif /* USE_AIO_INTRINSICS */
|
||||
#define AIO_VALIDATE(uptr) \
|
||||
if (!pthread_equal ( pthread_self(), sim_asynch_main_threadid )) { \
|
||||
SIM_SCP_ABORT ("Improper thread context for operation detected");\
|
||||
} else (void)0
|
||||
#define AIO_CHECK_EVENT \
|
||||
if (0 > --sim_asynch_check) { \
|
||||
AIO_UPDATE_QUEUE; \
|
||||
sim_asynch_check = sim_asynch_inst_latency; \
|
||||
} else (void)0
|
||||
#define AIO_SET_INTERRUPT_LATENCY(instpersec) \
|
||||
do { \
|
||||
sim_asynch_inst_latency = (int32)((((double)(instpersec))*sim_asynch_latency)/1000000000);\
|
||||
if (sim_asynch_inst_latency == 0) \
|
||||
sim_asynch_inst_latency = 1; \
|
||||
} while (0)
|
||||
#if defined(SIM_ASYNCH_IO)
|
||||
#define AIO_CHECK_EVENT sim_aio_check_event()
|
||||
#define AIO_SET_INTERRUPT_LATENCY(instpersec) sim_aio_set_interrupt_latency(instpersec)
|
||||
#else /* !SIM_ASYNCH_IO */
|
||||
#define AIO_QUEUE_MODE "Asynchronous I/O is not available"
|
||||
#define AIO_UPDATE_QUEUE
|
||||
#define AIO_ACTIVATE(caller, uptr, event_time)
|
||||
#define AIO_VALIDATE(uptr)
|
||||
#define AIO_CHECK_EVENT
|
||||
#define AIO_INIT
|
||||
#define AIO_MAIN_THREAD TRUE
|
||||
#define AIO_LOCK
|
||||
#define AIO_UNLOCK
|
||||
#define AIO_CLEANUP
|
||||
#define AIO_IS_ACTIVE(uptr) FALSE
|
||||
#define AIO_SET_INTERRUPT_LATENCY(instpersec)
|
||||
#define AIO_TLS
|
||||
#endif /* SIM_ASYNCH_IO */
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@ -89,7 +89,8 @@ Internal routines:
|
||||
#include "sim_disk.h"
|
||||
#include "sim_ether.h"
|
||||
#include "sim_scsi.h"
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "sim_scp_private.h"
|
||||
|
||||
#define DKUF_F_AUTO 0 /* Auto detect format format */
|
||||
#define DKUF_F_STD 1 /* SIMH format */
|
||||
@ -7880,8 +7881,6 @@ return r;
|
||||
|
||||
/* disk testing */
|
||||
|
||||
#include <setjmp.h>
|
||||
|
||||
struct disk_test_coverage {
|
||||
t_lba total_sectors;
|
||||
uint32 max_xfer_size;
|
||||
|
||||
@ -369,7 +369,7 @@
|
||||
------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
#include "sim_ether.h"
|
||||
#include "sim_sock.h"
|
||||
#include "sim_timer.h"
|
||||
@ -379,6 +379,10 @@
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#if defined (USE_READER_THREAD)
|
||||
#include <pthread.h>
|
||||
#endif
|
||||
|
||||
#define MAX(a,b) (((a) > (b)) ? (a) : (b))
|
||||
|
||||
/* Internal routine - forward declaration */
|
||||
@ -1021,7 +1025,6 @@ const char *eth_capabilities(void)
|
||||
/*============================================================================*/
|
||||
|
||||
#include <pcap.h>
|
||||
#include <string.h>
|
||||
#else
|
||||
struct pcap_pkthdr {
|
||||
uint32 caplen; /* length of portion present */
|
||||
@ -4505,8 +4508,6 @@ if (bpf_compile_skip_count)
|
||||
return (errors == 0) ? SCPE_OK : SCPE_IERR;
|
||||
}
|
||||
|
||||
#include <setjmp.h>
|
||||
|
||||
t_stat sim_ether_test (DEVICE *dptr, const char *cptr)
|
||||
{
|
||||
t_stat stat = SCPE_OK;
|
||||
|
||||
@ -149,9 +149,6 @@ extern "C" {
|
||||
#define DONT_USE_PCAP_FINDALLDEVS 1
|
||||
#endif
|
||||
|
||||
#if defined (USE_READER_THREAD)
|
||||
#include <pthread.h>
|
||||
#endif
|
||||
|
||||
/* structure declarations */
|
||||
|
||||
|
||||
@ -75,6 +75,8 @@
|
||||
|
||||
#include "sim_defs.h"
|
||||
|
||||
#include "sim_scp_private.h"
|
||||
|
||||
t_bool sim_end; /* TRUE = little endian, FALSE = big endian */
|
||||
t_bool sim_taddr_64; /* t_addr is > 32b and Large File Support available */
|
||||
t_bool sim_toffset_64; /* Large File (>2GB) file I/O Support available */
|
||||
@ -982,7 +984,6 @@ return (t_offset)(ftell (st));
|
||||
|
||||
#if defined (_WIN32)
|
||||
#define S_SIM_IO_FSEEK_EXT_ 1
|
||||
#include <sys/stat.h>
|
||||
|
||||
int sim_fseeko (FILE *st, t_offset offset, int whence)
|
||||
{
|
||||
@ -1218,7 +1219,6 @@ int sim_set_fsize (FILE *fptr, t_addr size)
|
||||
return ftruncate(fileno(fptr), (off_t)size);
|
||||
}
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#if defined (HAVE_UTIME)
|
||||
#include <utime.h>
|
||||
@ -1789,7 +1789,6 @@ return SCPE_OK;
|
||||
|
||||
#else /* !defined (_WIN32) */
|
||||
|
||||
#include <sys/stat.h>
|
||||
#if defined (HAVE_GLOB)
|
||||
#include <glob.h>
|
||||
#else /* !defined (HAVE_GLOB) */
|
||||
|
||||
@ -81,7 +81,6 @@ t_stat sim_copyfile (const char *source_file, const char *dest_file, t_bool over
|
||||
char *sim_filepath_parts (const char *pathname, const char *parts);
|
||||
const char *sim_relative_path (const char *filepath);
|
||||
char *sim_getcwd (char *buf, size_t buf_size);
|
||||
#include <sys/stat.h>
|
||||
typedef void (*DIR_ENTRY_CALLBACK)(const char *directory,
|
||||
const char *filename,
|
||||
t_offset FileSize,
|
||||
|
||||
290
sim_scp_private.h
Normal file
290
sim_scp_private.h
Normal file
@ -0,0 +1,290 @@
|
||||
/* sim_scp_private.h: scp library private definitions
|
||||
|
||||
Copyright (c) 2023, Mark Pizzolato
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a
|
||||
copy of this software and associated documentation files (the "Software"),
|
||||
to deal in the Software without restriction, including without limitation
|
||||
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
and/or sell copies of the Software, and to permit persons to whom the
|
||||
Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
MARK PIZZOLATO BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
Except as contained in this notice, the name of Mark Pizzolato shall not be
|
||||
used in advertising or otherwise to promote the sale, use or other dealings
|
||||
in this Software without prior written authorization from Mark Pizzolato.
|
||||
|
||||
This include file may only be included by code in SCP libraries and should
|
||||
never be included directly in any simulator source code modules.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef SIM_SCP_PRIVATE_H_
|
||||
#define SIM_SCP_PRIVATE_H_ 0
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "sim_sock.h"
|
||||
|
||||
#ifdef USE_REGEX
|
||||
#undef USE_REGEX
|
||||
#endif
|
||||
#if defined(HAVE_PCRE_H)
|
||||
#include <pcre.h>
|
||||
#define USE_REGEX 1
|
||||
#endif
|
||||
|
||||
|
||||
/* Asynch/Threaded I/O support */
|
||||
|
||||
#if defined (SIM_ASYNCH_IO)
|
||||
#include <pthread.h>
|
||||
|
||||
#define SIM_ASYNCH_CLOCKS 1
|
||||
|
||||
extern pthread_mutex_t sim_asynch_lock;
|
||||
extern pthread_cond_t sim_asynch_wake;
|
||||
extern pthread_mutex_t sim_timer_lock;
|
||||
extern pthread_cond_t sim_timer_wake;
|
||||
extern t_bool sim_timer_event_canceled;
|
||||
extern int32 sim_tmxr_poll_count;
|
||||
extern pthread_cond_t sim_tmxr_poll_cond;
|
||||
extern pthread_mutex_t sim_tmxr_poll_lock;
|
||||
extern pthread_t sim_asynch_main_threadid;
|
||||
extern UNIT * volatile sim_asynch_queue;
|
||||
extern volatile t_bool sim_idle_wait;
|
||||
extern int32 sim_asynch_check;
|
||||
extern int32 sim_asynch_latency;
|
||||
extern int32 sim_asynch_inst_latency;
|
||||
|
||||
/* Thread local storage */
|
||||
#if defined(thread_local)
|
||||
#define AIO_TLS thread_local
|
||||
#elif (__STDC_VERSION__ >= 201112) && !(defined(__STDC_NO_THREADS__))
|
||||
#define AIO_TLS _Thread_local
|
||||
#elif defined(__GNUC__) && !defined(__APPLE__) && !defined(__hpux) && !defined(__OpenBSD__) && !defined(_AIX)
|
||||
#define AIO_TLS __thread
|
||||
#elif defined(_MSC_VER)
|
||||
#define AIO_TLS __declspec(thread)
|
||||
#else
|
||||
/* Other compiler environment, then don't worry about thread local storage. */
|
||||
/* It is primarily used only used in debugging messages */
|
||||
#define AIO_TLS
|
||||
#endif
|
||||
#define AIO_QUEUE_CHECK(que, lock) \
|
||||
do { \
|
||||
UNIT *_cptr; \
|
||||
if (lock) \
|
||||
pthread_mutex_lock (lock); \
|
||||
for (_cptr = que; \
|
||||
(_cptr != QUEUE_LIST_END); \
|
||||
_cptr = _cptr->next) \
|
||||
if (!_cptr->next) \
|
||||
SIM_SCP_ABORT ("Queue Corruption detected"); \
|
||||
if (lock) \
|
||||
pthread_mutex_unlock (lock); \
|
||||
} while (0)
|
||||
#define AIO_MAIN_THREAD (pthread_equal ( pthread_self(), sim_asynch_main_threadid ))
|
||||
#define AIO_LOCK \
|
||||
pthread_mutex_lock(&sim_asynch_lock)
|
||||
#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(__DECC_VER)
|
||||
#include <builtins>
|
||||
#if defined(__IA64)
|
||||
#define USE_AIO_INTRINSICS 1
|
||||
#endif
|
||||
#endif
|
||||
#if defined(_WIN32) || defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4) || defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8)
|
||||
#define USE_AIO_INTRINSICS 1
|
||||
#endif
|
||||
/* Provide a way to test both Intrinsic and Lock based queue manipulations */
|
||||
/* when both are available on a particular platform */
|
||||
#if defined(DONT_USE_AIO_INTRINSICS) && defined(USE_AIO_INTRINSICS)
|
||||
#undef USE_AIO_INTRINSICS
|
||||
#endif
|
||||
#ifdef USE_AIO_INTRINSICS
|
||||
/* This approach uses intrinsics to manage access to the link list head */
|
||||
/* sim_asynch_queue. This implementation is a completely lock free design */
|
||||
/* which avoids the potential ABA issues. */
|
||||
#define AIO_QUEUE_MODE "Lock free asynchronous event queue"
|
||||
#define AIO_INIT \
|
||||
do { \
|
||||
sim_asynch_main_threadid = pthread_self(); \
|
||||
/* Empty list/list end uses the point value (void *)1. \
|
||||
This allows NULL in an entry's a_next pointer to \
|
||||
indicate that the entry is not currently in any list */ \
|
||||
sim_asynch_queue = QUEUE_LIST_END; \
|
||||
} while (0)
|
||||
#define AIO_CLEANUP \
|
||||
do { \
|
||||
pthread_mutex_destroy(&sim_asynch_lock); \
|
||||
pthread_cond_destroy(&sim_asynch_wake); \
|
||||
pthread_mutex_destroy(&sim_timer_lock); \
|
||||
pthread_cond_destroy(&sim_timer_wake); \
|
||||
pthread_mutex_destroy(&sim_tmxr_poll_lock); \
|
||||
pthread_cond_destroy(&sim_tmxr_poll_cond); \
|
||||
} while (0)
|
||||
#ifdef _WIN32
|
||||
#elif defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4) || defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8)
|
||||
#define InterlockedCompareExchangePointer(Destination, Exchange, Comparand) __sync_val_compare_and_swap(Destination, Comparand, Exchange)
|
||||
#elif defined(__DECC_VER)
|
||||
#define InterlockedCompareExchangePointer(Destination, Exchange, Comparand) (void *)((int32)_InterlockedCompareExchange64(Destination, Exchange, Comparand))
|
||||
#else
|
||||
#error "Implementation of function InterlockedCompareExchangePointer() is needed to build with USE_AIO_INTRINSICS"
|
||||
#endif
|
||||
#define AIO_ILOCK AIO_LOCK
|
||||
#define AIO_IUNLOCK AIO_UNLOCK
|
||||
#define AIO_QUEUE_VAL (UNIT *)(InterlockedCompareExchangePointer((void * volatile *)&sim_asynch_queue, (void *)sim_asynch_queue, NULL))
|
||||
#define AIO_QUEUE_SET(newval, oldval) (UNIT *)(InterlockedCompareExchangePointer((void * volatile *)&sim_asynch_queue, (void *)newval, oldval))
|
||||
#define AIO_UPDATE_QUEUE sim_aio_update_queue ()
|
||||
#define AIO_ACTIVATE(caller, uptr, event_time) \
|
||||
if (!pthread_equal ( pthread_self(), sim_asynch_main_threadid )) { \
|
||||
sim_aio_activate ((ACTIVATE_API)caller, uptr, event_time); \
|
||||
return SCPE_OK; \
|
||||
} else (void)0
|
||||
#else /* !USE_AIO_INTRINSICS */
|
||||
/* This approach uses a pthread mutex to manage access to the link list */
|
||||
/* head sim_asynch_queue. It will always work, but may be slower than the */
|
||||
/* lock free approach when using USE_AIO_INTRINSICS */
|
||||
#define AIO_QUEUE_MODE "Lock based asynchronous event queue"
|
||||
#define AIO_INIT \
|
||||
do { \
|
||||
pthread_mutexattr_t attr; \
|
||||
\
|
||||
pthread_mutexattr_init (&attr); \
|
||||
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); \
|
||||
pthread_mutex_init (&sim_asynch_lock, &attr); \
|
||||
pthread_mutexattr_destroy (&attr); \
|
||||
sim_asynch_main_threadid = pthread_self(); \
|
||||
/* Empty list/list end uses the point value (void *)1. \
|
||||
This allows NULL in an entry's a_next pointer to \
|
||||
indicate that the entry is not currently in any list */ \
|
||||
sim_asynch_queue = QUEUE_LIST_END; \
|
||||
} while (0)
|
||||
#define AIO_CLEANUP \
|
||||
do { \
|
||||
pthread_mutex_destroy(&sim_asynch_lock); \
|
||||
pthread_cond_destroy(&sim_asynch_wake); \
|
||||
pthread_mutex_destroy(&sim_timer_lock); \
|
||||
pthread_cond_destroy(&sim_timer_wake); \
|
||||
pthread_mutex_destroy(&sim_tmxr_poll_lock); \
|
||||
pthread_cond_destroy(&sim_tmxr_poll_cond); \
|
||||
} while (0)
|
||||
#define AIO_ILOCK AIO_LOCK
|
||||
#define AIO_IUNLOCK AIO_UNLOCK
|
||||
#define AIO_QUEUE_VAL sim_asynch_queue
|
||||
#define AIO_QUEUE_SET(newval, oldval) ((sim_asynch_queue = newval),oldval)
|
||||
#define AIO_UPDATE_QUEUE sim_aio_update_queue ()
|
||||
#define AIO_ACTIVATE(caller, uptr, event_time) \
|
||||
if (!pthread_equal ( pthread_self(), sim_asynch_main_threadid )) { \
|
||||
sim_debug (SIM_DBG_AIO_QUEUE, sim_dflt_dev, "Queueing Asynch event for %s after %d instructions\n", sim_uname(uptr), event_time);\
|
||||
AIO_LOCK; \
|
||||
if (uptr->a_next) { /* already queued? */ \
|
||||
uptr->a_activate_call = sim_activate_abs; \
|
||||
} else { \
|
||||
uptr->a_next = sim_asynch_queue; \
|
||||
uptr->a_event_time = event_time; \
|
||||
uptr->a_activate_call = (ACTIVATE_API)&caller; \
|
||||
sim_asynch_queue = uptr; \
|
||||
} \
|
||||
if (sim_idle_wait) { \
|
||||
if (sim_deb) { /* only while debug do lock/unlock overhead */ \
|
||||
AIO_UNLOCK; \
|
||||
sim_debug (TIMER_DBG_IDLE, &sim_timer_dev, "waking due to event on %s after %d instructions\n", sim_uname(uptr), event_time);\
|
||||
AIO_LOCK; \
|
||||
} \
|
||||
pthread_cond_signal (&sim_asynch_wake); \
|
||||
} \
|
||||
AIO_UNLOCK; \
|
||||
sim_asynch_check = 0; \
|
||||
return SCPE_OK; \
|
||||
} else (void)0
|
||||
#endif /* USE_AIO_INTRINSICS */
|
||||
#define AIO_VALIDATE(uptr) \
|
||||
if (!pthread_equal ( pthread_self(), sim_asynch_main_threadid )) { \
|
||||
SIM_SCP_ABORT ("Improper thread context for operation detected");\
|
||||
} else (void)0
|
||||
#else /* !SIM_ASYNCH_IO */
|
||||
#define AIO_QUEUE_MODE "Asynchronous I/O is not available"
|
||||
#define AIO_UPDATE_QUEUE
|
||||
#define AIO_ACTIVATE(caller, uptr, event_time)
|
||||
#define AIO_VALIDATE(uptr)
|
||||
#define AIO_INIT
|
||||
#define AIO_MAIN_THREAD TRUE
|
||||
#define AIO_LOCK
|
||||
#define AIO_UNLOCK
|
||||
#define AIO_CLEANUP
|
||||
#define AIO_IS_ACTIVE(uptr) FALSE
|
||||
#define AIO_TLS
|
||||
#endif /* SIM_ASYNCH_IO */
|
||||
|
||||
/* Private SCP only structures */
|
||||
|
||||
/* Expect rule */
|
||||
|
||||
struct EXPTAB {
|
||||
uint8 *match; /* match string */
|
||||
uint32 size; /* match string size */
|
||||
char *match_pattern; /* match pattern for format */
|
||||
int32 cnt; /* proceed count */
|
||||
uint32 after; /* delay before halting */
|
||||
int32 switches; /* flags */
|
||||
#define EXP_TYP_PERSIST (SWMASK ('P')) /* rule persists after match, default is once a rule matches, it is removed */
|
||||
#define EXP_TYP_CLEARALL (SWMASK ('C')) /* clear all rules after matching this rule, default is to once a rule matches, it is removed */
|
||||
#define EXP_TYP_REGEX (SWMASK ('R')) /* rule pattern is a regular expression */
|
||||
#define EXP_TYP_REGEX_I (SWMASK ('I')) /* regular expression pattern matching should be case independent */
|
||||
#define EXP_TYP_TIME (SWMASK ('T')) /* halt delay is in microseconds instead of instructions */
|
||||
#if defined(USE_REGEX)
|
||||
pcre *regex; /* compiled regular expression */
|
||||
int re_nsub; /* regular expression sub expression count */
|
||||
#endif
|
||||
char *act; /* action string */
|
||||
};
|
||||
|
||||
/* Expect Context */
|
||||
|
||||
struct EXPECT {
|
||||
DEVICE *dptr; /* Device (for Debug) */
|
||||
uint32 dbit; /* Debugging Bit */
|
||||
EXPTAB *rules; /* match rules */
|
||||
int32 size; /* count of match rules */
|
||||
uint8 *buf; /* buffer of output data which has produced */
|
||||
uint32 buf_ins; /* buffer insertion point for the next output data */
|
||||
uint32 buf_size; /* buffer size */
|
||||
uint32 buf_data; /* count of data in buffer */
|
||||
};
|
||||
|
||||
/* Send Context */
|
||||
|
||||
struct SEND {
|
||||
uint32 delay; /* instruction delay between sent data */
|
||||
#define SEND_DEFAULT_DELAY 1000 /* default delay instruction count */
|
||||
DEVICE *dptr; /* Device (for Debug) */
|
||||
uint32 dbit; /* Debugging Bit */
|
||||
uint32 after; /* instruction delay before sending any data */
|
||||
double next_time; /* execution time when next data can be sent */
|
||||
uint8 *buffer; /* buffer */
|
||||
size_t bufsize; /* buffer size */
|
||||
int32 insoff; /* insert offset */
|
||||
int32 extoff; /* extra offset */
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@ -125,11 +125,10 @@
|
||||
|
||||
|
||||
#include "sim_defs.h"
|
||||
#include "sim_scp_private.h"
|
||||
#include "sim_serial.h"
|
||||
#include "sim_tmxr.h"
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
#define SER_DEV_NAME_MAX 256 /* maximum device name size */
|
||||
#define SER_DEV_DESC_MAX 256 /* maximum device description size */
|
||||
#define SER_DEV_CONFIG_MAX 64 /* maximum device config size */
|
||||
|
||||
17
sim_sock.h
17
sim_sock.h
@ -51,8 +51,25 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
#if defined (_WIN32) /* Windows */
|
||||
#pragma push_macro ("INT_PTR")
|
||||
#pragma push_macro ("PURE")
|
||||
#pragma push_macro ("BYTE")
|
||||
#pragma push_macro ("WORD")
|
||||
#undef INT_PTR /* avoid macro name collision */
|
||||
#undef PURE /* avoid macro name collision */
|
||||
#undef BYTE /* avoid macro name collision */
|
||||
#undef WORD /* avoid macro name collision */
|
||||
#include <winsock2.h>
|
||||
#include <winerror.h>
|
||||
#undef PACKED /* avoid macro name collision */
|
||||
#undef ERROR /* avoid macro name collision */
|
||||
#undef MEM_MAPPED /* avoid macro name collision */
|
||||
#undef INTERFACE /* avoid macro name collision */
|
||||
#include <process.h>
|
||||
#pragma pop_macro ("WORD")
|
||||
#pragma pop_macro ("BYTE")
|
||||
#pragma pop_macro ("PURE")
|
||||
#pragma pop_macro ("INT_PTR")
|
||||
|
||||
#elif !defined (__OS2__) || defined (__EMX__) /* VMS, Mac, Unix, OS/2 EMX */
|
||||
#include <sys/types.h> /* for fcntl, getpid */
|
||||
|
||||
@ -96,6 +96,8 @@
|
||||
#include "sim_defs.h"
|
||||
#include "sim_tape.h"
|
||||
|
||||
#include "sim_scp_private.h"
|
||||
|
||||
#ifndef MAX
|
||||
#define MAX(a,b) (((a) >= (b)) ? (a) : (b))
|
||||
#endif
|
||||
@ -4376,9 +4378,6 @@ for (t = classify_tests; t->testname != NULL; t++) {
|
||||
return SCPE_OK;
|
||||
}
|
||||
|
||||
|
||||
#include <setjmp.h>
|
||||
|
||||
t_stat sim_tape_test (DEVICE *dptr, const char *cptr)
|
||||
{
|
||||
int32 saved_switches = sim_switches;
|
||||
|
||||
@ -86,8 +86,8 @@
|
||||
#define NOT_MUX_USING_CODE /* sim_tmxr library provider or agnostic */
|
||||
|
||||
#include "sim_defs.h"
|
||||
#include <ctype.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "sim_scp_private.h"
|
||||
|
||||
#define SIM_INTERNAL_CLK (SIM_NTIMERS+(1<<30))
|
||||
#define SIM_INTERNAL_UNIT sim_internal_timer_unit
|
||||
|
||||
@ -41,9 +41,6 @@ extern "C" {
|
||||
#if defined(__struct_timespec_defined)
|
||||
#define _TIMESPEC_DEFINED
|
||||
#endif
|
||||
#if defined(SIM_ASYNCH_IO) || defined(USE_READER_THREAD)
|
||||
#include <pthread.h>
|
||||
#endif
|
||||
|
||||
#if defined (__APPLE__)
|
||||
#define HAVE_STRUCT_TIMESPEC /* OSX defined the structure but doesn't tell us */
|
||||
|
||||
@ -332,6 +332,7 @@
|
||||
#define NOT_MUX_USING_CODE /* sim_tmxr library define */
|
||||
|
||||
#include "sim_defs.h"
|
||||
#include "sim_scp_private.h"
|
||||
#include "sim_serial.h"
|
||||
#include "sim_sock.h"
|
||||
#include "sim_timer.h"
|
||||
@ -341,8 +342,6 @@
|
||||
|
||||
#define MIN(a,b) (((a) < (b)) ? (a) : (b))
|
||||
|
||||
#include <math.h>
|
||||
|
||||
/* Telnet protocol constants - negatives are for init'ing signed char data */
|
||||
|
||||
/* Commands */
|
||||
@ -5550,8 +5549,6 @@ return SCPE_OK;
|
||||
}
|
||||
|
||||
|
||||
#include <setjmp.h>
|
||||
|
||||
t_stat tmxr_sock_test (DEVICE *dptr, const char *cptr)
|
||||
{
|
||||
char cmd[CBUFSIZE], host[CBUFSIZE], port[CBUFSIZE];
|
||||
|
||||
@ -30,6 +30,8 @@
|
||||
#include "sim_video.h"
|
||||
#include "scp.h"
|
||||
|
||||
#include "sim_scp_private.h"
|
||||
|
||||
int vid_active = 0;
|
||||
int32 vid_cursor_x;
|
||||
int32 vid_cursor_y;
|
||||
@ -2607,7 +2609,6 @@ return _screenshot_stat;
|
||||
}
|
||||
|
||||
#include <SDL_audio.h>
|
||||
#include <math.h>
|
||||
|
||||
const int AMPLITUDE = 20000;
|
||||
const int SAMPLE_FREQUENCY = 11025;
|
||||
|
||||
@ -38,6 +38,7 @@
|
||||
#include "qemu/timer.h"
|
||||
#include "libslirp.h"
|
||||
#include "sim_defs.h"
|
||||
#include "sim_scp_private.h"
|
||||
#include "sim_slirp.h"
|
||||
#include "sim_sock.h"
|
||||
#include "libslirp.h"
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user