patch-2.2.15 linux/ipc/sem.c
Next file: linux/ipc/shm.c
Previous file: linux/init/main.c
Back to the patch index
Back to the overall index
- Lines: 96
- Date:
Fri Apr 21 12:47:01 2000
- Orig file:
v2.2.14/ipc/sem.c
- Orig date:
Tue Jan 4 21:19:03 2000
diff -u --new-file --recursive --exclude-from ../../exclude v2.2.14/ipc/sem.c linux/ipc/sem.c
@@ -282,7 +282,7 @@
for (q = sma->sem_pending; q; q = q->next) {
if (q->status == 1)
- return; /* wait for other process */
+ continue; /* this one was woken up before */
error = try_atomic_semop(sma, q->sops, q->nsops,
q->undo, q->pid, q->alter);
@@ -521,16 +521,14 @@
break;
case IPC_SET:
buf = arg.buf;
- err = copy_from_user (&tbuf, buf, sizeof (*buf));
- if (err)
- err = -EFAULT;
+ err = -EFAULT;
+ if(copy_from_user (&tbuf, buf, sizeof (*buf)))
+ goto out;
break;
}
err = -EIDRM;
- if (semary[id] == IPC_UNUSED || semary[id] == IPC_NOID)
- goto out;
- if (sma->sem_perm.seq != (unsigned int) semid / SEMMNI)
+ if ((sma != semary[id]) || (sma->sem_perm.seq != (unsigned int) semid / SEMMNI))
goto out;
switch (cmd) {
@@ -540,8 +538,9 @@
goto out;
for (i = 0; i < sma->sem_nsems; i++)
sem_io[i] = sma->sem_base[i].semval;
+ err = -EFAULT;
if (copy_to_user (array, sem_io, nsems*sizeof(ushort)))
- err = -EFAULT;
+ goto out;
break;
case SETVAL:
err = -EACCES;
@@ -575,8 +574,9 @@
tbuf.sem_otime = sma->sem_otime;
tbuf.sem_ctime = sma->sem_ctime;
tbuf.sem_nsems = sma->sem_nsems;
+ err = -EFAULT;
if (copy_to_user (buf, &tbuf, sizeof(*buf)))
- err = -EFAULT;
+ goto out;
break;
case SETALL:
err = -EACCES;
@@ -601,6 +601,25 @@
return err;
}
+
+static struct sem_undo* freeundos(struct sem_undo* un)
+{
+ struct sem_undo* u;
+ struct sem_undo** up;
+
+ for (up = ¤t->semundo;(u=*up);up=&u->proc_next) {
+ if(un==u) {
+ un=u->proc_next;
+ *up=un;
+ kfree(u);
+ return un;
+ }
+ }
+ printk ("freeundos undo list error id=%d\n", un->semid);
+ return un->proc_next;
+}
+
+
asmlinkage int sys_semop (int semid, struct sembuf *tsops, unsigned nsops)
{
int id, size, error = -EINVAL;
@@ -647,9 +666,15 @@
/* Make sure we have an undo structure
* for this process and this semaphore set.
*/
- for (un = current->semundo; un; un = un->proc_next)
- if (un->semid == semid)
+ un = current->semundo;
+ while(un != NULL) {
+ if(un->semid==semid)
break;
+ if(un->semid==-1)
+ un=freeundos(un);
+ else
+ un=un->proc_next;
+ }
if (!un) {
size = sizeof(struct sem_undo) + sizeof(short)*sma->sem_nsems;
un = (struct sem_undo *) kmalloc(size, GFP_ATOMIC);
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)