diff options
Diffstat (limited to 'ipc')
| -rw-r--r-- | ipc/mqueue.c | 4 | ||||
| -rw-r--r-- | ipc/sem.c | 56 |
2 files changed, 57 insertions, 3 deletions
diff --git a/ipc/mqueue.c b/ipc/mqueue.c index ed049ea568f4..2e0ecfcc881d 100644 --- a/ipc/mqueue.c +++ b/ipc/mqueue.c | |||
| @@ -449,8 +449,8 @@ static int wq_sleep(struct mqueue_inode_info *info, int sr, | |||
| 449 | set_current_state(TASK_INTERRUPTIBLE); | 449 | set_current_state(TASK_INTERRUPTIBLE); |
| 450 | 450 | ||
| 451 | spin_unlock(&info->lock); | 451 | spin_unlock(&info->lock); |
| 452 | time = schedule_hrtimeout_range_clock(timeout, | 452 | time = schedule_hrtimeout_range_clock(timeout, 0, |
| 453 | HRTIMER_MODE_ABS, 0, CLOCK_REALTIME); | 453 | HRTIMER_MODE_ABS, CLOCK_REALTIME); |
| 454 | 454 | ||
| 455 | while (ewp->state == STATE_PENDING) | 455 | while (ewp->state == STATE_PENDING) |
| 456 | cpu_relax(); | 456 | cpu_relax(); |
| @@ -90,6 +90,52 @@ | |||
| 90 | #include <asm/uaccess.h> | 90 | #include <asm/uaccess.h> |
| 91 | #include "util.h" | 91 | #include "util.h" |
| 92 | 92 | ||
| 93 | /* One semaphore structure for each semaphore in the system. */ | ||
| 94 | struct sem { | ||
| 95 | int semval; /* current value */ | ||
| 96 | int sempid; /* pid of last operation */ | ||
| 97 | struct list_head sem_pending; /* pending single-sop operations */ | ||
| 98 | }; | ||
| 99 | |||
| 100 | /* One queue for each sleeping process in the system. */ | ||
| 101 | struct sem_queue { | ||
| 102 | struct list_head simple_list; /* queue of pending operations */ | ||
| 103 | struct list_head list; /* queue of pending operations */ | ||
| 104 | struct task_struct *sleeper; /* this process */ | ||
| 105 | struct sem_undo *undo; /* undo structure */ | ||
| 106 | int pid; /* process id of requesting process */ | ||
| 107 | int status; /* completion status of operation */ | ||
| 108 | struct sembuf *sops; /* array of pending operations */ | ||
| 109 | int nsops; /* number of operations */ | ||
| 110 | int alter; /* does *sops alter the array? */ | ||
| 111 | }; | ||
| 112 | |||
| 113 | /* Each task has a list of undo requests. They are executed automatically | ||
| 114 | * when the process exits. | ||
| 115 | */ | ||
| 116 | struct sem_undo { | ||
| 117 | struct list_head list_proc; /* per-process list: * | ||
| 118 | * all undos from one process | ||
| 119 | * rcu protected */ | ||
| 120 | struct rcu_head rcu; /* rcu struct for sem_undo */ | ||
| 121 | struct sem_undo_list *ulp; /* back ptr to sem_undo_list */ | ||
| 122 | struct list_head list_id; /* per semaphore array list: | ||
| 123 | * all undos for one array */ | ||
| 124 | int semid; /* semaphore set identifier */ | ||
| 125 | short *semadj; /* array of adjustments */ | ||
| 126 | /* one per semaphore */ | ||
| 127 | }; | ||
| 128 | |||
| 129 | /* sem_undo_list controls shared access to the list of sem_undo structures | ||
| 130 | * that may be shared among all a CLONE_SYSVSEM task group. | ||
| 131 | */ | ||
| 132 | struct sem_undo_list { | ||
| 133 | atomic_t refcnt; | ||
| 134 | spinlock_t lock; | ||
| 135 | struct list_head list_proc; | ||
| 136 | }; | ||
| 137 | |||
| 138 | |||
| 93 | #define sem_ids(ns) ((ns)->ids[IPC_SEM_IDS]) | 139 | #define sem_ids(ns) ((ns)->ids[IPC_SEM_IDS]) |
| 94 | 140 | ||
| 95 | #define sem_unlock(sma) ipc_unlock(&(sma)->sem_perm) | 141 | #define sem_unlock(sma) ipc_unlock(&(sma)->sem_perm) |
| @@ -1426,6 +1472,8 @@ SYSCALL_DEFINE4(semtimedop, int, semid, struct sembuf __user *, tsops, | |||
| 1426 | 1472 | ||
| 1427 | queue.status = -EINTR; | 1473 | queue.status = -EINTR; |
| 1428 | queue.sleeper = current; | 1474 | queue.sleeper = current; |
| 1475 | |||
| 1476 | sleep_again: | ||
| 1429 | current->state = TASK_INTERRUPTIBLE; | 1477 | current->state = TASK_INTERRUPTIBLE; |
| 1430 | sem_unlock(sma); | 1478 | sem_unlock(sma); |
| 1431 | 1479 | ||
| @@ -1460,7 +1508,6 @@ SYSCALL_DEFINE4(semtimedop, int, semid, struct sembuf __user *, tsops, | |||
| 1460 | * Array removed? If yes, leave without sem_unlock(). | 1508 | * Array removed? If yes, leave without sem_unlock(). |
| 1461 | */ | 1509 | */ |
| 1462 | if (IS_ERR(sma)) { | 1510 | if (IS_ERR(sma)) { |
| 1463 | error = -EIDRM; | ||
| 1464 | goto out_free; | 1511 | goto out_free; |
| 1465 | } | 1512 | } |
| 1466 | 1513 | ||
| @@ -1479,6 +1526,13 @@ SYSCALL_DEFINE4(semtimedop, int, semid, struct sembuf __user *, tsops, | |||
| 1479 | */ | 1526 | */ |
| 1480 | if (timeout && jiffies_left == 0) | 1527 | if (timeout && jiffies_left == 0) |
| 1481 | error = -EAGAIN; | 1528 | error = -EAGAIN; |
| 1529 | |||
| 1530 | /* | ||
| 1531 | * If the wakeup was spurious, just retry | ||
| 1532 | */ | ||
| 1533 | if (error == -EINTR && !signal_pending(current)) | ||
| 1534 | goto sleep_again; | ||
| 1535 | |||
| 1482 | unlink_queue(sma, &queue); | 1536 | unlink_queue(sma, &queue); |
| 1483 | 1537 | ||
| 1484 | out_unlock_free: | 1538 | out_unlock_free: |
