summaryrefslogtreecommitdiffstats
path: root/ipc
diff options
context:
space:
mode:
authorMauro Carvalho Chehab <mchehab@redhat.com>2011-11-23 19:42:09 -0200
committerMauro Carvalho Chehab <mchehab@redhat.com>2011-11-23 19:42:09 -0200
commit12cbfd0a3c52a52c2948c91b9e62e73c468d1572 (patch)
tree9252b3929159a83fc81ca0a48706bfa959660967 /ipc
parentb32e724308300a6ecead0f4895f0452a06a4291d (diff)
parentcfcfc9eca2bcbd26a8e206baeb005b055dbf8e37 (diff)
Merge tag 'v3.2-rc2' into staging/for_v3.3
* tag 'v3.2-rc2': (3068 commits) Linux 3.2-rc2 hfs: add sanity check for file name length fsl-rio: fix compile error blackfin: Fixup export.h includes Blackfin: add serial TX IRQ in individual platform resource virtio-pci: fix use after free ACPI / cpuidle: Remove acpi_idle_suspend (to fix suspend regression) drm/radeon/kms/combios: fix dynamic allocation of PM clock modes [CPUFREQ] db8500: fix build error due to undeclared i variable bma023: Add SFI translation for this device vrtc: change its year offset from 1960 to 1972 ce4100: fix a build error arm/imx: fix imx6q mmc error when mounting rootfs arm/imx: fix AUTO_ZRELADDR selection arm/imx: fix the references to ARCH_MX3 ARM: mx51/53: set pwm clock parent to ipg_perclk btrfs: rename the option to nospace_cache drm/radeon/kms/pm: switch to dynamically allocating clock mode array drm/radeon/kms: optimize r600_pm_profile_init drm/radeon/kms/pm: add a proper pm profile init function for fusion ... Conflicts: drivers/media/radio/Kconfig
Diffstat (limited to 'ipc')
-rw-r--r--ipc/mqueue.c4
-rw-r--r--ipc/sem.c56
2 files changed, 57 insertions, 3 deletions
diff --git a/ipc/mqueue.c b/ipc/mqueue.c
index ed049ea568f..2e0ecfcc881 100644
--- a/ipc/mqueue.c
+++ b/ipc/mqueue.c
@@ -449,8 +449,8 @@ static int wq_sleep(struct mqueue_inode_info *info, int sr,
set_current_state(TASK_INTERRUPTIBLE);
spin_unlock(&info->lock);
- time = schedule_hrtimeout_range_clock(timeout,
- HRTIMER_MODE_ABS, 0, CLOCK_REALTIME);
+ time = schedule_hrtimeout_range_clock(timeout, 0,
+ HRTIMER_MODE_ABS, CLOCK_REALTIME);
while (ewp->state == STATE_PENDING)
cpu_relax();
diff --git a/ipc/sem.c b/ipc/sem.c
index c8e00f8b4be..5215a81420d 100644
--- a/ipc/sem.c
+++ b/ipc/sem.c
@@ -90,6 +90,52 @@
#include <asm/uaccess.h>
#include "util.h"
+/* One semaphore structure for each semaphore in the system. */
+struct sem {
+ int semval; /* current value */
+ int sempid; /* pid of last operation */
+ struct list_head sem_pending; /* pending single-sop operations */
+};
+
+/* One queue for each sleeping process in the system. */
+struct sem_queue {
+ struct list_head simple_list; /* queue of pending operations */
+ struct list_head list; /* queue of pending operations */
+ struct task_struct *sleeper; /* this process */
+ struct sem_undo *undo; /* undo structure */
+ int pid; /* process id of requesting process */
+ int status; /* completion status of operation */
+ struct sembuf *sops; /* array of pending operations */
+ int nsops; /* number of operations */
+ int alter; /* does *sops alter the array? */
+};
+
+/* Each task has a list of undo requests. They are executed automatically
+ * when the process exits.
+ */
+struct sem_undo {
+ struct list_head list_proc; /* per-process list: *
+ * all undos from one process
+ * rcu protected */
+ struct rcu_head rcu; /* rcu struct for sem_undo */
+ struct sem_undo_list *ulp; /* back ptr to sem_undo_list */
+ struct list_head list_id; /* per semaphore array list:
+ * all undos for one array */
+ int semid; /* semaphore set identifier */
+ short *semadj; /* array of adjustments */
+ /* one per semaphore */
+};
+
+/* sem_undo_list controls shared access to the list of sem_undo structures
+ * that may be shared among all a CLONE_SYSVSEM task group.
+ */
+struct sem_undo_list {
+ atomic_t refcnt;
+ spinlock_t lock;
+ struct list_head list_proc;
+};
+
+
#define sem_ids(ns) ((ns)->ids[IPC_SEM_IDS])
#define sem_unlock(sma) ipc_unlock(&(sma)->sem_perm)
@@ -1426,6 +1472,8 @@ SYSCALL_DEFINE4(semtimedop, int, semid, struct sembuf __user *, tsops,
queue.status = -EINTR;
queue.sleeper = current;
+
+sleep_again:
current->state = TASK_INTERRUPTIBLE;
sem_unlock(sma);
@@ -1460,7 +1508,6 @@ SYSCALL_DEFINE4(semtimedop, int, semid, struct sembuf __user *, tsops,
* Array removed? If yes, leave without sem_unlock().
*/
if (IS_ERR(sma)) {
- error = -EIDRM;
goto out_free;
}
@@ -1479,6 +1526,13 @@ SYSCALL_DEFINE4(semtimedop, int, semid, struct sembuf __user *, tsops,
*/
if (timeout && jiffies_left == 0)
error = -EAGAIN;
+
+ /*
+ * If the wakeup was spurious, just retry
+ */
+ if (error == -EINTR && !signal_pending(current))
+ goto sleep_again;
+
unlink_queue(sma, &queue);
out_unlock_free: