Index: firmware/export/kernel.h =================================================================== --- firmware/export/kernel.h (revision 16246) +++ firmware/export/kernel.h (working copy) @@ -7,7 +7,7 @@ * \/ \/ \/ \/ \/ * $Id$ * - * Copyright (C) 2002 by Björn Stenberg + * Copyright (C) 2002 by Bj?rn Stenberg * * All files in this archive are subject to the GNU General Public License. * See the file COPYING in the source tree root for full license agreement. @@ -119,14 +119,18 @@ unsigned char locked; /* locked semaphore */ }; -#if NUM_CORES > 1 struct spinlock { +#if NUM_CORES > 1 struct corelock cl; /* inter-core sync */ +#endif struct thread_entry *thread; /* lock owner */ int count; /* lock owner recursion count */ + unsigned char locked; /* is locked if nonzero */ +#if NUM_CORES > 1 + unsigned char task_switch; /* can task switch? */ +#endif }; -#endif #ifdef HAVE_SEMAPHORE_OBJECTS struct semaphore @@ -223,11 +227,12 @@ extern void mutex_init(struct mutex *m); extern void mutex_lock(struct mutex *m); extern void mutex_unlock(struct mutex *m); -#if NUM_CORES > 1 -extern void spinlock_init(struct spinlock *l); +#define SPINLOCK_TASK_SWITCH 0x10 +#define SPINLOCK_NO_TASK_SWITCH 0x00 +extern void spinlock_init(struct spinlock *l IF_COP(, unsigned int flags)); extern void spinlock_lock(struct spinlock *l); extern void spinlock_unlock(struct spinlock *l); -#endif +extern int spinlock_lock_w_tmo(struct spinlock *l, int ticks); #ifdef HAVE_SEMAPHORE_OBJECTS extern void semaphore_init(struct semaphore *s, int max, int start); extern void semaphore_wait(struct semaphore *s); Index: firmware/kernel.c =================================================================== --- firmware/kernel.c (revision 16246) +++ firmware/kernel.c (working copy) @@ -7,7 +7,7 @@ * \/ \/ \/ \/ \/ * $Id$ * - * Copyright (C) 2002 by Björn Stenberg + * Copyright (C) 2002 by Bj?rn Stenberg * * All files in this archive are subject to the GNU General Public License. * See the file COPYING in the source tree root for full license agreement. @@ -1073,12 +1073,15 @@ /**************************************************************************** * Simpl-er mutex functions ;) ****************************************************************************/ -#if NUM_CORES > 1 -void spinlock_init(struct spinlock *l) +void spinlock_init(struct spinlock *l IF_COP(, unsigned int flags)) { - corelock_init(&l->cl); + l->locked = 0; l->thread = NULL; l->count = 0; +#if NUM_CORES > 1 + l->task_switch = flags & SPINLOCK_TASK_SWITCH; + corelock_init(&l->cl); +#endif } void spinlock_lock(struct spinlock *l) @@ -1091,7 +1094,24 @@ return; } - corelock_lock(&l->cl); +#if NUM_CORES > 1 + if (l->task_switch != 0) +#endif + { + /* Let other threads run until the lock is free */ + while(test_and_set(&l->locked, 1, &l->cl) != 0) + { + /* spin and switch until the lock is open... */ + switch_thread(NULL); + } + } +#if NUM_CORES > 1 + else + { + /* Use the corelock purely */ + corelock_lock(&l->cl); + } +#endif l->thread = thread; } @@ -1112,10 +1132,23 @@ /* clear owner */ l->thread = NULL; - /* release lock */ +#if NUM_CORES > 1 + if (l->task_switch != 0) +#endif + { + /* release lock */ +#if CONFIG_CORELOCK == SW_CORELOCK + /* This must be done since our unlock could be missed by the + test_and_set and leave the object locked permanently */ + corelock_lock(&l->cl); +#endif + l->locked = 0; + } + +#if NUM_CORES > 1 corelock_unlock(&l->cl); +#endif } -#endif /* NUM_CORES > 1 */ /**************************************************************************** * Simple semaphore functions ;) Index: firmware/system.c =================================================================== --- firmware/system.c (revision 16246) +++ firmware/system.c (working copy) @@ -39,7 +39,7 @@ struct spinlock boostctrl_spin NOCACHEBSS_ATTR; void cpu_boost_init(void) { - spinlock_init(&boostctrl_spin); + spinlock_init(&boostctrl_spin, SPINLOCK_NO_TASK_SWITCH); } #endif @@ -280,4 +280,3 @@ #endif #endif /* CPU_ARM */ - Index: firmware/target/arm/ipod/1g2g/adc-ipod-1g2g.c =================================================================== --- firmware/target/arm/ipod/1g2g/adc-ipod-1g2g.c (revision 16246) +++ firmware/target/arm/ipod/1g2g/adc-ipod-1g2g.c (working copy) @@ -22,7 +22,7 @@ #include "hwcompat.h" #include "kernel.h" -static struct mutex adc_mtx NOCACHEBSS_ATTR; +static struct spinlock adc_spin NOCACHEBSS_ATTR; /* used in the 2nd gen ADC interrupt */ static unsigned int_data; @@ -33,7 +33,7 @@ unsigned short data = 0; (void)channel; /* there is only one */ - mutex_lock(&adc_mtx); + spinlock_lock(&adc_spin); if ((IPOD_HW_REVISION >> 16) == 1) { @@ -69,7 +69,7 @@ data = int_data & 0xff; } - mutex_unlock(&adc_mtx); + spinlock_unlock(&adc_spin); return data; } @@ -100,7 +100,7 @@ void adc_init(void) { - mutex_init(&adc_mtx); + spinlock_init(&adc_spin IF_COP(, SPINLOCK_TASK_SWITCH)); GPIOB_ENABLE |= 0x1e; /* enable B1..B4 */ Index: firmware/target/arm/sandisk/ata-c200_e200.c =================================================================== --- firmware/target/arm/sandisk/ata-c200_e200.c (revision 16246) +++ firmware/target/arm/sandisk/ata-c200_e200.c (working copy) @@ -162,7 +162,7 @@ /* Shoot for around 75% usage */ static long sd_stack [(DEFAULT_STACK_SIZE*2 + 0x1c0)/sizeof(long)]; static const char sd_thread_name[] = "ata/sd"; -static struct mutex sd_mtx NOCACHEBSS_ATTR; +static struct spinlock sd_spin NOCACHEBSS_ATTR; static struct event_queue sd_queue; /* Posted when card plugged status has changed */ @@ -801,7 +801,7 @@ /* TODO: Add DMA support. */ - mutex_lock(&sd_mtx); + spinlock_lock(&sd_spin); ata_led(true); @@ -888,7 +888,7 @@ while (1) { ata_led(false); - mutex_unlock(&sd_mtx); + spinlock_unlock(&sd_spin); return ret; @@ -916,7 +916,7 @@ const unsigned char *buf, *buf_end; int bank; - mutex_lock(&sd_mtx); + spinlock_lock(&sd_spin); ata_led(true); @@ -1016,7 +1016,7 @@ while (1) { ata_led(false); - mutex_unlock(&sd_mtx); + spinlock_unlock(&sd_spin); return ret; @@ -1050,7 +1050,7 @@ /* Lock to keep us from messing with this variable while an init may be in progress */ - mutex_lock(&sd_mtx); + spinlock_lock(&sd_spin); card_info[1].initialized = 0; sd_status[1].retry = 0; @@ -1073,7 +1073,7 @@ if (action != SDA_NONE) queue_broadcast(SYS_FS_CHANGED, 0); - mutex_unlock(&sd_mtx); + spinlock_unlock(&sd_spin); break; } /* SD_HOTSWAP */ #endif /* HAVE_HOTSWAP */ @@ -1150,9 +1150,9 @@ int ret = 0; if (!initialized) - mutex_init(&sd_mtx); + spinlock_init(&sd_spin IF_COP(, SPINLOCK_TASK_SWITCH)); - mutex_lock(&sd_mtx); + spinlock_lock(&sd_spin); ata_led(false); @@ -1215,7 +1215,7 @@ #endif } - mutex_unlock(&sd_mtx); + spinlock_unlock(&sd_spin); return ret; } Index: firmware/target/arm/tms320dm320/spi-dm320.c =================================================================== --- firmware/target/arm/tms320dm320/spi-dm320.c (revision 16246) +++ firmware/target/arm/tms320dm320/spi-dm320.c (working copy) @@ -32,7 +32,7 @@ #define GIO_RTC_ENABLE (1<<12) #define GIO_BL_ENABLE (1<<13) -struct mutex spi_mtx; +struct spinlock spi_lock; struct SPI_info { volatile unsigned short *setreg; @@ -60,7 +60,7 @@ const uint8_t *tx_bytes, unsigned int tx_size, uint8_t *rx_bytes, unsigned int rx_size) { - mutex_lock(&spi_mtx); + spinlock_lock(&spi_lock); /* Activate the slave select pin */ *spi_targets[target].setreg = spi_targets[target].bit; @@ -87,13 +87,13 @@ *spi_targets[target].clrreg = spi_targets[target].bit; - mutex_unlock(&spi_mtx); + spinlock_unlock(&spi_lock); return 0; } void spi_init(void) { - mutex_init(&spi_mtx); + spinlock_init(&spi_lock); /* Set SCLK idle level = 0 */ IO_SERIAL0_MODE |= 1<<10; /* Enable TX */ Index: firmware/drivers/ata.c =================================================================== --- firmware/drivers/ata.c (revision 16246) +++ firmware/drivers/ata.c (working copy) @@ -66,7 +66,7 @@ #define ATA_POWER_OFF_TIMEOUT 2*HZ #endif -static struct mutex ata_mtx NOCACHEBSS_ATTR; +static struct spinlock ata_spinlock NOCACHEBSS_ATTR; int ata_device; /* device 0 (master) or 1 (slave) */ int ata_spinup_time = 0; @@ -234,7 +234,7 @@ #ifdef HAVE_MULTIVOLUME (void)drive; /* unused for now */ #endif - mutex_lock(&ata_mtx); + spinlock_lock(&ata_spinlock); #endif last_disk_activity = current_tick; @@ -246,14 +246,14 @@ spinup = true; if (poweroff) { if (ata_power_on()) { - mutex_unlock(&ata_mtx); + spinlock_unlock(&ata_spinlock); ata_led(false); return -1; } } else { if (perform_soft_reset()) { - mutex_unlock(&ata_mtx); + spinlock_unlock(&ata_spinlock); ata_led(false); return -1; } @@ -265,7 +265,7 @@ SET_REG(ATA_SELECT, ata_device); if (!wait_for_rdy()) { - mutex_unlock(&ata_mtx); + spinlock_unlock(&ata_spinlock); ata_led(false); return -2; } @@ -376,7 +376,7 @@ ata_led(false); #ifndef MAX_PHYS_SECTOR_SIZE - mutex_unlock(&ata_mtx); + spinlock_unlock(&ata_spinlock); #endif return ret; @@ -442,7 +442,7 @@ #ifdef HAVE_MULTIVOLUME (void)drive; /* unused for now */ #endif - mutex_lock(&ata_mtx); + spinlock_lock(&ata_spinlock); #endif last_disk_activity = current_tick; @@ -454,14 +454,14 @@ spinup = true; if (poweroff) { if (ata_power_on()) { - mutex_unlock(&ata_mtx); + spinlock_unlock(&ata_spinlock); ata_led(false); return -1; } } else { if (perform_soft_reset()) { - mutex_unlock(&ata_mtx); + spinlock_unlock(&ata_spinlock); ata_led(false); return -1; } @@ -471,7 +471,7 @@ SET_REG(ATA_SELECT, ata_device); if (!wait_for_rdy()) { - mutex_unlock(&ata_mtx); + spinlock_unlock(&ata_spinlock); ata_led(false); return -2; } @@ -534,7 +534,7 @@ ata_led(false); #ifndef MAX_PHYS_SECTOR_SIZE - mutex_unlock(&ata_mtx); + spinlock_unlock(&ata_spinlock); #endif return ret; @@ -580,7 +580,7 @@ #ifdef HAVE_MULTIVOLUME (void)drive; /* unused for now */ #endif - mutex_lock(&ata_mtx); + spinlock_lock(&ata_spinlock); offset = start & (phys_sector_mult - 1); @@ -630,7 +630,7 @@ } error: - mutex_unlock(&ata_mtx); + spinlock_unlock(&ata_spinlock); return rc; } @@ -646,7 +646,7 @@ #ifdef HAVE_MULTIVOLUME (void)drive; /* unused for now */ #endif - mutex_lock(&ata_mtx); + spinlock_lock(&ata_spinlock); offset = start & (phys_sector_mult - 1); @@ -707,7 +707,7 @@ } error: - mutex_unlock(&ata_mtx); + spinlock_unlock(&ata_spinlock); return rc; } @@ -767,13 +767,13 @@ { int ret = 0; - mutex_lock(&ata_mtx); + spinlock_lock(&ata_spinlock); SET_REG(ATA_SELECT, ata_device); if(!wait_for_rdy()) { DEBUGF("ata_perform_sleep() - not RDY\n"); - mutex_unlock(&ata_mtx); + spinlock_unlock(&ata_spinlock); return -1; } @@ -786,7 +786,7 @@ } sleeping = true; - mutex_unlock(&ata_mtx); + spinlock_unlock(&ata_spinlock); return ret; } @@ -797,7 +797,7 @@ void ata_sleepnow(void) { - if (!spinup && !sleeping && !ata_mtx.locked && initialized) + if (!spinup && !sleeping && !ata_spinlock.locked && initialized) { call_ata_idle_notifys(false); ata_perform_sleep(); @@ -819,7 +819,7 @@ while ( queue_empty( &ata_queue ) ) { if (!spinup && !sleeping) { - if (!ata_mtx.locked) + if (!ata_spinlock.locked) { if (!last_seen_mtx_unlock) last_seen_mtx_unlock = current_tick; @@ -844,9 +844,9 @@ if ( !spinup && sleeping && !poweroff && TIME_AFTER( current_tick, last_sleep + ATA_POWER_OFF_TIMEOUT )) { - mutex_lock(&ata_mtx); + spinlock_lock(&ata_spinlock); ide_power_enable(false); - mutex_unlock(&ata_mtx); + spinlock_unlock(&ata_spinlock); poweroff = true; } #endif @@ -858,11 +858,11 @@ #ifndef USB_NONE case SYS_USB_CONNECTED: if (poweroff) { - mutex_lock(&ata_mtx); + spinlock_lock(&ata_spinlock); ata_led(true); ata_power_on(); ata_led(false); - mutex_unlock(&ata_mtx); + spinlock_unlock(&ata_spinlock); } /* Tell the USB thread that we are safe */ @@ -936,11 +936,11 @@ { int ret; - mutex_lock(&ata_mtx); + spinlock_lock(&ata_spinlock); ret = perform_soft_reset(); - mutex_unlock(&ata_mtx); + spinlock_unlock(&ata_spinlock); return ret; } @@ -1132,11 +1132,11 @@ bool coldstart; if ( !initialized ) { - mutex_init(&ata_mtx); + spinlock_init(&ata_spinlock IF_COP(, SPINLOCK_TASK_SWITCH)); queue_init(&ata_queue, true); } - mutex_lock(&ata_mtx); + spinlock_lock(&ata_spinlock); /* must be called before ata_device_init() */ coldstart = ata_is_coldstart(); @@ -1150,7 +1150,7 @@ if ( !initialized ) { /* First call won't have multiple thread contention */ - mutex_unlock(&ata_mtx); + spinlock_unlock(&ata_spinlock); if (!ide_powered()) /* somebody has switched it off */ { @@ -1223,7 +1223,7 @@ if (rc) rc = -70 + rc; - mutex_unlock(&ata_mtx); + spinlock_unlock(&ata_spinlock); return rc; } Index: uisimulator/sdl/kernel.c =================================================================== --- uisimulator/sdl/kernel.c (revision 16246) +++ uisimulator/sdl/kernel.c (working copy) @@ -594,7 +594,7 @@ /* unlocker not being the owner is an unlocking violation */ if(m->thread != thread_get_current()) { - fprintf(stderr, "mutex_unlock->wrong thread"); + fprintf(stderr, "spinlock_unlock->wrong thread"); exit(-1); } @@ -614,6 +614,52 @@ } } +void spinlock_init(struct spinlock *l) +{ + l->locked = 0; + l->thread = NULL; + l->count = 0; +} + +void spinlock_lock(struct spinlock *l) +{ + struct thread_entry *const thread = thread_get_current(); + + if (l->thread == thread) + { + l->count++; + return; + } + + while(test_and_set(&l->locked, 1)) + { + switch_thread(NULL); + } + + l->thread = thread; +} + +void spinlock_unlock(struct spinlock *l) +{ + /* unlocker not being the owner is an unlocking violation */ + if(l->thread != thread_get_current()) + { + fprintf(stderr, "spinlock_unlock->wrong thread"); + exit(-1); + } + + if (l->count > 0) + { + /* this thread still owns lock */ + l->count--; + return; + } + + /* clear owner */ + l->thread = NULL; + l->locked = 0; +} + #ifdef HAVE_SEMAPHORE_OBJECTS void semaphore_init(struct semaphore *s, int max, int start) {