While testing some other changes in SheepShaver on Linux, I ran into this situation:
SheepShaver is hung not responding to input or redrawing.
The main thread is in
(gdb) bt
#0 __lll_lock_wait (futex=futex@entry=0xaaaab1b477e0 <wakeup_time_lock>, private=0) at lowlevellock.c:52
#1 0x0000ffff823a4b98 in __GI___pthread_mutex_lock (mutex=mutex@entry=0xaaaab1b477e0 <wakeup_time_lock>) at pthread_mutex_lock.c:80
#2 0x0000aaaab1a93390 in RmvTime(unsigned int) (tm=271287612) at ../timer.cpp:379
#3 0x0000aaaab1a90674 in EmulOp(M68kRegisters*, uint32, int) (r=r@entry=0xffffc2531490, pc=<optimized out>, selector=<optimized out>) at ../emul_op.cpp:220
#4 0x0000aaaab1ad9e38 in sheepshaver_cpu::execute_emul_op(unsigned int) (this=0xaaaae9fef360, emul_op=<optimized out>) at ../kpx_cpu/src/cpu/ppc/ppc-cpu.hpp:110
#5 0x0000000020a12068 in ()
#6 0x0000aaaab1accc30 in basic_dyngen::execute(unsigned char*) (this=0xaaaaea0efbb0, this=0xaaaaea0efbb0, entry_point=<optimized out>)
at ../kpx_cpu/src/cpu/jit/basic-dyngen.hpp:293
#7 powerpc_cpu::execute(unsigned int) (this=0xaaaae9fef360, entry=540092988) at ../kpx_cpu/src/cpu/ppc/ppc-cpu.cpp:594
#8 0x0000aaaab1accc30 in basic_dyngen::execute(unsigned char*) (this=0xaaaab1be8c30, this=0xaaaab1be8c30, entry_point=<optimized out>)
at ../kpx_cpu/src/cpu/jit/basic-dyngen.hpp:293
#9 powerpc_cpu::execute(unsigned int) (this=0xaaaab1ae83e0, entry=3929737344) at ../kpx_cpu/src/cpu/ppc/ppc-cpu.cpp:594
#10 0x0000aaaaea0efbb0 in ()
#3 0x0000aaaab1a90674 in EmulOp (r=r@entry=0xffffc2531490, pc=<optimized out>, selector=<optimized out>) at ../emul_op.cpp:220
220 r->d[0] = RmvTime(r->a[0]);
(gdb) list
215
216 case OP_INSTIME: // InsTime() replacement
217 r->d[0] = InsTime(r->a[0], r->d[1]);
218 break;
219 case OP_RMVTIME: // RmvTime() replacement
220 r->d[0] = RmvTime(r->a[0]);
221 break;
222 case OP_PRIMETIME: // PrimeTime() replacement
223 r->d[0] = PrimeTime(r->a[0], r->d[0]);
224 break;
#2 0x0000aaaab1a93390 in RmvTime (tm=271287612) at ../timer.cpp:379
379 pthread_mutex_lock(&wakeup_time_lock);
(gdb) list
374 semaphore_wait(wakeup_time_sem);
375 thread_suspend(timer_thread);
376 #endif
377 #if PRECISE_TIMING_POSIX
378 timer_thread_suspend();
379 pthread_mutex_lock(&wakeup_time_lock);
380 #endif
381 if (ReadMacInt16(tm + qType) & 0x8000) {
382
383 // Yes, make task inactive and remove it from the Time Manager queue
i.e. the main thread has run RmvTime which has just suspended the timer thread and is now waiting on wakeup_time_lock.
Meanwhile in the timer thread
(gdb) thread 16
[Switching to thread 16 (Thread 0xffff227fbe60 (LWP 15700))]
#0 0x0000ffff810f944c in __GI___sigsuspend (set=0xaaaab1b47848 <suspend_handler_mask>) at ../sysdeps/unix/sysv/linux/sigsuspend.c:26
26 ../sysdeps/unix/sysv/linux/sigsuspend.c: No such file or directory.
(gdb) bt
#0 0x0000ffff810f944c in __GI___sigsuspend (set=0xaaaab1b47848 <suspend_handler_mask>) at ../sysdeps/unix/sysv/linux/sigsuspend.c:26
#1 0x0000ffff824105b8 in <signal handler called> ()
#2 0x0000aaaab1a92f78 in timer_func(void*) (arg=<optimized out>) at ../timer.cpp:593
#3 0x0000ffff823a24fc in start_thread (arg=0xffffc2531a9f) at pthread_create.c:477
#4 0x0000ffff811960cc in thread_start () at ../sysdeps/unix/sysv/linux/aarch64/clone.S:78
(gdb) up
#1 <signal handler called>
(gdb) up
#2 0x0000aaaab1a92f78 in timer_func (arg=<optimized out>) at ../timer.cpp:593
593 wakeup_time = wakeup_time_max;
(gdb) list
588 timer_current_time(system_time);
589 if (timer_cmp_time(wakeup_time, system_time) < 0) {
590
591 // Timer expired, trigger interrupt
592 pthread_mutex_lock(&wakeup_time_lock);
593 wakeup_time = wakeup_time_max;
594 pthread_mutex_unlock(&wakeup_time_lock);
595 SetInterruptFlag(INTFLAG_TIMER);
596 TriggerInterrupt();
597 }
The timer thread is in the middle of the critical section on wakeup_time_lock but it has received the suspend from the main thread's timer_thread_suspend() and is now suspended so it is never going to release the lock.
While testing some other changes in SheepShaver on Linux, I ran into this situation:
SheepShaver is hung not responding to input or redrawing.
The main thread is in
i.e. the main thread has run
RmvTime
which has just suspended the timer thread and is now waiting onwakeup_time_lock
.Meanwhile in the timer thread
The timer thread is in the middle of the critical section on
wakeup_time_lock
but it has received the suspend from the main thread'stimer_thread_suspend()
and is now suspended so it is never going to release the lock.A deadlock.