[SSI] openssi/kernel/ipc sem.c,1.35,1.36
Roger Tsang <[email protected]> Sat, 03 Apr 2010 19:41:54 +0000
| Newsgroups | gmane.linux.cluster.ssic.cvs |
|---|---|
| Message-ID | <[email protected]> |
Update of /cvsroot/ssic-linux/openssi/kernel/ipc
In directory sfp-cvsdas-3.v30.ch3.sourceforge.com:/tmp/cvs-serv30015/kernel/ipc
Modified Files:
Tag: OPENSSI-FC
sem.c
Log Message:
- sys_semctl()
- Move SSI code into ssi_semctl().
- Handle cli_ripc_semctl() error -EAGAIN.
- Fix semctl_nolock() deadlock with destination node when both nodes are doing RPC for SEM_INFO command.
- semctl_nolock()
- Move SSI code to ssi_semctl_nolock_info().
- Handle cli_ripc_semctl() error -EAGAIN.
- Fix race with sys_semctl() over global variable "remote_cmd".
- Fix alloc_semundo() sem_semundo struct memory leak; assigning sem_semundo struct to sem_array that is going away when lost race with ipc_rmid().
- Remove redundant in ssi_semop() which is mostly taken from original sys_semtimedop().
- Fix ssi_semop() dereferencing invalid sem_semundo struct if lost race with ssi_semexit() though this is unlikely to occur because in sem_exit() the last thread removes the the sem_semundo struct.
- Enable debug message in freeundos().
- sem_exit() handle cli_ripc_semexit() error -EAGAIN.
- Remove ugly goto's in __ssi_semexit().
Index: sem.c
===================================================================
RCS file: /cvsroot/ssic-linux/openssi/kernel/ipc/sem.c,v
retrieving revision 1.35
retrieving revision 1.36
diff -u -d -r1.35 -r1.36
--- sem.c 2 Apr 2010 20:42:31 -0000 1.35
+++ sem.c 3 Apr 2010 19:41:51 -0000 1.36
@@ -103,7 +103,6 @@
#endif /* CONFIG_SSI */
#ifdef CONFIG_SSI
-static int remote_cmd=FALSE;
#define SEM_MAX_ID (local_view ? sem_ids.max_id : size-1)
#define SEM_IPC_ID(i,seq) (local_view ? sem_buildid(i,seq) : ipc_id)
#define PRINT_HEADER len += sprintf(buffer, " key semid perms nsems uid gid cuid cgid otime ctime view node_num\n")
@@ -139,8 +138,6 @@
#define sc_semmni (sem_ctls[3])
#ifdef CONFIG_SSI
-void ssi_semexit(int semid, pid_t pid);
-
static void freeundos(int);
static clusternode_t sem_get_svr_node(int);
static void sem_set_svr_node(int, clusternode_t);
@@ -701,6 +698,58 @@
}
}
+#ifdef CONFIG_SSI
+int
+ssi_semctl_nolock_info(
+ struct seminfo *seminfo,
+ union semun arg)
+{
+ ssi_procstate_t pstate;
+ nsc_nodelist_t *nl;
+ nsc_nlcookie_t cookie = CLUSTERNODE_INVAL;
+ clusternode_t svrnode;
+ int status, rval, max_id = 0;
+
+ ssi_procstate_get(&pstate);
+
+ nl = clms_get_nsc_nodelist(CLMS_NODE_UP);
+ while ((svrnode = nsc_nodelist_get_next(&cookie, nl))
+ != CLUSTERNODE_INVAL) {
+ if (svrnode == this_node)
+ continue;
+ memset (arg.__buf, 0, sizeof(struct seminfo));
+retry:
+ status = cli_ripc_semctl(svrnode, &rval, -1, 0, SEM_INFO,
+ &pstate, &arg, 1);
+ if (status == -EREMOTE)
+ continue;
+ if (status) {
+ idelay(HZ/10);
+ goto retry;
+ }
+ if (arg.__buf->semusz) {
+ seminfo->semusz += arg.__buf->semusz;
+ seminfo->semaem += arg.__buf->semaem;
+ max_id += rval;
+ }
+ }
+ NSC_NODELIST_FREE(nl);
+
+ /* Now obtain sem_ids.sem mutex because
+ * cli_ripc_semctl() could deadlock with
+ * another incoming RPC from destination node
+ * that already holds sem_ids.sem mutex.
+ */
+ down(&sem_ids.sem);
+ seminfo->semusz += sem_ids.in_use;
+ seminfo->semaem += used_sems;
+ max_id += sem_ids.max_id;
+ up(&sem_ids.sem);
+
+ return max_id;
+}
+#endif /* CONFIG_SSI */
+
static int semctl_nolock(int semid, int semnum, int cmd, int version, union semun arg)
{
int err = -EINVAL;
@@ -712,12 +761,6 @@
{
struct seminfo seminfo;
int max_id;
-#ifdef CONFIG_SSI
- clusternode_t svrnode;
- ssi_procstate_t pstate;
- nsc_nodelist_t *nl;
- nsc_nlcookie_t cookie;
-#endif /* CONFIG_SSI */
err = security_sem_semctl(NULL, cmd);
if (err)
@@ -732,43 +775,15 @@
seminfo.semmnu = SEMMNU;
seminfo.semmap = SEMMAP;
seminfo.semume = SEMUME;
- down(&sem_ids.sem);
- if (cmd == SEM_INFO) {
#ifdef CONFIG_SSI
- if (!ssi_get_localview() && (remote_cmd == FALSE))
- {
- ssi_procstate_get(&pstate);
- max_id = 0;
- nl = clms_get_nsc_nodelist(CLMS_NODE_UP);
- cookie = CLUSTERNODE_INVAL;
- svrnode = nsc_nodelist_get_next(&cookie, nl);
- for (;svrnode != CLUSTERNODE_INVAL;
- svrnode = nsc_nodelist_get_next(&cookie,nl))
- {
- if( svrnode != this_node )
- {
- memset (arg.__buf, 0,
- sizeof(struct seminfo));
- cli_ripc_semctl(svrnode, &err, -1, 0, SEM_INFO, &pstate, &arg, 1);
- if (arg.__buf->semusz)
- {
- seminfo.semusz +=
- arg.__buf->semusz;
- seminfo.semaem +=
- arg.__buf->semaem;
- max_id += err;
- err = 0;
- }
- }
- }
- NSC_NODELIST_FREE(nl);
- seminfo.semusz += sem_ids.in_use;
- seminfo.semaem += used_sems;
- max_id += sem_ids.max_id;
- goto out_up;
- }
- remote_cmd = FALSE;
+ if (cmd == SEM_INFO &&
+ !ssi_get_localview() && !ssi_isremote()) {
+ max_id = ssi_semctl_nolock_info(&seminfo, arg);
+ goto out_info;
+ }
#endif /* CONFIG_SSI */
+ down(&sem_ids.sem);
+ if (cmd == SEM_INFO) {
seminfo.semusz = sem_ids.in_use;
seminfo.semaem = used_sems;
} else {
@@ -776,10 +791,10 @@
seminfo.semaem = SEMAEM;
}
max_id = sem_ids.max_id;
+ up(&sem_ids.sem);
#ifdef CONFIG_SSI
-out_up:
+out_info:
#endif /* CONFIG_SSI */
- up(&sem_ids.sem);
if (copy_to_user (arg.__buf, &seminfo, sizeof(struct seminfo)))
return -EFAULT;
return (max_id < 0) ? 0: max_id;
@@ -1122,66 +1137,67 @@
return err;
}
-asmlinkage long sys_semctl (int semid, int semnum, int cmd, union semun arg)
-{
- int err = -EINVAL;
- int version;
-
#ifdef CONFIG_SSI
+static int
+ssi_semctl(
+ int semid,
+ int semnum,
+ int cmd,
+ union semun arg,
+ int *err)
+{
+ ssi_procstate_t pstate;
clusternode_t svr_node;
- int rval;
- int tmpcmd = cmd;
+ int status, rval;
- remote_cmd = FALSE;
+ svr_node = sem_get_svr_node(semid);
+ if (!svr_node) {
+namesvr_go:
+ svr_node = sem_find_svr_node(semid);
+ if (!svr_node) {
+ *err = -EINVAL;
+ return 0;
+ }
+ sem_set_svr_node(semid, svr_node);
+ }
+ if (svr_node == this_node)
+ return -ESRCH;
- version = ipc_parse_version(&cmd);
- if ((cmd == SEM_INFO) || (cmd == IPC_INFO)) {
- svr_node = this_node;
- if (semid == -1) {
- remote_cmd=TRUE;
- semid = 0;
+ ssi_procstate_get(&pstate);
+retry:
+ status = cli_ripc_semctl(svr_node, &rval, semid,
+ semnum, cmd, &pstate, &arg, 1);
+ if (status) {
+ if (status != -EREMOTE) {
+ idelay(HZ/10);
+ goto retry;
}
- } else
- svr_node = 0;
- cmd = tmpcmd;
+ sem_set_svr_node(semid, 0);
+ goto namesvr_go;
+ }
+ if (rval == 0 && cmd == IPC_RMID) {
+ /* If we are able to invalidate server semaphore
+ objects, delete the local objects. */
+ freeundos(semid);
+ sem_set_svr_node(semid, 0);
+ }
+ *err = rval;
+ return 0;
+}
#endif /* CONFIG_SSI */
+asmlinkage long sys_semctl (int semid, int semnum, int cmd, union semun arg)
+{
+ int err = -EINVAL;
+ int version;
+
if (semid < 0)
return -EINVAL;
#ifdef CONFIG_SSI
- if (svr_node != this_node &&
- semid >= 0 && cmd >= 0) {
-namesvr_go:
- svr_node = sem_get_svr_node(semid);
- if (!svr_node) {
- svr_node = sem_find_svr_node(semid);
- if (!svr_node)
- return -EINVAL;
- sem_set_svr_node(semid, svr_node);
- }
-
- if (svr_node != this_node) {
- ssi_procstate_t pstate;
- int status;
-
- ssi_procstate_get(&pstate);
- status = cli_ripc_semctl(svr_node, &rval, semid,
- semnum, cmd, &pstate, &arg, 1);
- if (status) {
- sem_set_svr_node(semid, 0);
- idelay(HZ/10);
- goto namesvr_go;
- }
- if (rval == 0 && cmd == IPC_RMID) {
- /* If we are able to invalidate server semaphore
- objects, delete the local objects. */
- freeundos(semid);
- sem_set_svr_node(semid, 0);
- }
- return rval;
- }
- cmd = tmpcmd;
+ if (cmd != SEM_INFO && cmd != IPC_INFO && cmd >= 0) {
+ if (!ssi_semctl(semid, semnum, cmd, arg, &err))
+ return err;
}
#endif /* CONFIG_SSI */
@@ -1409,18 +1425,23 @@
lock_semundo();
if ((un = lookup_undo(undo_list, semid)))
un->semid =-1;
- /* else */
+ else
/* SSI_XXX: Needed anymore? */
- /* printk ("freeundos undo list error id=%d\n", semid); */
+ printk(KERN_DEBUG "freeundos: undo list error id=%d\n", semid);
unlock_semundo();
}
-static int alloc_semundo(struct sem_array *sma, struct sem_semundo** unp, int semid,int alter)
+/* Called with sem_array locked.
+ * On error returns with sem_array unlocked.
+ */
+static int alloc_semundo(struct sem_array *sma, struct sem_semundo** unp, int alter)
{
int size, nsems;
struct sem_semundo *un;
nsems = sma->sem_nsems;
+ ipc_rcu_getref(sma);
+ sem_unlock(sma);
size = sizeof(struct sem_semundo) + sizeof(short)*nsems;
@@ -1434,193 +1455,51 @@
ipc_lock_by_ptr(&sma->sem_perm);
ipc_rcu_putref(sma);
+ if (sma->sem_perm.deleted) {
+ /* ipc_rmid() got to it while we slept */
+ sem_unlock(sma);
+ kfree(un);
+ return -EIDRM;
+ }
un->semadj = (short *) &un[1];
un->id_next = sma->undo;
un->pid = current->tgid;
sma->undo = un;
- sem_unlock(sma);
+
*unp = un;
return 0;
}
-long ssi_semop(int semid, struct sembuf *tsops, unsigned nsops,
- const struct timespec *timeout)
+/*
+ * Called with sem locked.
+ * Returns with sem unlocked on error.
+ */
+static struct sem_semundo *ssi_find_undo(struct sem_array *sma, int alter)
{
- int error = -EINVAL;
- struct sem_array *sma;
- struct sembuf fast_sops[SEMOPM_FAST];
- struct sembuf* sops = fast_sops, *sop;
struct sem_semundo *un;
- int undos = 0, decrease = 0, alter = 0;
- struct sem_queue queue;
- unsigned long jiffies_left = 0;
- int max;
-
- if(nsops > SEMOPM_FAST) {
- sops = kmalloc(sizeof(*sops)*nsops,GFP_KERNEL);
- if(sops==NULL)
- return -ENOMEM;
- }
- if (copy_from_user (sops, tsops, nsops * sizeof(*tsops))) {
- error=-EFAULT;
- goto out_free;
- }
- if (timeout) {
- struct timespec _timeout;
- if (copy_from_user(&_timeout, timeout, sizeof(*timeout))) {
- error = -EFAULT;
- goto out_free;
- }
- if (_timeout.tv_sec < 0 || _timeout.tv_nsec < 0 ||
- _timeout.tv_nsec >= 1000000000L) {
- error = -EINVAL;
- goto out_free;
- }
- jiffies_left = timespec_to_jiffies(&_timeout);
- }
- max = 0;
- for (sop = sops; sop < sops + nsops; sop++) {
- if (sop->sem_num >= max)
- max = sop->sem_num;
- if (sop->sem_flg & SEM_UNDO)
- undos++;
- if (sop->sem_op < 0)
- decrease = 1;
- if (sop->sem_op > 0)
- alter = 1;
- }
- alter |= decrease;
-
- if (undos) {
- sma = sem_lock(semid);
- if (sma == NULL)
- goto out_free;
- error = -EIDRM;
- if (sem_checkid(sma,semid))
- goto out_unlock_free;
-
- un = sma->undo;
-
- /* Make sure we have an undo structure
- * for this process and this semaphore set.
- */
- while(un != NULL) {
- /* Bug [ 1984656 ] semaphore undo count
- sometimes screws up:
- we need to check thread group id, not
- [effective] pid, undo lists are shared by
- all threads in process. */
- if(un->pid==current->tgid)
- break;
- un=un->id_next;
- }
-
- if (!un) { /* No sem_undo struct already exists */
- ipc_rcu_getref(sma);
- sem_unlock(sma);
- error = alloc_semundo(sma,&un,semid,alter);
- if (error)
- goto out_free;
- } else
- sem_unlock(sma);
- } else
- un = NULL;
-
- sma = sem_lock(semid);
- error=-EINVAL;
- if(sma==NULL)
- goto out_free;
- error = -EIDRM;
- if (sem_checkid(sma,semid))
- goto out_unlock_free;
-
- error = -EFBIG;
- if (max >= sma->sem_nsems)
- goto out_unlock_free;
-
- error = -EACCES;
- if (ipcperms(&sma->sem_perm, alter ? S_IWUGO : S_IRUGO))
- goto out_unlock_free;
-
- error = security_sem_semop(sma, sops, nsops, alter);
- if (error)
- goto out_unlock_free;
-
- error = try_atomic_semop (sma, sops, nsops, un, current->tgid);
- if (error <= 0) {
- if (alter && error == 0)
- update_queue (sma);
- goto out_unlock_free;
- }
-
- /* We need to sleep on this operation, so we put the current
- * task into the pending queue and go to sleep.
- */
-
- queue.sma = sma;
- queue.sops = sops;
- queue.nsops = nsops;
- queue.undo = un;
- queue.pid = current->tgid;
- queue.id = semid;
- queue.alter = alter;
- if (alter)
- append_to_queue(sma ,&queue);
- else
- prepend_to_queue(sma ,&queue);
-
- queue.status = -EINTR;
- queue.sleeper = current;
- current->state = TASK_INTERRUPTIBLE;
- sem_unlock(sma);
-
- if (timeout)
- jiffies_left = schedule_timeout(jiffies_left);
- else
- schedule();
-
- error = queue.status;
- while(unlikely(error == IN_WAKEUP)) {
- cpu_relax();
- error = queue.status;
- }
-
- if (error != -EINTR) {
- /* fast path: update_queue already obtained all requested
- * resources */
- goto out_free;
- }
+ int error;
- sma = sem_lock(semid);
- if(sma==NULL) {
- if(queue.prev != NULL)
- BUG();
- error = -EIDRM;
- goto out_free;
- }
+ un = sma->undo;
- /*
- * If queue.status != -EINTR we are woken up by another process
+ /* Make sure we have an undo structure
+ * for this process and this semaphore set.
*/
- error = queue.status;
- if (error != -EINTR) {
- goto out_unlock_free;
+ while(un != NULL) {
+ /* Bug [ 1984656 ] semaphore undo count
+ sometimes screws up:
+ we need to check thread group id, not
+ [effective] pid, undo lists are shared by
+ all threads in process. */
+ if(un->pid==current->tgid)
+ return un;
+ un=un->id_next;
}
- /*
- * If an interrupt occurred we have to clean up the queue
- */
- if (timeout && jiffies_left == 0)
- error = -EAGAIN;
- remove_from_queue(sma,&queue);
- goto out_unlock_free;
+ error = alloc_semundo(sma, &un, alter);
+ if (error)
+ return ERR_PTR(error);
-out_unlock_free:
- sem_unlock(sma);
-out_free:
- if(sops != fast_sops)
- kfree(sops);
- return error;
+ return un;
}
int undocheck(struct sembuf* sops,int semid, int nsops)
@@ -1632,7 +1511,7 @@
for (sop = sops; sop < sops + nsops; sop++) {
if (sop->sem_flg & SEM_UNDO)
- undos++;
+ undos++;
}
if (undos) {
@@ -1661,64 +1540,95 @@
for (up = &undo_list->proc_list; (u = *up); *up = u->proc_next, kfree(u));
}
+
+int
+ssi_semtimedop(
+ int semid,
+ struct sembuf __user *tsops,
+ unsigned nsops,
+ const struct timespec __user *timeout,
+ int *error)
+{
+ ssi_procstate_t pstate;
+ ics_userbuf_t utsops;
+ ics_userbuf_t utimeout;
+ clusternode_t svr_node;
+ int status, rval;
+
+ svr_node = sem_get_svr_node(semid);
+ if (!svr_node) {
+namesvr_op_go:
+ svr_node = sem_find_svr_node(semid);
+ if (!svr_node) {
+ *error = -EINVAL;
+ return 0;
+ }
+ sem_set_svr_node(semid, svr_node);
+ }
+ if (svr_node == this_node)
+ return -ESRCH;
+
+ ssi_procstate_get(&pstate);
+ ics_userbuf_set(&utsops, tsops, nsops * sizeof(*tsops));
+ ics_userbuf_set(&utimeout, timeout, sizeof(*timeout));
+retry:
+ status = cli_ripc_semop(svr_node, &rval, semid, nsops,
+ &pstate, &utsops, &utimeout);
+ if (status) {
+ if (status != -EREMOTE) {
+ idelay(HZ/10);
+ goto retry;
+ }
+ sem_set_svr_node(semid, 0);
+ goto namesvr_op_go;
+ }
+ *error = rval;
+ return 0;
+}
#endif /* CONFIG_SSI */
asmlinkage long sys_semtimedop(int semid, struct sembuf __user *tsops,
unsigned nsops, const struct timespec __user *timeout)
{
- int error = -EINVAL;
#ifdef CONFIG_SSI
- clusternode_t svr_node;
-#else
+ int error;
+
+ if (nsops < 1 || semid < 0)
+ return -EINVAL;
+ if (nsops > sc_semopm)
+ return -E2BIG;
+
+ if (ssi_semtimedop(semid, tsops, nsops, timeout, &error))
+ error = ssi_semop(semid, tsops, nsops, timeout);
+ if(!error)
+ undocheck(tsops, semid, nsops);
+ return error;
+}
+
+long ssi_semop(int semid, struct sembuf *tsops, unsigned nsops,
+ const struct timespec *timeout)
+{
+#endif /* CONFIG_SSI */
+ int error = -EINVAL;
struct sem_array *sma;
struct sembuf fast_sops[SEMOPM_FAST];
struct sembuf* sops = fast_sops, *sop;
+#ifdef CONFIG_SSI
+ struct sem_semundo *un;
+#else
struct sem_undo *un;
+#endif
int undos = 0, decrease = 0, alter = 0, max;
struct sem_queue queue;
unsigned long jiffies_left = 0;
-#endif /* CONFIG_SSI */
+#ifndef CONFIG_SSI
if (nsops < 1 || semid < 0)
return -EINVAL;
if (nsops > sc_semopm)
return -E2BIG;
+#endif /* !CONFIG_SSI */
-#ifdef CONFIG_SSI
-namesvr_op_go:
- svr_node = sem_get_svr_node(semid);
- if (!svr_node) {
- svr_node = sem_find_svr_node(semid);
- if (!svr_node)
- return -EINVAL;
- sem_set_svr_node(semid, svr_node);
- }
- if (svr_node != this_node) {
- ssi_procstate_t pstate;
- ics_userbuf_t utsops;
- ics_userbuf_t utimeout;
- int status;
-
- ssi_procstate_get(&pstate);
- ics_userbuf_set(&utsops, tsops, nsops * sizeof(*tsops));
- ics_userbuf_set(&utimeout, timeout, sizeof(*timeout));
-
- status = cli_ripc_semop(svr_node, &error, semid, nsops,
- &pstate, &utsops, &utimeout);
- if (status) {
- sem_set_svr_node(semid, 0);
- idelay(HZ/10);
- goto namesvr_op_go;
- }
- if (!error)
- undocheck(tsops, semid, nsops);
- } else {
- error = ssi_semop(semid, tsops, nsops, timeout);
- if(!error)
- undocheck(tsops, semid, nsops);
- }
- return error;
-#else /* CONFIG_SSI */
if(nsops > SEMOPM_FAST) {
sops = kmalloc(sizeof(*sops)*nsops,GFP_KERNEL);
if(sops==NULL)
@@ -1754,6 +1664,7 @@
}
alter |= decrease;
+#ifndef CONFIG_SSI
retry_undos:
if (undos) {
un = find_undo(semid);
@@ -1763,6 +1674,7 @@
}
} else
un = NULL;
+#endif /* !CONFIG_SSI */
sma = sem_lock(semid);
error=-EINVAL;
@@ -1771,6 +1683,17 @@
error = -EIDRM;
if (sem_checkid(sma,semid))
goto out_unlock_free;
+#ifdef CONFIG_SSI
+ if (undos) {
+ un = ssi_find_undo(sma, alter);
+ if (IS_ERR(un)) {
+ error = PTR_ERR(un);
+ goto out_free;
+ }
+ } else
+ un = NULL;
+ /* SSI: there is no un->semid. sem_lock must be held throughout */
+#else /* CONFIG_SSI */
/*
* semid identifies are not unique - find_undo may have
* allocated an undo structure, it was invalidated by an RMID
@@ -1780,6 +1703,7 @@
sem_unlock(sma);
goto retry_undos;
}
+#endif /* !CONFIG_SSI */
error = -EFBIG;
if (max >= sma->sem_nsems)
goto out_unlock_free;
@@ -1866,7 +1790,6 @@
if(sops != fast_sops)
kfree(sops);
return error;
-#endif /* !CONFIG_SSI */
}
asmlinkage long sys_semop (int semid, struct sembuf __user *tsops, unsigned nsops)
@@ -1930,12 +1853,14 @@
return svr_node;
}
+/* Called with sem_array locked */
static inline void __ssi_semexit(int semid, pid_t pid, struct sem_array *sma)
{
struct sem_semundo *un, **unp;
int nsems, i;
if (sem_checkid(sma, semid)) {
+ sem_unlock(sma);
/* [ ssic-linux-Bugs-1941808 ] semundo structures confused.
* sem_checkid() failure here is not a bug because in OpenSSI
* tsk->sysvsem.undo_list (struct sem_undo) is separated from
@@ -1945,21 +1870,24 @@
*/
printk(KERN_DEBUG "%s: stale undo sem %d for pid %d\n",
__FUNCTION__, semid, pid);
- goto out_unlock;
+ return;
}
/* remove u from the sma->undo list */
for (unp = &sma->undo; (un = *unp); unp = &un->id_next) {
/* u == un */
- if (pid == un->pid)
- goto found;
+ if (pid == un->pid) {
+ *unp = un->id_next;
+ break;
+ }
+ }
+ if (!un) {
+ sem_unlock(sma);
+ printk(KERN_WARNING "%s: missing undo sem %d for pid %d\n",
+ __FUNCTION__, semid, pid);
+ return;
}
- printk(KERN_WARNING "%s: missing undo sem %d for pid %d\n",
- __FUNCTION__, semid, pid);
- goto out_unlock;
-found:
- *unp = un->id_next;
/* perform adjustments registered in u */
nsems = sma->sem_nsems;
for (i = 0; i < nsems; i++) {
@@ -1989,13 +1917,25 @@
sma->sem_otime = get_seconds();
/* maybe some queued-up processes were waiting for this */
update_queue(sma);
+ sem_unlock(sma);
/* Unlike base code we must free our sem_semundo, no-one else will
do it for us */
kfree (un);
+}
-out_unlock:
- sem_unlock(sma);
+void ssi_semexit(int semid, pid_t pid)
+{
+ struct sem_array *sma;
+
+ if(semid == -1)
+ return;
+
+ sma = sem_lock(semid);
+ if (sma == NULL)
+ return;
+
+ __ssi_semexit(semid, pid, sma);
}
#endif /* CONFIG_SSI */
@@ -2045,11 +1985,16 @@
if (svr_node != this_node) {
ssi_procstate_t pstate;
- int rval;
+ int status, rval;
ssi_procstate_get(&pstate);
- cli_ripc_semexit(svr_node, &rval, &pstate,
+retry:
+ status = cli_ripc_semexit(svr_node, &rval, &pstate,
u->semid, current->tgid);
+ if (status && status != -EREMOTE) {
+ idelay(HZ/10);
+ goto retry;
+ }
/* Ignoring -EREMOTE */
} else
ssi_semexit(u->semid, current->tgid);
@@ -2258,19 +2203,6 @@
#endif
#ifdef CONFIG_SSI
-void ssi_semexit(int semid, pid_t pid)
-{
- struct sem_array *sma;
-
- if(semid == -1)
- return;
- sma = sem_lock(semid);
- if (sma == NULL)
- return;
-
- __ssi_semexit(semid, pid, sma);
-}
-
/* Go thru the sem_semundo structures; for each pid in there, see if it
* is dead, and if dead undo the semaphore operations.
*/
@@ -2293,7 +2225,7 @@
* existing semaphores at the time of node down event.
*/
/* SMP safe because sem_ids.entries->size does not shrink */
- down(&sem_ids.sem);
+ down(&sem_ids.sem); /* ensure existing operations are done */
max_id = sem_ids.entries->size;
up(&sem_ids.sem);
------------------------------------------------------------------------------
Download Intel® Parallel Studio Eval
Try the new software tools for yourself. Speed compiling, find bugs
proactively, and fine-tune applications for parallel performance.
See why Intel Parallel Studio got high marks during beta.
http://p.sf.net/sfu/intel-sw-dev