Race conditions

John Baldwin john at araratriver.co
Wed Aug 19 02:31:25 UTC 2015


On Tuesday, August 18, 2015 11:41:34 AM Leonardo Fogel wrote:
> Hi.
> The following code is an exerpt from the FreeBSD Architecture Handbook, chapter 11.1.1. Sample Driver Source. I've included labels i1, i2, i3.
> 
>    int
>    mypci_open(struct cdev *dev, int oflags, int devtype, struct thread *td)
>    {
>            struct mypci_softc *sc;
> 
>            /* Look up our softc. */
>    i1:     sc = dev->si_drv1;
>            device_printf(sc->my_dev, "Opened successfully.\n");
>            return (0);
>    }
> 
>    static int
>    mypci_attach(device_t dev)
>    {
>            struct mypci_softc *sc;
>    ...
>    i2:     sc->my_cdev = make_dev(&mypci_cdevsw, device_get_unit(dev),
>                UID_ROOT, GID_WHEEL, 0600, "mypci%u", device_get_unit(dev));
>    i3:     sc->my_cdev->si_drv1 = sc;
>            printf("Mypci device loaded.\n");
>            return (0);
>    }
> 
> 
> As I understand it, as soon as instruction at label i2 completes, there is a rare possibility that another thread opens the device file and executes the instruction at i1, before the instruction at i3 is executed. Is it correct? How could one fix it?

It is a race, yes.  I know there is a MAKEDEV_REF flag that can be passed to
make_dev_p() and make_dev_credf() that can hold a reference on the returned
cdev (so it can't be immediately deleted), but I don't know that that helps
close the race you reference.

I think I would probably prefer we add some sort of wrapper for make_dev
that accepts the si_drv1 value (and possibly other values) as an argument to
close this.  I'm cc'ing kib@ to see if he has any suggestions or better ideas.

-- 
John Baldwin



More information about the freebsd-drivers mailing list