--- sem.c.old Sun Feb 25 10:50:55 2001 +++ sem.c Sun Feb 25 10:51:19 2001 @@ -250,23 +250,23 @@ curr = sma->sem_base + sop->sem_num; sem_op = sop->sem_op; - if (!sem_op && curr->semval) + result = curr->semval; + if (!sem_op && result) goto would_block; + result += sem_op; + if (result < 0) + goto would_block; + if (result > SEMVMX) + goto out_of_range; curr->sempid = (curr->sempid << 16) | pid; - curr->semval += sem_op; + curr->semval = result; if (sop->sem_flg & SEM_UNDO) un->semadj[sop->sem_num] -= sem_op; - - if (curr->semval < 0) - goto would_block; - if (curr->semval > SEMVMX) - goto out_of_range; } if (do_undo) { - sop--; result = 0; goto undo; } @@ -285,6 +285,7 @@ result = 1; undo: + sop--; while (sop >= sops) { curr = sma->sem_base + sop->sem_num; curr->semval -= sop->sem_op; @@ -305,7 +306,9 @@ { int error; struct sem_queue * q; + int do_retry = 0; +retry: for (q = sma->sem_pending; q; q = q->next) { if (q->status == 1) @@ -323,10 +326,17 @@ q->status = 1; return; } - q->status = error; remove_from_queue(sma,q); + wmb(); + q->status = error; + /* FIXME: retry only required if an increase was + * executed + */ + do_retry = 1; } } + if (do_retry) + goto retry; } /* The following counts are associated to each semaphore: @@ -919,7 +929,13 @@ sem_unlock(semid); schedule(); - + if (queue.status == 0) { + error = 0; + if (queue.prev) + BUG(); + current->semsleeping = NULL; + goto out_free; + } tmp = sem_lock(semid); if(tmp==NULL) { if(queue.prev != NULL)