From 6ded785a192f3fd5dc0b402f26eb7d8aab001846 Mon Sep 17 00:00:00 2001 From: Hans Rosenfeld Date: Tue, 17 Sep 2019 10:15:24 +0200 Subject: [PATCH] OS-7991 port_get() and port_getn() implementation disagrees with documentation --- usr/src/head/port.h | 10 ++++++---- usr/src/lib/libc/port/gen/event_port.c | 7 +++++-- usr/src/uts/common/fs/portfs/port.c | 16 +++++++++++++++- 3 files changed, 26 insertions(+), 7 deletions(-) diff --git a/usr/src/head/port.h b/usr/src/head/port.h index 8b09b39c8b3e..66ced20d37dd 100644 --- a/usr/src/head/port.h +++ b/usr/src/head/port.h @@ -23,12 +23,13 @@ * Copyright 2003 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ +/* + * Copyright 2019 Joyent, Inc. + */ #ifndef _PORT_H #define _PORT_H -#pragma ident "%Z%%M% %I% %E% SMI" - #include #include @@ -45,8 +46,9 @@ int port_associate(int, int, uintptr_t, int, void *); int port_dissociate(int, int, uintptr_t); int port_send(int, int, void *); int port_sendn(int [], int [], uint_t, int, void *); -int port_get(int, port_event_t *, struct timespec *); -int port_getn(int, port_event_t [], uint_t, uint_t *, struct timespec *); +int port_get(int, port_event_t *, const struct timespec *); +int port_getn(int, port_event_t [], uint_t, uint_t *, + const struct timespec *); int port_alert(int, int, int, void *); #ifdef __cplusplus diff --git a/usr/src/lib/libc/port/gen/event_port.c b/usr/src/lib/libc/port/gen/event_port.c index df8f5c7a6419..58cc8334e44c 100644 --- a/usr/src/lib/libc/port/gen/event_port.c +++ b/usr/src/lib/libc/port/gen/event_port.c @@ -23,6 +23,9 @@ * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ +/* + * Copyright 2019 Joyent, Inc. + */ #include "lint.h" #include @@ -64,7 +67,7 @@ port_associate(int port, int source, uintptr_t object, int events, void *user) int -port_get(int port, port_event_t *pe, struct timespec *to) +port_get(int port, port_event_t *pe, const struct timespec *to) { rval_t r; if (to) @@ -77,7 +80,7 @@ port_get(int port, port_event_t *pe, struct timespec *to) int port_getn(int port, port_event_t list[], uint_t max, uint_t *nget, - struct timespec *timeout) + const struct timespec *timeout) { rval_t r; if (nget == NULL) { diff --git a/usr/src/uts/common/fs/portfs/port.c b/usr/src/uts/common/fs/portfs/port.c index 04a2a421dbf4..384d54276dbd 100644 --- a/usr/src/uts/common/fs/portfs/port.c +++ b/usr/src/uts/common/fs/portfs/port.c @@ -25,7 +25,7 @@ */ /* - * Copyright (c) 2015 Joyent, Inc. All rights reserved. + * Copyright 2019 Joyent, Inc. */ #include @@ -615,6 +615,20 @@ portfs(int opcode, uintptr_t a0, uintptr_t a1, uintptr_t a2, uintptr_t a3, error = port_getn(pp, (port_event_t *)a1, 1, (uint_t *)&nget, &port_timer); } while (nget == 0 && error == 0 && port_timer.pgt_loop); + + /* + * There are cases when a timeout is given to port_getn() where + * it returns no events but also no error, such as when events + * are available but can't be copied out, or when there are no + * events and the timeout is all zero. + * + * This isn't a problem in PORT_GETN as the number of retrieved + * events is always returned correctly, but in the case of + * PORT_GET we need to fix this up here and return ETIME as + * documented. + */ + if (nget == 0 && error == 0 && a4 != 0) + error = ETIME; break; } case PORT_GETN: