mutex subsystem, ANNOUNCE
cover mutex subsystem, ANNOUNCE
this is the latest version of the mutex subsystem patch-queue. It consists of the following patches:
xfs-mutex-namespace-collision-fix.patch
add-atomic-xchg.patch
add-atomic-call-func-i386.patch
add-atomic-call-func-x86_64.patch
add-atomic-call-wrappers-rest.patch
mutex-core.patch
mutex-debug.patch
mutex-debug-more.patch
the patches are against Linus' latest tree, and were tested on i386, x86_64 and ia64. [the tests were also done in DEBUG_MUTEX_FULL mode, to make sure the code works fine. MUTEX_FULL support is not included in this patchqueue].
The patches can also be downloaded from:
http://redhat.com/~mingo/generic-mutex-subsystem/
Changes since the previous version:
- dropped the semaphore-renaming and migration-helper patches. The patches now contain only the pure mutex subsystem, nothing more.
- removed the fastpath dependency on __HAVE_ARCH_CMPXCHG: now every architecture is able to use the generic mutex_lock/mutex_unlock lockless fastpath. The quality of the fastpath is still as good as in the previous version.
- added ARCH_IMPLEMENTS_MUTEX_FASTPATH for architectures that want to hand-code their own fastpath. The mutex_lock_slowpath, mutex_unlock_slowpath and mutex_lock_interruptible_slowpath global functions can be used by such architectures in this case, and they should implement the mutex_lock(), mutex_unlock() and mutex_lock_interruptible() functions themselves. I have tested this mechanism on x86. (but x86 wants to use the generic functions otherwise, so those changes are not included in this patchqueue.)
- fixed the x86_64 register-clobber bug noticed by Zwane Mwaikambo
- XFS namespace collision fixes from Jes Sorensen
- lots of cleanups to "hide" the debugging code, it should now be much less intrusive visually - kernel/mutex.c is now both smaller and easier to read. There's no reduction in debugging functionality.
- cleaned up the debugging code
- unified all the externally visible debugging functions around the mutex_debug_ prefix.
- added the proper atomic ops to every architecture - so in theory mutexes should now work on every architectures. i386, x86_64 and ia64 was tested.
- created mutex-debug.h to hide some of the debugging details. Moved the mm.h and sched.h debug-function declarations into this file.
- documentation updates
- eliminated the ->file, ->line debugging variant - __FUNCTION__ is good enough and resulted in nicer code.
- properly check for held locks in kfree() too, if DEBUG.
- check for held-lock reinitialization via mutex_init(), if DEBUG.
- more micro-optimizations: eliminated an extra spinlock drop/reacquire in the slowpath.
- dropped waiter->woken, profiles showed that it triggered very rarely.
- dropped the timeout/timer bits - nothing is using them right now, we can add them back later.
- new mutex_trylock() optimization on architectures that support cmpxchg.
- marked ->name as const
- fixed typo: CONFIG_DEBUG_MUTEXESS -> CONFIG_DEBUG_MUTEXES
- mb() -> smp_mb() in mutex_is_locked()
- mutex_trylock doesnt need __sched
comments, fixes, bugreports are welcome,
Ingo
On Wed, 2005-12-21 at 16:54 +0100, Ingo Molnar wrote:
as an experiment I looked at how hard it is to turn some of the current using-semaphore-as-mutex into using this new primitive.
Below are a few dozen such conversions; they are all
1) manually inspected for properties 2 and 3
2) cases where the lock is static to the .c file
3) all up()'s are done in the same function as the down, eg the most basic simple usage model
or in short: these are really simple obvious cases only.
drivers/cpufreq/cpufreq.c +10 -9
@@ -26,6 +26,7 @@#include <linux/slab.h> #include <linux/cpu.h> #include <linux/completion.h> +#include <linux/mutex.h> #define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_CORE, "cpufreq-core", msg)
@@ -56,7 +57,7 @@ static DECLARE_RWSEM (cpufreq_notifier_static LIST_HEAD (cpufreq_governor_list); -static DECLARE_MUTEX (cpufreq_governor_sem); +static DEFINE_MUTEX (cpufreq_governor_mutex);struct cpufreq_policy *cpufreq_cpu_get (unsigned int cpu) {
@@ -298,18 +299,18 @@ static int cpufreq_parse_governor (charreturn -EINVAL ; }else {struct cpufreq_governor *t; -down (&cpufreq_governor_sem); +mutex_lock (&cpufreq_governor_mutex);if (!cpufreq_driver || !cpufreq_driver->target) goto out;list_for_each_entry (t, &cpufreq_governor_list, governor_list) {if (!strnicmp (str_governor,t->name,CPUFREQ_NAME_LEN )) { *governor = t; -up (&cpufreq_governor_sem); +mutex_unlock (&cpufreq_governor_mutex);return 0 ; } } out: -up (&cpufreq_governor_sem); +mutex_unlock (&cpufreq_governor_mutex); }return -EINVAL ; }
@@ -1194,17 +1195,17 @@ int cpufreq_register_governor(struct cpuif (!governor)return -EINVAL ; -down (&cpufreq_governor_sem); +mutex_lock (&cpufreq_governor_mutex);list_for_each_entry (t, &cpufreq_governor_list, governor_list) {if (!strnicmp (governor->name,t->name,CPUFREQ_NAME_LEN )) { -up (&cpufreq_governor_sem); +mutex_unlock (&cpufreq_governor_mutex);return -EBUSY ; } }list_add (&governor->governor_list, &cpufreq_governor_list); -up (&cpufreq_governor_sem); +mutex_unlock (&cpufreq_governor_mutex);return 0 ; }
@@ -1216,9 +1217,9 @@ void cpufreq_unregister_governor(structif (!governor)return ; -down (&cpufreq_governor_sem); +mutex_lock (&cpufreq_governor_mutex);list_del (&governor->governor_list); -up (&cpufreq_governor_sem); +mutex_unlock (&cpufreq_governor_mutex);return ; }EXPORT_SYMBOL_GPL (cpufreq_unregister_governor);
drivers/cpufreq/cpufreq_conservative.c +26 -26
169 lines not on this page · raw message
drivers/cpufreq/cpufreq_ondemand.c +21 -20
137 lines not on this page · raw message
drivers/cpufreq/cpufreq_userspace.c +13 -12
@@ -21,6 +21,7 @@#include <linux/types.h> #include <linux/fs.h> #include <linux/sysfs.h> +#include <linux/mutex.h> #include <asm/uaccess.h>
@@ -35,7 +36,7 @@ static unsigned int cpu_set_freq[NR_CPUSstatic unsigned int cpu_is_managed[NR_CPUS ];static struct cpufreq_policy current_policy[NR_CPUS ]; -static DECLARE_MUTEX (userspace_sem); +static DECLARE_MUTEX (userspace_mutex); #define dprintk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_GOVERNOR, "userspace", msg)
@@ -70,7 +71,7 @@ static int cpufreq_set(unsigned int freqdprintk ("cpufreq_set for cpu %u, freq %u kHz\n" , cpu, freq); -down (&userspace_sem); +mutex_lock (&userspace_mutex);if (!cpu_is_managed[cpu]) goto err;
@@ -83,16 +84,16 @@ static int cpufreq_set(unsigned int freq/* * We're safe from concurrent calls to ->target() here -* as we hold the userspace_sem lock. If we were calling +* as we hold the userspace_mutex lock. If we were calling * cpufreq_driver_target, a deadlock situation might occur: -* A: cpufreq_set (lock userspace_sem) -> cpufreq_driver_target(lock policy->lock) -* B: cpufreq_set_policy(lock policy->lock) -> __cpufreq_governor -> cpufreq_governor_userspace (lock userspace_sem) +* A: cpufreq_set (lock userspace_mutex) -> cpufreq_driver_target(lock policy->lock) +* B: cpufreq_set_policy(lock policy->lock) -> __cpufreq_governor -> cpufreq_governor_userspace (lock userspace_mutex) */ ret =__cpufreq_driver_target (¤t_policy[cpu], freq,CPUFREQ_RELATION_L ); err: -up (&userspace_sem); +mutex_unlock (&userspace_mutex);return ret; }
@@ -134,7 +135,7 @@ static int cpufreq_governor_userspace(stif (!cpu_online (cpu))return -EINVAL ;BUG_ON (!policy->cur); -down (&userspace_sem); +mutex_lock (&userspace_mutex); cpu_is_managed[cpu] =1 ; cpu_min_freq[cpu] = policy->min; cpu_max_freq[cpu] = policy->max;
@@ -143,20 +144,20 @@ static int cpufreq_governor_userspace(stsysfs_create_file (&policy->kobj, &freq_attr_scaling_setspeed.attr);memcpy (¤t_policy[cpu], policy,sizeof (struct cpufreq_policy ));dprintk ("managing cpu %u started (%u - %u kHz, currently %u kHz)\n" , cpu, cpu_min_freq[cpu], cpu_max_freq[cpu], cpu_cur_freq[cpu]); -up (&userspace_sem); +mutex_unlock (&userspace_mutex);break ;case CPUFREQ_GOV_STOP : -down (&userspace_sem); +mutex_lock (&userspace_mutex); cpu_is_managed[cpu] =0 ; cpu_min_freq[cpu] =0 ; cpu_max_freq[cpu] =0 ; cpu_set_freq[cpu] =0 ;sysfs_remove_file (&policy->kobj, &freq_attr_scaling_setspeed.attr);dprintk ("managing cpu %u stopped\n" , cpu); -up (&userspace_sem); +mutex_unlock (&userspace_mutex);break ;case CPUFREQ_GOV_LIMITS : -down (&userspace_sem); +mutex_lock (&userspace_mutex); cpu_min_freq[cpu] = policy->min; cpu_max_freq[cpu] = policy->max;dprintk ("limit event for cpu %u: %u - %u kHz, currently %u kHz, last set to %u kHz\n" , cpu, cpu_min_freq[cpu], cpu_max_freq[cpu], cpu_cur_freq[cpu], cpu_set_freq[cpu]);
@@ -171,7 +172,7 @@ static int cpufreq_governor_userspace(st CPUFREQ_RELATION_L); }memcpy (¤t_policy[cpu], policy,sizeof (struct cpufreq_policy )); -up (&userspace_sem); +mutex_unlock (&userspace_mutex);break ; }return 0 ;
drivers/i2c/busses/i2c-ali1535.c +4 -3
@@ -62,6 +62,7 @@#include <linux/ioport.h> #include <linux/i2c.h> #include <linux/init.h> +#include <linux/mutex.h> #include <asm/io.h> #include <asm/semaphore.h>
@@ -136,7 +137,7 @@static struct pci_driver ali1535_driver;static unsigned short ali1535_smba; -static DECLARE_MUTEX (i2c_ali1535_sem); +static DEFINE_MUTEX (i2c_ali1535_mutex);/* Detect whether a ALI1535 can be found, and initialize it, where necessary. Note the differences between kernels with the old PCI BIOS interface and
@@ -345,7 +346,7 @@ static s32 ali1535_access(struct i2c_adaint timeout;s32 result =0 ; -down (&i2c_ali1535_sem); +mutex_lock (&i2c_ali1535_mutex);/* make sure SMBus is idle */ temp =inb_p (SMBHSTSTS ); for (timeout = 0;
@@ -460,7 +461,7 @@ static s32 ali1535_access(struct i2c_adabreak ; } EXIT: -up (&i2c_ali1535_sem); +mutex_unlock (&i2c_ali1535_mutex);return result; }
drivers/i2c/chips/ds1374.c +6 -5
@@ -26,6 +26,7 @@#include <linux/i2c.h> #include <linux/rtc.h> #include <linux/bcd.h> +#include <linux/mutex.h> #define DS1374_REG_TOD0 0x00#define DS1374_REG_TOD1 0x01
@@ -41,7 +42,7 @@#define DS1374_DRV_NAME "ds1374" -static DECLARE_MUTEX (ds1374_mutex); +static DEFINE_MUTEX (ds1374_mutex);static struct i2c_driver ds1374_driver;static struct i2c_client *save_client;
@@ -114,7 +115,7 @@ ulong ds1374_get_rtc_time(void)ulong t1, t2;int limit =10 ;/* arbitrary retry limit */ -down (&ds1374_mutex); +mutex_lock (&ds1374_mutex);/* * Since the reads are being performed one byte at a time using
@@ -127,7 +128,7 @@ ulong ds1374_get_rtc_time(void) t2 =ds1374_read_rtc (); }while (t1 != t2 && limit--); -up (&ds1374_mutex); +mutex_unlock (&ds1374_mutex);if (t1 != t2) { dev_warn(&save_client->dev,
@@ -145,7 +146,7 @@ static void ds1374_set_tlet(ulong arg) t1 = *(ulong *) arg; -down (&ds1374_mutex); +mutex_lock (&ds1374_mutex);/* * Since the writes are being performed one byte at a time using
@@ -158,7 +159,7 @@ static void ds1374_set_tlet(ulong arg) t2 =ds1374_read_rtc (); }while (t1 != t2 && limit--); -up (&ds1374_mutex); +mutex_unlock (&ds1374_mutex);if (t1 != t2) dev_warn(&save_client->dev,
drivers/i2c/chips/m41t00.c +6 -5
@@ -24,13 +24,14 @@#include <linux/i2c.h> #include <linux/rtc.h> #include <linux/bcd.h> +#include <linux/mutex.h> #include <asm/time.h> #include <asm/rtc.h> #define M41T00_DRV_NAME "m41t00" -static DECLARE_MUTEX (m41t00_mutex); +static DEFINE_MUTEX (m41t00_mutex);static struct i2c_driver m41t00_driver;static struct i2c_client *save_client;
@@ -54,7 +55,7 @@ m41t00_get_rtc_time(void) sec = min = hour = day = mon = year =0 ; sec1 = min1 = hour1 = day1 = mon1 = year1 =0 ; -down (&m41t00_mutex); +mutex_lock (&m41t00_mutex); do { if (((sec = i2c_smbus_read_byte_data(save_client, 0)) >= 0) && ((min = i2c_smbus_read_byte_data(save_client, 1))
@@ -80,7 +81,7 @@ m41t00_get_rtc_time(void) mon1 = mon; year1 = year; }while (--limit >0 ); -up (&m41t00_mutex); +mutex_unlock (&m41t00_mutex);if (limit ==0 ) { dev_warn(&save_client->dev,
@@ -125,7 +126,7 @@ m41t00_set_tlet(ulong arg)BIN_TO_BCD (tm.tm_mday);BIN_TO_BCD (tm.tm_year); -down (&m41t00_mutex); +mutex_lock (&m41t00_mutex);if ((i2c_smbus_write_byte_data (save_client,0 , tm.tm_sec &0x7f ) <0 ) || (i2c_smbus_write_byte_data (save_client,1 , tm.tm_min &0x7f ) < 0)
@@ -140,7 +141,7 @@ m41t00_set_tlet(ulong arg)dev_warn (&save_client->dev,"m41t00: can't write to rtc chip\n" ); -up (&m41t00_mutex); +mutex_unlock (&m41t00_mutex);return ; }
drivers/i2c/i2c-core.c +12 -11
@@ -31,12 +31,13 @@#include <linux/idr.h> #include <linux/seq_file.h> #include <linux/platform_device.h> +#include <linux/mutex.h> #include <asm/uaccess.h> static LIST_HEAD (adapters);static LIST_HEAD (drivers); -static DECLARE_MUTEX (core_lists); +static DEFINE_MUTEX (core_lists);static DEFINE_IDR (i2c_adapter_idr);/* match always succeeds, as we want the probe() to tell if we really accept this match */
@@ -153,7 +154,7 @@ int i2c_add_adapter(struct i2c_adapter *struct list_head *item;struct i2c_driver *driver; -down (&core_lists); +mutex_lock (&core_lists);if (idr_pre_get (&i2c_adapter_idr,GFP_KERNEL ) ==0 ) { res = -ENOMEM ;
@@ -203,7 +204,7 @@ int i2c_add_adapter(struct i2c_adapter * } out_unlock: -up (&core_lists); +mutex_unlock (&core_lists);return res; }
@@ -216,7 +217,7 @@ int i2c_del_adapter(struct i2c_adapter *struct i2c_client *client;int res =0 ; -down (&core_lists); +mutex_lock (&core_lists);/* First make sure that this adapter was ever added */ list_for_each_entry (adap_from_list, &adapters, list) {
@@ -275,7 +276,7 @@ int i2c_del_adapter(struct i2c_adapter *dev_dbg (&adap->dev,"adapter [%s] unregistered\n" , adap->name); out_unlock: -up (&core_lists); +mutex_unlock (&core_lists);return res; }
@@ -292,7 +293,7 @@ int i2c_add_driver(struct i2c_driver *drstruct i2c_adapter *adapter;int res =0 ; -down (&core_lists); +mutex_lock (&core_lists);/* add the driver to the list of i2c drivers in the driver core */ driver->driver.owner = driver->owner;
@@ -317,7 +318,7 @@ int i2c_add_driver(struct i2c_driver *dr } out_unlock: -up (&core_lists); +mutex_unlock (&core_lists);return res; }
@@ -329,7 +330,7 @@ int i2c_del_driver(struct i2c_driver *drint res =0 ; -down (&core_lists); +mutex_lock (&core_lists);/* Have a look at each adapter, if clients of this driver are still * attached. If so, detach them to be able to kill the driver
@@ -371,7 +372,7 @@ int i2c_del_driver(struct i2c_driver *drpr_debug ("i2c-core: driver [%s] unregistered\n" , driver->name); out_unlock: -up (&core_lists); +mutex_unlock (&core_lists);return 0 ; }
@@ -802,12 +803,12 @@ struct i2c_adapter* i2c_get_adapter(int {struct i2c_adapter *adapter; -down (&core_lists); +mutex_lock (&core_lists); adapter = (struct i2c_adapter *)idr_find (&i2c_adapter_idr, id);if (adapter && !try_module_get (adapter->owner)) adapter =NULL ; -up (&core_lists); +mutex_unlock (&core_lists);return adapter; }
drivers/ide/ide-cd.c +6 -5
@@ -313,6 +313,7 @@#include <linux/cdrom.h> #include <linux/ide.h> #include <linux/completion.h> +#include <linux/mutex.h> #include <scsi/scsi.h> /* For SCSI -> ATAPI command conversion */
@@ -324,7 +325,7 @@#include "ide-cd.h" -static DECLARE_MUTEX (idecd_ref_sem); +static DEFINE_MUTEX (idecd_ref_mutex);#define to_ide_cd (obj) container_of(obj, struct cdrom_info, kref)
@@ -335,11 +336,11 @@ static struct cdrom_info *ide_cd_get(str {struct cdrom_info *cd =NULL ; -down (&idecd_ref_sem); +mutex_lock (&idecd_ref_mutex); cd =ide_cd_g (disk);if (cd)kref_get (&cd->kref); -up (&idecd_ref_sem); +mutex_unlock (&idecd_ref_mutex);return cd; }
@@ -347,9 +348,9 @@ static void ide_cd_release(struct kref *static void ide_cd_put (struct cdrom_info *cd) { -down (&idecd_ref_sem); +mutex_lock (&idecd_ref_mutex);kref_put (&cd->kref, ide_cd_release); -up (&idecd_ref_sem); +mutex_unlock (&idecd_ref_mutex); }/****************************************************************************
drivers/ide/ide-disk.c +6 -5
@@ -60,6 +60,7 @@#include <linux/genhd.h> #include <linux/slab.h> #include <linux/delay.h> +#include <linux/mutex.h> #define _IDE_DISK
@@ -78,7 +79,7 @@ struct ide_disk_obj {struct kref kref; }; -static DECLARE_MUTEX (idedisk_ref_sem); +static DEFINE_MUTEX (idedisk_ref_mutex);#define to_ide_disk (obj) container_of(obj, struct ide_disk_obj, kref)
@@ -89,11 +90,11 @@ static struct ide_disk_obj *ide_disk_get {struct ide_disk_obj *idkp =NULL ; -down (&idedisk_ref_sem); +mutex_lock (&idedisk_ref_mutex); idkp =ide_disk_g (disk);if (idkp)kref_get (&idkp->kref); -up (&idedisk_ref_sem); +mutex_unlock (&idedisk_ref_mutex);return idkp; }
@@ -101,9 +102,9 @@ static void ide_disk_release(struct krefstatic void ide_disk_put (struct ide_disk_obj *idkp) { -down (&idedisk_ref_sem); +mutex_lock (&idedisk_ref_mutex);kref_put (&idkp->kref, ide_disk_release); -up (&idedisk_ref_sem); +mutex_unlock (&idedisk_ref_mutex); }/*
drivers/ide/ide-floppy.c +6 -5
@@ -98,6 +98,7 @@#include <linux/cdrom.h> #include <linux/ide.h> #include <linux/bitops.h> +#include <linux/mutex.h> #include <asm/byteorder.h> #include <asm/irq.h>
@@ -517,7 +518,7 @@ typedef struct {u8 reserved[4 ]; } idefloppy_mode_parameter_header_t; -static DECLARE_MUTEX (idefloppy_ref_sem); +static DEFINE_MUTEX (idefloppy_ref_mutex);#define to_ide_floppy (obj) container_of(obj, struct ide_floppy_obj, kref)
@@ -528,11 +529,11 @@ static struct ide_floppy_obj *ide_floppy {struct ide_floppy_obj *floppy =NULL ; -down (&idefloppy_ref_sem); +mutex_lock (&idefloppy_ref_mutex); floppy =ide_floppy_g (disk);if (floppy)kref_get (&floppy->kref); -up (&idefloppy_ref_sem); +mutex_unlock (&idefloppy_ref_mutex);return floppy; }
@@ -540,9 +541,9 @@ static void ide_floppy_release(struct krstatic void ide_floppy_put (struct ide_floppy_obj *floppy) { -down (&idefloppy_ref_sem); +mutex_lock (&idefloppy_ref_mutex);kref_put (&floppy->kref, ide_floppy_release); -up (&idefloppy_ref_sem); +mutex_unlock (&idefloppy_ref_mutex); }/*
drivers/ide/ide-tape.c +10 -9
@@ -443,6 +443,7 @@#include <linux/smp_lock.h> #include <linux/completion.h> #include <linux/bitops.h> +#include <linux/mutex.h> #include <asm/byteorder.h> #include <asm/irq.h>
@@ -1011,7 +1012,7 @@ typedef struct ide_tape_obj {int debug_level; } idetape_tape_t; -static DECLARE_MUTEX (idetape_ref_sem); +static DEFINE_MUTEX (idetape_ref_mutex);static struct class *idetape_sysfs_class;
@@ -1024,11 +1025,11 @@ static struct ide_tape_obj *ide_tape_get {struct ide_tape_obj *tape =NULL ; -down (&idetape_ref_sem); +mutex_lock (&idetape_ref_mutex); tape =ide_tape_g (disk);if (tape)kref_get (&tape->kref); -up (&idetape_ref_sem); +mutex_unlock (&idetape_ref_mutex);return tape; }
@@ -1036,9 +1037,9 @@ static void ide_tape_release(struct krefstatic void ide_tape_put (struct ide_tape_obj *tape) { -down (&idetape_ref_sem); +mutex_lock (&idetape_ref_mutex);kref_put (&tape->kref, ide_tape_release); -up (&idetape_ref_sem); +mutex_unlock (&idetape_ref_mutex); }/*
@@ -1290,11 +1291,11 @@ static struct ide_tape_obj *ide_tape_chr {struct ide_tape_obj *tape =NULL ; -down (&idetape_ref_sem); +mutex_lock (&idetape_ref_mutex); tape = idetape_devs[i];if (tape)kref_get (&tape->kref); -up (&idetape_ref_sem); +mutex_unlock (&idetape_ref_mutex);return tape; }
@@ -4874,11 +4875,11 @@ static int ide_tape_probe(struct device drive->driver_data = tape; -down (&idetape_ref_sem); +mutex_lock (&idetape_ref_mutex);for (minor =0 ; idetape_devs[minor]; minor++) ; idetape_devs[minor] = tape; -up (&idetape_ref_sem); +mutex_unlock (&idetape_ref_mutex);idetape_setup (drive, tape, minor);
drivers/mmc/mmc_block.c +6 -5
@@ -28,6 +28,7 @@#include <linux/kdev_t.h> #include <linux/blkdev.h> #include <linux/devfs_fs_kernel.h> +#include <linux/mutex.h> #include <linux/mmc/card.h> #include <linux/mmc/protocol.h>
@@ -56,33 +57,33 @@ struct mmc_blk_data {unsigned int block_bits; }; -static DECLARE_MUTEX (open_lock); +static DEFINE_MUTEX (open_lock);static struct mmc_blk_data *mmc_blk_get (struct gendisk *disk) {struct mmc_blk_data *md; -down (&open_lock); +mutex_lock (&open_lock); md = disk->private_data;if (md && md->usage ==0 ) md =NULL ;if (md) md->usage++; -up (&open_lock); +mutex_unlock (&open_lock);return md; }static void mmc_blk_put (struct mmc_blk_data *md) { -down (&open_lock); +mutex_lock (&open_lock); md->usage--;if (md->usage ==0 ) {put_disk (md->disk);mmc_cleanup_queue (&md->queue);kfree (md); } -up (&open_lock); +mutex_unlock (&open_lock); }static inline int mmc_blk_readonly (struct mmc_card *card)
drivers/mtd/devices/doc2000.c +4 -3
@@ -20,6 +20,7 @@#include <linux/init.h> #include <linux/types.h> #include <linux/bitops.h> +#include <linux/mutex.h> #include <linux/mtd/mtd.h> #include <linux/mtd/nand.h>
@@ -975,13 +976,13 @@ static int doc_writev_ecc(struct mtd_inf u_char *eccbuf, struct nand_oobinfo *oobsel) { static char static_buf[512]; -static DECLARE_MUTEX (writev_buf_sem); +static DEFINE_MUTEX (writev_buf_mutex);size_t totretlen =0 ;size_t thisvecofs =0 ;int ret=0 ; -down (&writev_buf_sem); +mutex_lock (&writev_buf_mutex);while (count) {size_t thislen, thisretlen;
@@ -1024,7 +1025,7 @@ static int doc_writev_ecc(struct mtd_inf to += thislen; } -up (&writev_buf_sem); +mutex_unlock (&writev_buf_mutex); *retlen = totretlen;return ret; }
drivers/pci/hotplug/sgi_hotplug.c +10 -9
@@ -15,6 +15,7 @@#include <linux/pci.h> #include <linux/proc_fs.h> #include <linux/types.h> +#include <linux/mutex.h> #include <asm/sn/addrs.h> #include <asm/sn/l1.h>
@@ -81,7 +82,7 @@ static struct hotplug_slot_ops sn_hotplu .get_power_status = get_power_status, }; -static DECLARE_MUTEX (sn_hotplug_sem); +static DEFINE_MUTEX (sn_hotplug_mutex);static ssize_t path_show (struct hotplug_slot *bss_hotplug_slot,char *buf)
@@ -339,7 +340,7 @@ static int enable_slot(struct hotplug_slint rc;/* Serialize the Linux PCI infrastructure */ -down (&sn_hotplug_sem); +mutex_lock (&sn_hotplug_mutex);/* * Power-on and initialize the slot in the SN
@@ -347,7 +348,7 @@ static int enable_slot(struct hotplug_sl*/ rc =sn_slot_enable (bss_hotplug_slot, slot->device_num);if (rc) { -up (&sn_hotplug_sem); +mutex_unlock (&sn_hotplug_mutex);return rc; }
@@ -355,7 +356,7 @@ static int enable_slot(struct hotplug_sl PCI_DEVFN(slot->device_num + 1, 0));if (!num_funcs) {dev_dbg (slot->pci_bus->self,"no device in slot\n" ); -up (&sn_hotplug_sem); +mutex_unlock (&sn_hotplug_mutex);return -ENODEV ; }
@@ -395,7 +396,7 @@ static int enable_slot(struct hotplug_slif (new_ppb)pci_bus_add_devices (new_bus); -up (&sn_hotplug_sem); +mutex_unlock (&sn_hotplug_mutex);if (rc ==0 ) dev_dbg(slot->pci_bus->self,
@@ -415,7 +416,7 @@ static int disable_slot(struct hotplug_sint rc;/* Acquire update access to the bus */ -down (&sn_hotplug_sem); +mutex_lock (&sn_hotplug_mutex);/* is it okay to bring this slot down? */ rc = sn_slot_disable(bss_hotplug_slot, slot->device_num,
@@ -450,7 +451,7 @@ static int disable_slot(struct hotplug_s PCI_REQ_SLOT_DISABLE); leaving:/* Release the bus lock */ -up (&sn_hotplug_sem); +mutex_unlock (&sn_hotplug_mutex);return rc; }
@@ -462,9 +463,9 @@ static inline int get_power_status(strucstruct pcibus_info *pcibus_info; pcibus_info =SN_PCIBUS_BUSSOFT_INFO (slot->pci_bus); -down (&sn_hotplug_sem); +mutex_lock (&sn_hotplug_mutex); *value = pcibus_info->pbi_enabled_devices & (1 << slot->device_num); -up (&sn_hotplug_sem); +mutex_unlock (&sn_hotplug_mutex);return 0 ; }
drivers/pcmcia/ds.c +5 -4
@@ -23,6 +23,7 @@#include <linux/workqueue.h> #include <linux/crc32.h> #include <linux/firmware.h> +#include <linux/mutex.h> #define IN_CARD_SERVICES #include <pcmcia/cs_types.h>
@@ -499,7 +500,7 @@ static int pcmcia_device_query(struct pc* won't work, this doesn't matter much at the moment: the driver core doesn't * support it either. */ -static DECLARE_MUTEX (device_add_lock); +static DEFINE_MUTEX (device_add_lock);struct pcmcia_device *pcmcia_device_add (struct pcmcia_socket *s,unsigned int function) {
@@ -511,7 +512,7 @@ struct pcmcia_device * pcmcia_device_addif (!s)return NULL ; -down (&device_add_lock); +mutex_lock (&device_add_lock);/* max of 2 devices per card */ if (s->device_count ==2 )
@@ -557,7 +558,7 @@ struct pcmcia_device * pcmcia_device_add goto err_free; } -up (&device_add_lock); +mutex_unlock (&device_add_lock);return p_dev;
@@ -566,7 +567,7 @@ struct pcmcia_device * pcmcia_device_addkfree (p_dev); s->device_count--; err_put: -up (&device_add_lock); +mutex_unlock (&device_add_lock);pcmcia_put_socket (s);return NULL ;
drivers/pcmcia/rsrc_nonstatic.c +20 -19
@@ -25,6 +25,7 @@#include <linux/timer.h> #include <linux/pci.h> #include <linux/device.h> +#include <linux/mutex.h> #include <asm/irq.h> #include <asm/io.h>
@@ -61,7 +62,7 @@ struct socket_data {unsigned int rsrc_mem_probe; }; -static DECLARE_MUTEX (rsrc_sem); +static DEFINE_MUTEX (rsrc_mutex);#define MEM_PROBE_LOW (1 << 0)#define MEM_PROBE_HIGH (1 << 1)
@@ -484,7 +485,7 @@ static void pcmcia_nonstatic_validate_meif (probe_mem) {unsigned int probe_mask; -down (&rsrc_sem); +mutex_lock (&rsrc_mutex); probe_mask =MEM_PROBE_LOW ;if (s->features &SS_CAP_PAGE_REGS )
@@ -497,7 +498,7 @@ static void pcmcia_nonstatic_validate_mevalidate_mem (s, probe_mask); } -up (&rsrc_sem); +mutex_unlock (&rsrc_mutex); } }
@@ -574,7 +575,7 @@ static int nonstatic_adjust_io_region(ststruct socket_data *s_data = s->resource_data;int ret = -ENOMEM ; -down (&rsrc_sem); +mutex_lock (&rsrc_mutex);for (m = s_data->io_db.next; m != &s_data->io_db; m = m->next) {unsigned long start = m->base;unsigned long end = m->base + m->num -1 ;
@@ -585,7 +586,7 @@ static int nonstatic_adjust_io_region(st ret =adjust_resource (res, r_start, r_end - r_start +1 );break ; } -up (&rsrc_sem); +mutex_unlock (&rsrc_mutex);return ret; }
@@ -619,7 +620,7 @@ static struct resource *nonstatic_find_i data.offset = base & data.mask; data.map = &s_data->io_db; -down (&rsrc_sem); +mutex_lock (&rsrc_mutex);#ifdef CONFIG_PCI if (s->cb_dev) { ret = pci_bus_alloc_resource(s->cb_dev->bus, res, num, 1,
@@ -628,7 +629,7 @@ static struct resource *nonstatic_find_i#endif ret =allocate_resource (&ioport_resource, res, num, min, ~0UL ,1 , pcmcia_align, &data); -up (&rsrc_sem); +mutex_unlock (&rsrc_mutex);if (ret !=0 ) {kfree (res);
@@ -661,7 +662,7 @@ static struct resource * nonstatic_find_ min =0x100000UL + base; } -down (&rsrc_sem); +mutex_lock (&rsrc_mutex);#ifdef CONFIG_PCI if (s->cb_dev) { ret = pci_bus_alloc_resource(s->cb_dev->bus, res, num,
@@ -671,7 +672,7 @@ static struct resource * nonstatic_find_#endif ret =allocate_resource (&iomem_resource, res, num, min, max,1 , pcmcia_align, &data); -up (&rsrc_sem); +mutex_unlock (&rsrc_mutex);if (ret ==0 || low)break ; low =1 ;
@@ -694,7 +695,7 @@ static int adjust_memory(struct pcmcia_sif (end < start)return -EINVAL ; -down (&rsrc_sem); +mutex_lock (&rsrc_mutex);switch (action) {case ADD_MANAGED_RESOURCE : ret =add_interval (&data->mem_db, start, size);
@@ -712,7 +713,7 @@ static int adjust_memory(struct pcmcia_sdefault : ret = -EINVAL ; } -up (&rsrc_sem); +mutex_unlock (&rsrc_mutex);return ret; }
@@ -730,7 +731,7 @@ static int adjust_io(struct pcmcia_sockeif (end >IO_SPACE_LIMIT )return -EINVAL ; -down (&rsrc_sem); +mutex_lock (&rsrc_mutex);switch (action) {case ADD_MANAGED_RESOURCE :if (add_interval (&data->io_db, start, size) !=0 ) {
@@ -749,7 +750,7 @@ static int adjust_io(struct pcmcia_socke ret = -EINVAL ;break ; } -up (&rsrc_sem); +mutex_unlock (&rsrc_mutex);return ret; }
@@ -857,7 +858,7 @@ static void nonstatic_release_resource_dstruct socket_data *data = s->resource_data;struct resource_map *p, *q; -down (&rsrc_sem); +mutex_lock (&rsrc_mutex);for (p = data->mem_db.next; p != &data->mem_db; p = q) { q = p->next;kfree (p);
@@ -866,7 +867,7 @@ static void nonstatic_release_resource_d q = p->next;kfree (p); } -up (&rsrc_sem); +mutex_unlock (&rsrc_mutex); }
@@ -891,7 +892,7 @@ static ssize_t show_io_db(struct class_dstruct resource_map *p;ssize_t ret =0 ; -down (&rsrc_sem); +mutex_lock (&rsrc_mutex); data = s->resource_data;for (p = data->io_db.next; p != &data->io_db; p = p->next) {
@@ -903,7 +904,7 @@ static ssize_t show_io_db(struct class_d ((unsigned long) p->base + p->num - 1)); } -up (&rsrc_sem); +mutex_unlock (&rsrc_mutex);return (ret); }
@@ -943,7 +944,7 @@ static ssize_t show_mem_db(struct class_struct resource_map *p;ssize_t ret =0 ; -down (&rsrc_sem); +mutex_lock (&rsrc_mutex); data = s->resource_data;for (p = data->mem_db.next; p != &data->mem_db; p = p->next) {
@@ -955,7 +956,7 @@ static ssize_t show_mem_db(struct class_ ((unsigned long) p->base + p->num - 1)); } -up (&rsrc_sem); +mutex_unlock (&rsrc_mutex);return (ret); }
drivers/scsi/dpt_i2o.c +18 -17
@@ -61,6 +61,7 @@ MODULE_DESCRIPTION("Adaptec I2O RAID Dri#include <linux/timer.h> #include <linux/string.h> #include <linux/ioport.h> +#include <linux/mutex.h> #include <asm/processor.h> /* for boot_cpu_data */ #include <asm/pgtable.h>
@@ -106,7 +107,7 @@ static dpt_sig_S DPTI_sig = {*============================================================================ */ -static DECLARE_MUTEX (adpt_configuration_lock); +static DEFINE_MUTEX (adpt_configuration_lock);static struct i2o_sys_tbl *sys_tbl =NULL ;static int sys_tbl_ind =0 ;
@@ -537,13 +538,13 @@ static int adpt_proc_info(struct Scsi_Ho*/ // Find HBA (host bus adapter) we are looking for -down (&adpt_configuration_lock); +mutex_lock (&adpt_configuration_lock);for (pHba = hba_chain; pHba; pHba = pHba->next) {if (pHba->host == host) {break ;/* found adapter */ } } -up (&adpt_configuration_lock); +mutex_unlock (&adpt_configuration_lock);if (pHba ==NULL ) {return 0 ; }
@@ -958,7 +959,7 @@ static int adpt_install_hba(struct scsi_ }memset (pHba,0 ,sizeof (adpt_hba)); -down (&adpt_configuration_lock); +mutex_lock (&adpt_configuration_lock);if (hba_chain !=NULL ){for (p = hba_chain; p->next; p = p->next);
@@ -971,7 +972,7 @@ static int adpt_install_hba(struct scsi_sprintf (pHba->name,"dpti%d" , hba_count); hba_count++; -up (&adpt_configuration_lock); +mutex_unlock (&adpt_configuration_lock); pHba->pDev = pDev; pHba->base_addr_phys = base_addr0_phys;
@@ -1027,7 +1028,7 @@ static void adpt_i2o_delete_hba(adpt_hbastruct adpt_device * pNext; -down (&adpt_configuration_lock); +mutex_lock (&adpt_configuration_lock);// scsi_unregister calls our adpt_release which // does a quiese if (pHba->host){
@@ -1046,7 +1047,7 @@ static void adpt_i2o_delete_hba(adpt_hba } hba_count--; -up (&adpt_configuration_lock); +mutex_unlock (&adpt_configuration_lock);iounmap (pHba->base_addr_virt);pci_release_regions (pHba->pDev);
@@ -1549,7 +1550,7 @@ static int adpt_i2o_parse_lct(adpt_hba*static int adpt_i2o_install_device (adpt_hba * pHba,struct i2o_device *d) { -down (&adpt_configuration_lock); +mutex_lock (&adpt_configuration_lock); d->controller=pHba; d->owner=NULL ; d->next=pHba->devices;
@@ -1560,7 +1561,7 @@ static int adpt_i2o_install_device(adpt_ pHba->devices=d; *d->dev_name =0 ; -up (&adpt_configuration_lock); +mutex_unlock (&adpt_configuration_lock);return 0 ; }
@@ -1575,24 +1576,24 @@ static int adpt_open(struct inode *inodeif (minor >= hba_count) {return -ENXIO ; } -down (&adpt_configuration_lock); +mutex_lock (&adpt_configuration_lock);for (pHba = hba_chain; pHba; pHba = pHba->next) {if (pHba->unit == minor) {break ;/* found adapter */ } }if (pHba ==NULL ) { -up (&adpt_configuration_lock); +mutex_unlock (&adpt_configuration_lock);return -ENXIO ; }// if(pHba->in_use){ -// up(&adpt_configuration_lock); +// mutex_unlock(&adpt_configuration_lock); // return -EBUSY; // } pHba->in_use =1 ; -up (&adpt_configuration_lock); +mutex_unlock (&adpt_configuration_lock);return 0 ; }
@@ -1606,13 +1607,13 @@ static int adpt_close(struct inode *inodif (minor >= hba_count) {return -ENXIO ; } -down (&adpt_configuration_lock); +mutex_lock (&adpt_configuration_lock);for (pHba = hba_chain; pHba; pHba = pHba->next) {if (pHba->unit == minor) {break ;/* found adapter */ } } -up (&adpt_configuration_lock); +mutex_unlock (&adpt_configuration_lock);if (pHba ==NULL ) {return -ENXIO ; }
@@ -1910,13 +1911,13 @@ static int adpt_ioctl(struct inode *inodif (minor >=DPTI_MAX_HBA ){return -ENXIO ; } -down (&adpt_configuration_lock); +mutex_lock (&adpt_configuration_lock);for (pHba = hba_chain; pHba; pHba = pHba->next) {if (pHba->unit == minor) {break ;/* found adapter */ } } -up (&adpt_configuration_lock); +mutex_unlock (&adpt_configuration_lock);if (pHba ==NULL ){return -ENXIO ; }
drivers/scsi/ide-scsi.c +6 -5
@@ -47,6 +47,7 @@#include <linux/ide.h> #include <linux/scatterlist.h> #include <linux/delay.h> +#include <linux/mutex.h> #include <asm/io.h> #include <asm/bitops.h>
@@ -109,7 +110,7 @@ typedef struct ide_scsi_obj {unsigned long log;/* log flags */ } idescsi_scsi_t; -static DECLARE_MUTEX (idescsi_ref_sem); +static DEFINE_MUTEX (idescsi_ref_mutex);#define ide_scsi_g (disk) \ container_of((disk)->private_data, struct ide_scsi_obj, driver)
@@ -118,19 +119,19 @@ static struct ide_scsi_obj *ide_scsi_get {struct ide_scsi_obj *scsi =NULL ; -down (&idescsi_ref_sem); +mutex_lock (&idescsi_ref_mutex); scsi =ide_scsi_g (disk);if (scsi)scsi_host_get (scsi->host); -up (&idescsi_ref_sem); +mutex_unlock (&idescsi_ref_mutex);return scsi; }static void ide_scsi_put (struct ide_scsi_obj *scsi) { -down (&idescsi_ref_sem); +mutex_lock (&idescsi_ref_mutex);scsi_host_put (scsi->host); -up (&idescsi_ref_sem); +mutex_unlock (&idescsi_ref_mutex); }static inline idescsi_scsi_t *scsihost_to_idescsi (struct Scsi_Host *host)
drivers/scsi/megaraid/megaraid_sas.c +4 -3
@@ -35,6 +35,7 @@#include <asm/uaccess.h> #include <linux/fs.h> #include <linux/compat.h> +#include <linux/mutex.h> #include <scsi/scsi.h> #include <scsi/scsi_cmnd.h>
@@ -72,7 +73,7 @@ MODULE_DEVICE_TABLE(pci, megasas_pci_tabstatic int megasas_mgmt_majorno;static struct megasas_mgmt_info megasas_mgmt_info;static struct fasync_struct *megasas_async_queue; -static DECLARE_MUTEX (megasas_async_queue_mutex); +static DEFINE_MUTEX (megasas_async_queue_mutex);/** * megasas_get_cmd - Get a command from the free pool
@@ -2362,11 +2363,11 @@ static int megasas_mgmt_fasync(int fd, s {int rc; -down (&megasas_async_queue_mutex); +mutex_lock (&megasas_async_queue_mutex); rc =fasync_helper (fd, filep, mode, &megasas_async_queue); -up (&megasas_async_queue_mutex); +mutex_unlock (&megasas_async_queue_mutex);if (rc >=0 ) {/* For sanity check when we get ioctl */
drivers/scsi/scsi.c +7 -6
@@ -55,6 +55,7 @@#include <linux/interrupt.h> #include <linux/notifier.h> #include <linux/cpu.h> +#include <linux/mutex.h> #include <scsi/scsi.h> #include <scsi/scsi_cmnd.h>
@@ -210,7 +211,7 @@ static struct scsi_host_cmd_pool scsi_cm .gfp_mask = __GFP_DMA, }; -static DECLARE_MUTEX (host_cmd_pool_mutex); +static DEFINE_MUTEX (host_cmd_pool_mutex);static struct scsi_cmnd *__scsi_get_command (struct Scsi_Host *shost,gfp_t gfp_mask)
@@ -331,7 +332,7 @@ int scsi_setup_command_freelist(struct S* Select a command slab for this host and create it if not * yet existant. */ -down (&host_cmd_pool_mutex); +mutex_lock (&host_cmd_pool_mutex); pool = (shost->unchecked_isa_dma ? &scsi_cmd_dma_pool : &scsi_cmd_pool);if (!pool->users) { pool->slab = kmem_cache_create(pool->name,
@@ -343,7 +344,7 @@ int scsi_setup_command_freelist(struct S pool->users++; shost->cmd_pool = pool; -up (&host_cmd_pool_mutex); +mutex_unlock (&host_cmd_pool_mutex);/* * Get one backup command for this host.
@@ -360,7 +361,7 @@ int scsi_setup_command_freelist(struct Skmem_cache_destroy (pool->slab);return -ENOMEM ; fail: -up (&host_cmd_pool_mutex); +mutex_unlock (&host_cmd_pool_mutex);return -ENOMEM ; }
@@ -382,10 +383,10 @@ void scsi_destroy_command_freelist(struckmem_cache_free (shost->cmd_pool->slab, cmd); } -down (&host_cmd_pool_mutex); +mutex_lock (&host_cmd_pool_mutex);if (!--shost->cmd_pool->users)kmem_cache_destroy (shost->cmd_pool->slab); -up (&host_cmd_pool_mutex); +mutex_unlock (&host_cmd_pool_mutex); }#ifdef CONFIG_SCSI_LOGGING
drivers/scsi/scsi_proc.c +6 -5
@@ -25,6 +25,7 @@#include <linux/errno.h> #include <linux/blkdev.h> #include <linux/seq_file.h> +#include <linux/mutex.h> #include <asm/uaccess.h> #include <scsi/scsi.h>
@@ -41,7 +42,7 @@static struct proc_dir_entry *proc_scsi;/* Protect sht->present and sht->proc_dir */ -static DECLARE_MUTEX (global_host_template_sem); +static DEFINE_MUTEX (global_host_template_mutex);static int proc_scsi_read (char *buffer,char **start,off_t offset,int length,int *eof,void *data)
@@ -83,7 +84,7 @@ void scsi_proc_hostdir_add(struct scsi_hif (!sht->proc_info)return ; -down (&global_host_template_sem); +mutex_lock (&global_host_template_mutex);if (!sht->present++) { sht->proc_dir =proc_mkdir (sht->proc_name, proc_scsi);if (!sht->proc_dir)
@@ -92,7 +93,7 @@ void scsi_proc_hostdir_add(struct scsi_helse sht->proc_dir->owner = sht->module; } -up (&global_host_template_sem); +mutex_unlock (&global_host_template_mutex); }void scsi_proc_hostdir_rm (struct scsi_host_template *sht)
@@ -100,12 +101,12 @@ void scsi_proc_hostdir_rm(struct scsi_hoif (!sht->proc_info)return ; -down (&global_host_template_sem); +mutex_lock (&global_host_template_mutex);if (!--sht->present && sht->proc_dir) {remove_proc_entry (sht->proc_name, proc_scsi); sht->proc_dir =NULL ; } -up (&global_host_template_sem); +mutex_unlock (&global_host_template_mutex); }void scsi_proc_host_add (struct Scsi_Host *shost)
drivers/scsi/scsi_transport_iscsi.c +9 -8
@@ -24,6 +24,7 @@#include <linux/string.h> #include <linux/slab.h> #include <linux/mempool.h> +#include <linux/mutex.h> #include <net/tcp.h> #include <scsi/scsi.h>
@@ -46,7 +47,7 @@ struct iscsi_internal {struct list_head sessions;/* * lock to serialize access to the sessions list which must -* be taken after the rx_queue_sema +* be taken after the rx_queue_mutex */ spinlock_t session_lock;/*
@@ -70,7 +71,7 @@ struct iscsi_internal {/* * list of registered transports and lock that must * be held while accessing list. The iscsi_transport_lock must -* be acquired after the rx_queue_sema. +* be acquired after the rx_queue_mutex. */ static LIST_HEAD (iscsi_transports);static DEFINE_SPINLOCK (iscsi_transport_lock);
@@ -145,7 +146,7 @@ static DECLARE_TRANSPORT_CLASS(iscsi_constatic struct sock *nls;static int daemon_pid; -static DECLARE_MUTEX (rx_queue_sema); +static DEFINE_MUTEX (rx_queue_mutex);struct mempool_zone {mempool_t *pool;
@@ -881,7 +882,7 @@ iscsi_if_rx(struct sock *sk, int len) {struct sk_buff *skb; -down (&rx_queue_sema); +mutex_lock (&rx_queue_mutex);while ((skb =skb_dequeue (&sk->sk_receive_queue)) !=NULL ) {while (skb->len >=NLMSG_SPACE (0 )) {int err;
@@ -923,7 +924,7 @@ iscsi_if_rx(struct sock *sk, int len) }kfree_skb (skb); } -up (&rx_queue_sema); +mutex_unlock (&rx_queue_mutex); }/*
@@ -1159,7 +1160,7 @@ int iscsi_unregister_transport(struct isBUG_ON (!tt); -down (&rx_queue_sema); +mutex_lock (&rx_queue_mutex); priv =iscsi_if_transport_lookup (tt);BUG_ON (!priv);
@@ -1167,7 +1168,7 @@ int iscsi_unregister_transport(struct isspin_lock_irqsave (&priv->session_lock, flags);if (!list_empty (&priv->sessions)) {spin_unlock_irqrestore (&priv->session_lock, flags); -up (&rx_queue_sema); +mutex_unlock (&rx_queue_mutex);return -EPERM ; }spin_unlock_irqrestore (&priv->session_lock, flags);
@@ -1181,7 +1182,7 @@ int iscsi_unregister_transport(struct issysfs_remove_group (&priv->cdev.kobj, &iscsi_transport_group);class_device_unregister (&priv->cdev); -up (&rx_queue_sema); +mutex_unlock (&rx_queue_mutex);return 0 ; }
drivers/scsi/sd.c +11 -10
@@ -49,6 +49,7 @@#include <linux/blkpg.h> #include <linux/kref.h> #include <linux/delay.h> +#include <linux/mutex.h> #include <asm/uaccess.h> #include <scsi/scsi.h>
@@ -110,7 +111,7 @@ static DEFINE_SPINLOCK(sd_index_lock);/* This semaphore is used to mediate the 0->1 reference get in the * face of object destruction (i.e. we can't allow a get on an * object after last put) */ -static DECLARE_MUTEX (sd_ref_sem); +static DEFINE_MUTEX (sd_ref_mutex);static int sd_revalidate_disk (struct gendisk *disk);static void sd_rw_intr (struct scsi_cmnd * SCpnt);
@@ -195,9 +196,9 @@ static struct scsi_disk *scsi_disk_get(s {struct scsi_disk *sdkp; -down (&sd_ref_sem); +mutex_lock (&sd_ref_mutex); sdkp =__scsi_disk_get (disk); -up (&sd_ref_sem); +mutex_unlock (&sd_ref_mutex);return sdkp; }
@@ -205,11 +206,11 @@ static struct scsi_disk *scsi_disk_get_f {struct scsi_disk *sdkp; -down (&sd_ref_sem); +mutex_lock (&sd_ref_mutex); sdkp =dev_get_drvdata (dev);if (sdkp) sdkp =__scsi_disk_get (sdkp->disk); -up (&sd_ref_sem); +mutex_unlock (&sd_ref_mutex);return sdkp; }
@@ -217,10 +218,10 @@ static void scsi_disk_put(struct scsi_di {struct scsi_device *sdev = sdkp->device; -down (&sd_ref_sem); +mutex_lock (&sd_ref_mutex);kref_put (&sdkp->kref, scsi_disk_release);scsi_device_put (sdev); -up (&sd_ref_sem); +mutex_unlock (&sd_ref_mutex); }/**
@@ -1643,10 +1644,10 @@ static int sd_remove(struct device *dev)del_gendisk (sdkp->disk);sd_shutdown (dev); -down (&sd_ref_sem); +mutex_lock (&sd_ref_mutex);dev_set_drvdata (dev,NULL );kref_put (&sdkp->kref, scsi_disk_release); -up (&sd_ref_sem); +mutex_unlock (&sd_ref_mutex);return 0 ; }
@@ -1655,7 +1656,7 @@ static int sd_remove(struct device *dev)* scsi_disk_release - Called to free the scsi_disk structure * @kref: pointer to embedded kref * -* sd_ref_sem must be held entering this routine. Because it is +* sd_ref_mutex must be held entering this routine. Because it is * called on last put, you should always use the scsi_disk_get() * scsi_disk_put() helpers which manipulate the semaphore directly * and never do a direct kref_put().
drivers/scsi/sr.c +9 -8
@@ -44,6 +44,7 @@#include <linux/interrupt.h> #include <linux/init.h> #include <linux/blkdev.h> +#include <linux/mutex.h> #include <asm/uaccess.h> #include <scsi/scsi.h>
@@ -90,7 +91,7 @@ static DEFINE_SPINLOCK(sr_index_lock);/* This semaphore is used to mediate the 0->1 reference get in the * face of object destruction (i.e. we can't allow a get on an * object after last put) */ -static DECLARE_MUTEX (sr_ref_sem); +static DEFINE_MUTEX (sr_ref_mutex);static int sr_open (struct cdrom_device_info *,int );static void sr_release (struct cdrom_device_info *);
@@ -133,7 +134,7 @@ static inline struct scsi_cd *scsi_cd_ge {struct scsi_cd *cd =NULL ; -down (&sr_ref_sem); +mutex_lock (&sr_ref_mutex);if (disk->private_data ==NULL ) goto out; cd =scsi_cd (disk);
@@ -146,7 +147,7 @@ static inline struct scsi_cd *scsi_cd_gekref_put (&cd->kref, sr_kref_release); cd =NULL ; out: -up (&sr_ref_sem); +mutex_unlock (&sr_ref_mutex);return cd; }
@@ -154,10 +155,10 @@ static inline void scsi_cd_put(struct sc {struct scsi_device *sdev = cd->device; -down (&sr_ref_sem); +mutex_lock (&sr_ref_mutex);kref_put (&cd->kref, sr_kref_release);scsi_device_put (sdev); -up (&sr_ref_sem); +mutex_unlock (&sr_ref_mutex); }/*
@@ -845,7 +846,7 @@ static int sr_packet(struct cdrom_device* sr_kref_release - Called to free the scsi_cd structure * @kref: pointer to embedded kref * -* sr_ref_sem must be held entering this routine. Because it is +* sr_ref_mutex must be held entering this routine. Because it is * called on last put, you should always use the scsi_cd_get() * scsi_cd_put() helpers which manipulate the semaphore directly * and never do a direct kref_put().
@@ -874,9 +875,9 @@ static int sr_remove(struct device *dev)del_gendisk (cd->disk); -down (&sr_ref_sem); +mutex_lock (&sr_ref_mutex);kref_put (&cd->kref, sr_kref_release); -up (&sr_ref_sem); +mutex_unlock (&sr_ref_mutex);return 0 ; }
drivers/scsi/st.c +9 -8
@@ -38,6 +38,7 @@ static char *verstr = "20050830";#include <linux/devfs_fs_kernel.h> #include <linux/cdev.h> #include <linux/delay.h> +#include <linux/mutex.h> #include <asm/uaccess.h> #include <asm/dma.h>
@@ -223,7 +224,7 @@ static void scsi_tape_release(struct kre#define to_scsi_tape (obj) container_of(obj, struct scsi_tape, kref) -static DECLARE_MUTEX (st_ref_sem); +static DEFINE_MUTEX (st_ref_mutex);#include "osst_detect.h"
@@ -240,7 +241,7 @@ static struct scsi_tape *scsi_tape_get(i {struct scsi_tape *STp =NULL ; -down (&st_ref_sem); +mutex_lock (&st_ref_mutex);write_lock (&st_dev_arr_lock);if (dev < st_dev_max && scsi_tapes !=NULL )
@@ -262,7 +263,7 @@ out_put: STp =NULL ; out:write_unlock (&st_dev_arr_lock); -up (&st_ref_sem); +mutex_unlock (&st_ref_mutex);return STp; }
@@ -270,10 +271,10 @@ static void scsi_tape_put(struct scsi_ta {struct scsi_device *sdev = STp->device; -down (&st_ref_sem); +mutex_lock (&st_ref_mutex);kref_put (&STp->kref, scsi_tape_release);scsi_device_put (sdev); -up (&st_ref_sem); +mutex_unlock (&st_ref_mutex); }struct st_reject_data {
@@ -4144,9 +4145,9 @@ static int st_remove(struct device *dev) } } -down (&st_ref_sem); +mutex_lock (&st_ref_mutex);kref_put (&tpnt->kref, scsi_tape_release); -up (&st_ref_sem); +mutex_unlock (&st_ref_mutex);return 0 ; } }
@@ -4159,7 +4160,7 @@ static int st_remove(struct device *dev)* scsi_tape_release - Called to free the Scsi_Tape structure * @kref: pointer to embedded kref * -* st_ref_sem must be held entering this routine. Because it is +* st_ref_mutex must be held entering this routine. Because it is * called on last put, you should always use the scsi_tape_get() * scsi_tape_put() helpers which manipulate the semaphore directly * and never do a direct kref_put().
drivers/serial/8250.c +6 -5
@@ -41,6 +41,7 @@#include <linux/serial.h> #include <linux/serial_8250.h> #include <linux/nmi.h> +#include <linux/mutex.h> #include <asm/io.h> #include <asm/irq.h>
@@ -2480,7 +2481,7 @@ static struct platform_device *serial825* 16x50 serial ports to be configured at run-time, to support PCMCIA * modems and PCI multiport cards. */ -static DECLARE_MUTEX (serial_sem); +static DEFINE_MUTEX (serial_mutex);static struct uart_8250_port *serial8250_find_match_or_unused (struct uart_port *port) {
@@ -2535,7 +2536,7 @@ int serial8250_register_port(struct uartif (port->uartclk ==0 )return -EINVAL ; -down (&serial_sem); +mutex_lock (&serial_mutex); uart =serial8250_find_match_or_unused (port);if (uart) {
@@ -2557,7 +2558,7 @@ int serial8250_register_port(struct uartif (ret ==0 ) ret = uart->port.line; } -up (&serial_sem); +mutex_unlock (&serial_mutex);return ret; }
@@ -2574,7 +2575,7 @@ void serial8250_unregister_port(int line {struct uart_8250_port *uart = &serial8250_ports[line]; -down (&serial_sem); +mutex_lock (&serial_mutex);uart_remove_one_port (&serial8250_reg, &uart->port);if (serial8250_isa_devs) { uart->port.flags &= ~UPF_BOOT_AUTOCONF ;
@@ -2584,7 +2585,7 @@ void serial8250_unregister_port(int line }else { uart->port.dev =NULL ; } -up (&serial_sem); +mutex_unlock (&serial_mutex); }EXPORT_SYMBOL (serial8250_unregister_port);
drivers/serial/crisv10.c +4 -7
@@ -442,6 +442,7 @@ static char *serial_version = "$Revision#include <linux/init.h> #include <asm/uaccess.h> #include <linux/kernel.h> +#include <linux/mutex.h> #include <asm/io.h> #include <asm/irq.h>
@@ -1315,11 +1316,7 @@ static const struct control_pins e100_mo* memory if large numbers of serial ports are open. */ static unsigned char *tmp_buf; -#ifdef DECLARE_MUTEX -static DECLARE_MUTEX (tmp_buf_sem); -#else -static struct semaphore tmp_buf_sem =MUTEX ; -#endif +static DEFINE_MUTEX (tmp_buf_mutex);/* Calculate the chartime depending on baudrate, numbor of bits etc. */ static void update_char_time (struct e100_serial * info)
@@ -3661,7 +3658,7 @@ rs_raw_write(struct tty_struct * tty, in* design. */ if (from_user) { -down (&tmp_buf_sem); +mutex_lock (&tmp_buf_mutex);while (1 ) {int c1; c = CIRC_SPACE_TO_END(info->xmit.head,
@@ -3692,7 +3689,7 @@ rs_raw_write(struct tty_struct * tty, in count -= c; ret += c; } -up (&tmp_buf_sem); +mutex_unlock (&tmp_buf_mutex); }else {cli ();while (count) {
drivers/serial/pmac_zilog.c +12 -11
@@ -60,6 +60,7 @@#include <linux/pmu.h> #include <linux/bitops.h> #include <linux/sysrq.h> +#include <linux/mutex.h> #include <asm/sections.h> #include <asm/io.h> #include <asm/irq.h>
@@ -96,7 +97,7 @@ MODULE_LICENSE("GPL");*/ static struct uart_pmac_port pmz_ports[MAX_ZS_PORTS ];static int pmz_ports_count; -static DECLARE_MUTEX (pmz_irq_sem); +static DEFINE_MUTEX (pmz_irq_mutex);static struct uart_driver pmz_uart_reg = { .owner =THIS_MODULE ,
@@ -945,7 +946,7 @@ static int pmz_startup(struct uart_portif (uap->node ==NULL )return -ENODEV ; -down (&pmz_irq_sem); +mutex_lock (&pmz_irq_mutex); uap->flags |=PMACZILOG_FLAG_IS_OPEN ;
@@ -963,11 +964,11 @@ static int pmz_startup(struct uart_portdev_err (&uap->dev->ofdev.dev,"Unable to register zs interrupt handler.\n" );pmz_set_scc_power (uap,0 ); -up (&pmz_irq_sem); +mutex_unlock (&pmz_irq_mutex);return -ENXIO ; } -up (&pmz_irq_sem); +mutex_unlock (&pmz_irq_mutex);/* Right now, we deal with delay by blocking here, I'll be * smarter later on
@@ -1004,7 +1005,7 @@ static void pmz_shutdown(struct uart_porif (uap->node ==NULL )return ; -down (&pmz_irq_sem); +mutex_lock (&pmz_irq_mutex);/* Release interrupt handler */ free_irq (uap->port.irq, uap);
@@ -1025,7 +1026,7 @@ static void pmz_shutdown(struct uart_porif (ZS_IS_CONS (uap) ||ZS_IS_ASLEEP (uap)) {spin_unlock_irqrestore (&port->lock, flags); -up (&pmz_irq_sem); +mutex_unlock (&pmz_irq_mutex);return ; }
@@ -1042,7 +1043,7 @@ static void pmz_shutdown(struct uart_porspin_unlock_irqrestore (&port->lock, flags); -up (&pmz_irq_sem); +mutex_unlock (&pmz_irq_mutex);pmz_debug ("pmz: shutdown() done.\n" ); }
@@ -1607,7 +1608,7 @@ static int pmz_suspend(struct macio_dev state = pmz_uart_reg.state + uap->port.line; -down (&pmz_irq_sem); +mutex_lock (&pmz_irq_mutex);down (&state->sem);spin_lock_irqsave (&uap->port.lock, flags);
@@ -1640,7 +1641,7 @@ static int pmz_suspend(struct macio_devpmz_set_scc_power (uap,0 );up (&state->sem); -up (&pmz_irq_sem); +mutex_unlock (&pmz_irq_mutex);pmz_debug ("suspend, switching complete\n" );
@@ -1667,7 +1668,7 @@ static int pmz_resume(struct macio_dev * state = pmz_uart_reg.state + uap->port.line; -down (&pmz_irq_sem); +mutex_lock (&pmz_irq_mutex);down (&state->sem);spin_lock_irqsave (&uap->port.lock, flags);
@@ -1701,7 +1702,7 @@ static int pmz_resume(struct macio_dev * bail:up (&state->sem); -up (&pmz_irq_sem); +mutex_unlock (&pmz_irq_mutex);/* Right now, we deal with delay by blocking here, I'll be * smarter later on
drivers/serial/serial_core.c +8 -7
@@ -33,6 +33,7 @@#include <linux/device.h> #include <linux/serial.h> /* for serial_state and serial_icounter_struct */ #include <linux/delay.h> +#include <linux/mutex.h> #include <asm/irq.h> #include <asm/uaccess.h>
@@ -47,7 +48,7 @@/* * This is used to lock changes in serial line configuration. */ -static DECLARE_MUTEX (port_sem); +static DEFINE_MUTEX (port_mutex);#define HIGH_BITS_OFFSET ((sizeof(long)-sizeof(int))*8)
@@ -1471,7 +1472,7 @@ static struct uart_state *uart_get(struc {struct uart_state *state; -down (&port_sem); +mutex_lock (&port_mutex); state = drv->state + line;if (down_interruptible (&state->sem)) { state =ERR_PTR (-ERESTARTSYS );
@@ -1508,7 +1509,7 @@ static struct uart_state *uart_get(struc } out: -up (&port_sem); +mutex_unlock (&port_mutex);return state; }
@@ -2218,7 +2219,7 @@ int uart_add_one_port(struct uart_driver state = drv->state + port->line; -down (&port_sem); +mutex_lock (&port_mutex);if (state->port) { ret = -EINVAL ; goto out;
@@ -2254,7 +2255,7 @@ int uart_add_one_port(struct uart_driverregister_console (port->cons); out: -up (&port_sem); +mutex_unlock (&port_mutex);return ret; }
@@ -2278,7 +2279,7 @@ int uart_remove_one_port(struct uart_driprintk (KERN_ALERT "Removing wrong port: %p != %p\n" , state->port, port); -down (&port_sem); +mutex_lock (&port_mutex);/* * Remove the devices from devfs
@@ -2287,7 +2288,7 @@ int uart_remove_one_port(struct uart_driuart_unconfigure_port (drv, state); state->port =NULL ; -up (&port_sem); +mutex_unlock (&port_mutex);return 0 ; }
drivers/serial/serial_txx9.c +6 -5
@@ -52,6 +52,7 @@#include <linux/tty_flip.h> #include <linux/serial_core.h> #include <linux/serial.h> +#include <linux/mutex.h> #include <asm/io.h> #include <asm/irq.h>
@@ -1029,7 +1030,7 @@ static void serial_txx9_resume_port(intuart_resume_port (&serial_txx9_reg, &serial_txx9_ports[line].port); } -static DECLARE_MUTEX (serial_txx9_sem); +static DEFINE_MUTEX (serial_txx9_mutex);/** * serial_txx9_register_port - register a serial port
@@ -1048,7 +1049,7 @@ static int __devinit serial_txx9_registestruct uart_txx9_port *uart;int ret = -ENOSPC ; -down (&serial_txx9_sem); +mutex_lock (&serial_txx9_mutex);for (i =0 ; i <UART_NR ; i++) { uart = &serial_txx9_ports[i];if (uart->port.type ==PORT_UNKNOWN )
@@ -1069,7 +1070,7 @@ static int __devinit serial_txx9_registeif (ret ==0 ) ret = uart->port.line; } -up (&serial_txx9_sem); +mutex_unlock (&serial_txx9_mutex);return ret; }
@@ -1084,7 +1085,7 @@ static void __devexit serial_txx9_unregi {struct uart_txx9_port *uart = &serial_txx9_ports[line]; -down (&serial_txx9_sem); +mutex_lock (&serial_txx9_mutex);uart_remove_one_port (&serial_txx9_reg, &uart->port); uart->port.flags =0 ; uart->port.type =PORT_UNKNOWN ;
@@ -1093,7 +1094,7 @@ static void __devexit serial_txx9_unregi uart->port.membase =0 ; uart->port.dev =NULL ;uart_add_one_port (&serial_txx9_reg, &uart->port); -up (&serial_txx9_sem); +mutex_unlock (&serial_txx9_mutex); }/*
drivers/usb/class/cdc-acm.c +10 -9
@@ -58,6 +58,7 @@#include <linux/tty_flip.h> #include <linux/module.h> #include <linux/smp_lock.h> +#include <linux/mutex.h> #include <asm/uaccess.h> #include <linux/usb.h> #include <linux/usb_cdc.h>
@@ -77,7 +78,7 @@ static struct usb_driver acm_driver;static struct tty_driver *acm_tty_driver;static struct acm *acm_table[ACM_TTY_MINORS ]; -static DECLARE_MUTEX (open_sem); +static DEFINE_MUTEX (open_mutex);#define ACM_READY (acm) (acm && acm->dev && acm->used)
@@ -371,7 +372,7 @@ static int acm_tty_open(struct tty_strucint rv = -EINVAL ;dbg ("Entering acm_tty_open.\n" ); -down (&open_sem); +mutex_lock (&open_mutex); acm = acm_table[tty->index];if (!acm || !acm->dev)
@@ -409,7 +410,7 @@ static int acm_tty_open(struct tty_struc done: err_out: -up (&open_sem); +mutex_unlock (&open_mutex);return rv; full_bailout:
@@ -418,7 +419,7 @@ bail_out_and_unlink:usb_kill_urb (acm->ctrlurb); bail_out: acm->used--; -up (&open_sem); +mutex_unlock (&open_mutex);return -EIO ; }
@@ -440,7 +441,7 @@ static void acm_tty_close(struct tty_strif (!acm || !acm->used)return ; -down (&open_sem); +mutex_lock (&open_mutex);if (!--acm->used) {if (acm->dev) {acm_set_control (acm, acm->ctrlout =0 );
@@ -450,7 +451,7 @@ static void acm_tty_close(struct tty_str }else acm_tty_unregister (acm); } -up (&open_sem); +mutex_unlock (&open_mutex); }static int acm_tty_write (struct tty_struct *tty,const unsigned char *buf,int count)
@@ -942,7 +943,7 @@ static void acm_disconnect(struct usb_inreturn ; } -down (&open_sem); +mutex_lock (&open_mutex); acm->dev =NULL ;usb_set_intfdata (intf,NULL );
@@ -960,11 +961,11 @@ static void acm_disconnect(struct usb_inif (!acm->used) {acm_tty_unregister (acm); -up (&open_sem); +mutex_unlock (&open_mutex);return ; } -up (&open_sem); +mutex_unlock (&open_mutex);if (acm->tty)tty_hangup (acm->tty);
drivers/usb/class/usblp.c +8 -7
@@ -54,6 +54,7 @@#include <linux/init.h> #include <linux/slab.h> #include <linux/lp.h> +#include <linux/mutex.h> #undef DEBUG#include <linux/usb.h>
@@ -222,7 +223,7 @@ static int usblp_cache_device_id_string(/* forward reference to make our lives easier */ static struct usb_driver usblp_driver; -static DECLARE_MUTEX (usblp_sem);/* locks the existence of usblp's */ +static DEFINE_MUTEX (usblp_mutex);/* locks the existence of usblp's */ /* * Functions for usblp control messages.
@@ -345,7 +346,7 @@ static int usblp_open(struct inode *inodif (minor <0 )return -ENODEV ; -down (&usblp_sem); +mutex_lock (&usblp_mutex); retval = -ENODEV ; intf =usb_find_interface (&usblp_driver, minor);
@@ -393,7 +394,7 @@ static int usblp_open(struct inode *inod } } out: -up (&usblp_sem); +mutex_unlock (&usblp_mutex);return retval; }
@@ -419,13 +420,13 @@ static int usblp_release(struct inode *i {struct usblp *usblp = file->private_data; -down (&usblp_sem); +mutex_lock (&usblp_mutex); usblp->used =0 ;if (usblp->present) {usblp_unlink_urbs (usblp); }else /* finish cleanup from disconnect */ usblp_cleanup (usblp); -up (&usblp_sem); +mutex_unlock (&usblp_mutex);return 0 ; }
@@ -1156,7 +1157,7 @@ static void usblp_disconnect(struct usb_BUG (); } -down (&usblp_sem); +mutex_lock (&usblp_mutex);down (&usblp->sem); usblp->present =0 ;usb_set_intfdata (intf,NULL );
@@ -1170,7 +1171,7 @@ static void usblp_disconnect(struct usb_if (!usblp->used)usblp_cleanup (usblp); -up (&usblp_sem); +mutex_unlock (&usblp_mutex); }static struct usb_device_id usblp_ids [] = {
drivers/usb/core/hub.c +4 -3
@@ -22,6 +22,7 @@#include <linux/usb.h> #include <linux/usbdevice_fs.h> #include <linux/kthread.h> +#include <linux/mutex.h> #include <asm/semaphore.h> #include <asm/uaccess.h>
@@ -2107,7 +2108,7 @@ static int hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1, int retry_counter) { - static DECLARE_MUTEX(usb_address0_sem); + static DEFINE_MUTEX(usb_address0_mutex);struct usb_device *hdev = hub->hdev;int i, j, retval;
@@ -2128,7 +2129,7 @@ hub_port_init (struct usb_hub *hub, struif (oldspeed ==USB_SPEED_LOW ) delay =HUB_LONG_RESET_TIME ; -down (&usb_address0_sem); +mutex_lock (&usb_address0_mutex);/* Reset the device; full speed may morph to high speed */ retval =hub_port_reset (hub, port1, udev, delay);
@@ -2326,7 +2327,7 @@ hub_port_init (struct usb_hub *hub, stru fail:if (retval)hub_port_disable (hub, port1,0 ); -up (&usb_address0_sem); +mutex_unlock (&usb_address0_mutex);return retval; }
drivers/usb/core/notify.c +8 -7
@@ -13,16 +13,17 @@#include <linux/kernel.h> #include <linux/notifier.h> #include <linux/usb.h> +#include <linux/mutex.h> #include "usb.h" static struct notifier_block *usb_notifier_list; -static DECLARE_MUTEX (usb_notifier_lock); +static DEFINE_MUTEX (usb_notifier_lock);static void usb_notifier_chain_register (struct notifier_block **list,struct notifier_block *n) { -down (&usb_notifier_lock); +mutex_lock (&usb_notifier_lock);while (*list) {if (n->priority > (*list)->priority)break ;
@@ -30,13 +31,13 @@ static void usb_notifier_chain_register( } n->next = *list; *list = n; -up (&usb_notifier_lock); +mutex_unlock (&usb_notifier_lock); }static void usb_notifier_chain_unregister (struct notifier_block **nl,struct notifier_block *n) { -down (&usb_notifier_lock); +mutex_lock (&usb_notifier_lock);while ((*nl)!=NULL ) {if ((*nl)==n) { *nl = n->next;
@@ -45,7 +46,7 @@ static void usb_notifier_chain_unregiste nl=&((*nl)->next); } exit: -up (&usb_notifier_lock); +mutex_unlock (&usb_notifier_lock); } static int usb_notifier_call_chain(struct notifier_block **n,
@@ -54,7 +55,7 @@ static int usb_notifier_call_chain(strucint ret=NOTIFY_DONE ;struct notifier_block *nb = *n; -down (&usb_notifier_lock); +mutex_lock (&usb_notifier_lock);while (nb) { ret = nb->notifier_call (nb,val,v);if (ret&NOTIFY_STOP_MASK ) {
@@ -63,7 +64,7 @@ static int usb_notifier_call_chain(struc nb = nb->next; } exit: -up (&usb_notifier_lock); +mutex_unlock (&usb_notifier_lock);return ret; }
drivers/usb/input/ati_remote.c +0 -2
@@ -158,8 +158,6 @@ static char accel[] = { 1, 2, 4, 6, 9, 1*/ #define FILTER_TIME (HZ / 20) -static DECLARE_MUTEX (disconnect_sem); -struct ati_remote {struct input_dev *idev;struct usb_device *udev;
drivers/usb/misc/idmouse.c +13 -12
@@ -25,6 +25,7 @@#include <linux/module.h> #include <linux/smp_lock.h> #include <linux/completion.h> +#include <linux/mutex.h> #include <asm/uaccess.h> #include <linux/usb.h>
@@ -122,7 +123,7 @@ static struct usb_driver idmouse_driver };/* prevent races between open() and disconnect() */ -static DECLARE_MUTEX (disconnect_sem); +static DEFINE_MUTEX (disconnect_mutex);static int idmouse_create_image (struct usb_idmouse *dev) {
@@ -214,18 +215,18 @@ static int idmouse_open(struct inode *inint result =0 ;/* prevent disconnects */ -down (&disconnect_sem); +mutex_lock (&disconnect_mutex);/* get the interface from minor number and driver information */ interface =usb_find_interface (&idmouse_driver,iminor (inode));if (!interface) { -up (&disconnect_sem); +mutex_unlock (&disconnect_mutex);return -ENODEV ; }/* get the device information block from the interface */ dev =usb_get_intfdata (interface);if (!dev) { -up (&disconnect_sem); +mutex_unlock (&disconnect_mutex);return -ENODEV ; }
@@ -259,7 +260,7 @@ error:up (&dev->sem);/* unlock the disconnect semaphore */ -up (&disconnect_sem); +mutex_unlock (&disconnect_mutex);return result; }
@@ -268,12 +269,12 @@ static int idmouse_release(struct inodestruct usb_idmouse *dev;/* prevent a race condition with open() */ -down (&disconnect_sem); +mutex_lock (&disconnect_mutex); dev = (struct usb_idmouse *) file->private_data;if (dev ==NULL ) { -up (&disconnect_sem); +mutex_unlock (&disconnect_mutex);return -ENODEV ; }
@@ -283,7 +284,7 @@ static int idmouse_release(struct inode/* are we really open? */ if (dev->open <=0 ) {up (&dev->sem); -up (&disconnect_sem); +mutex_unlock (&disconnect_mutex);return -ENODEV ; }
@@ -293,12 +294,12 @@ static int idmouse_release(struct inode/* the device was unplugged before the file was released */ up (&dev->sem);idmouse_delete (dev); -up (&disconnect_sem); +mutex_unlock (&disconnect_mutex);return 0 ; }up (&dev->sem); -up (&disconnect_sem); +mutex_unlock (&disconnect_mutex);return 0 ; }
@@ -401,7 +402,7 @@ static void idmouse_disconnect(struct usstruct usb_idmouse *dev;/* prevent races with open() */ -down (&disconnect_sem); +mutex_lock (&disconnect_mutex);/* get device structure */ dev =usb_get_intfdata (interface);
@@ -423,7 +424,7 @@ static void idmouse_disconnect(struct usif (!dev->open)idmouse_delete (dev); -up (&disconnect_sem); +mutex_unlock (&disconnect_mutex);info ("%s disconnected" ,DRIVER_DESC ); }
drivers/usb/misc/ldusb.c +6 -5
@@ -32,6 +32,7 @@#include <linux/init.h> #include <linux/slab.h> #include <linux/module.h> +#include <linux/mutex.h> #include <asm/uaccess.h> #include <linux/input.h>
@@ -165,7 +166,7 @@ struct ld_usb { };/* prevent races between open() and disconnect() */ -static DECLARE_MUTEX (disconnect_sem); +static DEFINE_MUTEX (disconnect_mutex);static struct usb_driver ld_usb_driver;
@@ -286,7 +287,7 @@ static int ld_usb_open(struct inode *inononseekable_open (inode, file); subminor =iminor (inode); -down (&disconnect_sem); +mutex_lock (&disconnect_mutex); interface =usb_find_interface (&ld_usb_driver, subminor);
@@ -348,7 +349,7 @@ unlock_exit:up (&dev->sem); unlock_disconnect_exit: -up (&disconnect_sem); +mutex_unlock (&disconnect_mutex);return retval; }
@@ -734,7 +735,7 @@ static void ld_usb_disconnect(struct usbstruct ld_usb *dev;int minor; -down (&disconnect_sem); +mutex_lock (&disconnect_mutex); dev =usb_get_intfdata (intf);usb_set_intfdata (intf,NULL );
@@ -755,7 +756,7 @@ static void ld_usb_disconnect(struct usbup (&dev->sem); } -up (&disconnect_sem); +mutex_unlock (&disconnect_mutex);dev_info (&intf->dev,"LD USB Device #%d now disconnected\n" , (minor -USB_LD_MINOR_BASE ));
drivers/usb/misc/legousbtower.c +6 -5
@@ -83,6 +83,7 @@#include <linux/module.h> #include <linux/smp_lock.h> #include <linux/completion.h> +#include <linux/mutex.h> #include <asm/uaccess.h> #include <linux/usb.h> #include <linux/poll.h>
@@ -256,7 +257,7 @@ static void tower_disconnect (struct usb/* prevent races between open() and disconnect */ -static DECLARE_MUTEX (disconnect_sem); +static DEFINE_MUTEX (disconnect_mutex);/* file operations needed when we register this driver */ static struct file_operations tower_fops = {
@@ -350,7 +351,7 @@ static int tower_open (struct inode *inononseekable_open (inode, file); subminor =iminor (inode); -down (&disconnect_sem); +mutex_lock (&disconnect_mutex); interface =usb_find_interface (&tower_driver, subminor);
@@ -428,7 +429,7 @@ unlock_exit:up (&dev->sem); unlock_disconnect_exit: -up (&disconnect_sem); +mutex_unlock (&disconnect_mutex);dbg (2 ,"%s: leave, return value %d " , __FUNCTION__, retval);
@@ -1006,7 +1007,7 @@ static void tower_disconnect (struct usbdbg (2 ,"%s: enter" , __FUNCTION__); -down (&disconnect_sem); +mutex_lock (&disconnect_mutex); dev =usb_get_intfdata (interface);usb_set_intfdata (interface,NULL );
@@ -1028,7 +1029,7 @@ static void tower_disconnect (struct usbup (&dev->sem); } -up (&disconnect_sem); +mutex_unlock (&disconnect_mutex);info ("LEGO USB Tower #%d now disconnected" , (minor -LEGO_USB_TOWER_MINOR_BASE ));
drivers/usb/serial/pl2303.c +0 -2
@@ -43,8 +43,6 @@ static int debug;#define PL2303_BUF_SIZE 1024#define PL2303_TMP_BUF_SIZE 1024 -static DECLARE_MUTEX (pl2303_tmp_buf_sem); -struct pl2303_buf {unsigned int buf_size;char *buf_buf;
kernel/kthread.c +4 -3
@@ -12,6 +12,7 @@#include <linux/unistd.h> #include <linux/file.h> #include <linux/module.h> +#include <linux/mutex.h> #include <asm/semaphore.h> /*
@@ -41,7 +42,7 @@ struct kthread_stop_info/* Thread stopping is done by setthing this var: lock serializes * multiple kthread_stop calls. */ -static DECLARE_MUTEX (kthread_stop_lock); +static DEFINE_MUTEX (kthread_stop_lock);static struct kthread_stop_info kthread_stop_info;int kthread_should_stop (void )
@@ -173,7 +174,7 @@ int kthread_stop_sem(struct task_struct {int ret; -down (&kthread_stop_lock); +mutex_lock (&kthread_stop_lock);/* It could exit after stop_info.k set, but before wake_up_process. */ get_task_struct (k);
@@ -194,7 +195,7 @@ int kthread_stop_sem(struct task_structwait_for_completion (&kthread_stop_info.done); kthread_stop_info.k =NULL ; ret = kthread_stop_info.err; -up (&kthread_stop_lock); +mutex_unlock (&kthread_stop_lock);return ret; }
kernel/module.c +8 -7
@@ -38,6 +38,7 @@#include <linux/device.h> #include <linux/string.h> #include <linux/sched.h> +#include <linux/mutex.h> #include <asm/uaccess.h> #include <asm/semaphore.h> #include <asm/cacheflush.h>
@@ -62,15 +63,15 @@ static DEFINE_SPINLOCK(modlist_lock);static DECLARE_MUTEX (module_mutex);static LIST_HEAD (modules); -static DECLARE_MUTEX (notify_mutex); +static DEFINE_MUTEX (notify_mutex);static struct notifier_block * module_notify_list;int register_module_notifier (struct notifier_block * nb) {int err; -down (¬ify_mutex); +mutex_lock (¬ify_mutex); err =notifier_chain_register (&module_notify_list, nb); -up (¬ify_mutex); +mutex_unlock (¬ify_mutex);return err; }EXPORT_SYMBOL (register_module_notifier);
@@ -78,9 +79,9 @@ EXPORT_SYMBOL(register_module_notifier);int unregister_module_notifier (struct notifier_block * nb) {int err; -down (¬ify_mutex); +mutex_lock (¬ify_mutex); err =notifier_chain_unregister (&module_notify_list, nb); -up (¬ify_mutex); +mutex_unlock (¬ify_mutex);return err; }EXPORT_SYMBOL (unregister_module_notifier);
@@ -1905,9 +1906,9 @@ sys_init_module(void __user *umod,/* Drop lock so they can recurse */ up (&module_mutex); -down (¬ify_mutex); +mutex_lock (¬ify_mutex);notifier_call_chain (&module_notify_list,MODULE_STATE_COMING , mod); -up (¬ify_mutex); +mutex_unlock (¬ify_mutex);/* Start the module */ if (mod->init !=NULL )
kernel/posix-timers.c +4 -3
@@ -35,6 +35,7 @@#include <linux/interrupt.h> #include <linux/slab.h> #include <linux/time.h> +#include <linux/mutex.h> #include <asm/uaccess.h> #include <asm/semaphore.h>
@@ -1312,7 +1313,7 @@ sys_clock_getres(clockid_t which_clock,static DECLARE_WAIT_QUEUE_HEAD (nanosleep_abs_wqueue); static DECLARE_WORK(clock_was_set_work, (void(*)(void*))clock_was_set, NULL); -static DECLARE_MUTEX (clock_was_set_lock); +static DEFINE_MUTEX (clock_was_set_lock);void clock_was_set (void ) {
@@ -1363,7 +1364,7 @@ void clock_was_set(void)*/ -down (&clock_was_set_lock); +mutex_lock (&clock_was_set_lock);spin_lock_irq (&abs_list.lock);list_splice_init (&abs_list.list, &cws_list);spin_unlock_irq (&abs_list.lock);
@@ -1389,7 +1390,7 @@ void clock_was_set(void)spin_unlock_irq (&abs_list.lock); }while (1 ); -up (&clock_was_set_lock); +mutex_unlock (&clock_was_set_lock); }long clock_nanosleep_restart (struct restart_block *restart_block);
kernel/power/pm.c +11 -10
@@ -25,6 +25,7 @@#include <linux/pm.h> #include <linux/pm_legacy.h> #include <linux/interrupt.h> +#include <linux/mutex.h> int pm_active;
@@ -40,7 +41,7 @@ int pm_active;* until a resume but that will be fine. */ -static DECLARE_MUTEX (pm_devs_lock); +static DEFINE_MUTEX (pm_devs_lock);static LIST_HEAD (pm_devs);/**
@@ -67,9 +68,9 @@ struct pm_dev *pm_register(pm_dev_t type dev->id = id; dev->callback = callback; -down (&pm_devs_lock); +mutex_lock (&pm_devs_lock);list_add (&dev->entry, &pm_devs); -up (&pm_devs_lock); +mutex_unlock (&pm_devs_lock); }return dev; }
@@ -85,9 +86,9 @@ struct pm_dev *pm_register(pm_dev_t typevoid pm_unregister (struct pm_dev *dev) {if (dev) { -down (&pm_devs_lock); +mutex_lock (&pm_devs_lock);list_del (&dev->entry); -up (&pm_devs_lock); +mutex_unlock (&pm_devs_lock);kfree (dev); }
@@ -118,7 +119,7 @@ void pm_unregister_all(pm_callback callbif (!callback)return ; -down (&pm_devs_lock); +mutex_lock (&pm_devs_lock); entry = pm_devs.next;while (entry != &pm_devs) { struct pm_dev *dev = list_entry(entry, struct pm_dev, entry);
@@ -126,7 +127,7 @@ void pm_unregister_all(pm_callback callbif (dev->callback == callback)__pm_unregister (dev); } -up (&pm_devs_lock); +mutex_unlock (&pm_devs_lock); }/**
@@ -234,7 +235,7 @@ int pm_send_all(pm_request_t rqst, void {struct list_head *entry; -down (&pm_devs_lock); +mutex_lock (&pm_devs_lock); entry = pm_devs.next;while (entry != &pm_devs) { struct pm_dev *dev = list_entry(entry, struct pm_dev, entry);
@@ -246,13 +247,13 @@ int pm_send_all(pm_request_t rqst, void*/ if (rqst ==PM_SUSPEND )pm_undo_all (dev); -up (&pm_devs_lock); +mutex_unlock (&pm_devs_lock);return status; } } entry = entry->next; } -up (&pm_devs_lock); +mutex_unlock (&pm_devs_lock);return 0 ; }
kernel/profile.c +6 -5
@@ -23,6 +23,7 @@#include <linux/cpu.h> #include <linux/profile.h> #include <linux/highmem.h> +#include <linux/mutex.h> #include <asm/sections.h> #include <asm/semaphore.h>
@@ -44,7 +45,7 @@ static cpumask_t prof_cpu_mask = CPU_MAS#ifdef CONFIG_SMP static DEFINE_PER_CPU(struct profile_hit *[2], cpu_profile_hits); static DEFINE_PER_CPU(int, cpu_profile_flip); -static DECLARE_MUTEX (profile_flip_mutex); +static DEFINE_MUTEX (profile_flip_mutex);#endif /* CONFIG_SMP */ static int __init profile_setup (char * str)
@@ -243,7 +244,7 @@ static void profile_flip_buffers(void) {int i, j, cpu; -down (&profile_flip_mutex); +mutex_lock (&profile_flip_mutex); j =per_cpu (cpu_profile_flip,get_cpu ());put_cpu ();on_each_cpu (__profile_flip_buffers,NULL ,0 ,1 );
@@ -259,14 +260,14 @@ static void profile_flip_buffers(void) hits[i].hits = hits[i].pc =0 ; } } -up (&profile_flip_mutex); +mutex_unlock (&profile_flip_mutex); }static void profile_discard_flip_buffers (void ) {int i, cpu; -down (&profile_flip_mutex); +mutex_lock (&profile_flip_mutex); i =per_cpu (cpu_profile_flip,get_cpu ());put_cpu ();on_each_cpu (__profile_flip_buffers,NULL ,0 ,1 );
@@ -274,7 +275,7 @@ static void profile_discard_flip_buffersstruct profile_hit *hits =per_cpu (cpu_profile_hits, cpu)[i];memset (hits,0 ,NR_PROFILE_HIT *sizeof (struct profile_hit )); } -up (&profile_flip_mutex); +mutex_unlock (&profile_flip_mutex); }void profile_hit (int type,void *__pc)
lib/reed_solomon/reed_solomon.c +6 -5
@@ -44,12 +44,13 @@#include <linux/module.h> #include <linux/rslib.h> #include <linux/slab.h> +#include <linux/mutex.h> #include <asm/semaphore.h> /* This list holds all currently allocated rs control structures */ static LIST_HEAD (rslist);/* Protection for the list */ -static DECLARE_MUTEX (rslistlock); +static DEFINE_MUTEX (rslistlock);/** * rs_init - Initialize a Reed-Solomon codec
@@ -161,7 +162,7 @@ errrs:*/ void free_rs (struct rs_control *rs) { -down (&rslistlock); +mutex_lock (&rslistlock); rs->users--;if (!rs->users) {list_del (&rs->list);
@@ -170,7 +171,7 @@ void free_rs(struct rs_control *rs)kfree (rs->genpoly);kfree (rs); } -up (&rslistlock); +mutex_unlock (&rslistlock); }/**
@@ -201,7 +202,7 @@ struct rs_control *init_rs(int symsize,if (nroots <0 || nroots >= (1 <<symsize))return NULL ; -down (&rslistlock); +mutex_lock (&rslistlock);/* Walk through the list and look for a matching entry */ list_for_each (tmp, &rslist) {
@@ -228,7 +229,7 @@ struct rs_control *init_rs(int symsize,list_add (&rs->list, &rslist); } out: -up (&rslistlock); +mutex_unlock (&rslistlock);return rs; }
security/keys/process_keys.c +4 -3
@@ -16,11 +16,12 @@#include <linux/keyctl.h> #include <linux/fs.h> #include <linux/err.h> +#include <linux/mutex.h> #include <asm/uaccess.h> #include "internal.h" /* session keyring create vs join semaphore */ -static DECLARE_MUTEX (key_session_sem); +static DEFINE_MUTEX (key_session_mutex);/* the root user's tracking struct */ struct key_user root_key_user = {
@@ -706,7 +707,7 @@ long join_session_keyring(const char *na }/* allow the user to join or create a named keyring */ -down (&key_session_sem); +mutex_lock (&key_session_mutex);/* look for an existing keyring of this name */ keyring =find_keyring_by_name (name,0 );
@@ -732,7 +733,7 @@ long join_session_keyring(const char *nakey_put (keyring); error2: -up (&key_session_sem); +mutex_unlock (&key_session_mutex); error:return ret;
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
"Ingo" == Ingo Molnar <[email protected]> writes:
Ingo> this is the latest version of the mutex subsystem Ingo> patch-queue. It consists of the following patches:
[snip]
Ingo> the patches are against Linus' latest tree, and were tested on Ingo> i386, x86_64 and ia64. [the tests were also done in Ingo> DEBUG_MUTEX_FULL mode, to make sure the code works Ingo> fine. MUTEX_FULL support is not included in this patchqueue].
Hi,
I have been working with Ingo on porting this to ehe ia64 and run a bunch of benchmarks using the DEBUG_MUTEX_FULL settings to see how it behaves on various sized systems (8, 24 and 60 CPUs). In general I am seeing speedups of roughly a factor 4 on XFS and 2.4 on TMPFS.
Below you will find the results. It's basically the same kernel version with and without the mutex patch running in DEBUG_MUTEX_FULL mode without debugging enabled. No other config options were changed.
I won't rule out any pilot errors, but at least it gives an idea about the change in performance for a specific workload on different sized boxes.
Cheers,
Jes
All tests on 2.6.15-rc6 with and without the mutex patch, using the same test app used by Ingo. MUTEX refers to the mutex kernel and the 'no mutex' numbers are for the regular kernel.
I have run the tests on the following systems:
8-way system (1.3GHz ia64)
24-way system (1.3GHz ia64)
60-way system (1.5GHz ia64)
===========================
Tests on XFS MUTEX NO MUTEX
8 CPUs, running 16 parallel test-tasks.
avg ops/sec: 173589 43136 average cost per op: 80.97 usecs 327.03 usecs average cost per lock: 79.69 usecs 325.20 usecs average cost per unlock: 1.28 usecs 1.83 usecs average deviance per op: 65.75 usecs 191.65 usecs
24 CPUs, running 48 parallel test-tasks.
avg ops/sec: 156312 38976 average cost per op: 277.80 usecs 1087.65 usecs average cost per lock: 276.06 usecs 1085.43 usecs average cost per unlock: 1.74 usecs 2.22 usecs average deviance per op: 229.80 usecs 613.78 usecs
60 CPUs, running 120 parallel test-tasks.
avg ops/sec: 188204 41794 average cost per op: 678.86 usecs 2538.53 usecs average cost per lock: 675.56 usecs 2536.53 usecs average cost per unlock: 3.29 usecs 1.99 usecs average deviance per op: 565.65 usecs 1584.21 usecs
60 CPUs, running 540 parallel test-tasks.
avg ops/sec: 181230 44757 average cost per op: 3131.09 usecs 10711.06 usecs average cost per lock: 3128.05 usecs 10709.21 usecs average cost per unlock: 3.04 usecs 1.86 usecs average deviance per op: 2525.36 usecs 6787.48 usecs
Tests on TMPFS MUTEX NO MUTEX
8 CPUs, running 16 parallel test-tasks.
avg ops/sec: 139621 57817 average cost per op: 100.70 usecs 243.71 usecs average cost per lock: 98.54 usecs 242.28 usecs average cost per unlock: 2.16 usecs 1.43 usecs average deviance per op: 76.03 usecs 156.32 usecs
Quoted 20 lines · Jes Sorensen
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
"Ingo" == Ingo Molnar <[email protected]> writes:
Ingo> this is the latest version of the mutex subsystem Ingo> patch-queue. It consists of the following patches:
[snip]
Ingo> the patches are against Linus' latest tree, and were tested on Ingo> i386,
x86_64and ia64. [the tests were also done in Ingo>DEBUG_MUTEX_FULLmode, to make sure the code works Ingo> fine.MUTEX_FULLsupport is not included in this patchqueue].Hi,
I have been working with Ingo on porting this to ehe ia64 and run a bunch of benchmarks using the
DEBUG_MUTEX_FULLsettings to see how it behaves on various sized systems (8, 24 and 60 CPUs). In general I am seeing speedups of roughly a factor 4 on XFS and 2.4 on TMPFS.
Quoted 8 lines
Below you will find the results. It's basically the same kernel version with and without the mutex patch running in
DEBUG_MUTEX_FULLmode without debugging enabled. No other config options were changed.I won't rule out any pilot errors, but at least it gives an idea about the change in performance for a specific workload on different sized boxes.
It would be nice to first do a run with a fair implementation of mutexes.
The improvements are definitely large enough that you cannot dismiss the unfair implementation... I wonder if you can record a maximum cost per op? That would be more interesting than either average or standard deviation.
Thanks,
Nick
Signature · 3 lines
SUSE Labs, Novell Inc. Send instant messages to your online friends http://au.messenger.yahoo.com
Quoted 4 lines · Nick Piggin
I wonder if you can record a maximum
cost per op? That would be more interesting than either average or standard deviation.
More interesting from a fairness point of view, I mean.
Signature · 3 lines
SUSE Labs, Novell Inc. Send instant messages to your online friends http://au.messenger.yahoo.com
Quoted 2 lines · Nick Piggin
It would be nice to first do a run with a fair implementation of mutexes.
which fairness implementation do you mean - the one where all tasks will get the lock in fair FIFO order, and a 'lucky bastard' cannot steal the lock from waiters and thus put them at an indefinite disadvantage?
Ingo
Quoted 8 lines · Ingo Molnar
Quoted 1 line · Nick Piggin
It would be nice to first do a run with a fair implementation of mutexes.
which fairness implementation do you mean - the one where all tasks will get the lock in fair FIFO order, and a 'lucky bastard' cannot steal the lock from waiters and thus put them at an indefinite disadvantage?
I guess so. I'm not so worried about the rare 'lucky bastard' ie. a lock request coming in concurrently, but rather the naturally favoured 'this CPU' taking the lock again after waking up the head waiter but before it gets a chance to run / transfer the cacheline.
At the very least, the head waiter should not put itself on the end of the FIFO when it finds the lock contended and waits again.
But yes, also interesting would be performance of the _completely_ FIFO implementation.
Signature · 3 lines
SUSE Labs, Novell Inc. Send instant messages to your online friends http://au.messenger.yahoo.com
Quoted 13 lines · Nick Piggin
Quoted 11 lines · Ingo Molnar
Quoted 2 lines · Nick Piggin
It would be nice to first do a run with a fair implementation of mutexes.
which fairness implementation do you mean - the one where all tasks will get the lock in fair FIFO order, and a 'lucky bastard' cannot steal the lock from waiters and thus put them at an indefinite disadvantage?
Quoted 4 lines
I guess so. I'm not so worried about the rare 'lucky bastard' ie. a lock request coming in concurrently, but rather the naturally favoured 'this CPU' taking the lock again after waking up the head waiter but before it gets a chance to run / transfer the cacheline.
that's just the most evil lucky bastard....
Quoted 14 lines · Arjan van de Ven
Quoted 12 lines · Nick Piggin
Quoted 9 lines · Ingo Molnar
Quoted 1 line · Nick Piggin
It would be nice to first do a run with a fair implementation of mutexes.
which fairness implementation do you mean - the one where all tasks will get the lock in fair FIFO order, and a 'lucky bastard' cannot steal the lock from waiters and thus put them at an indefinite disadvantage?
Quoted 8 lines
Quoted 4 lines
I guess so. I'm not so worried about the rare 'lucky bastard' ie. a lock request coming in concurrently, but rather the naturally favoured 'this CPU' taking the lock again after waking up the head waiter but before it gets a chance to run / transfer the cacheline.
that's just the most evil lucky bastard....
I'd probably just call "bastard": it is probably _unlucky_ when _doesn't_ get to retake the lock, judging by the factor-of-4 speedup that Jes demonstrated.
Which might be the right thing to do, but having the front waiter go to the back of the queue I think is not.
Signature · 3 lines
SUSE Labs, Novell Inc. Send instant messages to your online friends http://au.messenger.yahoo.com
Quoted 4 lines
I'd probably just call "bastard": it is probably _unlucky_ when _doesn't_ get to retake the lock, judging by the factor-of-4 speedup that Jes demonstrated.
I suspect that's more avoiding the double wakeup that semaphores have (semaphores aren't quite fair either)
Quoted 3 lines
Which might be the right thing to do, but having the front waiter go to the back of the queue I think is not.
afaik that isn't happening though.
Quoted 8 lines · Arjan van de Ven
Quoted 3 lines
I'd probably just call "bastard": it is probably _unlucky_ when _doesn't_ get to retake the lock, judging by the factor-of-4 speedup that Jes demonstrated.
I suspect that's more avoiding the double wakeup that semaphores have (semaphores aren't quite fair either)
It would be great if that were the case.
Quoted 7 lines
Quoted 3 lines
Which might be the right thing to do, but having the front waiter go to the back of the queue I think is not.
afaik that isn't happening though.
AFAIKS it does.
Failed lockers will go through to __mutex_lock_nonatomic, which calls __mutex_lock_common to queue it on the tail of the FIFO list race-free.
__mutex_lock_nonatomic then sleeps, waiting for the task to become head of the list and be worken up.
__mutex_lock_nonatomic then removes this task from the FIFO and calls __mutex_lock_common again.
If I read right, not only is it a fairness problem, but it could also harm performance because it will cycle through all waiting tasks rather than just the next one to go.
If I don't read right... can you explain how it works? :P
Signature · 3 lines
SUSE Labs, Novell Inc. Send instant messages to your online friends http://au.messenger.yahoo.com
Quoted 2 lines · Nick Piggin
At the very least, the head waiter should not put itself on the end of the FIFO when it finds the lock contended and waits again.
It's on my list. I had this implemented a couple of days ago, but then profiled it and it turns out that the scenario isnt actually happening in any significant way, not even on the most extreme 512-task workloads. So i just removed the extra bloat. But i'll look at this again today, together with some 'max delay' statistics.
Ingo
Quoted 8 lines · Ingo Molnar
Quoted 1 line · Nick Piggin
At the very least, the head waiter should not put itself on the end of the FIFO when it finds the lock contended and waits again.
It's on my list. I had this implemented a couple of days ago, but then profiled it and it turns out that the scenario isnt actually happening in any significant way, not even on the most extreme 512-task workloads. So i just removed the extra bloat. But i'll look at this again today, together with some 'max delay' statistics.
That would be good.
If it isn't happening in a significant quantity, then something else must be responsible for the performance increase. Arjan guesses the double wakeups which could be the case, but I'd still put my money on this issue (or maybe it is a combination of both).
Either way it would be good to work out where the performance is coming from, and I do think fixing this is a good idea for fairness (even though it may not technically improve deterministic max latencies because there are still race windows)
Signature · 3 lines
SUSE Labs, Novell Inc. Send instant messages to your online friends http://au.messenger.yahoo.com
Quoted 7 lines · Ingo Molnar
Changes since the previous version:
- removed the fastpath dependency on
__HAVE_ARCH_CMPXCHG: now every architecture is able to use the generic mutex_lock/mutex_unlock lockless fastpath. The quality of the fastpath is still as good as in the previous version.
Quoted 8 lines
- added
ARCH_IMPLEMENTS_MUTEX_FASTPATHfor architectures that want to hand-code their own fastpath. Themutex_lock_slowpath,mutex_unlock_slowpathandmutex_lock_interruptible_slowpathglobal functions can be used by such architectures in this case, and they should implement themutex_lock(),mutex_unlock()andmutex_lock_interruptible()functions themselves. I have tested this mechanism on x86. (but x86 wants to use the generic functions otherwise, so those changes are not included in this patchqueue.)
This is a good step in the right direction for ARM, but not quite there yet.
As it is, the core mutex code is still relying on atomic decrement/increment to work properly. What would be extremely beneficial on ARM is to be able to use (variants of) atomic_xchg everywhere. And the semantics of a mutex allows that where a semaphore doesn't (which is why I see big benefits for ARM with mutexes).
I even forsee a fast path implementation on ARMv6 that would use an hybrid approach which will be less instructions and cycles than a standard atomic decrement/increment (they are available only on ARM version 6 and above).
What we'd need is a bit more flexibility but only at the low level. No need to reimplement the whole of mutex_lock(), mutex_unlock(), and friends.
Please consider the 3 following patches that already bring an immediate benefit on ARM, even if the fast path isn't inlined yet.
Nicolas
PATCH 1/3 mutex subsystem: fix additions to the ARM atomic.h
In reply to Ingo MolnarThe original patch added new definitions to include/asm-arm/atomic.h inside the #if __LINUX_ARM_ARCH__ >= 6 and therefore they were unavailable on non ARMv6 builds. Move them outside that #if.
---
include/asm-arm/atomic.h +13 -13
@@ -99,19 +99,6 @@ static inline int atomic_cmpxchg(atomic_return oldval; } -#define atomic_xchg (v, new) (xchg(&((v)->counter), new)) - -/* -* Pull in the generic wrappers for atomic_dec_call_if_negative() and -* atomic_inc_call_if_nonpositive(). -* -* TODO: implement optimized primitives instead, or leave the generic -* implementation in place, or use the ARCH_IMPLEMENTS_MUTEX_FASTPATH -* mechanism to override the generic mutex_lock()/mutex_unlock() -* functions. -*/ -#include <asm-generic/atomic-call-if.h> -static inline void atomic_clear_mask (unsigned long mask,unsigned long *addr) {unsigned long tmp, tmp2;
@@ -188,6 +175,19 @@ static inline void atomic_clear_mask(uns#endif /* __LINUX_ARM_ARCH__ */ +#define atomic_xchg (v, new) (xchg(&((v)->counter), new)) + +/* +* Pull in the generic wrappers for atomic_dec_call_if_negative() and +* atomic_inc_call_if_nonpositive(). +* +* TODO: implement optimized primitives instead, or leave the generic +* implementation in place, or use the ARCH_IMPLEMENTS_MUTEX_FASTPATH +* mechanism to override the generic mutex_lock()/mutex_unlock() +* functions. +*/ +#include <asm-generic/atomic-call-if.h> +static inline int atomic_add_unless (atomic_t *v,int a,int u) {int c, old;
PATCH 2/3 mutex subsystem: add new atomic primitives
In reply to Ingo MolnarWhile atomic_dec_call_if_negative() and atomic_inc_call_if_nonpositive() are certainly really nice and probably a good starting point for some consolidation of the different semaphore implementations, they still have stricter semantics than necessary for mutex usage.
This patch adds 3 new helpers that allows for greater flexibility in their implementation while preserving the mutex semantics:
atomic_lock_call_if_contended()
atomic_unlock_call_if_contended()
atomic_contended_unlock_fixup()
In particular, they can be implemented in terms of a single atomic swap which most architectures can do natively without any locking. With this the mutex optimizations only have to be done in those atomic helpers while everything else may be generic common code.
On i386 and x86_64 those new helpers are simply defined in terms of the existing atomic_dec_call_if_negative() and atomic_inc_call_if_nonpositive() since they already provide the best that can be done.
---
include/asm-generic/atomic-call-if.h +47 -0
@@ -34,4 +34,51 @@ do { \fn_name (v); \ } while (0) +/** +* atomic_lock_call_if_contended - lock and call function if already locked +* @v: pointer of type atomic_t +* @fn: function to call if v was already locked +* +* Atomically locks @v and calls a function if @v was already locked. +* When @v == 1 it is unlocked, <= 0 means locked. + */ +#define atomic_lock_call_if_contended (v, fn_name) \ +do { \ + if (atomic_xchg(v, 0) != 1) \ + fn_name(v); \ +} while (0) + +/** +* atomic_unlock_call_if_contended - unlock and call function if contended +* @v: pointer of type atomic_t +* @fn: function to call if the value was contended +* +* Atomically unlocks @v and calls a function if @v was contended. +* When @v == 1 it is unlocked, 0 it is locked, any negative value means +* locked with contention. When @v is contended, it is undefined whether @v +* is locked or not (implementation dependent) after this call until the @fn +* function uses atomic_contended_unlock_fixup() to apply the necessary +* fixup (if any). +*/ +#define atomic_unlock_call_if_contended (v, fn_name) \ +do { \ + if (atomic_xchg(v, 1) != 0) \ + fn_name(v); \ +} while (0) + +/** +* atomic_contended_unlock_fixup - apply any needed fixup for contended unlock +* +* @v: pointer of type atomic_t +* +* This is meant to be called unconditionally from any function passed to +* atomic_unlock_call_if_contended. Provides any needed fixup for unlocking +* @v if the implementation of atomic_unlock_call_if_contended didn't manage +* to unlock it in the contended case. +*/ +#define atomic_contended_unlock_fixup(v) \ +do { \ + /* the xchg-based unlock doesn't need any fixup */ \ +} while (0) +#endif
include/asm-i386/atomic.h +40 -0
@@ -294,6 +294,46 @@ do { \ :"memory","cx","dx"); \ }while (0 ) +/** +* atomic_lock_call_if_contended - lock and call function if already locked +* @v: pointer of type atomic_t +* @fn: function to call if v was already locked +* +* Atomically locks @v and calls a function if @v was already locked. +* When @v == 1 it is unlocked, <= 0 means locked. + */ +#define atomic_lock_call_if_contended (v, fn_name) \ + atomic_dec_call_if_negative(v, fn_name) + +/** +* atomic_unlock_call_if_contended - unlock and call function if contended +* @v: pointer of type atomic_t +* @fn: function to call if the value was contended +* +* Atomically unlocks @v and calls a function if @v was contended. +* When @v == 1 it is unlocked, 0 it is locked, any negative value means +* locked with contention. When @v is contended, it is undefined whether @v +* is locked or not (implementation dependent) after this call until the @fn +* function uses atomic_contended_unlock_fixup() to apply the necessary +* fixup (if any). +*/ +#define atomic_unlock_call_if_contended (v, fn_name) \ + atomic_inc_call_if_nonpositive(v, fn_name) + +/** +* atomic_contended_unlock_fixup - apply any needed fixup for contended unlock +* +* @v: pointer of type atomic_t +* +* This is meant to be called unconditionally from any function passed to +* atomic_unlock_call_if_contended. Provides any needed fixup for unlocking +* @v if the implementation of atomic_unlock_call_if_contended didn't manage +* to unlock it in the contended case. +*/ +#define atomic_contended_unlock_fixup (v) \ +do { \ + atomic_set(v, 1); \ +} while (0)/* These are x86-specific, used by some header files */ #define atomic_clear_mask (mask, addr) \
include/asm-x86_64/atomic.h +41 -0
47 lines not on this page · raw message
PATCH 3/3 mutex subsystem: move the core to the new atomic helpers
In reply to Ingo MolnarThis patch moves the core mutex code over to the atomic helpers from previous patch. There is no change for i386 and x86_64, except for the forced unlock state that is now done outside the spinlock (doing so doesn't matter since another CPU could have locked the mutex right away even if it was unlocked inside the spinlock). This however brings great improvements on ARM for example.
---
kernel/mutex.c +15 -10
@@ -296,14 +296,6 @@ static inline void __mutex_unlock_nonatodebug_mutex_unlock (lock); -/* -* Set it back to 'unlocked'. We'll have a waiter in flight -* (if any), and if some other task comes around, let it -* steal the lock. Waiters take care of themselves and stay -* in flight until necessary. -*/ -atomic_set (&lock->count,1 ); -if (!list_empty (&lock->wait_list)) mutex_wakeup_waiter(lock __IP__);
@@ -329,7 +321,7 @@ static __sched void FASTCALL(__mutex_loc*/ static inline void __mutex_lock_atomic (struct mutex *lock) { -atomic_dec_call_if_negative (&lock->count, __mutex_lock_noinline); +atomic_lock_call_if_contended (&lock->count, __mutex_lock_noinline); } static fastcall __sched void __mutex_lock_noinline(atomic_t *lock_count)
@@ -359,13 +351,19 @@ static void __sched FASTCALL(__mutex_unl*/ static inline void __mutex_unlock_atomic (struct mutex *lock) { -atomic_inc_call_if_nonpositive (&lock->count, __mutex_unlock_noinline); +atomic_unlock_call_if_contended (&lock->count, __mutex_unlock_noinline); } static fastcall void __sched __mutex_unlock_noinline(atomic_t *lock_count) { struct mutex *lock = container_of(lock_count, struct mutex, count); +/* +* We were called via atomic_unlock_call_if_contended() therefore +* we need to call atomic_contended_unlock_fixup() which will set +* it to unlocked (if it wasn't done already). +*/ +atomic_contended_unlock_fixup (lock_count);__mutex_unlock_nonatomic (lock); }
@@ -383,6 +381,13 @@ static inline void __mutex_lock(struct m static inline void __mutex_unlock(struct mutex *lock __IP_DECL__) { +/* +* Set it back to 'unlocked'. We'll have a waiter in flight +* (if any), and if some other task comes around, let it +* steal the lock. Waiters take care of themselves and stay +* in flight until necessary. +*/ +atomic_set (&lock->count,1 ); __mutex_unlock_nonatomic(lock __IP__); }
Re: [patch 3/3] mutex subsystem: move the core to the new atomic helpers
Quoted 6 lines · Nicolas Pitre
This patch moves the core mutex code over to the atomic helpers from previous patch. There is no change for i386 and
x86_64, except for the forced unlock state that is now done outside the spinlock (doing so doesn't matter since another CPU could have locked the mutex right away even if it was unlocked inside the spinlock). This however brings great improvements on ARM for example.
i'm wondering how much difference it makes on ARM - could you show us the before and after disassembly of the fastpath, to see the improvement?
your patches look OK to me, only one small detail sticks out: i'd suggest to rename the atomic_*_contended macros to be arch_mutex_*_..., i dont think any other code can make use of it. Also, it would be nice to see the actual ARM patches as well, which make use of the new infrastructure.
could you resend them against my latest queue that i just posted? I'll look at integrating them tomorrow.
Ingo
Re: [patch 3/3] mutex subsystem: move the core to the new atomic helpers
Quoted 14 lines · Ingo Molnar
Quoted 6 lines · Nicolas Pitre
This patch moves the core mutex code over to the atomic helpers from previous patch. There is no change for i386 and
x86_64, except for the forced unlock state that is now done outside the spinlock (doing so doesn't matter since another CPU could have locked the mutex right away even if it was unlocked inside the spinlock). This however brings great improvements on ARM for example.i'm wondering how much difference it makes on ARM - could you show us the before and after disassembly of the fastpath, to see the improvement?
Quoted 5 lines
your patches look OK to me, only one small detail sticks out: i'd suggest to rename the atomic_*_contended macros to be arch_mutex_*_..., i dont think any other code can make use of it. Also, it would be nice to see the actual ARM patches as well, which make use of the new infrastructure.
I'm personally a little worried about the recent proliferation of atomic_*.
My take on atomic_* functions has always been: a "sensible" arch [1] implements the functionality in a single atomic instruction and this simply exposes that instruction at the C level which otherwise lacks appropriate semantics.
So functions like atomic_dec_call_if_negative seem a) excessively special purpose b) not fundamental in the ought-to-be-a-single-instruction sense c) a bit out of place in the in the atomic_* set. These might even encourage people to roll their own special-purpose locking primitives and we have way too many of those already.
[1] In Linus' famous sense of what an ideal architecture should look like
Signature · 1 line
Mathematics is the supreme nostalgia of our time.
Re: [patch 3/3] mutex subsystem: move the core to the new atomic helpers
In reply to Ingo MolnarQuoted 10 lines · Ingo Molnar
Quoted 6 lines · Nicolas Pitre
This patch moves the core mutex code over to the atomic helpers from previous patch. There is no change for i386 and
x86_64, except for the forced unlock state that is now done outside the spinlock (doing so doesn't matter since another CPU could have locked the mutex right away even if it was unlocked inside the spinlock). This however brings great improvements on ARM for example.
Quoted 3 lines
i'm wondering how much difference it makes on ARM - could you show us the before and after disassembly of the fastpath, to see the improvement?
The only way to do an atomic decrement on 99% of all ARM processors in the field requires disabling interrupts. So for instance:
void __mutex_lock(struct mutex *lock)
{
if (atomic_dec_return(&lock->count) < 0)
__mutex_lock_failed(lock);
}Would produce:
__mutex_lock_atomic:
mrs r1, cpsr @ local_irq_save orr r3, r1, #128 msr cpsr_c, r3 ldr r3, [r0, #0] sub r3, r3, #1 str r3, [r0, #0] msr cpsr_c, r1 @ local_irq_restore cmp r3, #0 movge pc, lr b __mutex_lock_failed
I can measure 23 cycles on an XScale processor for the first 8 instructions which corresponds to the "if (atomic_dec_return(v) < 0)".
It was suggested that a preempt_disable()/preempt_enable() would be sufficient and probably faster than the IRQ disable... which turned not to be true for non-XScale ARM variants. It would take 14 instructions on all variants, and on XScale it needs 20 cycles.
Now with my patch applied, it looks like this:
void __mutex_lock(struct mutex *lock)
{
if (atomic_xchg(&lock->count, 0) != 1)
__mutex_lock_failed(lock);
}with the following assembly:
__mutex_lock_atomic:
mov r3, #0 swp r2, r3, [r0] cmp r2, #1 moveq pc, lr b __mutex_lock_failed
The equivalent of the first 8 instructions in the first example is now down to 3. And when gcc can cse the constant 0 (which is not possible with the first example) then it would be only 2 instructions, which is really nice to inline. And the above takes only 8 cycles on an XScale instead of 20-23 cycles.
Quoted 3 lines
your patches look OK to me, only one small detail sticks out: i'd suggest to rename the atomic_*_contended macros to be arch_mutex_*_..., i dont think any other code can make use of it.
OK.
Quoted 3 lines
Also, it would be nice
to see the actual ARM patches as well, which make use of the new infrastructure.
Well, with the generic functions based on atomic_xchg() the generated code is pretty good actually. I don't think I could pack it more with a special handler. Well for ARM version 6 I have a kunning idea though... maybe for tomorrow.
Quoted 2 lines
could you resend them against my latest queue that i just posted? I'll look at integrating them tomorrow.
Yes, please find them in following emails.
Nicolas
PATCH 1/5 mutex subsystem: fix asm-arm/atomic.h
In reply to Ingo MolnarThe original patch added new definitions to include/asm-arm/atomic.h inside the #if __LINUX_ARM_ARCH__ >= 6 and therefore they were unavailable on non ARMv6 builds. Move them outside that #if.
---
include/asm-arm/atomic.h +13 -13
@@ -99,19 +99,6 @@ static inline int atomic_cmpxchg(atomic_return oldval; } -#define atomic_xchg (v, new) (xchg(&((v)->counter), new)) - -/* -* Pull in the generic wrappers for atomic_dec_call_if_negative() and -* atomic_inc_call_if_nonpositive(). -* -* TODO: implement optimized primitives instead, or leave the generic -* implementation in place, or use the ARCH_IMPLEMENTS_MUTEX_FASTPATH -* mechanism to override the generic mutex_lock()/mutex_unlock() -* functions. -*/ -#include <asm-generic/atomic-call-if.h> -static inline void atomic_clear_mask (unsigned long mask,unsigned long *addr) {unsigned long tmp, tmp2;
@@ -188,6 +175,19 @@ static inline void atomic_clear_mask(uns#endif /* __LINUX_ARM_ARCH__ */ +#define atomic_xchg (v, new) (xchg(&((v)->counter), new)) + +/* +* Pull in the generic wrappers for atomic_dec_call_if_negative() and +* atomic_inc_call_if_nonpositive(). +* +* TODO: implement optimized primitives instead, or leave the generic +* implementation in place, or use the ARCH_IMPLEMENTS_MUTEX_FASTPATH +* mechanism to override the generic mutex_lock()/mutex_unlock() +* functions. +*/ +#include <asm-generic/atomic-call-if.h> +static inline int atomic_add_unless (atomic_t *v,int a,int u) {int c, old;
PATCH 2/5 mutex subsystem: add architecture specific mutex primitives
In reply to Ingo MolnarWhile atomic_dec_call_if_negative() and atomic_inc_call_if_nonpositive() are certainly really nice and probably a good starting point for some consolidation of the different semaphore implementations, they still have stricter semantics than necessary for mutex usage.
This patch adds 2 new helpers that allows for greater flexibility in their implementation while preserving the mutex semantics:
arch_mutex_fast_lock()
arch_mutex_fast_unlock()
In particular, they can be implemented in terms of a single atomic swap which most architectures can do natively without any locking. With this the mutex optimizations only have to be done in those atomic helpers while everything else may be generic common code.
On i386 and x86_64 those new helpers are simply defined in terms of the existing atomic_dec_call_if_negative() and atomic_inc_call_if_nonpositive() since they already provide the best implementation that can be done.
A new include/asm/mutex.h file is created for all architectures and they all default to including asm-generic/mutex.h for now, except for i386 and x86_64 which have their own definitions.
---
include/asm-alpha/mutex.h new file +1 -0
@@ -0,0 +1 @@ +#include <asm-generic/mutex.h>
include/asm-arm/mutex.h new file +1 -0
@@ -0,0 +1 @@ +#include <asm-generic/mutex.h>
include/asm-arm26/mutex.h new file +1 -0
@@ -0,0 +1 @@ +#include <asm-generic/mutex.h>
include/asm-cris/mutex.h new file +1 -0
@@ -0,0 +1 @@ +#include <asm-generic/mutex.h>
include/asm-frv/mutex.h new file +1 -0
@@ -0,0 +1 @@ +#include <asm-generic/mutex.h>
include/asm-generic/mutex.h new file +62 -0
62 lines not on this page · raw message
include/asm-h8300/mutex.h new file +1 -0
@@ -0,0 +1 @@ +#include <asm-generic/mutex.h>
include/asm-i386/mutex.h new file +23 -0
@@ -0,0 +1,23 @@ +/* +* asm-i386/mutex.h +* +* Optimized i386 low-level mutex fast path locking and unlocking. +*/ + +#ifndef _ASM_MUTEX_H +#define _ASM_MUTEX_H + +#include <asm/atomic.h> + +/* Please look into asm-generic/mutex.h for a description of those */ + +#define arch_mutex_fast_lock (v, contention_fn) \ + atomic_dec_call_if_negative(v, contention_fn) + +#define arch_mutex_fast_unlock (v, contention_fn) \ + atomic_inc_call_if_nonpositive(v, contention_fn) + +#define arch_mutex_unlock_fixup (v) \ + atomic_set(v, 1) + +#endif
include/asm-ia64/mutex.h new file +1 -0
@@ -0,0 +1 @@ +#include <asm-generic/mutex.h>
include/asm-m32r/mutex.h new file +1 -0
@@ -0,0 +1 @@ +#include <asm-generic/mutex.h>
include/asm-m68k/mutex.h new file +1 -0
@@ -0,0 +1 @@ +#include <asm-generic/mutex.h>
include/asm-m68knommu/mutex.h new file +1 -0
@@ -0,0 +1 @@ +#include <asm-generic/mutex.h>
include/asm-mips/mutex.h new file +1 -0
@@ -0,0 +1 @@ +#include <asm-generic/mutex.h>
include/asm-parisc/mutex.h new file +1 -0
@@ -0,0 +1 @@ +#include <asm-generic/mutex.h>
include/asm-powerpc/mutex.h new file +1 -0
@@ -0,0 +1 @@ +#include <asm-generic/mutex.h>
include/asm-ppc/mutex.h new file +1 -0
@@ -0,0 +1 @@ +#include <asm-generic/mutex.h>
include/asm-ppc64/mutex.h new file +1 -0
@@ -0,0 +1 @@ +#include <asm-generic/mutex.h>
include/asm-s390/mutex.h new file +1 -0
@@ -0,0 +1 @@ +#include <asm-generic/mutex.h>
include/asm-sh/mutex.h new file +1 -0
@@ -0,0 +1 @@ +#include <asm-generic/mutex.h>
include/asm-sh64/mutex.h new file +1 -0
@@ -0,0 +1 @@ +#include <asm-generic/mutex.h>
include/asm-sparc/mutex.h new file +1 -0
@@ -0,0 +1 @@ +#include <asm-generic/mutex.h>
include/asm-sparc64/mutex.h new file +1 -0
@@ -0,0 +1 @@ +#include <asm-generic/mutex.h>
include/asm-um/mutex.h new file +1 -0
@@ -0,0 +1 @@ +#include <asm-generic/mutex.h>
include/asm-v850/mutex.h new file +1 -0
@@ -0,0 +1 @@ +#include <asm-generic/mutex.h>
include/asm-x86_64/mutex.h new file +23 -0
@@ -0,0 +1,23 @@ +/* +* asm-x86_64/mutex.h +* +* Optimized x86_64 low-level mutex fast path locking and unlocking. +*/ + +#ifndef _ASM_MUTEX_H +#define _ASM_MUTEX_H + +#include <asm/atomic.h> + +/* Please look into asm-generic/mutex.h for a description of those */ + +#define arch_mutex_fast_lock (v, contention_fn) \ + atomic_dec_call_if_negative(v, contention_fn) + +#define arch_mutex_fast_unlock (v, contention_fn) \ + atomic_inc_call_if_nonpositive(v, contention_fn) + +#define arch_mutex_unlock_fixup (v) \ + atomic_set(v, 1) + +#endif
include/asm-xtensa/mutex.h new file +1 -0
@@ -0,0 +1 @@ +#include <asm-generic/mutex.h>
Re: [patch 2/5] mutex subsystem: add architecture specific mutex primitives
Can you now simply remove the meddling with the atomic.h headers?
i386 can directly implement arch_mutex_fast_lock instead of atomic_dec_call_if_negative.
Not sure what the policy is with naming, but I prefer mutex_arch_xxx or __mutex_xxx for the arch specific names.
I think ARMv6 has a decent atomic_cmpxchg implementation but does not define __HAVE_ARCH_CMPXCHG. It might be useful to try to use this for ARMv6 SMP for a slightly better trylock.
Signature · 3 lines
SUSE Labs, Novell Inc. Send instant messages to your online friends http://au.messenger.yahoo.com
Re: [patch 2/5] mutex subsystem: add architecture specific mutex primitives
Quoted 4 lines · Nick Piggin
I think ARMv6 has a decent
atomic_cmpxchgimplementation but does not define__HAVE_ARCH_CMPXCHG. It might be useful to try to use this for ARMv6 SMP for a slightly better trylock.
And on UP builds, it may simply be best to open code an interrupt unsafe cmpxchg and use atomic_cmpxchg unconditionally on SMP builds (which I think generates half decent code on all SMP architectures).
Just something to think about. Of course this will require the dreaded preempt_disable() which might make it a showstopper.
Signature · 3 lines
SUSE Labs, Novell Inc. Send instant messages to your online friends http://au.messenger.yahoo.com
PATCH 3/5 mutex subsystem: move the core to the new atomic helpers
In reply to Ingo MolnarThis patch moves the core mutex code over to the atomic helpers from previous patch. There is no change for i386 and x86_64, except for the forced unlock state that is now done outside the spinlock (with no adverse effect).
At this point the patch adding asm-generic/atomic-call-if.h can probably be dropped from the original mutex patch serie.
---
kernel/mutex.c +15 -10
@@ -296,14 +296,6 @@ static inline void __mutex_unlock_nonatodebug_mutex_unlock (lock); -/* -* Set it back to 'unlocked'. We'll have a waiter in flight -* (if any), and if some other task comes around, let it -* steal the lock. Waiters take care of themselves and stay -* in flight until necessary. -*/ -atomic_set (&lock->count,1 ); -if (!list_empty (&lock->wait_list)) mutex_wakeup_waiter(lock __IP__);
@@ -329,7 +321,7 @@ static __sched void FASTCALL(__mutex_loc*/ static inline void __mutex_lock_atomic (struct mutex *lock) { -atomic_dec_call_if_negative (&lock->count, __mutex_lock_noinline); +arch_mutex_fast_lock (&lock->count, __mutex_lock_noinline); } static fastcall __sched void __mutex_lock_noinline(atomic_t *lock_count)
@@ -359,13 +351,19 @@ static void __sched FASTCALL(__mutex_unl*/ static inline void __mutex_unlock_atomic (struct mutex *lock) { -atomic_inc_call_if_nonpositive (&lock->count, __mutex_unlock_noinline); +arch_mutex_fast_unlock (&lock->count, __mutex_unlock_noinline); } static fastcall void __sched __mutex_unlock_noinline(atomic_t *lock_count) { struct mutex *lock = container_of(lock_count, struct mutex, count); +/* +* We were called via arch_mutex_fast_unlock() therefore +* we need to call arch_mutex_unlock_fixup() which will set +* the mutex to unlocked (but only if it wasn't done already). +*/ +arch_mutex_unlock_fixup (lock_count);__mutex_unlock_nonatomic (lock); }
@@ -383,6 +381,13 @@ static inline void __mutex_lock(struct m static inline void __mutex_unlock(struct mutex *lock __IP_DECL__) { +/* +* Set it back to 'unlocked'. We'll have a waiter in flight +* (if any), and if some other task comes around, let it +* steal the lock. Waiters take care of themselves and stay +* in flight until necessary. +*/ +atomic_set (&lock->count,1 ); __mutex_unlock_nonatomic(lock __IP__); }
include/linux/mutex.h +1 -0
@@ -14,6 +14,7 @@#include <asm/atomic.h> #include <linux/list.h> #include <linux/spinlock_types.h> +#include <asm/mutex.h> /* * Simple, straightforward mutexes with strict semantics:
PATCH 4/5 mutex subsystem: allow architecture defined fast path for mutex_lock_interruptible
In reply to Ingo MolnarThis patch adds another architecture helper, arch_mutex_fast_lock_retval(), to allows for mutex_lock_interruptible to have an architecture defined fast path.
---
include/asm-generic/mutex.h +18 -0
@@ -26,6 +26,24 @@ do { \ }while (0 )/** +* arch_mutex_fast_lock_retval - lock mutex and call function if already locked +* @v: pointer of type atomic_t +* @contention_fn: function to call if v was already locked +* +* Atomically locks @v and calls a function if @v was already locked. +* When @v == 1 it is unlocked, <= 0 means locked. +* +* Returns 0 if no contention, otherwise returns whatever from @contention_fn. +*/ +#define arch_mutex_fast_lock_retval(v, contention_fn) \ +({ \ +int __retval =0 ; \ +if (unlikely (atomic_xchg (v,0 ) !=1 )) \ + __retval =contention_fn (v); \ + __retval; \ +}) + +/** * arch_mutex_fast_unlock - unlock and call function if contended * @v: pointer of type atomic_t * @contention_fn: function to call if v was contended
include/asm-i386/mutex.h +8 -0
@@ -14,6 +14,14 @@#define arch_mutex_fast_lock (v, contention_fn) \ atomic_dec_call_if_negative(v, contention_fn) +#define arch_mutex_fast_lock_retval (v, contention_fn) \ +({ \ + int __retval = 0; \ + if (unlikely(atomic_dec_return(v) < 0)) \ + __retval = contention_fnv); \ + __retval; \ +}) +#define arch_mutex_fast_unlock (v, contention_fn) \ atomic_inc_call_if_nonpositive(v, contention_fn)
kernel/mutex.c +16 -3
@@ -336,11 +336,24 @@ static inline void __mutex_lock(struct m__mutex_lock_atomic (lock); } +static __sched int FASTCALL(__mutex_lock_interruptible_noinline(atomic_t *lock_count)); + +static inline int __mutex_lock_interruptible_atomic (struct mutex *lock) +{ +return arch_mutex_fast_lock_retval (&lock->count, + __mutex_lock_interruptible_noinline); +} + +static fastcall __sched int __mutex_lock_interruptible_noinline(atomic_t *lock_count) +{ + struct mutex *lock = container_of(lock_count, struct mutex, count); + +return __mutex_lock_interruptible_nonatomic (lock); +} +static inline int __mutex_lock_interruptible (struct mutex *lock) { -if (unlikely (atomic_dec_return (&lock->count) <0 )) -return __mutex_lock_interruptible_nonatomic (lock); -return 0 ; +return __mutex_lock_interruptible_atomic (lock); } static void __sched FASTCALL(__mutex_unlock_noinline(atomic_t *lock_count));
include/asm-x86_64/mutex.h +8 -0
@@ -14,6 +14,14 @@#define arch_mutex_fast_lock (v, contention_fn) \ atomic_dec_call_if_negative(v, contention_fn) +#define arch_mutex_fast_lock_retval (v, contention_fn) \ +({ \ + int __retval = 0; \ + if (unlikely(atomic_dec_return(v) < 0)) \ + __retval = contention_fnv); \ + __retval; \ +}) +#define arch_mutex_fast_unlock (v, contention_fn) \ atomic_inc_call_if_nonpositive(v, contention_fn)
PATCH 5/5 mutex subsystem: allow for the fast path to be inlined
In reply to Ingo MolnarThis lets the architecture decide whether it wants the mutex fast path inlined or not. On ARM it is (now) worthwhile to do so.
Also get rid of ARCH_IMPLEMENTS_MUTEX_FASTPATH since at this point it is rather useless.
---
include/linux/mutex.h +32 -1
@@ -92,10 +92,41 @@ struct mutex_waiter {extern void FASTCALL (__mutex_init (struct mutex *lock,const char *name)); +#ifdef CONFIG_DEBUG_MUTEXES +#undef MUTEX_INLINE_FASTPATH +#endif + +#ifdef MUTEX_INLINE_FASTPATH + +extern void FASTCALL (__mutex_lock_noinline (atomic_t *lock_count)); +extern int FASTCALL (__mutex_lock_interruptible_noinline (atomic_t *lock_count)); +extern void FASTCALL (__mutex_unlock_noinline (atomic_t *lock_count)); + +static inline void mutex_lock (struct mutex *lock) +{ +arch_mutex_fast_lock (&lock->count, __mutex_lock_noinline); +} + +static inline int mutex_lock_interruptible (struct mutex *lock) +{ +return arch_mutex_fast_lock_retval (&lock->count, + __mutex_lock_interruptible_noinline); +} + +static inline void mutex_unlock (struct mutex *lock) +{ +arch_mutex_fast_unlock (&lock->count, __mutex_unlock_noinline); +} + +#else +extern void FASTCALL (mutex_lock (struct mutex *lock));extern int FASTCALL (mutex_lock_interruptible (struct mutex *lock)); -extern int FASTCALL (mutex_trylock (struct mutex *lock));extern void FASTCALL (mutex_unlock (struct mutex *lock)); + +#endif + +extern int FASTCALL (mutex_trylock (struct mutex *lock));extern int FASTCALL (mutex_is_locked (struct mutex *lock));#endif
kernel/mutex.c +16 -26
97 lines not on this page · raw message
include/asm-arm/mutex.h +2 -0
@@ -1 +1,3 @@#include <asm-generic/mutex.h> + +#define MUTEX_INLINE_FASTPATH