Skip to content

Commit ceb5569

Browse files
pgerumldts
authored andcommitted
evl/monitor: event: differentiate causes for interrupted wait
A wait operation can be interrupted for the following reasons: - a signal was received while waiting for the event. - the caller got forcibly unblocked while waiting for the event. - a signal was received or the caller got forcibly unblocked while trying to reacquire the lock once the event was successfully received. Ensure these conditions are differentiated when returning to the caller via the operation status (req.status), which enables the user interface to decide whether it needs to restart the syscall transparently after some fixups on signal receipt, or bail out on error if forcibly unblocked for any other reason. This change causes a bump of the current ABI version (Freescale#28). However, it does not affect current and older libevl releases since none of them check the operation status when an interrupted wait is detected. Signed-off-by: Philippe Gerum <[email protected]>
1 parent 5c6402e commit ceb5569

File tree

2 files changed

+23
-10
lines changed

2 files changed

+23
-10
lines changed

include/uapi/evl/control.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
* latter to the former. CAUTION: a litteral value is required for the
1919
* current ABI definition (scripts reading this may be naive).
2020
*/
21-
#define EVL_ABI_LEVEL 27
21+
#define EVL_ABI_LEVEL 28
2222

2323
#define EVL_CONTROL_DEV "/dev/evl/control"
2424

kernel/evl/monitor.c

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -527,24 +527,37 @@ static int wait_monitor(struct file *filp,
527527
* be handled asap. So exit to user mode, allowing any pending
528528
* signal to be handled during the transition, then expect
529529
* userland to issue UNWAIT to recover (or exit, whichever
530-
* comes first). Consequently, disable syscall restart from
531-
* kernel upon interrupted wait, because the caller does not
532-
* hold the mutex until UNWAIT happens.
530+
* comes first).
531+
*
532+
* Consequently, disable syscall restart from kernel upon
533+
* interrupted wait, because the caller does not hold the
534+
* mutex until UNWAIT happens.
533535
*/
534536
ret = evl_wait_schedule(&event->wait_queue);
535537
if (ret) {
536538
untrack_event(event);
537-
if (ret == -EINTR) {
538-
/* Disable syscall restart upon signal (only). */
539-
if (signal_pending(current))
540-
curr->local_info |= T_NORST;
539+
/*
540+
* Disable syscall restart upon signal (only), user
541+
* receives -EINTR and a zero status in this case. If
542+
* the caller was forcibly unblocked for any other
543+
* reason, both the return value and the status word
544+
* are set to -EINTR.
545+
*/
546+
if (ret == -EINTR && signal_pending(current)) {
547+
curr->local_info |= T_NORST;
541548
goto put;
542549
}
543550
op_ret = ret;
551+
if (ret == -EIDRM)
552+
goto put;
544553
}
545554

546-
if (ret != -EIDRM) /* Success or -ETIMEDOUT */
547-
ret = __enter_monitor(gate, NULL);
555+
ret = __enter_monitor(gate, NULL);
556+
if (ret == -EINTR) {
557+
if (signal_pending(current))
558+
curr->local_info |= T_NORST;
559+
op_ret = -EAGAIN;
560+
}
548561
put:
549562
evl_put_file(efilp);
550563
out:

0 commit comments

Comments
 (0)