From 55eeddbac0c6ab43963ae71eefb7571a6b277285 Mon Sep 17 00:00:00 2001 From: Toni Wilen Date: Sun, 14 Jun 2026 10:55:34 +0300 Subject: [PATCH] Add queue for functions that must be called from main thread --- a2065.cpp | 56 +++++++++++++++++++++++------------------------ devices.cpp | 42 +++++++++++++++++++++++++++++++++++ include/devices.h | 2 ++ include/newcpu.h | 33 ++++++++++++++-------------- newcpu.cpp | 28 ++++++++++++++++++++---- 5 files changed, 113 insertions(+), 48 deletions(-) diff --git a/a2065.cpp b/a2065.cpp index a1280bee..13b51dc4 100644 --- a/a2065.cpp +++ b/a2065.cpp @@ -256,6 +256,7 @@ static void rethink_a2065(void) { if (!configured) return; + bool wasintr = (csr[0] & CSR0_INTR) != 0; csr[0] &= ~CSR0_INTR; uae_u16 mask = csr[0]; if (AM79C960) @@ -264,11 +265,13 @@ static void rethink_a2065(void) csr[0] |= CSR0_INTR; if ((csr[0] & (CSR0_INTR | CSR0_INEA)) == (CSR0_INTR | CSR0_INEA)) { safe_interrupt_set(IRQ_SOURCE_A2065, 0, false); - if (log_a2065 > 2) + if (log_a2065 > 1 && !wasintr) { write_log(_T("7990 +IRQ\n")); - } - if (log_a2065) { - write_log(_T("7990 -IRQ\n")); + } + } else if (wasintr) { + if (log_a2065 > 1) { + write_log(_T("7990 -IRQ\n")); + } } } @@ -556,6 +559,7 @@ static void gotfunc(void *devv, const uae_u8 *databuf, int len) receive_buffer_size[receive_buffer_write] = len; receive_buffer_write = nextwrite; uae_sem_post(&receive_sem); + device_add_main_thread_callback(receive_queue_drain); } static int getfunc (void *devv, uae_u8 *d, int *len) @@ -815,11 +819,11 @@ static void chip_wput (uaecptr addr, uae_u16 v) uae_u16 t; if (log_a2065 > 2) - write_log (_T("7990_CHIPWPUT: CSR%d=%04X PC=%08X\n"), rap, v & 0xffff, M68K_GETPC); + write_log(_T("7990_CHIPWPUT: CSR%d=%04X PC=%08X\n"), rap, v & 0xffff, M68K_GETPC); switch (rap) { - case 0: + case 0: csr[0] &= ~CSR0_INEA; csr[0] |= v & CSR0_INEA; // bit = 1 -> set, bit = 0 -> nop t = v & (CSR0_INIT | CSR0_STRT | CSR0_STOP | CSR0_TDMD); @@ -833,7 +837,7 @@ static void chip_wput (uaecptr addr, uae_u16 v) csr[0] = CSR0_STOP; if (log_a2065) - write_log (_T("7990: STOP. %04X -> %04X -> %04X\n"), oreg, v, csr[0]); + write_log(_T("7990: STOP. %04X -> %04X -> %04X\n"), oreg, v, csr[0]); csr[3] = 0; dbyteswap = 0; @@ -845,24 +849,24 @@ static void chip_wput (uaecptr addr, uae_u16 v) if (!(am_mode & MODE_DRX)) csr[0] |= CSR0_RXON; if ((csr[0] & CSR0_INIT) && !(oreg & CSR0_INIT)) { - chip_init (); + chip_init(); csr[0] |= CSR0_IDON; am_initialized = 1; if (log_a2065) - write_log (_T("7990: INIT+START. %04X -> %04X -> %04X\n"), oreg, v, csr[0]); + write_log(_T("7990: INIT+START. %04X -> %04X -> %04X\n"), oreg, v, csr[0]); } if (log_a2065) - write_log (_T("7990: START. %04X -> %04X -> %04X\n"), oreg, v, csr[0]); - + write_log(_T("7990: START. %04X -> %04X -> %04X\n"), oreg, v, csr[0]); + } else if ((csr[0] & CSR0_INIT) && !(oreg & CSR0_INIT) && (oreg & CSR0_STOP)) { - chip_init (); + chip_init(); csr[0] |= CSR0_IDON; csr[0] &= ~(CSR0_RXON | CSR0_TXON | CSR0_STOP); am_initialized = 1; csr[3] = 0; if (log_a2065) - write_log (_T("7990: INIT. %04X -> %04X -> %04X\n"), oreg, v, csr[0]); + write_log(_T("7990: INIT. %04X -> %04X -> %04X\n"), oreg, v, csr[0]); } if ((csr[0] & CSR0_STRT)) { @@ -880,40 +884,36 @@ static void chip_wput (uaecptr addr, uae_u16 v) devices_rethink_all(rethink_a2065); break; - case 1: + case 1: if (csr[0] & 4) { csr[1] = v; csr[1] &= ~1; } break; - case 2: + case 2: if (csr[0] & 4) { csr[2] = v; csr[2] &= 0x00ff; } break; - case 3: + case 3: + // interrupt masks if ((csr[0] & 4) || AM79C960) { csr[3] = v; - if (AM79C960) + if (AM79C960) { csr[3] &= 0x4000 | 0x1000 | 0x800 | 0x400 | 0x200 | 0x100 | 0x10 | 8; - else + } else { csr[3] &= 7; + } } dbyteswap = 0; - /* - * Some drivers set this but only work if no byteswapping - * is done. Weird.. - * dbyteswap = (csr[3] & CSR3_BSWP) ? 1 : 0; - */ + if (!AM79C960) { + dbyteswap = (csr[3] & CSR3_BSWP) ? 1 : 0; + } break; - // Am79C960 extra + // Am79C960 extra - // interrupt masks - case 4: - v &= ~(0x80 | 0x40); - break; // logical address filter case 8: am_ladrf &= 0x0000ffffffffffff; diff --git a/devices.cpp b/devices.cpp index 6f9a86e5..5c77b853 100644 --- a/devices.cpp +++ b/devices.cpp @@ -4,6 +4,7 @@ #include "devices.h" #include "options.h" +#include "uae.h" #include "threaddep/thread.h" #include "memory.h" #include "audio.h" @@ -101,6 +102,7 @@ static void execute_device_items(DEVICE_VOID *pp, int cnt) } } +static uae_sem_t thread_sema; static int device_configs_cnt; static DEVICE_VOID device_configs[MAX_DEVICE_ITEMS]; static int device_vsync_pre_cnt; @@ -118,6 +120,32 @@ static DEVICE_VOID device_leaves_early[MAX_DEVICE_ITEMS]; static int device_resets_cnt; static DEVICE_INT device_resets[MAX_DEVICE_ITEMS]; static bool device_reset_done[MAX_DEVICE_ITEMS]; +static int device_callbacks_cnt; +static DEVICE_VOID device_callbacks[MAX_DEVICE_ITEMS]; + +void device_call_main_thread_callbacks(void) +{ + uae_sem_wait(&thread_sema); + DEVICE_VOID device_callbacks_tmp[MAX_DEVICE_ITEMS]; + int device_callbacks_cnt_tmp = device_callbacks_cnt; + memcpy(device_callbacks_tmp, device_callbacks, sizeof(DEVICE_VOID) * device_callbacks_cnt); + device_callbacks_cnt = 0; + uae_sem_post(&thread_sema); + execute_device_items(device_callbacks_tmp, device_callbacks_cnt_tmp); +} + +// queues function for execution from main thread if called from another thread +void device_add_main_thread_callback(DEVICE_VOID p) +{ + if (is_mainthread()) { + p(); + } else { + uae_sem_wait(&thread_sema); + add_device_item(device_callbacks, &device_callbacks_cnt, p); + set_special(SPCFLAG_CALLBACK); + uae_sem_post(&thread_sema); + } +} static void reset_device_items(void) { @@ -263,6 +291,11 @@ void devices_reset(int hardreset) keymcu_reset(); keymcu2_reset(); keymcu3_reset(); + + uae_sem_wait(&thread_sema); + device_callbacks_cnt = 0; + uae_sem_post(&thread_sema); + uae_int_requested = 0; } @@ -400,10 +433,19 @@ void do_leave_program (void) SDL_Quit(); #endif machdep_free(); + + if (thread_sema) { + uae_sem_destroy(&thread_sema); + thread_sema = NULL; + } } void virtualdevice_init (void) { + if (!thread_sema) { + uae_sem_init(&thread_sema, 0, 1); + } + reset_device_items(); #ifdef CD32 diff --git a/include/devices.h b/include/devices.h index 75c76904..56820521 100644 --- a/include/devices.h +++ b/include/devices.h @@ -31,6 +31,8 @@ void device_add_check_config(DEVICE_VOID p); void device_add_reset(DEVICE_INT p); void device_add_reset_imm(DEVICE_INT p); void device_add_exit(DEVICE_VOID p, DEVICE_VOID p2); +void device_add_main_thread_callback(DEVICE_VOID p); +void device_call_main_thread_callbacks(void); #define IRQ_SOURCE_PCI 0 #define IRQ_SOURCE_SOUND 1 diff --git a/include/newcpu.h b/include/newcpu.h index db9405c5..9142c50e 100644 --- a/include/newcpu.h +++ b/include/newcpu.h @@ -352,24 +352,25 @@ extern bool m68k_interrupt_delay; extern void safe_interrupt_set(int, int, bool); -#define SPCFLAG_CPUINRESET 2 -#define SPCFLAG_CPU_SLOW 4 -#define SPCFLAG_INT 8 -#define SPCFLAG_BRK 16 -#define SPCFLAG_UAEINT 32 -#define SPCFLAG_TRACE 64 -#define SPCFLAG_DOTRACE 128 -#define SPCFLAG_DOINT 256 /* arg, JIT fails without this.. */ -#define SPCFLAG_BLTNASTY 512 -#define SPCFLAG_EXEC 1024 -#define SPCFLAG_ACTION_REPLAY 2048 -#define SPCFLAG_TRAP 4096 /* enforcer-hack */ -#define SPCFLAG_MODE_CHANGE 8192 +#define SPCFLAG_CPUINRESET 0x000002 +#define SPCFLAG_CPU_SLOW 0x000004 +#define SPCFLAG_INT 0x000008 +#define SPCFLAG_BRK 0x000010 +#define SPCFLAG_UAEINT 0x000020 +#define SPCFLAG_TRACE 0x000040 +#define SPCFLAG_DOTRACE 0x000080 +#define SPCFLAG_DOINT 0x000100 /* arg, JIT fails without this.. */ +#define SPCFLAG_BLTNASTY 0x000200 +#define SPCFLAG_EXEC 0x000400 +#define SPCFLAG_ACTION_REPLAY 0x000800 +#define SPCFLAG_TRAP 0x001000 /* enforcer-hack */ +#define SPCFLAG_MODE_CHANGE 0x002000 #ifdef JIT -#define SPCFLAG_END_COMPILE 16384 +#define SPCFLAG_END_COMPILE 0x004000 #endif -#define SPCFLAG_CHECK 32768 -#define SPCFLAG_MMURESTART 65536 +#define SPCFLAG_CHECK 0x008000 +#define SPCFLAG_MMURESTART 0x010000 +#define SPCFLAG_CALLBACK 0x020000 STATIC_INLINE void set_special_exter(uae_u32 x) { diff --git a/newcpu.cpp b/newcpu.cpp index 4c99d687..ea536cb1 100644 --- a/newcpu.cpp +++ b/newcpu.cpp @@ -4410,6 +4410,10 @@ static bool haltloop_do(int vsynctimeline, frame_time_t rpt_end, int lines) ppc_interrupt(intlev()); uae_ppc_execute_check(); #endif + if (regs.spcflags & SPCFLAG_CALLBACK) { + unset_special(SPCFLAG_CALLBACK); + device_call_main_thread_callbacks(); + } if (regs.spcflags & (SPCFLAG_BRK | SPCFLAG_MODE_CHANGE)) { if (regs.spcflags & SPCFLAG_BRK) { unset_special(SPCFLAG_BRK); @@ -4429,6 +4433,11 @@ static bool haltloop_do(int vsynctimeline, frame_time_t rpt_end, int lines) ppc_interrupt(intlev()); uae_ppc_execute_check(); #endif + if (regs.spcflags & SPCFLAG_CALLBACK) { + unset_special(SPCFLAG_CALLBACK); + device_call_main_thread_callbacks(); + } + if (event_wait) break; frame_time_t d = read_processor_time() - rpt_end; @@ -4697,6 +4706,11 @@ static int do_specialties (int cycles) if (spcflags & SPCFLAG_MODE_CHANGE) return 1; + if (spcflags & SPCFLAG_CALLBACK) { + unset_special(SPCFLAG_CALLBACK); + device_call_main_thread_callbacks(); + } + while (spcflags & SPCFLAG_CPUINRESET) { cpu_halt_clear(); x_do_cycles(4 * CYCLE_UNIT); @@ -5261,10 +5275,15 @@ static void init_cpu_thread(void) extern addrbank *thread_mem_banks[MEMORY_BANKS]; +static bool is_cpu_thread(void) +{ + return cpu_thread_tid == uae_thread_get_id(); +} + uae_u32 process_cpu_indirect_memory_read(uae_u32 addr, int size) { // Do direct access if call is from filesystem etc thread - if (cpu_thread_tid != uae_thread_get_id()) { + if (!is_cpu_thread()) { uae_u32 data = 0; addrbank *ab = thread_mem_banks[bankindex(addr)]; switch (size) @@ -5293,7 +5312,7 @@ uae_u32 process_cpu_indirect_memory_read(uae_u32 addr, int size) void process_cpu_indirect_memory_write(uae_u32 addr, uae_u32 data, int size) { - if (cpu_thread_tid != uae_thread_get_id()) { + if (!is_cpu_thread()) { addrbank *ab = thread_mem_banks[bankindex(addr)]; switch (size) { @@ -5456,7 +5475,7 @@ static void run_cpu_thread(void (*f)(void *)) static void custom_reset_cpu(bool hardreset, bool keyboardreset) { #ifdef WITH_THREADED_CPU - if (cpu_thread_tid != uae_thread_get_id()) { + if (!is_cpu_thread()) { custom_reset(hardreset, keyboardreset); return; } @@ -6459,7 +6478,6 @@ static void cpu_thread_run_2(void *v) struct regstruct *r = ®s; cpu_thread_tid = uae_thread_get_id(); - cpu_thread_active = 1; while (!exit) { TRY(prb) @@ -6653,6 +6671,8 @@ void m68k_run(void) currprefs.cpu_model < 68020 ? m68k_run_2_000 : m68k_run_2_020; run_func(); + + cpu_thread_tid = 0; } void m68k_go (int may_quit) -- 2.47.3