aboutsummaryrefslogtreecommitdiff
path: root/ipc/msg.c
diff options
context:
space:
mode:
authorChris Zankel2014-02-24 00:34:36 -0800
committerChris Zankel2014-02-24 00:34:36 -0800
commitb3fdfc1b4b641d372e35ced98814289bc60bc5d1 (patch)
tree5f11d5ba885031dde45690745646519fb887f447 /ipc/msg.c
parentc0e50d41126e4786d9cf1105bdf783e55c99f915 (diff)
parentf63b6d7555cd4064554b39da4d44c4cbbc9d6a4a (diff)
Merge tag 'xtensa-for-next-20140221-1' into for_next
Xtensa fixes for 3.14: - allow booting xtfpga on boards with new uBoot and >128MBytes memory; - drop nonexistent GPIO32 support from fsf variant; - don't select USE_GENERIC_SMP_HELPERS; - enable common clock framework support, set up ethoc clock on xtfpga; - wire up sched_setattr and sched_getattr syscalls. Signed-off-by: Chris Zankel <chris@zankel.net>
Diffstat (limited to 'ipc/msg.c')
-rw-r--r--ipc/msg.c44
1 files changed, 30 insertions, 14 deletions
diff --git a/ipc/msg.c b/ipc/msg.c
index 558aa91186b6..245db1140ad6 100644
--- a/ipc/msg.c
+++ b/ipc/msg.c
@@ -253,8 +253,14 @@ static void expunge_all(struct msg_queue *msq, int res)
struct msg_receiver *msr, *t;
list_for_each_entry_safe(msr, t, &msq->q_receivers, r_list) {
- msr->r_msg = NULL;
+ msr->r_msg = NULL; /* initialize expunge ordering */
wake_up_process(msr->r_tsk);
+ /*
+ * Ensure that the wakeup is visible before setting r_msg as
+ * the receiving end depends on it: either spinning on a nil,
+ * or dealing with -EAGAIN cases. See lockless receive part 1
+ * and 2 in do_msgrcv().
+ */
smp_mb();
msr->r_msg = ERR_PTR(res);
}
@@ -318,7 +324,7 @@ SYSCALL_DEFINE2(msgget, key_t, key, int, msgflg)
static inline unsigned long
copy_msqid_to_user(void __user *buf, struct msqid64_ds *in, int version)
{
- switch(version) {
+ switch (version) {
case IPC_64:
return copy_to_user(buf, in, sizeof(*in));
case IPC_OLD:
@@ -363,7 +369,7 @@ copy_msqid_to_user(void __user *buf, struct msqid64_ds *in, int version)
static inline unsigned long
copy_msqid_from_user(struct msqid64_ds *out, void __user *buf, int version)
{
- switch(version) {
+ switch (version) {
case IPC_64:
if (copy_from_user(out, buf, sizeof(*out)))
return -EFAULT;
@@ -375,9 +381,9 @@ copy_msqid_from_user(struct msqid64_ds *out, void __user *buf, int version)
if (copy_from_user(&tbuf_old, buf, sizeof(tbuf_old)))
return -EFAULT;
- out->msg_perm.uid = tbuf_old.msg_perm.uid;
- out->msg_perm.gid = tbuf_old.msg_perm.gid;
- out->msg_perm.mode = tbuf_old.msg_perm.mode;
+ out->msg_perm.uid = tbuf_old.msg_perm.uid;
+ out->msg_perm.gid = tbuf_old.msg_perm.gid;
+ out->msg_perm.mode = tbuf_old.msg_perm.mode;
if (tbuf_old.msg_qbytes == 0)
out->msg_qbytes = tbuf_old.msg_lqbytes;
@@ -606,13 +612,13 @@ SYSCALL_DEFINE3(msgctl, int, msqid, int, cmd, struct msqid_ds __user *, buf)
static int testmsg(struct msg_msg *msg, long type, int mode)
{
- switch(mode)
+ switch (mode)
{
case SEARCH_ANY:
case SEARCH_NUMBER:
return 1;
case SEARCH_LESSEQUAL:
- if (msg->m_type <=type)
+ if (msg->m_type <= type)
return 1;
break;
case SEARCH_EQUAL:
@@ -638,15 +644,22 @@ static inline int pipelined_send(struct msg_queue *msq, struct msg_msg *msg)
list_del(&msr->r_list);
if (msr->r_maxsize < msg->m_ts) {
+ /* initialize pipelined send ordering */
msr->r_msg = NULL;
wake_up_process(msr->r_tsk);
- smp_mb();
+ smp_mb(); /* see barrier comment below */
msr->r_msg = ERR_PTR(-E2BIG);
} else {
msr->r_msg = NULL;
msq->q_lrpid = task_pid_vnr(msr->r_tsk);
msq->q_rtime = get_seconds();
wake_up_process(msr->r_tsk);
+ /*
+ * Ensure that the wakeup is visible before
+ * setting r_msg, as the receiving end depends
+ * on it. See lockless receive part 1 and 2 in
+ * do_msgrcv().
+ */
smp_mb();
msr->r_msg = msg;
@@ -654,6 +667,7 @@ static inline int pipelined_send(struct msg_queue *msq, struct msg_msg *msg)
}
}
}
+
return 0;
}
@@ -696,7 +710,7 @@ long do_msgsnd(int msqid, long mtype, void __user *mtext,
goto out_unlock0;
/* raced with RMID? */
- if (msq->q_perm.deleted) {
+ if (!ipc_valid_object(&msq->q_perm)) {
err = -EIDRM;
goto out_unlock0;
}
@@ -716,6 +730,7 @@ long do_msgsnd(int msqid, long mtype, void __user *mtext,
goto out_unlock0;
}
+ /* enqueue the sender and prepare to block */
ss_add(msq, &s);
if (!ipc_rcu_getref(msq)) {
@@ -731,7 +746,8 @@ long do_msgsnd(int msqid, long mtype, void __user *mtext,
ipc_lock_object(&msq->q_perm);
ipc_rcu_putref(msq, ipc_rcu_free);
- if (msq->q_perm.deleted) {
+ /* raced with RMID? */
+ if (!ipc_valid_object(&msq->q_perm)) {
err = -EIDRM;
goto out_unlock0;
}
@@ -909,7 +925,7 @@ long do_msgrcv(int msqid, void __user *buf, size_t bufsz, long msgtyp, int msgfl
ipc_lock_object(&msq->q_perm);
/* raced with RMID? */
- if (msq->q_perm.deleted) {
+ if (!ipc_valid_object(&msq->q_perm)) {
msg = ERR_PTR(-EIDRM);
goto out_unlock0;
}
@@ -983,7 +999,7 @@ long do_msgrcv(int msqid, void __user *buf, size_t bufsz, long msgtyp, int msgfl
* wake_up_process(). There is a race with exit(), see
* ipc/mqueue.c for the details.
*/
- msg = (struct msg_msg*)msr_d.r_msg;
+ msg = (struct msg_msg *)msr_d.r_msg;
while (msg == NULL) {
cpu_relax();
msg = (struct msg_msg *)msr_d.r_msg;
@@ -1004,7 +1020,7 @@ long do_msgrcv(int msqid, void __user *buf, size_t bufsz, long msgtyp, int msgfl
/* Lockless receive, part 4:
* Repeat test after acquiring the spinlock.
*/
- msg = (struct msg_msg*)msr_d.r_msg;
+ msg = (struct msg_msg *)msr_d.r_msg;
if (msg != ERR_PTR(-EAGAIN))
goto out_unlock0;