[POWERPC] spufs: make state_mutex interruptible
authorChristoph Hellwig <hch@lst.de>
Thu, 20 Dec 2007 07:39:59 +0000 (16:39 +0900)
committerPaul Mackerras <paulus@samba.org>
Fri, 21 Dec 2007 08:46:21 +0000 (19:46 +1100)
Make most places that use spu_acquire/spu_acquire_saved interruptible,
this allows getting out of the spufs code when e.g. pressing ctrl+c.
There are a few places where we get called e.g. from spufs teardown
routines were we can't simply err out so these are left with a comment.
For now I've also not touched the poll routines because it's open what
libspe would expect in terms of interrupted system calls.

Acked-by: Arnd Bergmann <arnd.bergmann@de.ibm.com>
Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Jeremy Kerr <jk@ozlabs.org>
Signed-off-by: Paul Mackerras <paulus@samba.org>
arch/powerpc/platforms/cell/spufs/context.c
arch/powerpc/platforms/cell/spufs/coredump.c
arch/powerpc/platforms/cell/spufs/fault.c
arch/powerpc/platforms/cell/spufs/file.c
arch/powerpc/platforms/cell/spufs/run.c
arch/powerpc/platforms/cell/spufs/sched.c
arch/powerpc/platforms/cell/spufs/spufs.h

