STREAMS/UX for the HP 9000 Reference Manual
207
Debugging STREAMS/UX Modules and Drivers
Debugging Examples
We see that spput did not save r5. Callee registers are only saved if the
callee plans to overwrite the register. So we cannot get r5 from spput's stack
frame, but if spput did not save r5 that means it did not overwrite it;
therefore, the value for r5 in the save state area will be the same value that r5
had at csq_lateral+0x74. Look at 4*5 into the save state area:
<sp+0x14/X # sp + 4*5 == r5
7FFE6BEC: 11002A0
11002A0+0x18/X # q is r5 + 0x18
11002B8: 10EE674
10EE674+0x14/X # lp is q + 0x14
10EE688: 24C278
24C278+0xC/X # lp->last_mp = lp + 0xC
sp_sp+3C: 0 # lp->last_mp is NULL
0x24c278/4X # look at all of lp:
# state sp_rdq mp last_mp
sp_sp+30: 1 10EE600 0 0
Note that at the point the panic occurred, lp->mp was NULL, even though
we can be sure that at the time we checked lp->mp at instruction
spput+0x38, lp->mp was not NULL. How can this be true? As we saw in
the previous example, sp_timeout() modifies the lp structure, and it runs out
of timeout. In other words, spput() calls timeout() to schedule sp_timeout()
to run after a specified amount of time. At each system clock tick, the kernel
examines the list of procedures created by timeout() and schedules those
procedures whose time has expired to run. Because a clock tick is a high
level interrupt, it can occur at any time, and may suspend spput() if it is
running. A clock tick may have occurred between spput+0x38 and
spput+0x4C, allowing sp_timeout() to run and set lp->mp to NULL. In
order to prevent this, we need to protect access to the lp structure by using
splstr() around all critical sections of code in the sp driver which manipulate
lp. So spput() source code should be changed as shown below:
case M_DATA:
case M_PROTO:
case M_PCPROTO:
/*
* Use splstr() to protect access to q->q_ptr area from
* interrupts which may schedule sp_timeout().
*/
s = splstr();
lp = q->q_ptr;
if (!lp->mp)
lp->mp = mp;
else
lp->last_mp->b_next = mp;
/*
* Return to previous interrupt level