diff options
author | Kyösti Mälkki <kyosti.malkki@gmail.com> | 2012-07-07 17:15:51 +0300 |
---|---|---|
committer | Stefan Reinauer <stefan.reinauer@coreboot.org> | 2012-07-10 19:52:24 +0200 |
commit | a5650a4b4ac85722d772083761ffea32557774b4 (patch) | |
tree | 188f35747cf3f64d157bf7ef99e233d8dc6c27a2 /src/devices/device.c | |
parent | da09be6328505ac4473aff48b8ef27b9986bfa22 (diff) |
Use dev_lock for alloc_find_dev()
If threads called alloc_find_dev() with same device_path
simultaneously, two device nodes could be allocated.
This bug is not triggered by current code.
Change-Id: Ifc87021c8d6f422901c5de5dd17392e3e2309afa
Signed-off-by: Kyösti Mälkki <kyosti.malkki@gmail.com>
Reviewed-on: http://review.coreboot.org/1188
Tested-by: build bot (Jenkins)
Reviewed-by: Ronald G. Minnich <rminnich@gmail.com>
Reviewed-by: Sven Schnelle <svens@stackframe.org>
Diffstat (limited to 'src/devices/device.c')
-rw-r--r-- | src/devices/device.c | 30 |
1 files changed, 27 insertions, 3 deletions
diff --git a/src/devices/device.c b/src/devices/device.c index ebac1a073e..fafa59924e 100644 --- a/src/devices/device.c +++ b/src/devices/device.c @@ -66,12 +66,10 @@ DECLARE_SPIN_LOCK(dev_lock) * * @see device_path */ -device_t alloc_dev(struct bus *parent, struct device_path *path) +static device_t __alloc_dev(struct bus *parent, struct device_path *path) { device_t dev, child; - spin_lock(&dev_lock); - /* Find the last child of our parent. */ for (child = parent->children; child && child->sibling; /* */ ) child = child->sibling; @@ -99,11 +97,37 @@ device_t alloc_dev(struct bus *parent, struct device_path *path) last_dev->next = dev; last_dev = dev; + return dev; +} + +device_t alloc_dev(struct bus *parent, struct device_path *path) +{ + device_t dev; + spin_lock(&dev_lock); + dev = __alloc_dev(parent, path); spin_unlock(&dev_lock); return dev; } /** + * See if a device structure already exists and if not allocate it. + * + * @param parent The bus to find the device on. + * @param path The relative path from the bus to the appropriate device. + * @return Pointer to a device structure for the device on bus at path. + */ +device_t alloc_find_dev(struct bus *parent, struct device_path *path) +{ + device_t child; + spin_lock(&dev_lock); + child = find_dev_path(parent, path); + if (!child) + child = __alloc_dev(parent, path); + spin_unlock(&dev_lock); + return child; +} + +/** * Round a number up to an alignment. * * @param val The starting value. |