diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2006-04-04 15:09:06 +0100 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2006-04-19 04:14:22 +0200 |
commit | 193dd2ce2a4a1c5b2e7814544572424d497069db (patch) | |
tree | cca42417c505a8f68e2d2accc83d392fb7221432 /arch | |
parent | 62a442155ea58a17497b487324b27ec2f2dc5c5c (diff) | |
download | linux-3.10-193dd2ce2a4a1c5b2e7814544572424d497069db.tar.gz linux-3.10-193dd2ce2a4a1c5b2e7814544572424d497069db.tar.bz2 linux-3.10-193dd2ce2a4a1c5b2e7814544572424d497069db.zip |
[MIPS] R2: Implement shadow register allocation without spinlock.
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/mips/kernel/traps.c | 41 |
1 files changed, 18 insertions, 23 deletions
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c index 61efc61c45e..081e6ed5bb6 100644 --- a/arch/mips/kernel/traps.c +++ b/arch/mips/kernel/traps.c @@ -961,15 +961,19 @@ void *set_except_vector(int n, void *addr) #ifdef CONFIG_CPU_MIPSR2 /* - * Shadow register allocation + * MIPSR2 shadow register set allocation * FIXME: SMP... */ -/* MIPSR2 shadow register sets */ -struct shadow_registers { - spinlock_t sr_lock; /* */ - int sr_supported; /* Number of shadow register sets supported */ - int sr_allocated; /* Bitmap of allocated shadow registers */ +static struct shadow_registers { + /* + * Number of shadow register sets supported + */ + unsigned long sr_supported; + /* + * Bitmap of allocated shadow registers + */ + unsigned long sr_allocated; } shadow_registers; void mips_srs_init(void) @@ -980,7 +984,6 @@ void mips_srs_init(void) shadow_registers.sr_supported); #endif shadow_registers.sr_allocated = 1; /* Set 0 used by kernel */ - spin_lock_init(&shadow_registers.sr_lock); } int mips_srs_max(void) @@ -991,32 +994,24 @@ int mips_srs_max(void) int mips_srs_alloc(void) { struct shadow_registers *sr = &shadow_registers; - unsigned long flags; int set; - spin_lock_irqsave(&sr->sr_lock, flags); +again: + set = find_first_zero_bit(&sr->sr_allocated, sr->sr_supported); + if (set >= sr->sr_supported) + return -1; - for (set = 0; set < sr->sr_supported; set++) { - if ((sr->sr_allocated & (1 << set)) == 0) { - sr->sr_allocated |= 1 << set; - spin_unlock_irqrestore(&sr->sr_lock, flags); - return set; - } - } + if (test_and_set_bit(set, &sr->sr_allocated)) + goto again; - /* None available */ - spin_unlock_irqrestore(&sr->sr_lock, flags); - return -1; + return set; } void mips_srs_free (int set) { struct shadow_registers *sr = &shadow_registers; - unsigned long flags; - spin_lock_irqsave(&sr->sr_lock, flags); - sr->sr_allocated &= ~(1 << set); - spin_unlock_irqrestore(&sr->sr_lock, flags); + clear_bit(set, &sr->sr_allocated); } static void *set_vi_srs_handler(int n, void *addr, int srs) |