index 290b10e45105de3c4a1a3fcbd8e23269c63a056e..237e152d31dc9d3e7e5793dc267414412a0e78da 100644 (file)
@@ -106,7 +106,17 @@ int put_spu_context(struct spu_context *ctx)
 void spu_forget(struct spu_context *ctx)
 {
        struct mm_struct *mm;
-       spu_acquire_saved(ctx);
+
+       /*
+        * This is basically an open-coded spu_acquire_saved, except that
+        * we don't acquire the state mutex interruptible.
+        */
+       mutex_lock(&ctx->state_mutex);
+       if (ctx->state != SPU_STATE_SAVED) {
+               set_bit(SPU_SCHED_WAS_ACTIVE, &ctx->sched_flags);
+               spu_deactivate(ctx);
+       }
+
        mm = ctx->owner;
        ctx->owner = NULL;
        mmput(mm);
@@ -137,13 +147,20 @@ void spu_unmap_mappings(struct spu_context *ctx)
  * spu_acquire_saved - lock spu contex and make sure it is in saved state
  * @ctx:       spu contex to lock
  */
-void spu_acquire_saved(struct spu_context *ctx)
+int spu_acquire_saved(struct spu_context *ctx)
 {
-       spu_acquire(ctx);
+       int ret;
+
+       ret = spu_acquire(ctx);
+       if (ret)
+               return ret;
+
        if (ctx->state != SPU_STATE_SAVED) {
                set_bit(SPU_SCHED_WAS_ACTIVE, &ctx->sched_flags);
                spu_deactivate(ctx);
        }
+
+       return 0;
 }
 
 /**
index 80f62363e1ce1708c19662fa003bebc9b5459a72..0c6a96b82b2db9d22bfcd49c0e5df08a182e15f4 100644 (file)
@@ -148,7 +148,9 @@ int spufs_coredump_extra_notes_size(void)
 
        fd = 0;
        while ((ctx = coredump_next_context(&fd)) != NULL) {
-               spu_acquire_saved(ctx);
+               rc = spu_acquire_saved(ctx);
+               if (rc)
+                       break;
                rc = spufs_ctx_note_size(ctx, fd);
                spu_release_saved(ctx);
                if (rc < 0)
@@ -224,7 +226,9 @@ int spufs_coredump_extra_notes_write(struct file *file, loff_t *foffset)
 
        fd = 0;
        while ((ctx = coredump_next_context(&fd)) != NULL) {
-               spu_acquire_saved(ctx);
+               rc = spu_acquire_saved(ctx);
+               if (rc)
+                       return rc;
 
                for (j = 0; spufs_coredump_read[j].name != NULL; j++) {
                        rc = spufs_arch_write_note(ctx, j, file, fd, foffset);
index 720e111f1f6a05c975e57fdea4cd7de433b47b93..825001c2b0952f208921bc91b3b12d66ab290f07 100644 (file)
@@ -107,7 +107,7 @@ int spufs_handle_class1(struct spu_context *ctx)
        u64 ea, dsisr, access;
        unsigned long flags;
        unsigned flt = 0;
-       int ret;
+       int ret, ret2;
 
        /*
         * dar and dsisr get passed from the registers
@@ -146,7 +146,14 @@ int spufs_handle_class1(struct spu_context *ctx)
        if (ret)
                ret = spu_handle_mm_fault(current->mm, ea, dsisr, &flt);
 
-       spu_acquire(ctx);
+       /*
+        * If spu_acquire fails due to a pending signal we just want to return
+        * EINTR to userspace even if that means missing the dma restart or
+        * updating the page fault statistics.
+        */
+       ret2 = spu_acquire(ctx);
+       if (ret2)
+               goto out;
 
        /*
         * Clear dsisr under ctxt lock after handling the fault, so that
@@ -177,6 +184,7 @@ int spufs_handle_class1(struct spu_context *ctx)
        } else
                spufs_handle_event(ctx, ea, SPE_EVENT_SPE_DATA_STORAGE);
 
+ out:
        spuctx_switch_state(ctx, SPU_UTIL_SYSTEM);
        return ret;
 }
index 510adc57af9077831709521ae02c83968adf59ef..ba6101ae73a2ae3da7e910bbf1a2c45c6423c436 100644 (file)
@@ -198,9 +198,12 @@ spufs_mem_read(struct file *file, char __user *buffer,
        struct spu_context *ctx = file->private_data;
        ssize_t ret;
 
-       spu_acquire(ctx);
+       ret = spu_acquire(ctx);
+       if (ret)
+               return ret;
        ret = __spufs_mem_read(ctx, buffer, size, pos);
        spu_release(ctx);
+
        return ret;
 }
 
@@ -220,7 +223,10 @@ spufs_mem_write(struct file *file, const char __user *buffer,
        if (size > LS_SIZE - pos)
                size = LS_SIZE - pos;
 
-       spu_acquire(ctx);
+       ret = spu_acquire(ctx);
+       if (ret)
+               return ret;
+
        local_store = ctx->ops->get_ls(ctx);
        ret = copy_from_user(local_store + pos, buffer, size);
        spu_release(ctx);
@@ -260,7 +266,8 @@ static unsigned long spufs_mem_mmap_nopfn(struct vm_area_struct *vma,
        pr_debug("spufs_mem_mmap_nopfn address=0x%lx -> 0x%lx, offset=0x%lx\n",
                 addr0, address, offset);
 
-       spu_acquire(ctx);
+       if (spu_acquire(ctx))
+               return NOPFN_REFAULT;
 
        if (ctx->state == SPU_STATE_SAVED) {
                vma->vm_page_prot = __pgprot(pgprot_val(vma->vm_page_prot)
@@ -363,20 +370,19 @@ static unsigned long spufs_ps_nopfn(struct vm_area_struct *vma,
         * to return NOPFN_REFAULT because the mappings may have
         * hanged.
         */
-       spu_acquire(ctx);
+       if (spu_acquire(ctx))
+               return NOPFN_REFAULT;
+
        if (ctx->state == SPU_STATE_SAVED) {
                up_read(&current->mm->mmap_sem);
                spufs_wait(ctx->run_wq, ctx->state == SPU_STATE_RUNNABLE);
                down_read(&current->mm->mmap_sem);
-               goto out;
+       } else {
+               area = ctx->spu->problem_phys + ps_offs;
+               vm_insert_pfn(vma, address, (area + offset) >> PAGE_SHIFT);
        }
 
-       area = ctx->spu->problem_phys + ps_offs;
-       vm_insert_pfn(vma, address, (area + offset) >> PAGE_SHIFT);
-
-out:
        spu_release(ctx);
-
        return NOPFN_REFAULT;
 }
 
