diff options
author | Gary King <gking@nvidia.com> | 2010-01-25 18:06:05 -0800 |
---|---|---|
committer | Gary King <gking@nvidia.com> | 2010-01-26 14:16:13 -0800 |
commit | 73f6d4ab65fb57e19e3983421538637595b44a13 (patch) | |
tree | b87c1496acdb2fb418acbbe1e2b9ccc70a1b5597 /arch | |
parent | 3ede8bfc14f5398d5458b14413ab297943469213 (diff) |
tegra nvos: fix mutex and semaphore handling for frozen tasks
if a kernel mutex lock or semaphore wait is interrupted because the task
is being frozen, the correct action to take is to call try_to_freeze,
similar to wait_event_freezable
-ERESTARTSYS is not returned to higher-level software in the event of a
resume; the assumption is that the resume process will ensure that any
freezable task is resumed in a state where the NvOsSemaphore will be
signalable, and that the Wait operation should only return once the
semaphore is actually signalled.
bug 645292
Change-Id: Ia9c6c2426d889851437d93506ce33cb23cee5e8c
Diffstat (limited to 'arch')
-rw-r--r-- | arch/arm/mach-tegra/nvos/nvos.c | 26 |
1 files changed, 13 insertions, 13 deletions
diff --git a/arch/arm/mach-tegra/nvos/nvos.c b/arch/arm/mach-tegra/nvos/nvos.c index 620c9ed1b624..e41c5a99cce5 100644 --- a/arch/arm/mach-tegra/nvos/nvos.c +++ b/arch/arm/mach-tegra/nvos/nvos.c @@ -60,6 +60,7 @@ #include <asm/setup.h> #include <asm/cacheflush.h> #include <mach/irqs.h> +#include <linux/freezer.h> #if NVOS_TRACE || NV_DEBUG #undef NvOsAlloc @@ -984,10 +985,9 @@ void NvOsMutexLock(NvOsMutexHandle mutex) /* FIXME: interruptible mutexes may not be necessary, since this * implementation is only used by the kernel tasks. */ ret = mutex_lock_interruptible( &mutex->mutex ); - // If a signal arrives while the task is sleeping, // re-schedule it and attempt to reacquire the mutex - if (ret) + if (ret && !try_to_freeze()) schedule(); } while (ret); mutex->owner = info; @@ -1108,16 +1108,16 @@ NvError NvOsSemaphoreUnmarshal( int NvOsSemaphoreWaitInterruptible(NvOsSemaphoreHandle semaphore); int NvOsSemaphoreWaitInterruptible(NvOsSemaphoreHandle semaphore) { - NV_ASSERT( semaphore ); + NV_ASSERT(semaphore); - return down_interruptible( &semaphore->sem ); + return down_interruptible(&semaphore->sem); } void NvOsSemaphoreWait(NvOsSemaphoreHandle semaphore) { int ret; - NV_ASSERT( semaphore ); + NV_ASSERT(semaphore); do { @@ -1125,13 +1125,13 @@ void NvOsSemaphoreWait(NvOsSemaphoreHandle semaphore) * one for semaphore that were created by users ioctl'ing into * the nvos device (which need down_interruptible), and others that * are created and used by the kernel drivers, which do not */ - ret = down_interruptible( &semaphore->sem ); - - //The kernel doesn't reschedule tasks - //that have pending signals. If a signal - //is pending, forcibly reschedule the task. - if (ret) - schedule(); + ret = down_interruptible(&semaphore->sem); + /* The kernel doesn't reschedule tasks + * that have pending signals. If a signal + * is pending, forcibly reschedule the task. + */ + if (ret && !try_to_freeze()) + schedule(); } while (ret); } @@ -1163,7 +1163,7 @@ NvError NvOsSemaphoreWaitTimeout( /* FIXME: The kernel doesn't provide an interruptible timed * semaphore wait, which would be preferable for our the ioctl'd * NvOs sempahores. */ - t = down_timeout( &semaphore->sem, (long)msecs_to_jiffies( msec ) ); + t = down_timeout(&semaphore->sem, (long)msecs_to_jiffies( msec )); if (t == -ETIME) return NvError_Timeout; |