I'm counting my threads, one, two, three, four, five... [1]

From: Poul-Henning Kamp (phk_at_phk.freebsd.dk)
Date: 09/24/04

  • Next message: Eivind Eklund: "Re: AoE for 4.x"
    To: arch@freebsd.org
    Date: Fri, 24 Sep 2004 11:01:05 +0200
    
    

    I've completed my sweep of the kernel and I belive that we now have a
    reliable count of the number of threads currently inside any particular
    cdev and consequently, with a bit of adding up, also for each cdevsw.

    There are two soft spots marked with XXX (devfs_rule and vm_mmap)
    and one big hack, snp(4).

    The next step is to add a new method to the cdevsw which purges threads
    from the driver. The best name I can come up with is d_evict(). The
    drivers should make this function wakeup(9) on anything a thread could
    be sleeping on for the relevant cdev and the tread on waking up should
    examine whatever bits it can, realize the hw/driver/whatever is gone
    and exit the driver with ENXIO error return.

    If this cdevsw method is present, destroy_dev() will use it and will
    sleep until all threads have cleared out.

    So for a typical driver things will look like this:

    foo_evict(struct cdev *dev)
    {
            struct foo_sc *sc;

            /* XXX: NB: no locks, only wakeups */
            sc = dev->si_drv1;
            wakeup(sc->bing);
            wakeup(sc->bongle);
            wakeup(sc->bang);
    }

    foo_detach(dev)
    {
            ...

            sc->flags |= GONE;
            destroy_dev(sc->cdev);
            /* XXX: we now know there are no threads involved with this cdev */
            ...
    }

    destroy_dev() will work more or less this way:

            ...
            dev_lock();
            csw = cdev->si_devsw;
            cdev->si_devsw = NULL
            while (csw->d_evict != NULL && cdev->si_threacount > 0) {
                    (csw->d_evict)(cdev);
                    msleep(&dev_lock, ..., hz/10);
            }
            dev_unlock();
            ...

    I will also add a convenience function called destroy_cdevsw() which
    will call destroy_dev() on all cdevs using the cdevsw in question.

    I belive this gives us the handle we need to unload drivers and remove
    hardware without panicing in the lower layers of the kernel. The
    higher layers may still have a thing or two to learn in this respect.

    Poul-Henning

    [1] It used to be possible to legally download the D:A:D tune which
    inspired the subject, but I can't find the link anymore, sorry :-(

    -- 
    Poul-Henning Kamp       | UNIX since Zilog Zeus 3.20
    phk@FreeBSD.ORG         | TCP/IP since RFC 956
    FreeBSD committer       | BSD since 4.3-tahoe    
    Never attribute to malice what can adequately be explained by incompetence.
    _______________________________________________
    freebsd-arch@freebsd.org mailing list
    http://lists.freebsd.org/mailman/listinfo/freebsd-arch
    To unsubscribe, send any mail to "freebsd-arch-unsubscribe@freebsd.org"
    

  • Next message: Eivind Eklund: "Re: AoE for 4.x"

    Relevant Pages

    • Re: kldunload DIAGNOSTIC idea...
      ... All methods in cdevsw, ... >> needs to refcount. ... your close by destroying the cdev. ... already inside the driver and because there is no known relationship ...
      (freebsd-arch)
    • Re: kldunload DIAGNOSTIC idea...
      ... All methods in cdevsw, ... >> needs to refcount. ... your close by destroying the cdev. ... already inside the driver and because there is no known relationship ...
      (freebsd-arch)
    • Re: [BUG] cdev_put() race condition
      ... Laurent found a race condition in the uvc driver that we traced ... The USB device is removed, ... cdev is released when the kref of the cdev's kobject goes to 0. ...
      (Linux-Kernel)
    • Re: [BUG] cdev_put() race condition
      ... Laurent found a race condition in the uvc driver that we traced ... cdev is released when the kref of the cdev's kobject goes to 0. ... this isn't a "real" struct kobject in play here, ...
      (Linux-Kernel)
    • Re: [BUG] cdev_put() race condition
      ... Laurent found a race condition in the uvc driver that we traced ... cdev is released when the kref of the cdev's kobject goes to 0. ... this isn't a "real" struct kobject in play here, ...
      (Linux-Kernel)