GNU/Hurd's netdde can stop completely under load: TCP and ARP stop
responding while the machine and the serial console stay alive.  Both
bugs are in the DDE softirq layer.

1. __do_softirq() runs a bounded retry loop and returns while softirqs
   are still pending.  Linux wakes ksoftirqd there; DDE has no such
   helper, so the softirq thread blocks again on dde_softirq_sem and the
   pending work is never done.  This is reachable from net_rx_action()'s
   softnet_break, which re-raises NET_RX_SOFTIRQ with
   __raise_softirq_irqoff(), a macro that only sets the pending bit and
   does not post the semaphore.  With e1000 the interrupt stays masked, so
   no later interrupt arrives to wake the thread.

2. DDE runs each Linux "cpu" as CPU 0 in separate threads and
   local_irq_save() only disables interrupts on the current thread, so the
   one softirq pending word (irq_stat[0].__softirq_pending) is shared
   without real exclusion.  It is updated with a plain read-modify-write,
   so a raise can be lost between the softirq thread's read and its clear.

Patch 1 mirrors mainline's wakeup_softirqd(): if softirqs are still
pending after the retry budget, post dde_softirq_sem before returning.
Patch 2 makes the raise and the read-and-clear atomic
(__sync_fetch_and_or(), __sync_lock_test_and_set(..., 0)).

David Bidner (2):
  libdde_linux26: Wake the softirq thread when __do_softirq gives up
  libdde_linux26: Make the softirq pending word updates atomic

 .../contrib/include/linux/interrupt.h          |  7 ++++++-
 libdde_linux26/lib/src/arch/l4/softirq.c       | 18 ++++++++++++++----
 2 files changed, 20 insertions(+), 5 deletions(-)

-- 
2.47.3


Reply via email to