@@ -413,8 +419,11 @@ static int spufs_cntl_mmap(struct file *file, struct vm_area_struct *vma)
 static int spufs_cntl_get(void *data, u64 *val)
 {
        struct spu_context *ctx = data;
+       int ret;
 
-       spu_acquire(ctx);
+       ret = spu_acquire(ctx);
+       if (ret)
+               return ret;
        *val = ctx->ops->status_read(ctx);
        spu_release(ctx);
 
@@ -424,8 +433,11 @@ static int spufs_cntl_get(void *data, u64 *val)
 static int spufs_cntl_set(void *data, u64 val)
 {
        struct spu_context *ctx = data;
+       int ret;
 
-       spu_acquire(ctx);
+       ret = spu_acquire(ctx);
+       if (ret)
+               return ret;
        ctx->ops->runcntl_write(ctx, val);
        spu_release(ctx);
 
@@ -493,7 +505,9 @@ spufs_regs_read(struct file *file, char __user *buffer,
        int ret;
        struct spu_context *ctx = file->private_data;
 
-       spu_acquire_saved(ctx);
+       ret = spu_acquire_saved(ctx);
+       if (ret)
+               return ret;
        ret = __spufs_regs_read(ctx, buffer, size, pos);
        spu_release_saved(ctx);
        return ret;
@@ -512,7 +526,9 @@ spufs_regs_write(struct file *file, const char __user *buffer,
                return -EFBIG;
        *pos += size;
 
-       spu_acquire_saved(ctx);
+       ret = spu_acquire_saved(ctx);
+       if (ret)
+               return ret;
 
        ret = copy_from_user(lscsa->gprs + *pos - size,
                             buffer, size) ? -EFAULT : size;
@@ -544,7 +560,9 @@ spufs_fpcr_read(struct file *file, char __user * buffer,
        int ret;
        struct spu_context *ctx = file->private_data;
 
-       spu_acquire_saved(ctx);
+       ret = spu_acquire_saved(ctx);
+       if (ret)
+               return ret;
        ret = __spufs_fpcr_read(ctx, buffer, size, pos);
        spu_release_saved(ctx);
        return ret;
@@ -561,10 +579,12 @@ spufs_fpcr_write(struct file *file, const char __user * buffer,
        size = min_t(ssize_t, sizeof(lscsa->fpcr) - *pos, size);
        if (size <= 0)
                return -EFBIG;
-       *pos += size;
 
-       spu_acquire_saved(ctx);
+       ret = spu_acquire_saved(ctx);
+       if (ret)
+               return ret;
 
+       *pos += size;
        ret = copy_from_user((char *)&lscsa->fpcr + *pos - size,
                             buffer, size) ? -EFAULT : size;
 
@@ -611,7 +631,10 @@ static ssize_t spufs_mbox_read(struct file *file, char __user *buf,
 
        udata = (void __user *)buf;
 
-       spu_acquire(ctx);
+       count = spu_acquire(ctx);
+       if (count)
+               return count;
+
        for (count = 0; (count + 4) <= len; count += 4, udata++) {
                int ret;
                ret = ctx->ops->mbox_read(ctx, &mbox_data);
@@ -647,12 +670,15 @@ static ssize_t spufs_mbox_stat_read(struct file *file, char __user *buf,
                        size_t len, loff_t *pos)
 {
        struct spu_context *ctx = file->private_data;
+       ssize_t ret;
        u32 mbox_stat;
 
        if (len < 4)
                return -EINVAL;
 
-       spu_acquire(ctx);
+       ret = spu_acquire(ctx);
+       if (ret)
+               return ret;
 
        mbox_stat = ctx->ops->mbox_stat_read(ctx) & 0xff;
 
@@ -721,7 +747,9 @@ static ssize_t spufs_ibox_read(struct file *file, char __user *buf,
 
        udata = (void __user *)buf;
 
-       spu_acquire(ctx);
+       count = spu_acquire(ctx);
+       if (count)
+               return count;
 
        /* wait only for the first element */
        count = 0;
@@ -767,7 +795,11 @@ static unsigned int spufs_ibox_poll(struct file *file, poll_table *wait)
 
        poll_wait(file, &ctx->ibox_wq, wait);
 
-       spu_acquire(ctx);
+       /*
+        * For now keep this uninterruptible and also ignore the rule
+        * that poll should not sleep.  Will be fixed later.
+        */
+       mutex_lock(&ctx->state_mutex);
        mask = ctx->ops->mbox_stat_poll(ctx, POLLIN | POLLRDNORM);
        spu_release(ctx);
 
@@ -785,12 +817,15 @@ static ssize_t spufs_ibox_stat_read(struct file *file, char __user *buf,
                        size_t len, loff_t *pos)
 {
        struct spu_context *ctx = file->private_data;
+       ssize_t ret;
        u32 ibox_stat;
 
        if (len < 4)
                return -EINVAL;
 
-       spu_acquire(ctx);
+       ret = spu_acquire(ctx);
+       if (ret)
+               return ret;
        ibox_stat = (ctx->ops->mbox_stat_read(ctx) >> 16) & 0xff;
        spu_release(ctx);
 
@@ -862,7 +897,9 @@ static ssize_t spufs_wbox_write(struct file *file, const char __user *buf,
        if (__get_user(wbox_data, udata))
                return -EFAULT;
 
-       spu_acquire(ctx);
+       count = spu_acquire(ctx);
+       if (count)
+               return count;
 
        /*
         * make sure we can at least write one element, by waiting
@@ -903,7 +940,11 @@ static unsigned int spufs_wbox_poll(struct file *file, poll_table *wait)
 
        poll_wait(file, &ctx->wbox_wq, wait);
 
-       spu_acquire(ctx);
+       /*
+        * For now keep this uninterruptible and also ignore the rule
+        * that poll should not sleep.  Will be fixed later.
+        */
+       mutex_lock(&ctx->state_mutex);
        mask = ctx->ops->mbox_stat_poll(ctx, POLLOUT | POLLWRNORM);
        spu_release(ctx);
 
@@ -921,12 +962,15 @@ static ssize_t spufs_wbox_stat_read(struct file *file, char __user *buf,
                        size_t len, loff_t *pos)
 {
        struct spu_context *ctx = file->private_data;
+       ssize_t ret;
        u32 wbox_stat;
 
        if (len < 4)
                return -EINVAL;
 
-       spu_acquire(ctx);
+       ret = spu_acquire(ctx);
+       if (ret)
+               return ret;
        wbox_stat = (ctx->ops->mbox_stat_read(ctx) >> 8) & 0xff;
        spu_release(ctx);
 
@@ -997,7 +1041,9 @@ static ssize_t spufs_signal1_read(struct file *file, char __user *buf,
        int ret;
        struct spu_context *ctx = file->private_data;
 
-       spu_acquire_saved(ctx);
+       ret = spu_acquire_saved(ctx);
+       if (ret)
+               return ret;
        ret = __spufs_signal1_read(ctx, buf, len, pos);
        spu_release_saved(ctx);
 
@@ -1008,6 +1054,7 @@ static ssize_t spufs_signal1_write(struct file *file, const char __user *buf,
                        size_t len, loff_t *pos)
 {
        struct spu_context *ctx;
+       ssize_t ret;
        u32 data;
 
        ctx = file->private_data;
@@ -1018,7 +1065,9 @@ static ssize_t spufs_signal1_write(struct file *file, const char __user *buf,
        if (copy_from_user(&data, buf, 4))
                return -EFAULT;
 
-       spu_acquire(ctx);
+       ret = spu_acquire(ctx);
+       if (ret)
+               return ret;
        ctx->ops->signal1_write(ctx, data);
        spu_release(ctx);
 
@@ -1128,7 +1177,9 @@ static ssize_t spufs_signal2_read(struct file *file, char __user *buf,
        struct spu_context *ctx = file->private_data;
        int ret;
 
-       spu_acquire_saved(ctx);
+       ret = spu_acquire_saved(ctx);
+       if (ret)
+               return ret;
        ret = __spufs_signal2_read(ctx, buf, len, pos);
        spu_release_saved(ctx);
 
@@ -1139,6 +1190,7 @@ static ssize_t spufs_signal2_write(struct file *file, const char __user *buf,
                        size_t len, loff_t *pos)
 {
        struct spu_context *ctx;
+       ssize_t ret;
        u32 data;
 
        ctx = file->private_data;
@@ -1149,7 +1201,9 @@ static ssize_t spufs_signal2_write(struct file *file, const char __user *buf,
        if (copy_from_user(&data, buf, 4))
                return -EFAULT;
 
-       spu_acquire(ctx);
+       ret = spu_acquire(ctx);
+       if (ret)
+               return ret;
        ctx->ops->signal2_write(ctx, data);
        spu_release(ctx);
 
@@ -1220,13 +1274,18 @@ static const struct file_operations spufs_signal2_nosched_fops = {
 static int __##__get(void *data, u64 *val)                             \
 {                                                                      \
        struct spu_context *ctx = data;                                 \
+       int ret = 0;                                                    \
                                                                        \
        if (__acquire == SPU_ATTR_ACQUIRE) {                            \
-               spu_acquire(ctx);                                       \
+               ret = spu_acquire(ctx);                                 \
+               if (ret)                                                \
+                       return ret;                                     \
                *val = __get(ctx);                                      \
                spu_release(ctx);                                       \
        } else if (__acquire == SPU_ATTR_ACQUIRE_SAVED) {               \
-               spu_acquire_saved(ctx);                                 \
+               ret = spu_acquire_saved(ctx);                           \
+               if (ret)                                                \
+                       return ret;                                     \
                *val = __get(ctx);                                      \
                spu_release_saved(ctx);                                 \
        } else                                                          \
@@ -1239,8 +1298,11 @@ DEFINE_SPUFS_SIMPLE_ATTRIBUTE(__name, __##__get, __set, __fmt);
 static int spufs_signal1_type_set(void *data, u64 val)
 {
        struct spu_context *ctx = data;
+       int ret;
 
-       spu_acquire(ctx);
+       ret = spu_acquire(ctx);
+       if (ret)
+               return ret;
        ctx->ops->signal1_type_set(ctx, val);
        spu_release(ctx);
 
@@ -1258,8 +1320,11 @@ DEFINE_SPUFS_ATTRIBUTE(spufs_signal1_type, spufs_signal1_type_get,
 static int spufs_signal2_type_set(void *data, u64 val)
 {
        struct spu_context *ctx = data;
+       int ret;
 
-       spu_acquire(ctx);
+       ret = spu_acquire(ctx);
+       if (ret)
+               return ret;
        ctx->ops->signal2_type_set(ctx, val);
        spu_release(ctx);
 
@@ -1512,12 +1577,17 @@ static ssize_t spufs_mfc_read(struct file *file, char __user *buffer,
        if (size != 4)
                goto out;
 
-       spu_acquire(ctx);
+       ret = spu_acquire(ctx);
+       if (ret)
+               return ret;
+
+       ret = -EINVAL;
        if (file->f_flags & O_NONBLOCK) {
                status = ctx->ops->read_mfc_tagstatus(ctx);
                if (!(status & ctx->tagwait))
                        ret = -EAGAIN;
                else
+                       /* XXX(hch): shouldn't we clear ret here? */
                        ctx->tagwait &= ~status;
        } else {
                ret = spufs_wait(ctx->mfc_wq,
@@ -1642,7 +1712,10 @@ static ssize_t spufs_mfc_write(struct file *file, const char __user *buffer,
        if (ret)
                goto out;
 
-       spu_acquire(ctx);
+       ret = spu_acquire(ctx);
+       if (ret)
+               goto out;
+
        ret = spufs_wait(ctx->run_wq, ctx->state == SPU_STATE_RUNNABLE);
        if (ret)
                goto out;
@@ -1677,7 +1750,11 @@ static unsigned int spufs_mfc_poll(struct file *file,poll_table *wait)
 
        poll_wait(file, &ctx->mfc_wq, wait);
 
-       spu_acquire(ctx);
+       /*
+        * For now keep this uninterruptible and also ignore the rule
+        * that poll should not sleep.  Will be fixed later.
+        */
+       mutex_lock(&ctx->state_mutex);
        ctx->ops->set_mfc_query(ctx, ctx->tagwait, 2);
        free_elements = ctx->ops->get_mfc_free_elements(ctx);
        tagstatus = ctx->ops->read_mfc_tagstatus(ctx);
@@ -1700,7 +1777,9 @@ static int spufs_mfc_flush(struct file *file, fl_owner_t id)
        struct spu_context *ctx = file->private_data;
        int ret;
 
-       spu_acquire(ctx);
+       ret = spu_acquire(ctx);
+       if (ret)
+               return ret;
 #if 0
 /* this currently hangs */
        ret = spufs_wait(ctx->mfc_wq,
@@ -1746,7 +1825,11 @@ static const struct file_operations spufs_mfc_fops = {
 static int spufs_npc_set(void *data, u64 val)
 {
        struct spu_context *ctx = data;
-       spu_acquire(ctx);
+       int ret;
+
+       ret = spu_acquire(ctx);
+       if (ret)
+               return ret;
        ctx->ops->npc_write(ctx, val);
        spu_release(ctx);
 
@@ -1764,7 +1847,11 @@ static int spufs_decr_set(void *data, u64 val)
 {
        struct spu_context *ctx = data;
        struct spu_lscsa *lscsa = ctx->csa.lscsa;
-       spu_acquire_saved(ctx);
+       int ret;
+
+       ret = spu_acquire_saved(ctx);
+       if (ret)
+               return ret;
        lscsa->decr.slot[0] = (u32) val;
        spu_release_saved(ctx);
 
@@ -1782,7 +1869,11 @@ DEFINE_SPUFS_ATTRIBUTE(spufs_decr_ops, spufs_decr_get, spufs_decr_set,
 static int spufs_decr_status_set(void *data, u64 val)
 {
        struct spu_context *ctx = data;
-       spu_acquire_saved(ctx);
+       int ret;
+
+       ret = spu_acquire_saved(ctx);
+       if (ret)
+               return ret;
        if (val)
                ctx->csa.priv2.mfc_control_RW |= MFC_CNTL_DECREMENTER_RUNNING;
        else
@@ -1807,7 +1898,11 @@ static int spufs_event_mask_set(void *data, u64 val)
 {
        struct spu_context *ctx = data;
        struct spu_lscsa *lscsa = ctx->csa.lscsa;
-       spu_acquire_saved(ctx);
+       int ret;
+
+       ret = spu_acquire_saved(ctx);
+       if (ret)
+               return ret;
        lscsa->event_mask.slot[0] = (u32) val;
        spu_release_saved(ctx);
 
@@ -1840,7 +1935,11 @@ static int spufs_srr0_set(void *data, u64 val)
 {
        struct spu_context *ctx = data;
        struct spu_lscsa *lscsa = ctx->csa.lscsa;
-       spu_acquire_saved(ctx);
+       int ret;
+
+       ret = spu_acquire_saved(ctx);
+       if (ret)
+               return ret;
        lscsa->srr0.slot[0] = (u32) val;
        spu_release_saved(ctx);
 
@@ -1947,7 +2046,9 @@ static ssize_t spufs_mbox_info_read(struct file *file, char __user *buf,
        if (!access_ok(VERIFY_WRITE, buf, len))
                return -EFAULT;
 
-       spu_acquire_saved(ctx);
+       ret = spu_acquire_saved(ctx);
+       if (ret)
+               return ret;
        spin_lock(&ctx->csa.register_lock);
        ret = __spufs_mbox_info_read(ctx, buf, len, pos);
        spin_unlock(&ctx->csa.register_lock);
@@ -1985,7 +2086,9 @@ static ssize_t spufs_ibox_info_read(struct file *file, char __user *buf,
        if (!access_ok(VERIFY_WRITE, buf, len))
                return -EFAULT;
 
-       spu_acquire_saved(ctx);
+       ret = spu_acquire_saved(ctx);
+       if (ret)
+               return ret;
        spin_lock(&ctx->csa.register_lock);
        ret = __spufs_ibox_info_read(ctx, buf, len, pos);
        spin_unlock(&ctx->csa.register_lock);
@@ -2026,7 +2129,9 @@ static ssize_t spufs_wbox_info_read(struct file *file, char __user *buf,
        if (!access_ok(VERIFY_WRITE, buf, len))
                return -EFAULT;
 
-       spu_acquire_saved(ctx);
+       ret = spu_acquire_saved(ctx);
+       if (ret)
+               return ret;
        spin_lock(&ctx->csa.register_lock);
        ret = __spufs_wbox_info_read(ctx, buf, len, pos);
        spin_unlock(&ctx->csa.register_lock);
@@ -2076,7 +2181,9 @@ static ssize_t spufs_dma_info_read(struct file *file, char __user *buf,
        if (!access_ok(VERIFY_WRITE, buf, len))
                return -EFAULT;
 
-       spu_acquire_saved(ctx);
+       ret = spu_acquire_saved(ctx);
+       if (ret)
+               return ret;
        spin_lock(&ctx->csa.register_lock);
        ret = __spufs_dma_info_read(ctx, buf, len, pos);
        spin_unlock(&ctx->csa.register_lock);
@@ -2127,7 +2234,9 @@ static ssize_t spufs_proxydma_info_read(struct file *file, char __user *buf,
        struct spu_context *ctx = file->private_data;
        int ret;
 
-       spu_acquire_saved(ctx);
+       ret = spu_acquire_saved(ctx);
+       if (ret)
+               return ret;
        spin_lock(&ctx->csa.register_lock);
        ret = __spufs_proxydma_info_read(ctx, buf, len, pos);
        spin_unlock(&ctx->csa.register_lock);
@@ -2216,8 +2325,12 @@ static unsigned long long spufs_class2_intrs(struct spu_context *ctx)
 static int spufs_show_stat(struct seq_file *s, void *private)
 {
        struct spu_context *ctx = s->private;
+       int ret;
+
+       ret = spu_acquire(ctx);
+       if (ret)
+               return ret;
 
-       spu_acquire(ctx);
        seq_printf(s, "%s %llu %llu %llu %llu "
                      "%llu %llu %llu %llu %llu %llu %llu %llu\n",
                ctx_state_names[ctx->stats.util_state],
index b380050cdbc703c8547cf18b01c3726379b44e27..c01a09da1e562b277ce8000396b7ae382c2758fc 100644 (file)
@@ -292,7 +292,7 @@ static int spu_process_callback(struct spu_context *ctx)
        u32 ls_pointer, npc;
        void __iomem *ls;
        long spu_ret;
-       int ret;
+       int ret, ret2;
 
        /* get syscall block from local store */
        npc = ctx->ops->npc_read(ctx) & ~3;
@@ -314,9 +314,11 @@ static int spu_process_callback(struct spu_context *ctx)
                if (spu_ret <= -ERESTARTSYS) {
                        ret = spu_handle_restartsys(ctx, &spu_ret, &npc);
                }
-               spu_acquire(ctx);
+               ret2 = spu_acquire(ctx);
                if (ret == -ERESTARTSYS)
                        return ret;
+               if (ret2)
+                       return -EINTR;
        }
 
        /* write result, jump over indirect pointer */
@@ -338,7 +340,9 @@ long spufs_run_spu(struct spu_context *ctx, u32 *npc, u32 *event)
        spu_enable_spu(ctx);
        ctx->event_return = 0;
 
-       spu_acquire(ctx);
+       ret = spu_acquire(ctx);
+       if (ret)
+               goto out_unlock;
 
        spu_update_sched_info(ctx);
 
@@ -414,6 +418,7 @@ long spufs_run_spu(struct spu_context *ctx, u32 *npc, u32 *event)
 
 out:
        *event = ctx->event_return;
+out_unlock:
        mutex_unlock(&ctx->run_mutex);
        return ret;
 }
index 2775c1652ba4fcd0a04cf83d35f920e50790fe4d..eee7cef28f1a916029d0167f3fb1266c57117786 100644 (file)
@@ -705,7 +705,9 @@ static void __spu_schedule(struct spu *spu, struct spu_context *ctx)
 
 static void spu_schedule(struct spu *spu, struct spu_context *ctx)
 {
-       spu_acquire(ctx);
+       /* not a candidate for interruptible because it's called either
+          from the scheduler thread or from spu_deactivate */
+       mutex_lock(&ctx->state_mutex);
        __spu_schedule(spu, ctx);
        spu_release(ctx);
 }
@@ -823,7 +825,9 @@ static int __spu_deactivate(struct spu_context *ctx, int force, int max_prio)
                                else {
                                        spu_release(ctx);
                                        spu_schedule(spu, new);
-                                       spu_acquire(ctx);
+                                       /* this one can't easily be made
+                                          interruptible */
+                                       mutex_lock(&ctx->state_mutex);
                                }
                        }
                }
@@ -867,7 +871,8 @@ static noinline void spusched_tick(struct spu_context *ctx)
        struct spu *spu = NULL;
        u32 status;
 
-       spu_acquire(ctx);
+       if (spu_acquire(ctx))
+               BUG();  /* a kernel thread never has signals pending */
 
        if (ctx->state != SPU_STATE_RUNNABLE)
                goto out;
index 412de58f5b0f7495e8c2ac45ec066ee3fc9d0718..0e114038ea6fc136b5ec74e675987d848553629f 100644 (file)
@@ -229,9 +229,9 @@ struct spu *affinity_check(struct spu_context *ctx);
 
 /* context management */
 extern atomic_t nr_spu_contexts;
-static inline void spu_acquire(struct spu_context *ctx)
+static inline int __must_check spu_acquire(struct spu_context *ctx)
 {
-       mutex_lock(&ctx->state_mutex);
+       return mutex_lock_interruptible(&ctx->state_mutex);
 }
 
 static inline void spu_release(struct spu_context *ctx)
@@ -246,7 +246,7 @@ int put_spu_context(struct spu_context *ctx);
 void spu_unmap_mappings(struct spu_context *ctx);
 
 void spu_forget(struct spu_context *ctx);
-void spu_acquire_saved(struct spu_context *ctx);
+int __must_check spu_acquire_saved(struct spu_context *ctx);
 void spu_release_saved(struct spu_context *ctx);
 
 int spu_stopped(struct spu_context *ctx, u32 * stat);
@@ -284,7 +284,9 @@ extern char *isolated_loader;
                }                                                       \
                spu_release(ctx);                                       \
                schedule();                                             \
-               spu_acquire(ctx);                                       \
+               __ret = spu_acquire(ctx);                               \
+               if (__ret)                                              \
+                       break;                                          \
        }                                                               \
        finish_wait(&(wq), &__wait);                                    \
        __ret;                                                          \