Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 201062
b: refs/heads/master
c: c61284e
h: refs/heads/master
v: v3
  • Loading branch information
Manfred Spraul authored and Linus Torvalds committed Jul 20, 2010
1 parent cd228db commit 5a55684
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 8 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 19f0f0af097ba3138ae2780b471180512763a78f
refs/heads/master: c61284e99191b2284fb74dae6961d4d09e4e59e8
46 changes: 39 additions & 7 deletions trunk/ipc/sem.c
Original file line number Diff line number Diff line change
Expand Up @@ -1256,6 +1256,33 @@ static struct sem_undo *find_alloc_undo(struct ipc_namespace *ns, int semid)
return un;
}


/**
* get_queue_result - Retrieve the result code from sem_queue
* @q: Pointer to queue structure
*
* Retrieve the return code from the pending queue. If IN_WAKEUP is found in
* q->status, then we must loop until the value is replaced with the final
* value: This may happen if a task is woken up by an unrelated event (e.g.
* signal) and in parallel the task is woken up by another task because it got
* the requested semaphores.
*
* The function can be called with or without holding the semaphore spinlock.
*/
static int get_queue_result(struct sem_queue *q)
{
int error;

error = q->status;
while (unlikely(error == IN_WAKEUP)) {
cpu_relax();
error = q->status;
}

return error;
}


SYSCALL_DEFINE4(semtimedop, int, semid, struct sembuf __user *, tsops,
unsigned, nsops, const struct timespec __user *, timeout)
{
Expand Down Expand Up @@ -1409,15 +1436,18 @@ SYSCALL_DEFINE4(semtimedop, int, semid, struct sembuf __user *, tsops,
else
schedule();

error = queue.status;
while(unlikely(error == IN_WAKEUP)) {
cpu_relax();
error = queue.status;
}
error = get_queue_result(&queue);

if (error != -EINTR) {
/* fast path: update_queue already obtained all requested
* resources */
* resources.
* Perform a smp_mb(): User space could assume that semop()
* is a memory barrier: Without the mb(), the cpu could
* speculatively read in user space stale data that was
* overwritten by the previous owner of the semaphore.
*/
smp_mb();

goto out_free;
}

Expand All @@ -1427,10 +1457,12 @@ SYSCALL_DEFINE4(semtimedop, int, semid, struct sembuf __user *, tsops,
goto out_free;
}

error = get_queue_result(&queue);

/*
* If queue.status != -EINTR we are woken up by another process
*/
error = queue.status;

if (error != -EINTR) {
goto out_unlock_free;
}
Expand Down

0 comments on commit 5a55684

Please sign in to comment.