8179905: Remove the use of gettimeofday in Networking code
Reviewed-by: chegar, rriggs, dfuchs, clanger
--- a/jdk/src/java.base/aix/native/libnet/aix_close.c Wed May 10 12:00:08 2017 +0530
+++ b/jdk/src/java.base/aix/native/libnet/aix_close.c Wed May 10 23:06:49 2017 +0530
@@ -1,6 +1,6 @@
/*
- * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2016, SAP SE and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2017, SAP SE and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -65,6 +65,8 @@
#include <unistd.h>
#include <errno.h>
#include <sys/poll.h>
+#include "jvm.h"
+#include "net_util.h"
/*
* Stack allocated by thread when doing blocking operation
@@ -507,9 +509,9 @@
* Auto restarts with adjusted timeout if interrupted by
* signal other than our wakeup signal.
*/
-int NET_Timeout0(int s, long timeout, long currentTime) {
- long prevtime = currentTime, newtime;
- struct timeval t;
+int NET_Timeout(JNIEnv *env, int s, long timeout, jlong nanoTimeStamp) {
+ jlong prevNanoTime = nanoTimeStamp;
+ jlong nanoTimeout = (jlong) timeout * NET_NSEC_PER_MSEC;
fdEntry_t *fdEntry = getFdEntry(s);
/*
@@ -533,7 +535,7 @@
pfd.events = POLLIN | POLLERR;
startOp(fdEntry, &self);
- rv = poll(&pfd, 1, timeout);
+ rv = poll(&pfd, 1, nanoTimeout / NET_NSEC_PER_MSEC);
endOp(fdEntry, &self);
/*
@@ -541,18 +543,14 @@
* has expired return 0 (indicating timeout expired).
*/
if (rv < 0 && errno == EINTR) {
- if (timeout > 0) {
- gettimeofday(&t, NULL);
- newtime = t.tv_sec * 1000 + t.tv_usec / 1000;
- timeout -= newtime - prevtime;
- if (timeout <= 0) {
- return 0;
- }
- prevtime = newtime;
+ jlong newNanoTime = JVM_NanoTime(env, 0);
+ nanoTimeout -= newNanoTime - prevNanoTime;
+ if (nanoTimeout < NET_NSEC_PER_MSEC) {
+ return 0;
}
+ prevNanoTime = newNanoTime;
} else {
return rv;
}
-
}
}
--- a/jdk/src/java.base/linux/native/libnet/linux_close.c Wed May 10 12:00:08 2017 +0530
+++ b/jdk/src/java.base/linux/native/libnet/linux_close.c Wed May 10 23:06:49 2017 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -37,6 +37,8 @@
#include <unistd.h>
#include <errno.h>
#include <sys/poll.h>
+#include "jvm.h"
+#include "net_util.h"
/*
* Stack allocated by thread when doing blocking operation
@@ -410,9 +412,9 @@
* Auto restarts with adjusted timeout if interrupted by
* signal other than our wakeup signal.
*/
-int NET_Timeout0(int s, long timeout, long currentTime) {
- long prevtime = currentTime, newtime;
- struct timeval t;
+int NET_Timeout(JNIEnv *env, int s, long timeout, jlong nanoTimeStamp) {
+ jlong prevNanoTime = nanoTimeStamp;
+ jlong nanoTimeout = (jlong)timeout * NET_NSEC_PER_MSEC;
fdEntry_t *fdEntry = getFdEntry(s);
/*
@@ -436,26 +438,21 @@
pfd.events = POLLIN | POLLERR;
startOp(fdEntry, &self);
- rv = poll(&pfd, 1, timeout);
+ rv = poll(&pfd, 1, nanoTimeout / NET_NSEC_PER_MSEC);
endOp(fdEntry, &self);
-
/*
* If interrupted then adjust timeout. If timeout
* has expired return 0 (indicating timeout expired).
*/
if (rv < 0 && errno == EINTR) {
- if (timeout > 0) {
- gettimeofday(&t, NULL);
- newtime = t.tv_sec * 1000 + t.tv_usec / 1000;
- timeout -= newtime - prevtime;
- if (timeout <= 0) {
- return 0;
- }
- prevtime = newtime;
+ jlong newNanoTime = JVM_NanoTime(env, 0);
+ nanoTimeout -= newNanoTime - prevNanoTime;
+ if (nanoTimeout < NET_NSEC_PER_MSEC) {
+ return 0;
}
+ prevNanoTime = newNanoTime;
} else {
return rv;
}
-
}
}
--- a/jdk/src/java.base/macosx/native/libnet/bsd_close.c Wed May 10 12:00:08 2017 +0530
+++ b/jdk/src/java.base/macosx/native/libnet/bsd_close.c Wed May 10 23:06:49 2017 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -39,6 +39,8 @@
#include <unistd.h>
#include <errno.h>
#include <sys/poll.h>
+#include "jvm.h"
+#include "net_util.h"
/*
* Stack allocated by thread when doing blocking operation
@@ -414,8 +416,7 @@
* Auto restarts with adjusted timeout if interrupted by
* signal other than our wakeup signal.
*/
-int NET_Timeout0(int s, long timeout, long currentTime) {
- long prevtime = currentTime, newtime;
+int NET_Timeout(JNIEnv *env, int s, long timeout, jlong nanoTimeStamp) {
struct timeval t, *tp = &t;
fd_set fds;
fd_set* fdsp = NULL;
@@ -460,6 +461,8 @@
}
FD_SET(s, fdsp);
+ jlong prevNanoTime = nanoTimeStamp;
+ jlong nanoTimeout = (jlong) timeout * NET_NSEC_PER_MSEC;
for(;;) {
int rv;
@@ -477,25 +480,21 @@
* has expired return 0 (indicating timeout expired).
*/
if (rv < 0 && errno == EINTR) {
- if (timeout > 0) {
- struct timeval now;
- gettimeofday(&now, NULL);
- newtime = now.tv_sec * 1000 + now.tv_usec / 1000;
- timeout -= newtime - prevtime;
- if (timeout <= 0) {
- if (allocated != 0)
- free(fdsp);
- return 0;
- }
- prevtime = newtime;
- t.tv_sec = timeout / 1000;
- t.tv_usec = (timeout % 1000) * 1000;
+ jlong newNanoTime = JVM_NanoTime(env, 0);
+ nanoTimeout -= newNanoTime - prevNanoTime;
+ if (nanoTimeout < NET_NSEC_PER_MSEC) {
+ if (allocated != 0)
+ free(fdsp);
+ return 0;
}
+ prevNanoTime = newNanoTime;
+ t.tv_sec = nanoTimeout / NET_NSEC_PER_SEC;
+ t.tv_usec = (nanoTimeout % NET_NSEC_PER_SEC) / NET_NSEC_PER_USEC;
+
} else {
if (allocated != 0)
free(fdsp);
return rv;
}
-
}
}
--- a/jdk/src/java.base/solaris/native/libnet/solaris_close.c Wed May 10 12:00:08 2017 +0530
+++ b/jdk/src/java.base/solaris/native/libnet/solaris_close.c Wed May 10 23:06:49 2017 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -27,6 +27,8 @@
#include <sys/socket.h>
#include <stropts.h>
#include <unistd.h>
+#include "jvm.h"
+#include "net_util.h"
/* Support for restartable system calls on Solaris. */
@@ -90,25 +92,22 @@
RESTARTABLE_RETURN_INT(poll(ufds, nfds, timeout));
}
-int NET_Timeout0(int s, long timeout, long currentTime) {
+int NET_Timeout(JNIEnv *env, int s, long timeout, jlong nanoTimeStamp) {
int result;
- struct timeval t;
- long prevtime = currentTime, newtime;
+ jlong prevNanoTime = nanoTimeStamp;
+ jlong nanoTimeout = (jlong) timeout * NET_NSEC_PER_MSEC;
struct pollfd pfd;
pfd.fd = s;
pfd.events = POLLIN;
for(;;) {
- result = poll(&pfd, 1, timeout);
+ result = poll(&pfd, 1, nanoTimeout / NET_NSEC_PER_MSEC);
if (result < 0 && errno == EINTR) {
- if (timeout > 0) {
- gettimeofday(&t, NULL);
- newtime = (t.tv_sec * 1000) + t.tv_usec /1000;
- timeout -= newtime - prevtime;
- if (timeout <= 0)
- return 0;
- prevtime = newtime;
- }
+ jlong newNanoTime = JVM_NanoTime(env, 0);
+ nanoTimeout -= newNanoTime - prevNanoTime;
+ if (nanoTimeout < NET_NSEC_PER_MSEC)
+ return 0;
+ prevNanoTime = newNanoTime;
} else {
return result;
}
--- a/jdk/src/java.base/unix/native/libnet/PlainDatagramSocketImpl.c Wed May 10 12:00:08 2017 +0530
+++ b/jdk/src/java.base/unix/native/libnet/PlainDatagramSocketImpl.c Wed May 10 23:06:49 2017 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -485,7 +485,7 @@
return -1;
}
if (timeout) {
- int ret = NET_Timeout(fd, timeout);
+ int ret = NET_Timeout(env, fd, timeout, JVM_NanoTime(env, 0));
if (ret == 0) {
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketTimeoutException",
"Peek timed out");
@@ -576,7 +576,7 @@
packetBufferOffset = (*env)->GetIntField(env, packet, dp_offsetID);
packetBufferLen = (*env)->GetIntField(env, packet, dp_bufLengthID);
if (timeout) {
- int ret = NET_Timeout(fd, timeout);
+ int ret = NET_Timeout(env, fd, timeout, JVM_NanoTime(env, 0));
if (ret == 0) {
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketTimeoutException",
"Receive timed out");
@@ -789,7 +789,7 @@
retry = JNI_FALSE;
if (timeout) {
- int ret = NET_Timeout(fd, timeout);
+ int ret = NET_Timeout(env, fd, timeout, JVM_NanoTime(env, 0));
if (ret <= 0) {
if (ret == 0) {
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketTimeoutException",
--- a/jdk/src/java.base/unix/native/libnet/PlainSocketImpl.c Wed May 10 12:00:08 2017 +0530
+++ b/jdk/src/java.base/unix/native/libnet/PlainSocketImpl.c Wed May 10 23:06:49 2017 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -24,6 +24,7 @@
*/
#include <errno.h>
+#include "jvm.h"
#include "net_util.h"
#include "java_net_SocketOptions.h"
@@ -231,7 +232,6 @@
{
jint localport = (*env)->GetIntField(env, this, psi_localportID);
int len = 0;
-
/* fdObj is the FileDescriptor field on this */
jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID);
@@ -325,7 +325,8 @@
/* connection not established immediately */
if (connect_rv != 0) {
socklen_t optlen;
- jlong prevTime = JVM_CurrentTimeMillis(env, 0);
+ jlong nanoTimeout = (jlong) timeout * NET_NSEC_PER_MSEC;
+ jlong prevNanoTime = JVM_NanoTime(env, 0);
if (errno != EINPROGRESS) {
NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "ConnectException",
@@ -341,13 +342,13 @@
* this thread.
*/
while (1) {
- jlong newTime;
+ jlong newNanoTime;
struct pollfd pfd;
pfd.fd = fd;
pfd.events = POLLOUT;
errno = 0;
- connect_rv = NET_Poll(&pfd, 1, timeout);
+ connect_rv = NET_Poll(&pfd, 1, nanoTimeout / NET_NSEC_PER_MSEC);
if (connect_rv >= 0) {
break;
@@ -360,13 +361,13 @@
* The poll was interrupted so adjust timeout and
* restart
*/
- newTime = JVM_CurrentTimeMillis(env, 0);
- timeout -= (newTime - prevTime);
- if (timeout <= 0) {
+ newNanoTime = JVM_NanoTime(env, 0);
+ nanoTimeout -= (newNanoTime - prevNanoTime);
+ if (nanoTimeout < NET_NSEC_PER_MSEC) {
connect_rv = 0;
break;
}
- prevTime = newTime;
+ prevNanoTime = newNanoTime;
} /* while */
@@ -593,7 +594,8 @@
/* fields on this */
int port;
jint timeout = (*env)->GetIntField(env, this, psi_timeoutID);
- jlong prevTime = 0;
+ jlong prevNanoTime = 0;
+ jlong nanoTimeout = (jlong) timeout * NET_NSEC_PER_MSEC;
jobject fdObj = (*env)->GetObjectField(env, this, psi_fdID);
/* the FileDescriptor field on socket */
@@ -633,18 +635,19 @@
*/
for (;;) {
int ret;
+ jlong currNanoTime;
/* first usage pick up current time */
- if (prevTime == 0 && timeout > 0) {
- prevTime = JVM_CurrentTimeMillis(env, 0);
+ if (prevNanoTime == 0 && nanoTimeout > 0) {
+ prevNanoTime = JVM_NanoTime(env, 0);
}
/* passing a timeout of 0 to poll will return immediately,
but in the case of ServerSocket 0 means infinite. */
if (timeout <= 0) {
- ret = NET_Timeout(fd, -1);
+ ret = NET_Timeout(env, fd, -1, 0);
} else {
- ret = NET_Timeout(fd, timeout);
+ ret = NET_Timeout(env, fd, nanoTimeout / NET_NSEC_PER_MSEC, prevNanoTime);
}
if (ret == 0) {
JNU_ThrowByName(env, JNU_JAVANETPKG "SocketTimeoutException",
@@ -676,17 +679,14 @@
}
/* ECONNABORTED or EWOULDBLOCK error so adjust timeout if there is one. */
- if (timeout) {
- jlong currTime = JVM_CurrentTimeMillis(env, 0);
- timeout -= (currTime - prevTime);
-
- if (timeout <= 0) {
- JNU_ThrowByName(env, JNU_JAVANETPKG "SocketTimeoutException",
- "Accept timed out");
- return;
- }
- prevTime = currTime;
+ currNanoTime = JVM_NanoTime(env, 0);
+ nanoTimeout -= (currNanoTime - prevNanoTime);
+ if (nanoTimeout < NET_NSEC_PER_MSEC) {
+ JNU_ThrowByName(env, JNU_JAVANETPKG "SocketTimeoutException",
+ "Accept timed out");
+ return;
}
+ prevNanoTime = currNanoTime;
}
if (newfd < 0) {
--- a/jdk/src/java.base/unix/native/libnet/SocketInputStream.c Wed May 10 12:00:08 2017 +0530
+++ b/jdk/src/java.base/unix/native/libnet/SocketInputStream.c Wed May 10 23:06:49 2017 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -26,6 +26,7 @@
#include <stdlib.h>
#include <string.h>
+#include "jvm.h"
#include "net_util.h"
#include "java_net_SocketInputStream.h"
@@ -48,9 +49,10 @@
static int NET_ReadWithTimeout(JNIEnv *env, int fd, char *bufP, int len, long timeout) {
int result = 0;
- long prevtime = NET_GetCurrentTime(), newtime;
- while (timeout > 0) {
- result = NET_TimeoutWithCurrentTime(fd, timeout, prevtime);
+ jlong prevNanoTime = JVM_NanoTime(env, 0);
+ jlong nanoTimeout = (jlong) timeout * NET_NSEC_PER_MSEC;
+ while (nanoTimeout >= NET_NSEC_PER_MSEC) {
+ result = NET_Timeout(env, fd, nanoTimeout / NET_NSEC_PER_MSEC, prevNanoTime);
if (result <= 0) {
if (result == 0) {
JNU_ThrowByName(env, "java/net/SocketTimeoutException", "Read timed out");
@@ -68,10 +70,10 @@
}
result = NET_NonBlockingRead(fd, bufP, len);
if (result == -1 && ((errno == EAGAIN) || (errno == EWOULDBLOCK))) {
- newtime = NET_GetCurrentTime();
- timeout -= newtime - prevtime;
- if (timeout > 0) {
- prevtime = newtime;
+ jlong newtNanoTime = JVM_NanoTime(env, 0);
+ nanoTimeout -= newtNanoTime - prevNanoTime;
+ if (nanoTimeout >= NET_NSEC_PER_MSEC) {
+ prevNanoTime = newtNanoTime;
}
} else {
break;
--- a/jdk/src/java.base/unix/native/libnet/net_util_md.c Wed May 10 12:00:08 2017 +0530
+++ b/jdk/src/java.base/unix/native/libnet/net_util_md.c Wed May 10 23:06:49 2017 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -49,6 +49,7 @@
#include <sys/sysctl.h>
#endif
+#include "jvm.h"
#include "net_util.h"
#include "java_net_SocketOptions.h"
@@ -1543,11 +1544,12 @@
jint
NET_Wait(JNIEnv *env, jint fd, jint flags, jint timeout)
{
- jlong prevTime = JVM_CurrentTimeMillis(env, 0);
+ jlong prevNanoTime = JVM_NanoTime(env, 0);
+ jlong nanoTimeout = (jlong) timeout * NET_NSEC_PER_MSEC;
jint read_rv;
while (1) {
- jlong newTime;
+ jlong newNanoTime;
struct pollfd pfd;
pfd.fd = fd;
pfd.events = 0;
@@ -1559,36 +1561,18 @@
pfd.events |= POLLOUT;
errno = 0;
- read_rv = NET_Poll(&pfd, 1, timeout);
+ read_rv = NET_Poll(&pfd, 1, nanoTimeout / NET_NSEC_PER_MSEC);
- newTime = JVM_CurrentTimeMillis(env, 0);
- timeout -= (newTime - prevTime);
- if (timeout <= 0) {
+ newNanoTime = JVM_NanoTime(env, 0);
+ nanoTimeout -= (newNanoTime - prevNanoTime);
+ if (nanoTimeout < NET_NSEC_PER_MSEC) {
return read_rv > 0 ? 0 : -1;
}
- prevTime = newTime;
+ prevNanoTime = newNanoTime;
if (read_rv > 0) {
break;
}
-
-
} /* while */
-
- return timeout;
+ return (nanoTimeout / NET_NSEC_PER_MSEC);
}
-
-long NET_GetCurrentTime() {
- struct timeval time;
- gettimeofday(&time, NULL);
- return (time.tv_sec * 1000 + time.tv_usec / 1000);
-}
-
-int NET_TimeoutWithCurrentTime(int s, long timeout, long currentTime) {
- return NET_Timeout0(s, timeout, currentTime);
-}
-
-int NET_Timeout(int s, long timeout) {
- long currentTime = (timeout > 0) ? NET_GetCurrentTime() : 0;
- return NET_Timeout0(s, timeout, currentTime);
-}
--- a/jdk/src/java.base/unix/native/libnet/net_util_md.h Wed May 10 12:00:08 2017 +0530
+++ b/jdk/src/java.base/unix/native/libnet/net_util_md.h Wed May 10 23:06:49 2017 +0530
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -34,6 +34,10 @@
* Macros and constants
*/
+#define NET_NSEC_PER_MSEC 1000000
+#define NET_NSEC_PER_SEC 1000000000
+#define NET_NSEC_PER_USEC 1000
+
/* Defines SO_REUSEPORT */
#ifndef SO_REUSEPORT
#ifdef __linux__
@@ -68,12 +72,9 @@
* Functions
*/
-int NET_Timeout(int s, long timeout);
-int NET_Timeout0(int s, long timeout, long currentTime);
+int NET_Timeout(JNIEnv *env, int s, long timeout, jlong nanoTimeStamp);
int NET_Read(int s, void* buf, size_t len);
int NET_NonBlockingRead(int s, void* buf, size_t len);
-int NET_TimeoutWithCurrentTime(int s, long timeout, long currentTime);
-long NET_GetCurrentTime();
int NET_RecvFrom(int s, void *buf, int len, unsigned int flags,
struct sockaddr *from, socklen_t *fromlen);
int NET_ReadV(int s, const struct iovec * vector, int count);