static int perform_atomic_semop(struct sem_array *sma, struct sembuf *sops,
int nsops, struct sem_undo *un, int pid)
{
- int result, sem_op;
+ int result, undo, sem_op;
struct sembuf *sop;
struct sem * curr;
curr = sma->sem_base + sop->sem_num;
sem_op = sop->sem_op;
result = curr->semval;
-
+
if (!sem_op && result)
goto would_block;
goto would_block;
if (result > SEMVMX)
goto out_of_range;
+
if (sop->sem_flg & SEM_UNDO) {
- int undo = un->semadj[sop->sem_num] - sem_op;
- /*
- * Exceeding the undo range is an error.
- */
+ undo = un->semadj[sop->sem_num] - sem_op;
+ /* Exceeding the undo range is an error. */
if (undo < (-SEMAEM - 1) || undo > SEMAEM)
goto out_of_range;
+ un->semadj[sop->sem_num] = undo;
}
+
curr->semval = result;
}
sop--;
while (sop >= sops) {
sma->sem_base[sop->sem_num].sempid = pid;
- if (sop->sem_flg & SEM_UNDO)
- un->semadj[sop->sem_num] -= sop->sem_op;
sop--;
}
-
+
return 0;
out_of_range:
undo:
sop--;
while (sop >= sops) {
- sma->sem_base[sop->sem_num].semval -= sop->sem_op;
+ sem_op = sop->sem_op;
+ sma->sem_base[sop->sem_num].semval -= sem_op;
+ if (sop->sem_flg & SEM_UNDO)
+ un->semadj[sop->sem_num] += sem_op;
sop--;
}