* shutdown the pipe */
| 1619 | * shutdown the pipe |
| 1620 | */ |
| 1621 | static void |
| 1622 | pipeclose(struct pipe *cpipe) |
| 1623 | { |
| 1624 | struct pipepair *pp; |
| 1625 | struct pipe *ppipe; |
| 1626 | |
| 1627 | KASSERT(cpipe != NULL, ("pipeclose: cpipe == NULL")); |
| 1628 | |
| 1629 | PIPE_LOCK(cpipe); |
| 1630 | pipelock(cpipe, 0); |
| 1631 | pp = cpipe->pipe_pair; |
| 1632 | |
| 1633 | /* |
| 1634 | * If the other side is blocked, wake it up saying that |
| 1635 | * we want to close it down. |
| 1636 | */ |
| 1637 | cpipe->pipe_state |= PIPE_EOF; |
| 1638 | while (cpipe->pipe_busy) { |
| 1639 | wakeup(cpipe); |
| 1640 | cpipe->pipe_state |= PIPE_WANT; |
| 1641 | pipeunlock(cpipe); |
| 1642 | msleep(cpipe, PIPE_MTX(cpipe), PRIBIO, "pipecl", 0); |
| 1643 | pipelock(cpipe, 0); |
| 1644 | } |
| 1645 | |
| 1646 | pipeselwakeup(cpipe); |
| 1647 | |
| 1648 | /* |
| 1649 | * Disconnect from peer, if any. |
| 1650 | */ |
| 1651 | ppipe = cpipe->pipe_peer; |
| 1652 | if (ppipe->pipe_present == PIPE_ACTIVE) { |
| 1653 | ppipe->pipe_state |= PIPE_EOF; |
| 1654 | wakeup(ppipe); |
| 1655 | pipeselwakeup(ppipe); |
| 1656 | } |
| 1657 | |
| 1658 | /* |
| 1659 | * Mark this endpoint as free. Release kmem resources. We |
| 1660 | * don't mark this endpoint as unused until we've finished |
| 1661 | * doing that, or the pipe might disappear out from under |
| 1662 | * us. |
| 1663 | */ |
| 1664 | PIPE_UNLOCK(cpipe); |
| 1665 | pipe_free_kmem(cpipe); |
| 1666 | PIPE_LOCK(cpipe); |
| 1667 | cpipe->pipe_present = PIPE_CLOSING; |
| 1668 | pipeunlock(cpipe); |
| 1669 | |
| 1670 | /* |
| 1671 | * knlist_clear() may sleep dropping the PIPE_MTX. Set the |
| 1672 | * PIPE_FINALIZED, that allows other end to free the |
| 1673 | * pipe_pair, only after the knotes are completely dismantled. |
| 1674 | */ |
| 1675 | knlist_clear(&cpipe->pipe_sel.si_note, 1); |
| 1676 | cpipe->pipe_present = PIPE_FINALIZED; |
| 1677 | seldrain(&cpipe->pipe_sel); |
| 1678 | knlist_destroy(&cpipe->pipe_sel.si_note); |
no test coverage detected