]> git.unchartedbackwaters.co.uk Git - francis/winuae.git/commitdiff
Add queue for functions that must be called from main thread
authorToni Wilen <twilen@winuae.net>
Sun, 14 Jun 2026 07:55:34 +0000 (10:55 +0300)
committerToni Wilen <twilen@winuae.net>
Sun, 14 Jun 2026 07:55:34 +0000 (10:55 +0300)
a2065.cpp
devices.cpp
include/devices.h
include/newcpu.h
newcpu.cpp

index a1280beee09f8a18e10da509e91a350c6958c51b..13b51dc40ecdebec15c2edd98c06a06fbb26adeb 100644 (file)
--- 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;
index 6f9a86e581a9da5363f9d04f1019b090e783510f..5c77b853853431f39b77308286d5e5226b5765a5 100644 (file)
@@ -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
index 75c7690447ec13a3f2b746e464bfd4574704c736..568205216f8be3dde9c4bb16a343a9fe9c83ec7f 100644 (file)
@@ -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
index db9405c5784304949d468ded28cf2b40ae95b8a1..9142c50e1adcd7dc7eb182f88bd05da36bde3096 100644 (file)
@@ -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)
 {
index 4c99d6872e8e13fa2f0789fbece243e8291b454e..ea536cb186949a0e7d90d7f9db211927df5f979b 100644 (file)
@@ -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 = &regs;
 
        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)