Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
dragonwell11
提交
1a2968ae
D
dragonwell11
项目概览
openanolis
/
dragonwell11
通知
7
Star
2
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
D
dragonwell11
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
1a2968ae
编写于
3月 23, 2018
作者:
A
alanb
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
8199791: (se) More Selector cleanup
Reviewed-by: redestad, bpb
上级
21b2c57a
变更
33
显示空白变更内容
内联
并排
Showing
33 changed file
with
752 addition
and
1514 deletion
+752
-1514
make/mapfiles/libnio/mapfile-linux
make/mapfiles/libnio/mapfile-linux
+5
-15
make/mapfiles/libnio/mapfile-macosx
make/mapfiles/libnio/mapfile-macosx
+97
-99
make/mapfiles/libnio/mapfile-solaris
make/mapfiles/libnio/mapfile-solaris
+2
-2
src/java.base/linux/classes/sun/nio/ch/EPoll.java
src/java.base/linux/classes/sun/nio/ch/EPoll.java
+3
-3
src/java.base/linux/classes/sun/nio/ch/EPollArrayWrapper.java
...java.base/linux/classes/sun/nio/ch/EPollArrayWrapper.java
+0
-309
src/java.base/linux/classes/sun/nio/ch/EPollPort.java
src/java.base/linux/classes/sun/nio/ch/EPollPort.java
+36
-42
src/java.base/linux/classes/sun/nio/ch/EPollSelectorImpl.java
...java.base/linux/classes/sun/nio/ch/EPollSelectorImpl.java
+168
-60
src/java.base/linux/native/libnio/ch/EPoll.c
src/java.base/linux/native/libnio/ch/EPoll.c
+25
-25
src/java.base/linux/native/libnio/ch/EPollArrayWrapper.c
src/java.base/linux/native/libnio/ch/EPollArrayWrapper.c
+0
-160
src/java.base/linux/native/libnio/ch/EPollPort.c
src/java.base/linux/native/libnio/ch/EPollPort.c
+0
-76
src/java.base/macosx/classes/sun/nio/ch/KQueue.java
src/java.base/macosx/classes/sun/nio/ch/KQueue.java
+6
-6
src/java.base/macosx/classes/sun/nio/ch/KQueueArrayWrapper.java
...va.base/macosx/classes/sun/nio/ch/KQueueArrayWrapper.java
+0
-197
src/java.base/macosx/classes/sun/nio/ch/KQueuePort.java
src/java.base/macosx/classes/sun/nio/ch/KQueuePort.java
+37
-45
src/java.base/macosx/classes/sun/nio/ch/KQueueSelectorImpl.java
...va.base/macosx/classes/sun/nio/ch/KQueueSelectorImpl.java
+210
-101
src/java.base/macosx/classes/sun/nio/ch/KQueueSelectorProvider.java
...ase/macosx/classes/sun/nio/ch/KQueueSelectorProvider.java
+1
-8
src/java.base/macosx/native/libnio/ch/KQueue.c
src/java.base/macosx/native/libnio/ch/KQueue.c
+35
-20
src/java.base/macosx/native/libnio/ch/KQueueArrayWrapper.c
src/java.base/macosx/native/libnio/ch/KQueueArrayWrapper.c
+0
-175
src/java.base/macosx/native/libnio/ch/KQueuePort.c
src/java.base/macosx/native/libnio/ch/KQueuePort.c
+0
-76
src/java.base/share/classes/sun/nio/ch/IOUtil.java
src/java.base/share/classes/sun/nio/ch/IOUtil.java
+3
-1
src/java.base/share/classes/sun/nio/ch/SelectionKeyImpl.java
src/java.base/share/classes/sun/nio/ch/SelectionKeyImpl.java
+10
-3
src/java.base/share/classes/sun/nio/ch/SelectorImpl.java
src/java.base/share/classes/sun/nio/ch/SelectorImpl.java
+15
-2
src/java.base/share/classes/sun/nio/ch/ServerSocketChannelImpl.java
...ase/share/classes/sun/nio/ch/ServerSocketChannelImpl.java
+14
-19
src/java.base/solaris/classes/sun/nio/ch/DevPollArrayWrapper.java
....base/solaris/classes/sun/nio/ch/DevPollArrayWrapper.java
+12
-9
src/java.base/solaris/classes/sun/nio/ch/DevPollSelectorImpl.java
....base/solaris/classes/sun/nio/ch/DevPollSelectorImpl.java
+1
-1
src/java.base/solaris/classes/sun/nio/ch/EventPortWrapper.java
...ava.base/solaris/classes/sun/nio/ch/EventPortWrapper.java
+18
-4
src/java.base/solaris/classes/sun/nio/ch/SolarisEventPort.java
...ava.base/solaris/classes/sun/nio/ch/SolarisEventPort.java
+6
-3
src/java.base/solaris/native/libnio/ch/DevPollArrayWrapper.c
src/java.base/solaris/native/libnio/ch/DevPollArrayWrapper.c
+1
-12
src/java.base/solaris/native/libnio/ch/SolarisEventPort.c
src/java.base/solaris/native/libnio/ch/SolarisEventPort.c
+27
-14
src/java.base/unix/classes/sun/nio/ch/PipeImpl.java
src/java.base/unix/classes/sun/nio/ch/PipeImpl.java
+2
-2
src/java.base/unix/classes/sun/nio/ch/PollSelectorImpl.java
src/java.base/unix/classes/sun/nio/ch/PollSelectorImpl.java
+2
-2
src/java.base/unix/classes/sun/nio/ch/SocketDispatcher.java
src/java.base/unix/classes/sun/nio/ch/SocketDispatcher.java
+4
-4
src/java.base/unix/native/libnio/ch/IOUtil.c
src/java.base/unix/native/libnio/ch/IOUtil.c
+11
-2
test/jdk/java/nio/channels/Selector/CloseWhenKeyIdle.java
test/jdk/java/nio/channels/Selector/CloseWhenKeyIdle.java
+1
-17
未找到文件。
make/mapfiles/libnio/mapfile-linux
浏览文件 @
1a2968ae
#
# Copyright (c) 2001, 201
7
, Oracle and/or its affiliates. All rights reserved.
# Copyright (c) 2001, 201
8
, 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,23 +37,12 @@ SUNWprivate_1.1 {
Java_sun_nio_ch_DatagramDispatcher_readv0;
Java_sun_nio_ch_DatagramDispatcher_write0;
Java_sun_nio_ch_DatagramDispatcher_writev0;
Java_sun_nio_ch_EPollArrayWrapper_epollCreate;
Java_sun_nio_ch_EPollArrayWrapper_epollCtl;
Java_sun_nio_ch_EPollArrayWrapper_epollWait;
Java_sun_nio_ch_EPollArrayWrapper_init;
Java_sun_nio_ch_EPollArrayWrapper_interrupt;
Java_sun_nio_ch_EPollArrayWrapper_offsetofData;
Java_sun_nio_ch_EPollArrayWrapper_sizeofEPollEvent;
Java_sun_nio_ch_EPoll_eventSize;
Java_sun_nio_ch_EPoll_eventsOffset;
Java_sun_nio_ch_EPoll_dataOffset;
Java_sun_nio_ch_EPoll_epollCreate;
Java_sun_nio_ch_EPoll_epollCtl;
Java_sun_nio_ch_EPoll_epollWait;
Java_sun_nio_ch_EPollPort_close0;
Java_sun_nio_ch_EPollPort_drain1;
Java_sun_nio_ch_EPollPort_interrupt;
Java_sun_nio_ch_EPollPort_socketpair;
Java_sun_nio_ch_EPoll_create;
Java_sun_nio_ch_EPoll_ctl;
Java_sun_nio_ch_EPoll_wait;
Java_sun_nio_ch_FileChannelImpl_initIDs;
Java_sun_nio_ch_FileChannelImpl_map0;
Java_sun_nio_ch_FileChannelImpl_position0;
...
...
@@ -95,6 +84,7 @@ SUNWprivate_1.1 {
Java_sun_nio_ch_IOUtil_makePipe;
Java_sun_nio_ch_IOUtil_randomBytes;
Java_sun_nio_ch_IOUtil_setfdVal;
Java_sun_nio_ch_IOUtil_write1;
Java_sun_nio_ch_NativeThread_current;
Java_sun_nio_ch_NativeThread_init;
Java_sun_nio_ch_NativeThread_signal;
...
...
make/mapfiles/libnio/mapfile-macosx
浏览文件 @
1a2968ae
#
# Copyright (c) 2001, 201
7
, Oracle and/or its affiliates. All rights reserved.
# Copyright (c) 2001, 201
8
, 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
...
...
@@ -71,22 +71,20 @@ SUNWprivate_1.1 {
Java_sun_nio_ch_IOUtil_configureBlocking;
Java_sun_nio_ch_IOUtil_drain;
Java_sun_nio_ch_IOUtil_fdVal;
Java_sun_nio_ch_IOUtil_fdLimit;
Java_sun_nio_ch_IOUtil_initIDs;
Java_sun_nio_ch_IOUtil_iovMax;
Java_sun_nio_ch_IOUtil_makePipe;
Java_sun_nio_ch_IOUtil_randomBytes;
Java_sun_nio_ch_IOUtil_setfdVal;
Java_sun_nio_ch_IOUtil_
iovMax
;
Java_sun_nio_ch_KQueue_kqueu
e;
Java_sun_nio_ch_KQueue_keventR
egister;
Java_sun_nio_ch_KQueue_keventP
oll;
Java_sun_nio_ch_IOUtil_
write1
;
Java_sun_nio_ch_KQueue_creat
e;
Java_sun_nio_ch_KQueue_r
egister;
Java_sun_nio_ch_KQueue_p
oll;
Java_sun_nio_ch_KQueue_keventSize;
Java_sun_nio_ch_KQueue_identOffset;
Java_sun_nio_ch_KQueue_filterOffset;
Java_sun_nio_ch_KQueue_flagsOffset;
Java_sun_nio_ch_KQueuePort_socketpair;
Java_sun_nio_ch_KQueuePort_interrupt;
Java_sun_nio_ch_KQueuePort_drain1;
Java_sun_nio_ch_KQueuePort_close0;
Java_sun_nio_ch_NativeThread_current;
Java_sun_nio_ch_NativeThread_init;
Java_sun_nio_ch_NativeThread_signal;
...
...
make/mapfiles/libnio/mapfile-solaris
浏览文件 @
1a2968ae
#
# Copyright (c) 2001, 201
7
, Oracle and/or its affiliates. All rights reserved.
# Copyright (c) 2001, 201
8
, 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
...
...
@@ -38,7 +38,6 @@ SUNWprivate_1.1 {
Java_sun_nio_ch_DatagramDispatcher_write0;
Java_sun_nio_ch_DatagramDispatcher_writev0;
Java_sun_nio_ch_DevPollArrayWrapper_init;
Java_sun_nio_ch_DevPollArrayWrapper_interrupt;
Java_sun_nio_ch_DevPollArrayWrapper_poll0;
Java_sun_nio_ch_DevPollArrayWrapper_register;
Java_sun_nio_ch_DevPollArrayWrapper_registerMultiple;
...
...
@@ -83,6 +82,7 @@ SUNWprivate_1.1 {
Java_sun_nio_ch_IOUtil_makePipe;
Java_sun_nio_ch_IOUtil_randomBytes;
Java_sun_nio_ch_IOUtil_setfdVal;
Java_sun_nio_ch_IOUtil_write1;
Java_sun_nio_ch_NativeThread_current;
Java_sun_nio_ch_NativeThread_init;
Java_sun_nio_ch_NativeThread_signal;
...
...
src/java.base/linux/classes/sun/nio/ch/EPoll.java
浏览文件 @
1a2968ae
...
...
@@ -109,11 +109,11 @@ class EPoll {
private
static
native
int
dataOffset
();
static
native
int
epollC
reate
()
throws
IOException
;
static
native
int
c
reate
()
throws
IOException
;
static
native
int
epollC
tl
(
int
epfd
,
int
opcode
,
int
fd
,
int
events
);
static
native
int
c
tl
(
int
epfd
,
int
opcode
,
int
fd
,
int
events
);
static
native
int
epollWait
(
int
epfd
,
long
pollAddress
,
int
numfds
)
static
native
int
wait
(
int
epfd
,
long
pollAddress
,
int
numfds
,
int
timeout
)
throws
IOException
;
static
{
...
...
src/java.base/linux/classes/sun/nio/ch/EPollArrayWrapper.java
已删除
100644 → 0
浏览文件 @
21b2c57a
/*
* Copyright (c) 2005, 2018, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package
sun.nio.ch
;
import
java.io.IOException
;
import
java.security.AccessController
;
import
java.util.BitSet
;
import
java.util.HashMap
;
import
java.util.Map
;
import
sun.security.action.GetIntegerAction
;
/**
* Manipulates a native array of epoll_event structs on Linux:
*
* typedef union epoll_data {
* void *ptr;
* int fd;
* __uint32_t u32;
* __uint64_t u64;
* } epoll_data_t;
*
* struct epoll_event {
* __uint32_t events;
* epoll_data_t data;
* };
*
* The system call to wait for I/O events is epoll_wait(2). It populates an
* array of epoll_event structures that are passed to the call. The data
* member of the epoll_event structure contains the same data as was set
* when the file descriptor was registered to epoll via epoll_ctl(2). In
* this implementation we set data.fd to be the file descriptor that we
* register. That way, we have the file descriptor available when we
* process the events.
*/
class
EPollArrayWrapper
{
// EPOLL_EVENTS
private
static
final
int
EPOLLIN
=
0x001
;
// opcodes
private
static
final
int
EPOLL_CTL_ADD
=
1
;
private
static
final
int
EPOLL_CTL_DEL
=
2
;
private
static
final
int
EPOLL_CTL_MOD
=
3
;
// Miscellaneous constants
private
static
final
int
SIZE_EPOLLEVENT
=
sizeofEPollEvent
();
private
static
final
int
EVENT_OFFSET
=
0
;
private
static
final
int
DATA_OFFSET
=
offsetofData
();
private
static
final
int
FD_OFFSET
=
DATA_OFFSET
;
private
static
final
int
OPEN_MAX
=
IOUtil
.
fdLimit
();
private
static
final
int
NUM_EPOLLEVENTS
=
Math
.
min
(
OPEN_MAX
,
8192
);
// Special value to indicate that an update should be ignored
private
static
final
byte
KILLED
=
(
byte
)-
1
;
// Initial size of arrays for fd registration changes
private
static
final
int
INITIAL_PENDING_UPDATE_SIZE
=
64
;
// maximum size of updatesLow
private
static
final
int
MAX_UPDATE_ARRAY_SIZE
=
AccessController
.
doPrivileged
(
new
GetIntegerAction
(
"sun.nio.ch.maxUpdateArraySize"
,
Math
.
min
(
OPEN_MAX
,
64
*
1024
)));
// The fd of the epoll driver
private
final
int
epfd
;
// The epoll_event array for results from epoll_wait
private
final
AllocatedNativeObject
pollArray
;
// Base address of the epoll_event array
private
final
long
pollArrayAddress
;
// The fd of the interrupt line going out
private
final
int
outgoingInterruptFD
;
// Number of updated pollfd entries
private
int
updated
;
// object to synchronize fd registration changes
private
final
Object
updateLock
=
new
Object
();
// number of file descriptors with registration changes pending
private
int
updateCount
;
// file descriptors with registration changes pending
private
int
[]
updateDescriptors
=
new
int
[
INITIAL_PENDING_UPDATE_SIZE
];
// events for file descriptors with registration changes pending, indexed
// by file descriptor and stored as bytes for efficiency reasons. For
// file descriptors higher than MAX_UPDATE_ARRAY_SIZE (unlimited case at
// least) then the update is stored in a map.
private
final
byte
[]
eventsLow
=
new
byte
[
MAX_UPDATE_ARRAY_SIZE
];
private
final
Map
<
Integer
,
Byte
>
eventsHigh
=
new
HashMap
<>();
// Used by release and updateRegistrations to track whether a file
// descriptor is registered with epoll.
private
final
BitSet
registered
=
new
BitSet
();
EPollArrayWrapper
(
int
fd0
,
int
fd1
)
throws
IOException
{
// creates the epoll file descriptor
epfd
=
epollCreate
();
// the epoll_event array passed to epoll_wait
int
allocationSize
=
NUM_EPOLLEVENTS
*
SIZE_EPOLLEVENT
;
pollArray
=
new
AllocatedNativeObject
(
allocationSize
,
true
);
pollArrayAddress
=
pollArray
.
address
();
outgoingInterruptFD
=
fd1
;
epollCtl
(
epfd
,
EPOLL_CTL_ADD
,
fd0
,
EPOLLIN
);
}
void
putEventOps
(
int
i
,
int
event
)
{
int
offset
=
SIZE_EPOLLEVENT
*
i
+
EVENT_OFFSET
;
pollArray
.
putInt
(
offset
,
event
);
}
void
putDescriptor
(
int
i
,
int
fd
)
{
int
offset
=
SIZE_EPOLLEVENT
*
i
+
FD_OFFSET
;
pollArray
.
putInt
(
offset
,
fd
);
}
int
getEventOps
(
int
i
)
{
int
offset
=
SIZE_EPOLLEVENT
*
i
+
EVENT_OFFSET
;
return
pollArray
.
getInt
(
offset
);
}
int
getDescriptor
(
int
i
)
{
int
offset
=
SIZE_EPOLLEVENT
*
i
+
FD_OFFSET
;
return
pollArray
.
getInt
(
offset
);
}
/**
* Returns {@code true} if updates for the given key (file
* descriptor) are killed.
*/
private
boolean
isEventsHighKilled
(
Integer
key
)
{
assert
key
>=
MAX_UPDATE_ARRAY_SIZE
;
Byte
value
=
eventsHigh
.
get
(
key
);
return
(
value
!=
null
&&
value
==
KILLED
);
}
/**
* Sets the pending update events for the given file descriptor. This
* method has no effect if the update events is already set to KILLED,
* unless {@code force} is {@code true}.
*/
private
void
setUpdateEvents
(
int
fd
,
byte
events
,
boolean
force
)
{
if
(
fd
<
MAX_UPDATE_ARRAY_SIZE
)
{
if
((
eventsLow
[
fd
]
!=
KILLED
)
||
force
)
{
eventsLow
[
fd
]
=
events
;
}
}
else
{
Integer
key
=
Integer
.
valueOf
(
fd
);
if
(!
isEventsHighKilled
(
key
)
||
force
)
{
eventsHigh
.
put
(
key
,
Byte
.
valueOf
(
events
));
}
}
}
/**
* Returns the pending update events for the given file descriptor.
*/
private
byte
getUpdateEvents
(
int
fd
)
{
if
(
fd
<
MAX_UPDATE_ARRAY_SIZE
)
{
return
eventsLow
[
fd
];
}
else
{
Byte
result
=
eventsHigh
.
get
(
Integer
.
valueOf
(
fd
));
// result should never be null
return
result
.
byteValue
();
}
}
/**
* Update the events for a given file descriptor
*/
void
setInterest
(
int
fd
,
int
mask
)
{
synchronized
(
updateLock
)
{
// record the file descriptor and events
int
oldCapacity
=
updateDescriptors
.
length
;
if
(
updateCount
==
oldCapacity
)
{
int
newCapacity
=
oldCapacity
+
INITIAL_PENDING_UPDATE_SIZE
;
int
[]
newDescriptors
=
new
int
[
newCapacity
];
System
.
arraycopy
(
updateDescriptors
,
0
,
newDescriptors
,
0
,
oldCapacity
);
updateDescriptors
=
newDescriptors
;
}
updateDescriptors
[
updateCount
++]
=
fd
;
// events are stored as bytes for efficiency reasons
byte
b
=
(
byte
)
mask
;
assert
(
b
==
mask
)
&&
(
b
!=
KILLED
);
setUpdateEvents
(
fd
,
b
,
false
);
}
}
/**
* Add a file descriptor
*/
void
add
(
int
fd
)
{
// force the initial update events to 0 as it may be KILLED by a
// previous registration.
synchronized
(
updateLock
)
{
assert
!
registered
.
get
(
fd
);
setUpdateEvents
(
fd
,
(
byte
)
0
,
true
);
}
}
/**
* Remove a file descriptor
*/
void
remove
(
int
fd
)
{
synchronized
(
updateLock
)
{
// kill pending and future update for this file descriptor
setUpdateEvents
(
fd
,
KILLED
,
false
);
// remove from epoll
if
(
registered
.
get
(
fd
))
{
epollCtl
(
epfd
,
EPOLL_CTL_DEL
,
fd
,
0
);
registered
.
clear
(
fd
);
}
}
}
/**
* Close epoll file descriptor and free poll array
*/
void
close
()
throws
IOException
{
FileDispatcherImpl
.
closeIntFD
(
epfd
);
pollArray
.
free
();
}
int
poll
(
long
timeout
)
throws
IOException
{
updateRegistrations
();
return
epollWait
(
pollArrayAddress
,
NUM_EPOLLEVENTS
,
timeout
,
epfd
);
}
/**
* Update the pending registrations.
*/
private
void
updateRegistrations
()
{
synchronized
(
updateLock
)
{
int
j
=
0
;
while
(
j
<
updateCount
)
{
int
fd
=
updateDescriptors
[
j
];
short
events
=
getUpdateEvents
(
fd
);
boolean
isRegistered
=
registered
.
get
(
fd
);
int
opcode
=
0
;
if
(
events
!=
KILLED
)
{
if
(
isRegistered
)
{
opcode
=
(
events
!=
0
)
?
EPOLL_CTL_MOD
:
EPOLL_CTL_DEL
;
}
else
{
opcode
=
(
events
!=
0
)
?
EPOLL_CTL_ADD
:
0
;
}
if
(
opcode
!=
0
)
{
epollCtl
(
epfd
,
opcode
,
fd
,
events
);
if
(
opcode
==
EPOLL_CTL_ADD
)
{
registered
.
set
(
fd
);
}
else
if
(
opcode
==
EPOLL_CTL_DEL
)
{
registered
.
clear
(
fd
);
}
}
}
j
++;
}
updateCount
=
0
;
}
}
public
void
interrupt
()
{
interrupt
(
outgoingInterruptFD
);
}
static
{
IOUtil
.
load
();
init
();
}
private
native
int
epollCreate
();
private
native
void
epollCtl
(
int
epfd
,
int
opcode
,
int
fd
,
int
events
);
private
native
int
epollWait
(
long
pollAddress
,
int
numfds
,
long
timeout
,
int
epfd
)
throws
IOException
;
private
static
native
int
sizeofEPollEvent
();
private
static
native
int
offsetofData
();
private
static
native
void
interrupt
(
int
fd
);
private
static
native
void
init
();
}
src/java.base/linux/classes/sun/nio/ch/EPollPort.java
浏览文件 @
1a2968ae
...
...
@@ -30,7 +30,13 @@ import java.io.IOException;
import
java.util.concurrent.ArrayBlockingQueue
;
import
java.util.concurrent.RejectedExecutionException
;
import
java.util.concurrent.atomic.AtomicInteger
;
import
static
sun
.
nio
.
ch
.
EPoll
.*;
import
static
sun
.
nio
.
ch
.
EPoll
.
EPOLLIN
;
import
static
sun
.
nio
.
ch
.
EPoll
.
EPOLLONESHOT
;
import
static
sun
.
nio
.
ch
.
EPoll
.
EPOLL_CTL_ADD
;
import
static
sun
.
nio
.
ch
.
EPoll
.
EPOLL_CTL_DEL
;
import
static
sun
.
nio
.
ch
.
EPoll
.
EPOLL_CTL_MOD
;
/**
* AsynchronousChannelGroup implementation based on the Linux epoll facility.
...
...
@@ -48,6 +54,9 @@ final class EPollPort
// epoll file descriptor
private
final
int
epfd
;
// address of the poll array passed to epoll_wait
private
final
long
address
;
// true if epoll closed
private
boolean
closed
;
...
...
@@ -57,9 +66,6 @@ final class EPollPort
// number of wakeups pending
private
final
AtomicInteger
wakeupCount
=
new
AtomicInteger
();
// address of the poll array passed to epoll_wait
private
final
long
address
;
// encapsulates an event for a channel
static
class
Event
{
final
PollableChannel
channel
;
...
...
@@ -85,23 +91,21 @@ final class EPollPort
{
super
(
provider
,
pool
);
// open epoll
this
.
epfd
=
epollCreate
(
);
this
.
epfd
=
EPoll
.
create
();
this
.
address
=
EPoll
.
allocatePollArray
(
MAX_EPOLL_EVENTS
);
// create socket pair for wakeup mechanism
int
[]
sv
=
new
int
[
2
];
try
{
socketpair
(
sv
);
// register one end with epoll
epollCtl
(
epfd
,
EPOLL_CTL_ADD
,
sv
[
0
],
EPOLLIN
);
}
catch
(
IOException
x
)
{
close0
(
epfd
);
throw
x
;
long
fds
=
IOUtil
.
makePipe
(
true
);
this
.
sp
=
new
int
[]{(
int
)
(
fds
>>>
32
),
(
int
)
fds
};
}
catch
(
IOException
ioe
)
{
EPoll
.
freePollArray
(
address
);
FileDispatcherImpl
.
closeIntFD
(
epfd
);
throw
ioe
;
}
this
.
sp
=
sv
;
//
allocate the poll array
this
.
address
=
allocatePollArray
(
MAX_EPOLL_EVENTS
);
//
register one end with epoll
EPoll
.
ctl
(
epfd
,
EPOLL_CTL_ADD
,
sp
[
0
],
EPOLLIN
);
// create the queue and offer the special event to ensure that the first
// threads polls
...
...
@@ -123,17 +127,17 @@ final class EPollPort
return
;
closed
=
true
;
}
freePollArray
(
address
);
close0
(
sp
[
0
]);
close0
(
sp
[
1
]);
close0
(
epfd
);
try
{
FileDispatcherImpl
.
closeIntFD
(
epfd
);
}
catch
(
IOException
ioe
)
{
}
try
{
FileDispatcherImpl
.
closeIntFD
(
sp
[
0
]);
}
catch
(
IOException
ioe
)
{
}
try
{
FileDispatcherImpl
.
closeIntFD
(
sp
[
1
]);
}
catch
(
IOException
ioe
)
{
}
EPoll
.
freePollArray
(
address
);
}
private
void
wakeup
()
{
if
(
wakeupCount
.
incrementAndGet
()
==
1
)
{
// write byte to socketpair to force wakeup
try
{
interrupt
(
sp
[
1
]
);
IOUtil
.
write1
(
sp
[
1
],
(
byte
)
0
);
}
catch
(
IOException
x
)
{
throw
new
AssertionError
(
x
);
}
...
...
@@ -171,9 +175,9 @@ final class EPollPort
@Override
void
startPoll
(
int
fd
,
int
events
)
{
// update events (or add to epoll on first usage)
int
err
=
epollC
tl
(
epfd
,
EPOLL_CTL_MOD
,
fd
,
(
events
|
EPOLLONESHOT
));
int
err
=
EPoll
.
c
tl
(
epfd
,
EPOLL_CTL_MOD
,
fd
,
(
events
|
EPOLLONESHOT
));
if
(
err
==
ENOENT
)
err
=
epollC
tl
(
epfd
,
EPOLL_CTL_ADD
,
fd
,
(
events
|
EPOLLONESHOT
));
err
=
EPoll
.
c
tl
(
epfd
,
EPOLL_CTL_ADD
,
fd
,
(
events
|
EPOLLONESHOT
));
if
(
err
!=
0
)
throw
new
AssertionError
();
// should not happen
}
...
...
@@ -191,7 +195,11 @@ final class EPollPort
private
Event
poll
()
throws
IOException
{
try
{
for
(;;)
{
int
n
=
epollWait
(
epfd
,
address
,
MAX_EPOLL_EVENTS
);
int
n
;
do
{
n
=
EPoll
.
wait
(
epfd
,
address
,
MAX_EPOLL_EVENTS
,
-
1
);
}
while
(
n
==
IOStatus
.
INTERRUPTED
);
/*
* 'n' events have been read. Here we map them to their
* corresponding channel in batch and queue n-1 so that
...
...
@@ -201,14 +209,14 @@ final class EPollPort
fdToChannelLock
.
readLock
().
lock
();
try
{
while
(
n
--
>
0
)
{
long
eventAddress
=
getEvent
(
address
,
n
);
int
fd
=
getDescriptor
(
eventAddress
);
long
eventAddress
=
EPoll
.
getEvent
(
address
,
n
);
int
fd
=
EPoll
.
getDescriptor
(
eventAddress
);
// wakeup
if
(
fd
==
sp
[
0
])
{
if
(
wakeupCount
.
decrementAndGet
()
==
0
)
{
// no more wakeups so drain pipe
drain1
(
sp
[
0
]);
IOUtil
.
drain
(
sp
[
0
]);
}
// queue special event if there are more events
...
...
@@ -222,7 +230,7 @@ final class EPollPort
PollableChannel
channel
=
fdToChannel
.
get
(
fd
);
if
(
channel
!=
null
)
{
int
events
=
getEvents
(
eventAddress
);
int
events
=
EPoll
.
getEvents
(
eventAddress
);
Event
ev
=
new
Event
(
channel
,
events
);
// n-1 events are queued; This thread handles
...
...
@@ -306,18 +314,4 @@ final class EPollPort
}
}
}
// -- Native methods --
private
static
native
void
socketpair
(
int
[]
sv
)
throws
IOException
;
private
static
native
void
interrupt
(
int
fd
)
throws
IOException
;
private
static
native
void
drain1
(
int
fd
)
throws
IOException
;
private
static
native
void
close0
(
int
fd
);
static
{
IOUtil
.
load
();
}
}
src/java.base/linux/classes/sun/nio/ch/EPollSelectorImpl.java
浏览文件 @
1a2968ae
...
...
@@ -26,33 +26,59 @@
package
sun.nio.ch
;
import
java.io.IOException
;
import
java.nio.channels.*
;
import
java.nio.channels.spi.*
;
import
java.util.*
;
import
java.nio.channels.ClosedSelectorException
;
import
java.nio.channels.SelectableChannel
;
import
java.nio.channels.SelectionKey
;
import
java.nio.channels.Selector
;
import
java.nio.channels.spi.SelectorProvider
;
import
java.util.ArrayDeque
;
import
java.util.BitSet
;
import
java.util.Deque
;
import
java.util.HashMap
;
import
java.util.Iterator
;
import
java.util.Map
;
import
java.util.concurrent.TimeUnit
;
import
static
sun
.
nio
.
ch
.
EPoll
.
EPOLLIN
;
import
static
sun
.
nio
.
ch
.
EPoll
.
EPOLL_CTL_ADD
;
import
static
sun
.
nio
.
ch
.
EPoll
.
EPOLL_CTL_DEL
;
import
static
sun
.
nio
.
ch
.
EPoll
.
EPOLL_CTL_MOD
;
/**
* An implementation of Selector for Linux 2.6+ kernels that uses
* the epoll event notification facility.
* Linux epoll based Selector implementation
*/
class
EPollSelectorImpl
extends
SelectorImpl
{
// File descriptors used for interrupt
class
EPollSelectorImpl
extends
SelectorImpl
{
// maximum number of events to poll in one call to epoll_wait
private
static
final
int
NUM_EPOLLEVENTS
=
Math
.
min
(
IOUtil
.
fdLimit
(),
1024
);
// epoll file descriptor
private
final
int
epfd
;
// address of poll array when polling with epoll_wait
private
final
long
pollArrayAddress
;
// file descriptors used for interrupt
private
final
int
fd0
;
private
final
int
fd1
;
//
The poll object
private
final
EPollArrayWrapper
pollWrapper
;
//
maps file descriptor to selection key, synchronize on selector
private
final
Map
<
Integer
,
SelectionKeyImpl
>
fdToKey
=
new
HashMap
<>()
;
//
Maps from file descriptors to keys
private
final
Map
<
Integer
,
SelectionKeyImpl
>
fdToKey
;
//
file descriptors registered with epoll, synchronize on selector
private
final
BitSet
registered
=
new
BitSet
()
;
// True if this Selector has been closed
private
volatile
boolean
closed
;
// pending new registrations/updates, queued by implRegister and putEventOps
private
final
Object
updateLock
=
new
Object
();
private
final
Deque
<
SelectionKeyImpl
>
newKeys
=
new
ArrayDeque
<>();
private
final
Deque
<
SelectionKeyImpl
>
updateKeys
=
new
ArrayDeque
<>();
private
final
Deque
<
Integer
>
updateOps
=
new
ArrayDeque
<>();
//
Lock for
interrupt triggering and clearing
// interrupt triggering and clearing
private
final
Object
interruptLock
=
new
Object
();
private
boolean
interruptTriggered
=
false
;
private
boolean
interruptTriggered
;
/**
* Package private constructor called by factory method in
...
...
@@ -60,40 +86,57 @@ class EPollSelectorImpl
*/
EPollSelectorImpl
(
SelectorProvider
sp
)
throws
IOException
{
super
(
sp
);
long
pipeFds
=
IOUtil
.
makePipe
(
false
);
fd0
=
(
int
)
(
pipeFds
>>>
32
);
fd1
=
(
int
)
pipeFds
;
try
{
pollWrapper
=
new
EPollArrayWrapper
(
fd0
,
fd1
);
fdToKey
=
new
HashMap
<>();
}
catch
(
Throwable
t
)
{
try
{
FileDispatcherImpl
.
closeIntFD
(
fd0
);
}
catch
(
IOException
ioe0
)
{
t
.
addSuppressed
(
ioe0
);
}
this
.
epfd
=
EPoll
.
create
();
this
.
pollArrayAddress
=
EPoll
.
allocatePollArray
(
NUM_EPOLLEVENTS
);
try
{
FileDispatcherImpl
.
closeIntFD
(
fd1
);
}
catch
(
IOException
ioe1
)
{
t
.
addSuppressed
(
ioe1
);
}
throw
t
;
long
fds
=
IOUtil
.
makePipe
(
false
);
this
.
fd0
=
(
int
)
(
fds
>>>
32
);
this
.
fd1
=
(
int
)
fds
;
}
catch
(
IOException
ioe
)
{
EPoll
.
freePollArray
(
pollArrayAddress
);
FileDispatcherImpl
.
closeIntFD
(
epfd
);
throw
ioe
;
}
// register one end of the socket pair for wakeups
EPoll
.
ctl
(
epfd
,
EPOLL_CTL_ADD
,
fd0
,
EPOLLIN
);
}
private
void
ensureOpen
()
{
if
(
closed
)
if
(
!
isOpen
()
)
throw
new
ClosedSelectorException
();
}
@Override
protected
int
doSelect
(
long
timeout
)
throws
IOException
{
ensureOpen
();
assert
Thread
.
holdsLock
(
this
);
int
numEntries
;
processUpdateQueue
();
processDeregisterQueue
();
try
{
begin
();
numEntries
=
pollWrapper
.
poll
(
timeout
);
// epoll_wait timeout is int
int
to
=
(
int
)
Math
.
min
(
timeout
,
Integer
.
MAX_VALUE
);
boolean
timedPoll
=
(
to
>
0
);
do
{
long
startTime
=
timedPoll
?
System
.
nanoTime
()
:
0
;
numEntries
=
EPoll
.
wait
(
epfd
,
pollArrayAddress
,
NUM_EPOLLEVENTS
,
to
);
if
(
numEntries
==
IOStatus
.
INTERRUPTED
&&
timedPoll
)
{
// timed poll interrupted so need to adjust timeout
long
adjust
=
System
.
nanoTime
()
-
startTime
;
to
-=
TimeUnit
.
MILLISECONDS
.
convert
(
adjust
,
TimeUnit
.
NANOSECONDS
);
if
(
to
<=
0
)
{
// timeout expired so no retry
numEntries
=
0
;
}
}
}
while
(
numEntries
==
IOStatus
.
INTERRUPTED
);
assert
IOStatus
.
check
(
numEntries
);
}
finally
{
end
();
}
...
...
@@ -101,21 +144,70 @@ class EPollSelectorImpl
return
updateSelectedKeys
(
numEntries
);
}
/**
* Process new registrations and changes to the interest ops.
*/
private
void
processUpdateQueue
()
{
assert
Thread
.
holdsLock
(
this
);
synchronized
(
updateLock
)
{
SelectionKeyImpl
ski
;
// new registrations
while
((
ski
=
newKeys
.
pollFirst
())
!=
null
)
{
if
(
ski
.
isValid
())
{
SelChImpl
ch
=
ski
.
channel
;
int
fd
=
ch
.
getFDVal
();
SelectionKeyImpl
previous
=
fdToKey
.
put
(
fd
,
ski
);
assert
previous
==
null
;
assert
registered
.
get
(
fd
)
==
false
;
}
}
// changes to interest ops
assert
updateKeys
.
size
()
==
updateOps
.
size
();
while
((
ski
=
updateKeys
.
pollFirst
())
!=
null
)
{
int
ops
=
updateOps
.
pollFirst
();
int
fd
=
ski
.
channel
.
getFDVal
();
if
(
ski
.
isValid
()
&&
fdToKey
.
containsKey
(
fd
))
{
if
(
registered
.
get
(
fd
))
{
if
(
ops
==
0
)
{
// remove from epoll
EPoll
.
ctl
(
epfd
,
EPOLL_CTL_DEL
,
fd
,
0
);
registered
.
clear
(
fd
);
}
else
{
// modify events
EPoll
.
ctl
(
epfd
,
EPOLL_CTL_MOD
,
fd
,
ops
);
}
}
else
if
(
ops
!=
0
)
{
// add to epoll
EPoll
.
ctl
(
epfd
,
EPOLL_CTL_ADD
,
fd
,
ops
);
registered
.
set
(
fd
);
}
}
}
}
}
/**
* Update the keys whose fd's have been selected by the epoll.
* Add the ready keys to the ready queue.
*/
private
int
updateSelectedKeys
(
int
numEntries
)
throws
IOException
{
assert
Thread
.
holdsLock
(
this
);
assert
Thread
.
holdsLock
(
nioSelectedKeys
());
boolean
interrupted
=
false
;
int
numKeysUpdated
=
0
;
for
(
int
i
=
0
;
i
<
numEntries
;
i
++)
{
int
nextFD
=
pollWrapper
.
getDescriptor
(
i
);
if
(
nextFD
==
fd0
)
{
long
event
=
EPoll
.
getEvent
(
pollArrayAddress
,
i
);
int
fd
=
EPoll
.
getDescriptor
(
event
);
if
(
fd
==
fd0
)
{
interrupted
=
true
;
}
else
{
SelectionKeyImpl
ski
=
fdToKey
.
get
(
Integer
.
valueOf
(
nextFD
)
);
SelectionKeyImpl
ski
=
fdToKey
.
get
(
fd
);
if
(
ski
!=
null
)
{
int
rOps
=
pollWrapper
.
getEventOps
(
i
);
int
rOps
=
EPoll
.
getEvents
(
event
);
if
(
selectedKeys
.
contains
(
ski
))
{
if
(
ski
.
channel
.
translateAndSetReadyOps
(
rOps
,
ski
))
{
numKeysUpdated
++;
...
...
@@ -140,16 +232,17 @@ class EPollSelectorImpl
@Override
protected
void
implClose
()
throws
IOException
{
if
(
closed
)
return
;
closed
=
true
;
assert
Thread
.
holdsLock
(
this
);
assert
Thread
.
holdsLock
(
nioKeys
());
// prevent further wakeup
synchronized
(
interruptLock
)
{
interruptTriggered
=
true
;
}
pollWrapper
.
close
();
FileDispatcherImpl
.
closeIntFD
(
epfd
);
EPoll
.
freePollArray
(
pollArrayAddress
);
FileDispatcherImpl
.
closeIntFD
(
fd0
);
FileDispatcherImpl
.
closeIntFD
(
fd1
);
...
...
@@ -167,42 +260,57 @@ class EPollSelectorImpl
@Override
protected
void
implRegister
(
SelectionKeyImpl
ski
)
{
assert
Thread
.
holdsLock
(
nioKeys
());
ensureOpen
();
SelChImpl
ch
=
ski
.
channel
;
int
fd
=
Integer
.
valueOf
(
ch
.
getFDVal
());
fdToKey
.
put
(
fd
,
ski
);
pollWrapper
.
add
(
fd
);
synchronized
(
updateLock
)
{
newKeys
.
addLast
(
ski
);
}
keys
.
add
(
ski
);
}
@Override
protected
void
implDereg
(
SelectionKeyImpl
ski
)
throws
IOException
{
assert
(
ski
.
getIndex
()
>=
0
);
SelChImpl
ch
=
ski
.
channel
;
int
fd
=
ch
.
getFDVal
();
fdToKey
.
remove
(
Integer
.
valueOf
(
fd
));
pollWrapper
.
remove
(
fd
);
ski
.
setIndex
(-
1
);
keys
.
remove
(
ski
);
assert
!
ski
.
isValid
();
assert
Thread
.
holdsLock
(
this
);
assert
Thread
.
holdsLock
(
nioKeys
());
assert
Thread
.
holdsLock
(
nioSelectedKeys
());
int
fd
=
ski
.
channel
.
getFDVal
();
fdToKey
.
remove
(
fd
);
if
(
registered
.
get
(
fd
))
{
EPoll
.
ctl
(
epfd
,
EPOLL_CTL_DEL
,
fd
,
0
);
registered
.
clear
(
fd
);
}
selectedKeys
.
remove
(
ski
);
keys
.
remove
(
ski
);
// remove from channel's key set
deregister
(
ski
);
SelectableChannel
selch
=
ski
.
channel
();
if
(!
selch
.
isOpen
()
&&
!
selch
.
isRegistered
())
((
SelChImpl
)
selch
).
kill
();
((
SelChImpl
)
selch
).
kill
();
}
@Override
public
void
putEventOps
(
SelectionKeyImpl
ski
,
int
ops
)
{
ensureOpen
();
SelChImpl
ch
=
ski
.
channel
;
pollWrapper
.
setInterest
(
ch
.
getFDVal
(),
ops
);
synchronized
(
updateLock
)
{
updateOps
.
addLast
(
ops
);
// ops first in case adding the key fails
updateKeys
.
addLast
(
ski
);
}
}
@Override
public
Selector
wakeup
()
{
synchronized
(
interruptLock
)
{
if
(!
interruptTriggered
)
{
pollWrapper
.
interrupt
();
try
{
IOUtil
.
write1
(
fd1
,
(
byte
)
0
);
}
catch
(
IOException
ioe
)
{
throw
new
InternalError
(
ioe
);
}
interruptTriggered
=
true
;
}
}
...
...
src/java.base/linux/native/libnio/ch/EPoll.c
浏览文件 @
1a2968ae
/*
* Copyright (c) 2008, 201
1
, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2008, 201
8
, 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
...
...
@@ -23,43 +23,41 @@
* questions.
*/
#include <dlfcn.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/epoll.h>
#include "jni.h"
#include "jni_util.h"
#include "jvm.h"
#include "jlong.h"
#include "nio.h"
#include "nio_util.h"
#include "sun_nio_ch_EPoll.h"
#include <dlfcn.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/epoll.h>
JNIEXPORT
jint
JNICALL
Java_sun_nio_ch_EPoll_eventSize
(
JNIEnv
*
env
,
jclass
this
)
Java_sun_nio_ch_EPoll_eventSize
(
JNIEnv
*
env
,
jclass
clazz
)
{
return
sizeof
(
struct
epoll_event
);
}
JNIEXPORT
jint
JNICALL
Java_sun_nio_ch_EPoll_eventsOffset
(
JNIEnv
*
env
,
jclass
this
)
Java_sun_nio_ch_EPoll_eventsOffset
(
JNIEnv
*
env
,
jclass
clazz
)
{
return
offsetof
(
struct
epoll_event
,
events
);
}
JNIEXPORT
jint
JNICALL
Java_sun_nio_ch_EPoll_dataOffset
(
JNIEnv
*
env
,
jclass
this
)
Java_sun_nio_ch_EPoll_dataOffset
(
JNIEnv
*
env
,
jclass
clazz
)
{
return
offsetof
(
struct
epoll_event
,
data
);
}
JNIEXPORT
jint
JNICALL
Java_sun_nio_ch_EPoll_epollCreate
(
JNIEnv
*
env
,
jclass
c
)
{
/*
* epoll_create expects a size as a hint to the kernel about how to
* dimension internal structures. We can't predict the size in advance.
*/
Java_sun_nio_ch_EPoll_create
(
JNIEnv
*
env
,
jclass
clazz
)
{
/* size hint not used in modern kernels */
int
epfd
=
epoll_create
(
256
);
if
(
epfd
<
0
)
{
JNU_ThrowIOExceptionWithLastError
(
env
,
"epoll_create failed"
);
...
...
@@ -68,7 +66,7 @@ Java_sun_nio_ch_EPoll_epollCreate(JNIEnv *env, jclass c) {
}
JNIEXPORT
jint
JNICALL
Java_sun_nio_ch_EPoll_
epollCtl
(
JNIEnv
*
env
,
jclass
c
,
jint
epfd
,
Java_sun_nio_ch_EPoll_
ctl
(
JNIEnv
*
env
,
jclass
clazz
,
jint
epfd
,
jint
opcode
,
jint
fd
,
jint
events
)
{
struct
epoll_event
event
;
...
...
@@ -77,21 +75,23 @@ Java_sun_nio_ch_EPoll_epollCtl(JNIEnv *env, jclass c, jint epfd,
event
.
events
=
events
;
event
.
data
.
fd
=
fd
;
RESTARTABLE
(
epoll_ctl
(
epfd
,
(
int
)
opcode
,
(
int
)
fd
,
&
event
),
res
);
res
=
epoll_ctl
(
epfd
,
(
int
)
opcode
,
(
int
)
fd
,
&
event
);
return
(
res
==
0
)
?
0
:
errno
;
}
JNIEXPORT
jint
JNICALL
Java_sun_nio_ch_EPoll_
epollWait
(
JNIEnv
*
env
,
jclass
c
,
jint
epfd
,
jlong
address
,
jint
numfds
)
Java_sun_nio_ch_EPoll_
wait
(
JNIEnv
*
env
,
jclass
clazz
,
jint
epfd
,
jlong
address
,
jint
numfds
,
jint
timeout
)
{
struct
epoll_event
*
events
=
jlong_to_ptr
(
address
);
int
res
;
RESTARTABLE
(
epoll_wait
(
epfd
,
events
,
numfds
,
-
1
),
res
);
int
res
=
epoll_wait
(
epfd
,
events
,
numfds
,
timeout
);
if
(
res
<
0
)
{
if
(
errno
==
EINTR
)
{
return
IOS_INTERRUPTED
;
}
else
{
JNU_ThrowIOExceptionWithLastError
(
env
,
"epoll_wait failed"
);
return
IOS_THROWN
;
}
}
return
res
;
}
src/java.base/linux/native/libnio/ch/EPollArrayWrapper.c
已删除
100644 → 0
浏览文件 @
21b2c57a
/*
* Copyright (c) 2005, 2016, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
#include "jni.h"
#include "jni_util.h"
#include "jvm.h"
#include "jlong.h"
#include "sun_nio_ch_EPollArrayWrapper.h"
#include <unistd.h>
#include <sys/time.h>
#include <sys/epoll.h>
#define RESTARTABLE(_cmd, _result) do { \
do { \
_result = _cmd; \
} while((_result == -1) && (errno == EINTR)); \
} while(0)
static
int
iepoll
(
int
epfd
,
struct
epoll_event
*
events
,
int
numfds
,
jlong
timeout
)
{
jlong
start
,
now
;
int
remaining
=
timeout
;
struct
timeval
t
;
int
diff
;
gettimeofday
(
&
t
,
NULL
);
start
=
t
.
tv_sec
*
1000
+
t
.
tv_usec
/
1000
;
for
(;;)
{
int
res
=
epoll_wait
(
epfd
,
events
,
numfds
,
remaining
);
if
(
res
<
0
&&
errno
==
EINTR
)
{
if
(
remaining
>=
0
)
{
gettimeofday
(
&
t
,
NULL
);
now
=
t
.
tv_sec
*
1000
+
t
.
tv_usec
/
1000
;
diff
=
now
-
start
;
remaining
-=
diff
;
if
(
diff
<
0
||
remaining
<=
0
)
{
return
0
;
}
start
=
now
;
}
}
else
{
return
res
;
}
}
}
JNIEXPORT
void
JNICALL
Java_sun_nio_ch_EPollArrayWrapper_init
(
JNIEnv
*
env
,
jclass
this
)
{
}
JNIEXPORT
jint
JNICALL
Java_sun_nio_ch_EPollArrayWrapper_epollCreate
(
JNIEnv
*
env
,
jobject
this
)
{
/*
* epoll_create expects a size as a hint to the kernel about how to
* dimension internal structures. We can't predict the size in advance.
*/
int
epfd
=
epoll_create
(
256
);
if
(
epfd
<
0
)
{
JNU_ThrowIOExceptionWithLastError
(
env
,
"epoll_create failed"
);
}
return
epfd
;
}
JNIEXPORT
jint
JNICALL
Java_sun_nio_ch_EPollArrayWrapper_sizeofEPollEvent
(
JNIEnv
*
env
,
jclass
this
)
{
return
sizeof
(
struct
epoll_event
);
}
JNIEXPORT
jint
JNICALL
Java_sun_nio_ch_EPollArrayWrapper_offsetofData
(
JNIEnv
*
env
,
jclass
this
)
{
return
offsetof
(
struct
epoll_event
,
data
);
}
JNIEXPORT
void
JNICALL
Java_sun_nio_ch_EPollArrayWrapper_epollCtl
(
JNIEnv
*
env
,
jobject
this
,
jint
epfd
,
jint
opcode
,
jint
fd
,
jint
events
)
{
struct
epoll_event
event
;
int
res
;
event
.
events
=
events
;
event
.
data
.
fd
=
fd
;
RESTARTABLE
(
epoll_ctl
(
epfd
,
(
int
)
opcode
,
(
int
)
fd
,
&
event
),
res
);
/*
* A channel may be registered with several Selectors. When each Selector
* is polled a EPOLL_CTL_DEL op will be inserted into its pending update
* list to remove the file descriptor from epoll. The "last" Selector will
* close the file descriptor which automatically unregisters it from each
* epoll descriptor. To avoid costly synchronization between Selectors we
* allow pending updates to be processed, ignoring errors. The errors are
* harmless as the last update for the file descriptor is guaranteed to
* be EPOLL_CTL_DEL.
*/
if
(
res
<
0
&&
errno
!=
EBADF
&&
errno
!=
ENOENT
&&
errno
!=
EPERM
)
{
JNU_ThrowIOExceptionWithLastError
(
env
,
"epoll_ctl failed"
);
}
}
JNIEXPORT
jint
JNICALL
Java_sun_nio_ch_EPollArrayWrapper_epollWait
(
JNIEnv
*
env
,
jobject
this
,
jlong
address
,
jint
numfds
,
jlong
timeout
,
jint
epfd
)
{
struct
epoll_event
*
events
=
jlong_to_ptr
(
address
);
int
res
;
if
(
timeout
<=
0
)
{
/* Indefinite or no wait */
RESTARTABLE
(
epoll_wait
(
epfd
,
events
,
numfds
,
timeout
),
res
);
}
else
{
/* Bounded wait; bounded restarts */
res
=
iepoll
(
epfd
,
events
,
numfds
,
timeout
);
}
if
(
res
<
0
)
{
JNU_ThrowIOExceptionWithLastError
(
env
,
"epoll_wait failed"
);
}
return
res
;
}
JNIEXPORT
void
JNICALL
Java_sun_nio_ch_EPollArrayWrapper_interrupt
(
JNIEnv
*
env
,
jobject
this
,
jint
fd
)
{
int
fakebuf
[
1
];
fakebuf
[
0
]
=
1
;
if
(
write
(
fd
,
fakebuf
,
1
)
<
0
)
{
JNU_ThrowIOExceptionWithLastError
(
env
,
"write to interrupt fd failed"
);
}
}
src/java.base/linux/native/libnio/ch/EPollPort.c
已删除
100644 → 0
浏览文件 @
21b2c57a
/*
* Copyright (c) 2008, 2009, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
#include "jni.h"
#include "jni_util.h"
#include "jvm.h"
#include "jlong.h"
#include "nio_util.h"
#include "sun_nio_ch_EPollPort.h"
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
JNIEXPORT
void
JNICALL
Java_sun_nio_ch_EPollPort_socketpair
(
JNIEnv
*
env
,
jclass
clazz
,
jintArray
sv
)
{
int
sp
[
2
];
if
(
socketpair
(
PF_UNIX
,
SOCK_STREAM
,
0
,
sp
)
==
-
1
)
{
JNU_ThrowIOExceptionWithLastError
(
env
,
"socketpair failed"
);
}
else
{
jint
res
[
2
];
res
[
0
]
=
(
jint
)
sp
[
0
];
res
[
1
]
=
(
jint
)
sp
[
1
];
(
*
env
)
->
SetIntArrayRegion
(
env
,
sv
,
0
,
2
,
&
res
[
0
]);
}
}
JNIEXPORT
void
JNICALL
Java_sun_nio_ch_EPollPort_interrupt
(
JNIEnv
*
env
,
jclass
c
,
jint
fd
)
{
int
res
;
int
buf
[
1
];
buf
[
0
]
=
1
;
RESTARTABLE
(
write
(
fd
,
buf
,
1
),
res
);
if
(
res
<
0
)
{
JNU_ThrowIOExceptionWithLastError
(
env
,
"write failed"
);
}
}
JNIEXPORT
void
JNICALL
Java_sun_nio_ch_EPollPort_drain1
(
JNIEnv
*
env
,
jclass
cl
,
jint
fd
)
{
int
res
;
char
buf
[
1
];
RESTARTABLE
(
read
(
fd
,
buf
,
1
),
res
);
if
(
res
<
0
)
{
JNU_ThrowIOExceptionWithLastError
(
env
,
"drain1 failed"
);
}
}
JNIEXPORT
void
JNICALL
Java_sun_nio_ch_EPollPort_close0
(
JNIEnv
*
env
,
jclass
c
,
jint
fd
)
{
int
res
;
RESTARTABLE
(
close
(
fd
),
res
);
}
src/java.base/macosx/classes/sun/nio/ch/KQueue.java
浏览文件 @
1a2968ae
...
...
@@ -84,17 +84,17 @@ class KQueue {
}
/**
* Returns the file descriptor from a kevent (assuming
to be in
ident field)
* Returns the file descriptor from a kevent (assuming
it is in the
ident field)
*/
static
int
getDescriptor
(
long
address
)
{
return
unsafe
.
getInt
(
address
+
OFFSET_IDENT
);
}
static
in
t
getFilter
(
long
address
)
{
static
shor
t
getFilter
(
long
address
)
{
return
unsafe
.
getShort
(
address
+
OFFSET_FILTER
);
}
static
in
t
getFlags
(
long
address
)
{
static
shor
t
getFlags
(
long
address
)
{
return
unsafe
.
getShort
(
address
+
OFFSET_FLAGS
);
}
...
...
@@ -108,11 +108,11 @@ class KQueue {
private
static
native
int
flagsOffset
();
static
native
int
kqueu
e
()
throws
IOException
;
static
native
int
creat
e
()
throws
IOException
;
static
native
int
keventRegister
(
int
kqp
fd
,
int
fd
,
int
filter
,
int
flags
);
static
native
int
register
(
int
kq
fd
,
int
fd
,
int
filter
,
int
flags
);
static
native
int
keventPoll
(
int
kqpfd
,
long
pollAddress
,
int
nevents
)
static
native
int
poll
(
int
kqfd
,
long
pollAddress
,
int
nevents
,
long
timeout
)
throws
IOException
;
static
{
...
...
src/java.base/macosx/classes/sun/nio/ch/KQueueArrayWrapper.java
已删除
100644 → 0
浏览文件 @
21b2c57a
/*
* Copyright (c) 2011, 2018, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* KQueueArrayWrapper.java
* Implementation of Selector using FreeBSD / Mac OS X kqueues
* Derived from Sun's DevPollArrayWrapper
*/
package
sun.nio.ch
;
import
java.io.IOException
;
import
java.util.Iterator
;
import
java.util.LinkedList
;
import
sun.security.action.GetPropertyAction
;
/*
* struct kevent { // 32-bit 64-bit
* uintptr_t ident; // 4 8
* short filter; // 2 2
* u_short flags; // 2 2
* u_int fflags; // 4 4
* intptr_t data; // 4 8
* void *udata; // 4 8
* } // Total: 20 32
*
* The implementation works in 32-bit and 64-bit world. We do this by calling a
* native function that actually sets the sizes and offsets of the fields based
* on which mode we're in.
*/
class
KQueueArrayWrapper
{
// kevent filters
static
short
EVFILT_READ
;
static
short
EVFILT_WRITE
;
// kevent struct
// These fields are now set by initStructSizes in the static initializer.
static
short
SIZEOF_KEVENT
;
static
short
FD_OFFSET
;
static
short
FILTER_OFFSET
;
// kevent array size
static
final
int
NUM_KEVENTS
=
128
;
// Are we in a 64-bit VM?
static
boolean
is64bit
;
// The kevent array (used for outcoming events only)
private
final
AllocatedNativeObject
keventArray
;
private
final
long
keventArrayAddress
;
// The kqueue fd
private
final
int
kq
;
// The fd of the interrupt line going out
private
final
int
outgoingInterruptFD
;
static
{
IOUtil
.
load
();
initStructSizes
();
String
datamodel
=
GetPropertyAction
.
privilegedGetProperty
(
"sun.arch.data.model"
);
is64bit
=
"64"
.
equals
(
datamodel
);
}
KQueueArrayWrapper
(
int
fd0
,
int
fd1
)
throws
IOException
{
int
allocationSize
=
SIZEOF_KEVENT
*
NUM_KEVENTS
;
keventArray
=
new
AllocatedNativeObject
(
allocationSize
,
true
);
keventArrayAddress
=
keventArray
.
address
();
kq
=
init
();
register0
(
kq
,
fd0
,
1
,
0
);
outgoingInterruptFD
=
fd1
;
}
// Used to update file description registrations
private
static
class
Update
{
SelChImpl
channel
;
int
events
;
Update
(
SelChImpl
channel
,
int
events
)
{
this
.
channel
=
channel
;
this
.
events
=
events
;
}
}
private
LinkedList
<
Update
>
updateList
=
new
LinkedList
<
Update
>();
int
getReventOps
(
int
index
)
{
int
result
=
0
;
int
offset
=
SIZEOF_KEVENT
*
index
+
FILTER_OFFSET
;
short
filter
=
keventArray
.
getShort
(
offset
);
// This is all that's necessary based on inspection of usage:
// SinkChannelImpl, SourceChannelImpl, DatagramChannelImpl,
// ServerSocketChannelImpl, SocketChannelImpl
if
(
filter
==
EVFILT_READ
)
{
result
|=
Net
.
POLLIN
;
}
else
if
(
filter
==
EVFILT_WRITE
)
{
result
|=
Net
.
POLLOUT
;
}
return
result
;
}
int
getDescriptor
(
int
index
)
{
int
offset
=
SIZEOF_KEVENT
*
index
+
FD_OFFSET
;
/* The ident field is 8 bytes in 64-bit world, however the API wants us
* to return an int. Hence read the 8 bytes but return as an int.
*/
if
(
is64bit
)
{
long
fd
=
keventArray
.
getLong
(
offset
);
assert
fd
<=
Integer
.
MAX_VALUE
;
return
(
int
)
fd
;
}
else
{
return
keventArray
.
getInt
(
offset
);
}
}
void
setInterest
(
SelChImpl
channel
,
int
events
)
{
synchronized
(
updateList
)
{
// update existing registration
updateList
.
add
(
new
Update
(
channel
,
events
));
}
}
void
release
(
SelChImpl
channel
)
{
synchronized
(
updateList
)
{
// flush any pending updates
for
(
Iterator
<
Update
>
it
=
updateList
.
iterator
();
it
.
hasNext
();)
{
if
(
it
.
next
().
channel
==
channel
)
{
it
.
remove
();
}
}
// remove
register0
(
kq
,
channel
.
getFDVal
(),
0
,
0
);
}
}
void
updateRegistrations
()
{
synchronized
(
updateList
)
{
Update
u
;
while
((
u
=
updateList
.
poll
())
!=
null
)
{
SelChImpl
ch
=
u
.
channel
;
if
(!
ch
.
isOpen
())
continue
;
register0
(
kq
,
ch
.
getFDVal
(),
u
.
events
&
Net
.
POLLIN
,
u
.
events
&
Net
.
POLLOUT
);
}
}
}
void
close
()
throws
IOException
{
FileDispatcherImpl
.
closeIntFD
(
kq
);
keventArray
.
free
();
}
int
poll
(
long
timeout
)
{
updateRegistrations
();
return
kevent0
(
kq
,
keventArrayAddress
,
NUM_KEVENTS
,
timeout
);
}
void
interrupt
()
{
interrupt
(
outgoingInterruptFD
);
}
private
native
int
init
();
private
static
native
void
initStructSizes
();
private
native
void
register0
(
int
kq
,
int
fd
,
int
read
,
int
write
);
private
native
int
kevent0
(
int
kq
,
long
keventAddress
,
int
keventCount
,
long
timeout
);
private
static
native
void
interrupt
(
int
fd
);
}
src/java.base/macosx/classes/sun/nio/ch/KQueuePort.java
浏览文件 @
1a2968ae
/*
* Copyright (c) 2012, 201
3
, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 201
8
, 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
...
...
@@ -30,7 +30,11 @@ import java.io.IOException;
import
java.util.concurrent.ArrayBlockingQueue
;
import
java.util.concurrent.RejectedExecutionException
;
import
java.util.concurrent.atomic.AtomicInteger
;
import
static
sun
.
nio
.
ch
.
KQueue
.*;
import
static
sun
.
nio
.
ch
.
KQueue
.
EVFILT_READ
;
import
static
sun
.
nio
.
ch
.
KQueue
.
EVFILT_WRITE
;
import
static
sun
.
nio
.
ch
.
KQueue
.
EV_ADD
;
import
static
sun
.
nio
.
ch
.
KQueue
.
EV_ONESHOT
;
/**
* AsynchronousChannelGroup implementation based on the BSD kqueue facility.
...
...
@@ -45,6 +49,9 @@ final class KQueuePort
// kqueue file descriptor
private
final
int
kqfd
;
// address of the poll array passed to kqueue_wait
private
final
long
address
;
// true if kqueue closed
private
boolean
closed
;
...
...
@@ -54,9 +61,6 @@ final class KQueuePort
// number of wakeups pending
private
final
AtomicInteger
wakeupCount
=
new
AtomicInteger
();
// address of the poll array passed to kqueue_wait
private
final
long
address
;
// encapsulates an event for a channel
static
class
Event
{
final
PollableChannel
channel
;
...
...
@@ -82,28 +86,25 @@ final class KQueuePort
{
super
(
provider
,
pool
);
// open kqueue
this
.
kqfd
=
kqueue
(
);
this
.
kqfd
=
KQueue
.
create
();
this
.
address
=
KQueue
.
allocatePollArray
(
MAX_KEVENTS_TO_POLL
);
// create socket pair for wakeup mechanism
int
[]
sv
=
new
int
[
2
];
try
{
socketpair
(
sv
);
// register one end with kqueue
keventRegister
(
kqfd
,
sv
[
0
],
EVFILT_READ
,
EV_ADD
);
}
catch
(
IOException
x
)
{
close0
(
kqfd
);
throw
x
;
long
fds
=
IOUtil
.
makePipe
(
true
);
this
.
sp
=
new
int
[]{(
int
)
(
fds
>>>
32
),
(
int
)
fds
};
}
catch
(
IOException
ioe
)
{
KQueue
.
freePollArray
(
address
);
FileDispatcherImpl
.
closeIntFD
(
kqfd
);
throw
ioe
;
}
this
.
sp
=
sv
;
//
allocate the poll array
this
.
address
=
allocatePollArray
(
MAX_KEVENTS_TO_POLL
);
//
register one end with kqueue
KQueue
.
register
(
kqfd
,
sp
[
0
],
EVFILT_READ
,
EV_ADD
);
// create the queue and offer the special event to ensure that the first
// threads polls
this
.
queue
=
new
ArrayBlockingQueue
<
Event
>(
MAX_KEVENTS_TO_POLL
);
this
.
queue
=
new
ArrayBlockingQueue
<>(
MAX_KEVENTS_TO_POLL
);
this
.
queue
.
offer
(
NEED_TO_POLL
);
}
...
...
@@ -121,17 +122,18 @@ final class KQueuePort
return
;
closed
=
true
;
}
freePollArray
(
address
);
close0
(
sp
[
0
]);
close0
(
sp
[
1
]);
close0
(
kqfd
);
try
{
FileDispatcherImpl
.
closeIntFD
(
kqfd
);
}
catch
(
IOException
ioe
)
{
}
try
{
FileDispatcherImpl
.
closeIntFD
(
sp
[
0
]);
}
catch
(
IOException
ioe
)
{
}
try
{
FileDispatcherImpl
.
closeIntFD
(
sp
[
1
]);
}
catch
(
IOException
ioe
)
{
}
KQueue
.
freePollArray
(
address
);
}
private
void
wakeup
()
{
if
(
wakeupCount
.
incrementAndGet
()
==
1
)
{
// write byte to socketpair to force wakeup
try
{
interrupt
(
sp
[
1
]
);
IOUtil
.
write1
(
sp
[
1
],
(
byte
)
0
);
}
catch
(
IOException
x
)
{
throw
new
AssertionError
(
x
);
}
...
...
@@ -173,9 +175,9 @@ final class KQueuePort
int
err
=
0
;
int
flags
=
(
EV_ADD
|
EV_ONESHOT
);
if
((
events
&
Net
.
POLLIN
)
>
0
)
err
=
keventR
egister
(
kqfd
,
fd
,
EVFILT_READ
,
flags
);
err
=
KQueue
.
r
egister
(
kqfd
,
fd
,
EVFILT_READ
,
flags
);
if
(
err
==
0
&&
(
events
&
Net
.
POLLOUT
)
>
0
)
err
=
keventR
egister
(
kqfd
,
fd
,
EVFILT_WRITE
,
flags
);
err
=
KQueue
.
r
egister
(
kqfd
,
fd
,
EVFILT_WRITE
,
flags
);
if
(
err
!=
0
)
throw
new
InternalError
(
"kevent failed: "
+
err
);
// should not happen
}
...
...
@@ -193,7 +195,11 @@ final class KQueuePort
private
Event
poll
()
throws
IOException
{
try
{
for
(;;)
{
int
n
=
keventPoll
(
kqfd
,
address
,
MAX_KEVENTS_TO_POLL
);
int
n
;
do
{
n
=
KQueue
.
poll
(
kqfd
,
address
,
MAX_KEVENTS_TO_POLL
,
-
1L
);
}
while
(
n
==
IOStatus
.
INTERRUPTED
);
/*
* 'n' events have been read. Here we map them to their
* corresponding channel in batch and queue n-1 so that
...
...
@@ -203,14 +209,14 @@ final class KQueuePort
fdToChannelLock
.
readLock
().
lock
();
try
{
while
(
n
--
>
0
)
{
long
keventAddress
=
getEvent
(
address
,
n
);
int
fd
=
getDescriptor
(
keventAddress
);
long
keventAddress
=
KQueue
.
getEvent
(
address
,
n
);
int
fd
=
KQueue
.
getDescriptor
(
keventAddress
);
// wakeup
if
(
fd
==
sp
[
0
])
{
if
(
wakeupCount
.
decrementAndGet
()
==
0
)
{
// no more wakeups so drain pipe
drain1
(
sp
[
0
]);
IOUtil
.
drain
(
sp
[
0
]);
}
// queue special event if there are more events
...
...
@@ -224,7 +230,7 @@ final class KQueuePort
PollableChannel
channel
=
fdToChannel
.
get
(
fd
);
if
(
channel
!=
null
)
{
int
filter
=
getFilter
(
keventAddress
);
int
filter
=
KQueue
.
getFilter
(
keventAddress
);
int
events
=
0
;
if
(
filter
==
EVFILT_READ
)
events
=
Net
.
POLLIN
;
...
...
@@ -314,18 +320,4 @@ final class KQueuePort
}
}
}
// -- Native methods --
private
static
native
void
socketpair
(
int
[]
sv
)
throws
IOException
;
private
static
native
void
interrupt
(
int
fd
)
throws
IOException
;
private
static
native
void
drain1
(
int
fd
)
throws
IOException
;
private
static
native
void
close0
(
int
fd
);
static
{
IOUtil
.
load
();
}
}
src/java.base/macosx/classes/sun/nio/ch/KQueueSelectorImpl.java
浏览文件 @
1a2968ae
...
...
@@ -23,11 +23,6 @@
* questions.
*/
/*
* KQueueSelectorImpl.java
* Implementation of Selector using FreeBSD / Mac OS X kqueues
*/
package
sun.nio.ch
;
import
java.io.IOException
;
...
...
@@ -36,85 +31,111 @@ import java.nio.channels.SelectableChannel;
import
java.nio.channels.SelectionKey
;
import
java.nio.channels.Selector
;
import
java.nio.channels.spi.SelectorProvider
;
import
java.util.ArrayDeque
;
import
java.util.BitSet
;
import
java.util.Deque
;
import
java.util.HashMap
;
import
java.util.Iterator
;
import
java.util.Map
;
import
java.util.concurrent.TimeUnit
;
import
static
sun
.
nio
.
ch
.
KQueue
.
EVFILT_READ
;
import
static
sun
.
nio
.
ch
.
KQueue
.
EVFILT_WRITE
;
import
static
sun
.
nio
.
ch
.
KQueue
.
EV_ADD
;
import
static
sun
.
nio
.
ch
.
KQueue
.
EV_DELETE
;
/**
* KQueue based Selector implementation for macOS
*/
class
KQueueSelectorImpl
extends
SelectorImpl
{
// maximum number of events to poll in one call to kqueue
private
static
final
int
MAX_KEVENTS
=
256
;
// kqueue file descriptor
private
final
int
kqfd
;
class
KQueueSelectorImpl
extends
SelectorImpl
{
//
F
ile descriptors used for interrupt
// address of poll array (event list) when polling for pending events
private
final
long
pollArrayAddress
;
//
f
ile descriptors used for interrupt
private
final
int
fd0
;
private
final
int
fd1
;
//
The kqueue manipula
tor
private
final
KQueueArrayWrapper
kqueueWrapper
;
//
maps file descriptor to selection key, synchronize on selec
tor
private
final
Map
<
Integer
,
SelectionKeyImpl
>
fdToKey
=
new
HashMap
<>()
;
// Map from a file descriptor to an entry containing the selection key
private
final
HashMap
<
Integer
,
MapEntry
>
fdMap
;
// file descriptors registered with kqueue, synchronize on selector
private
final
BitSet
registeredReadFilter
=
new
BitSet
();
private
final
BitSet
registeredWriteFilter
=
new
BitSet
();
// True if this Selector has been closed
private
boolean
closed
;
// pending new registrations/updates, queued by implRegister and putEventOps
private
final
Object
updateLock
=
new
Object
();
private
final
Deque
<
SelectionKeyImpl
>
newKeys
=
new
ArrayDeque
<>();
private
final
Deque
<
SelectionKeyImpl
>
updateKeys
=
new
ArrayDeque
<>();
private
final
Deque
<
Integer
>
updateOps
=
new
ArrayDeque
<>();
//
Lock for
interrupt triggering and clearing
// interrupt triggering and clearing
private
final
Object
interruptLock
=
new
Object
();
private
boolean
interruptTriggered
;
// used by updateSelectedKeys to handle cases where the same file
// descriptor is polled by more than one filter
private
long
updateCount
;
// Used to map file descriptors to a selection key and "update count"
// (see updateSelectedKeys for usage).
private
static
class
MapEntry
{
SelectionKeyImpl
ski
;
long
updateCount
;
MapEntry
(
SelectionKeyImpl
ski
)
{
this
.
ski
=
ski
;
}
}
private
int
pollCount
;
/**
* Package private constructor called by factory method in
* the abstract superclass Selector.
*/
KQueueSelectorImpl
(
SelectorProvider
sp
)
throws
IOException
{
super
(
sp
);
long
fds
=
IOUtil
.
makePipe
(
false
);
fd0
=
(
int
)(
fds
>>>
32
);
fd1
=
(
int
)
fds
;
try
{
kqueueWrapper
=
new
KQueueArrayWrapper
(
fd0
,
fd1
);
fdMap
=
new
HashMap
<>();
}
catch
(
Throwable
t
)
{
try
{
FileDispatcherImpl
.
closeIntFD
(
fd0
);
}
catch
(
IOException
ioe0
)
{
t
.
addSuppressed
(
ioe0
);
}
this
.
kqfd
=
KQueue
.
create
();
this
.
pollArrayAddress
=
KQueue
.
allocatePollArray
(
MAX_KEVENTS
);
try
{
FileDispatcherImpl
.
closeIntFD
(
fd1
);
}
catch
(
IOException
ioe1
)
{
t
.
addSuppressed
(
ioe1
);
}
throw
t
;
long
fds
=
IOUtil
.
makePipe
(
false
);
this
.
fd0
=
(
int
)
(
fds
>>>
32
);
this
.
fd1
=
(
int
)
fds
;
}
catch
(
IOException
ioe
)
{
KQueue
.
freePollArray
(
pollArrayAddress
);
FileDispatcherImpl
.
closeIntFD
(
kqfd
);
throw
ioe
;
}
// register one end of the socket pair for wakeups
KQueue
.
register
(
kqfd
,
fd0
,
EVFILT_READ
,
EV_ADD
);
}
private
void
ensureOpen
()
{
if
(
closed
)
if
(
!
isOpen
()
)
throw
new
ClosedSelectorException
();
}
@Override
protected
int
doSelect
(
long
timeout
)
throws
IOException
{
ensureOpen
();
protected
int
doSelect
(
long
timeout
)
throws
IOException
{
assert
Thread
.
holdsLock
(
this
);
int
numEntries
;
processUpdateQueue
();
processDeregisterQueue
();
try
{
begin
();
numEntries
=
kqueueWrapper
.
poll
(
timeout
);
long
to
=
Math
.
min
(
timeout
,
Integer
.
MAX_VALUE
);
// max kqueue timeout
boolean
timedPoll
=
(
to
>
0
);
do
{
long
startTime
=
timedPoll
?
System
.
nanoTime
()
:
0
;
numEntries
=
KQueue
.
poll
(
kqfd
,
pollArrayAddress
,
MAX_KEVENTS
,
to
);
if
(
numEntries
==
IOStatus
.
INTERRUPTED
&&
timedPoll
)
{
// timed poll interrupted so need to adjust timeout
long
adjust
=
System
.
nanoTime
()
-
startTime
;
to
-=
TimeUnit
.
MILLISECONDS
.
convert
(
adjust
,
TimeUnit
.
NANOSECONDS
);
if
(
to
<=
0
)
{
// timeout expired so no retry
numEntries
=
0
;
}
}
}
while
(
numEntries
==
IOStatus
.
INTERRUPTED
);
assert
IOStatus
.
check
(
numEntries
);
}
finally
{
end
();
}
...
...
@@ -122,40 +143,101 @@ class KQueueSelectorImpl
return
updateSelectedKeys
(
numEntries
);
}
/**
* Process new registrations and changes to the interest ops.
*/
private
void
processUpdateQueue
()
{
assert
Thread
.
holdsLock
(
this
);
synchronized
(
updateLock
)
{
SelectionKeyImpl
ski
;
// new registrations
while
((
ski
=
newKeys
.
pollFirst
())
!=
null
)
{
if
(
ski
.
isValid
())
{
SelChImpl
ch
=
ski
.
channel
;
int
fd
=
ch
.
getFDVal
();
SelectionKeyImpl
previous
=
fdToKey
.
put
(
fd
,
ski
);
assert
previous
==
null
;
assert
registeredReadFilter
.
get
(
fd
)
==
false
;
assert
registeredWriteFilter
.
get
(
fd
)
==
false
;
}
}
// changes to interest ops
assert
updateKeys
.
size
()
==
updateOps
.
size
();
while
((
ski
=
updateKeys
.
pollFirst
())
!=
null
)
{
int
ops
=
updateOps
.
pollFirst
();
int
fd
=
ski
.
channel
.
getFDVal
();
if
(
ski
.
isValid
()
&&
fdToKey
.
containsKey
(
fd
))
{
// add or delete interest in read events
if
(
registeredReadFilter
.
get
(
fd
))
{
if
((
ops
&
Net
.
POLLIN
)
==
0
)
{
KQueue
.
register
(
kqfd
,
fd
,
EVFILT_READ
,
EV_DELETE
);
registeredReadFilter
.
clear
(
fd
);
}
}
else
if
((
ops
&
Net
.
POLLIN
)
!=
0
)
{
KQueue
.
register
(
kqfd
,
fd
,
EVFILT_READ
,
EV_ADD
);
registeredReadFilter
.
set
(
fd
);
}
// add or delete interest in write events
if
(
registeredWriteFilter
.
get
(
fd
))
{
if
((
ops
&
Net
.
POLLOUT
)
==
0
)
{
KQueue
.
register
(
kqfd
,
fd
,
EVFILT_WRITE
,
EV_DELETE
);
registeredWriteFilter
.
clear
(
fd
);
}
}
else
if
((
ops
&
Net
.
POLLOUT
)
!=
0
)
{
KQueue
.
register
(
kqfd
,
fd
,
EVFILT_WRITE
,
EV_ADD
);
registeredWriteFilter
.
set
(
fd
);
}
}
}
}
}
/**
* Update the keys whose fd's have been selected by kqueue.
* Add the ready keys to the selected key set.
* If the interrupt fd has been selected, drain it and clear the interrupt.
*/
private
int
updateSelectedKeys
(
int
numEntries
)
throws
IOException
{
private
int
updateSelectedKeys
(
int
numEntries
)
throws
IOException
{
assert
Thread
.
holdsLock
(
this
);
assert
Thread
.
holdsLock
(
nioSelectedKeys
());
int
numKeysUpdated
=
0
;
boolean
interrupted
=
false
;
// A file descriptor may be registered with kqueue with more than one
// filter and so there may be more than one event for a fd. The update
// count in the MapEntry tracks when the fd was last updated and this
// ensures that the ready ops are updated rather than replaced by a
// second or subsequent event.
updateCount
++;
// filter and so there may be more than one event for a fd. The poll
// count is incremented here and compared against the SelectionKey's
// "lastPolled" field. This ensures that the ready ops is updated rather
// than replaced when a file descriptor is polled by both the read and
// write filter.
pollCount
++;
for
(
int
i
=
0
;
i
<
numEntries
;
i
++)
{
int
nextFD
=
kqueueWrapper
.
getDescriptor
(
i
);
if
(
nextFD
==
fd0
)
{
long
kevent
=
KQueue
.
getEvent
(
pollArrayAddress
,
i
);
int
fd
=
KQueue
.
getDescriptor
(
kevent
);
if
(
fd
==
fd0
)
{
interrupted
=
true
;
}
else
{
MapEntry
me
=
fdMap
.
get
(
Integer
.
valueOf
(
nextFD
));
if
(
me
!=
null
)
{
int
rOps
=
kqueueWrapper
.
getReventOps
(
i
);
SelectionKeyImpl
ski
=
me
.
ski
;
SelectionKeyImpl
ski
=
fdToKey
.
get
(
fd
);
if
(
ski
!=
null
)
{
int
rOps
=
0
;
short
filter
=
KQueue
.
getFilter
(
kevent
);
if
(
filter
==
EVFILT_READ
)
{
rOps
|=
Net
.
POLLIN
;
}
else
if
(
filter
==
EVFILT_WRITE
)
{
rOps
|=
Net
.
POLLOUT
;
}
if
(
selectedKeys
.
contains
(
ski
))
{
// first time this file descriptor has been encountered on this
// update?
if
(
me
.
updateCount
!=
updateCount
)
{
// file descriptor may be polled more than once per poll
if
(
ski
.
lastPolled
!=
pollCount
)
{
if
(
ski
.
channel
.
translateAndSetReadyOps
(
rOps
,
ski
))
{
numKeysUpdated
++;
me
.
updateCount
=
update
Count
;
ski
.
lastPolled
=
poll
Count
;
}
}
else
{
// ready ops have already been set on this update
...
...
@@ -166,7 +248,7 @@ class KQueueSelectorImpl
if
((
ski
.
nioReadyOps
()
&
ski
.
nioInterestOps
())
!=
0
)
{
selectedKeys
.
add
(
ski
);
numKeysUpdated
++;
me
.
updateCount
=
update
Count
;
ski
.
lastPolled
=
poll
Count
;
}
}
}
...
...
@@ -181,15 +263,18 @@ class KQueueSelectorImpl
@Override
protected
void
implClose
()
throws
IOException
{
if
(!
closed
)
{
closed
=
true
;
assert
!
isOpen
();
assert
Thread
.
holdsLock
(
this
);
assert
Thread
.
holdsLock
(
nioKeys
());
// prevent further wakeup
synchronized
(
interruptLock
)
{
interruptTriggered
=
true
;
}
kqueueWrapper
.
close
();
FileDispatcherImpl
.
closeIntFD
(
kqfd
);
KQueue
.
freePollArray
(
pollArrayAddress
);
FileDispatcherImpl
.
closeIntFD
(
fd0
);
FileDispatcherImpl
.
closeIntFD
(
fd1
);
...
...
@@ -204,40 +289,64 @@ class KQueueSelectorImpl
i
.
remove
();
}
}
}
@Override
protected
void
implRegister
(
SelectionKeyImpl
ski
)
{
assert
Thread
.
holdsLock
(
nioKeys
());
ensureOpen
();
int
fd
=
IOUtil
.
fdVal
(
ski
.
channel
.
getFD
());
fdMap
.
put
(
Integer
.
valueOf
(
fd
),
new
MapEntry
(
ski
));
synchronized
(
updateLock
)
{
newKeys
.
addLast
(
ski
);
}
keys
.
add
(
ski
);
}
@Override
protected
void
implDereg
(
SelectionKeyImpl
ski
)
throws
IOException
{
assert
!
ski
.
isValid
();
assert
Thread
.
holdsLock
(
this
);
assert
Thread
.
holdsLock
(
nioKeys
());
assert
Thread
.
holdsLock
(
nioSelectedKeys
());
int
fd
=
ski
.
channel
.
getFDVal
();
fdMap
.
remove
(
Integer
.
valueOf
(
fd
));
kqueueWrapper
.
release
(
ski
.
channel
);
keys
.
remove
(
ski
);
fdToKey
.
remove
(
fd
);
if
(
registeredReadFilter
.
get
(
fd
))
{
KQueue
.
register
(
kqfd
,
fd
,
EVFILT_READ
,
EV_DELETE
);
registeredReadFilter
.
clear
(
fd
);
}
if
(
registeredWriteFilter
.
get
(
fd
))
{
KQueue
.
register
(
kqfd
,
fd
,
EVFILT_WRITE
,
EV_DELETE
);
registeredWriteFilter
.
clear
(
fd
);
}
selectedKeys
.
remove
(
ski
);
keys
.
remove
(
ski
);
// remove from channel's key set
deregister
(
ski
);
SelectableChannel
selch
=
ski
.
channel
();
if
(!
selch
.
isOpen
()
&&
!
selch
.
isRegistered
())
((
SelChImpl
)
selch
).
kill
();
((
SelChImpl
)
selch
).
kill
();
}
@Override
public
void
putEventOps
(
SelectionKeyImpl
ski
,
int
ops
)
{
ensureOpen
();
kqueueWrapper
.
setInterest
(
ski
.
channel
,
ops
);
synchronized
(
updateLock
)
{
updateOps
.
addLast
(
ops
);
// ops first in case adding the key fails
updateKeys
.
addLast
(
ski
);
}
}
@Override
public
Selector
wakeup
()
{
synchronized
(
interruptLock
)
{
if
(!
interruptTriggered
)
{
kqueueWrapper
.
interrupt
();
try
{
IOUtil
.
write1
(
fd1
,
(
byte
)
0
);
}
catch
(
IOException
ioe
)
{
throw
new
InternalError
(
ioe
);
}
interruptTriggered
=
true
;
}
}
...
...
src/java.base/macosx/classes/sun/nio/ch/KQueueSelectorProvider.java
浏览文件 @
1a2968ae
...
...
@@ -23,17 +23,10 @@
* questions.
*/
/*
* KQueueSelectorProvider.java
* Implementation of Selector using FreeBSD / Mac OS X kqueues
* Derived from Sun's DevPollSelectorProvider
*/
package
sun.nio.ch
;
import
java.io.IOException
;
import
java.nio.channels.*
;
import
java.nio.channels.spi.*
;
import
java.nio.channels.spi.AbstractSelector
;
public
class
KQueueSelectorProvider
extends
SelectorProviderImpl
...
...
src/java.base/macosx/native/libnio/ch/KQueue.c
浏览文件 @
1a2968ae
/*
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012,
2018,
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
...
...
@@ -23,76 +23,91 @@
* questions.
*/
#include <strings.h>
#include <sys/types.h>
#include <sys/event.h>
#include <sys/time.h>
#include "jni.h"
#include "jni_util.h"
#include "jvm.h"
#include "jlong.h"
#include "nio.h"
#include "nio_util.h"
#include "sun_nio_ch_KQueue.h"
#include <strings.h>
#include <sys/types.h>
#include <sys/event.h>
#include <sys/time.h>
JNIEXPORT
jint
JNICALL
Java_sun_nio_ch_KQueue_keventSize
(
JNIEnv
*
env
,
jclass
this
)
Java_sun_nio_ch_KQueue_keventSize
(
JNIEnv
*
env
,
jclass
clazz
)
{
return
sizeof
(
struct
kevent
);
}
JNIEXPORT
jint
JNICALL
Java_sun_nio_ch_KQueue_identOffset
(
JNIEnv
*
env
,
jclass
this
)
Java_sun_nio_ch_KQueue_identOffset
(
JNIEnv
*
env
,
jclass
clazz
)
{
return
offsetof
(
struct
kevent
,
ident
);
}
JNIEXPORT
jint
JNICALL
Java_sun_nio_ch_KQueue_filterOffset
(
JNIEnv
*
env
,
jclass
this
)
Java_sun_nio_ch_KQueue_filterOffset
(
JNIEnv
*
env
,
jclass
clazz
)
{
return
offsetof
(
struct
kevent
,
filter
);
}
JNIEXPORT
jint
JNICALL
Java_sun_nio_ch_KQueue_flagsOffset
(
JNIEnv
*
env
,
jclass
this
)
Java_sun_nio_ch_KQueue_flagsOffset
(
JNIEnv
*
env
,
jclass
clazz
)
{
return
offsetof
(
struct
kevent
,
flags
);
}
JNIEXPORT
jint
JNICALL
Java_sun_nio_ch_KQueue_
kqueue
(
JNIEnv
*
env
,
jclass
c
)
{
Java_sun_nio_ch_KQueue_
create
(
JNIEnv
*
env
,
jclass
clazz
)
{
int
kqfd
=
kqueue
();
if
(
kqfd
<
0
)
{
JNU_ThrowIOExceptionWithLastError
(
env
,
"kqueue failed"
);
return
IOS_THROWN
;
}
return
kqfd
;
}
JNIEXPORT
jint
JNICALL
Java_sun_nio_ch_KQueue_
keventRegister
(
JNIEnv
*
env
,
jclass
c
,
jint
kqfd
,
Java_sun_nio_ch_KQueue_
register
(
JNIEnv
*
env
,
jclass
clazz
,
jint
kqfd
,
jint
fd
,
jint
filter
,
jint
flags
)
{
struct
kevent
changes
[
1
];
struct
timespec
timeout
=
{
0
,
0
};
int
res
;
EV_SET
(
&
changes
[
0
],
fd
,
filter
,
flags
,
0
,
0
,
0
);
RESTARTABLE
(
kevent
(
kqfd
,
&
changes
[
0
],
1
,
NULL
,
0
,
&
timeout
),
res
);
RESTARTABLE
(
kevent
(
kqfd
,
&
changes
[
0
],
1
,
NULL
,
0
,
NULL
),
res
);
return
(
res
==
-
1
)
?
errno
:
0
;
}
JNIEXPORT
jint
JNICALL
Java_sun_nio_ch_KQueue_
keventPoll
(
JNIEnv
*
env
,
jclass
c
,
jint
kqfd
,
jlong
address
,
jint
nevents
)
Java_sun_nio_ch_KQueue_
poll
(
JNIEnv
*
env
,
jclass
clazz
,
jint
kqfd
,
jlong
address
,
jint
nevents
,
jlong
timeout
)
{
struct
kevent
*
events
=
jlong_to_ptr
(
address
);
int
res
;
struct
timespec
ts
;
struct
timespec
*
tsp
;
RESTARTABLE
(
kevent
(
kqfd
,
NULL
,
0
,
events
,
nevents
,
NULL
),
res
);
if
(
timeout
>=
0
)
{
ts
.
tv_sec
=
timeout
/
1000
;
ts
.
tv_nsec
=
(
timeout
%
1000
)
*
1000000
;
tsp
=
&
ts
;
}
else
{
tsp
=
NULL
;
}
res
=
kevent
(
kqfd
,
NULL
,
0
,
events
,
nevents
,
tsp
);
if
(
res
<
0
)
{
if
(
errno
==
EINTR
)
{
return
IOS_INTERRUPTED
;
}
else
{
JNU_ThrowIOExceptionWithLastError
(
env
,
"kqueue failed"
);
return
IOS_THROWN
;
}
}
return
res
;
}
src/java.base/macosx/native/libnio/ch/KQueueArrayWrapper.c
已删除
100644 → 0
浏览文件 @
21b2c57a
/*
* Copyright (c) 2011, 2018, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* KQueueArrayWrapper.c
* Implementation of Selector using FreeBSD / Mac OS X kqueues
* Derived from Sun's DevPollArrayWrapper
*/
#include "jni.h"
#include "jni_util.h"
#include "jvm.h"
#include "jlong.h"
#include "nio_util.h"
#include <sys/types.h>
#include <sys/event.h>
#include <sys/time.h>
JNIEXPORT
void
JNICALL
Java_sun_nio_ch_KQueueArrayWrapper_initStructSizes
(
JNIEnv
*
env
,
jclass
clazz
)
{
#define CHECK_EXCEPTION() { \
if ((*env)->ExceptionCheck(env)) { \
goto exceptionOccurred; \
} \
}
#define CHECK_ERROR_AND_EXCEPTION(_field) { \
if (_field == NULL) { \
goto badField; \
} \
CHECK_EXCEPTION(); \
}
jfieldID
field
;
field
=
(
*
env
)
->
GetStaticFieldID
(
env
,
clazz
,
"EVFILT_READ"
,
"S"
);
CHECK_ERROR_AND_EXCEPTION
(
field
);
(
*
env
)
->
SetStaticShortField
(
env
,
clazz
,
field
,
EVFILT_READ
);
CHECK_EXCEPTION
();
field
=
(
*
env
)
->
GetStaticFieldID
(
env
,
clazz
,
"EVFILT_WRITE"
,
"S"
);
CHECK_ERROR_AND_EXCEPTION
(
field
);
(
*
env
)
->
SetStaticShortField
(
env
,
clazz
,
field
,
EVFILT_WRITE
);
CHECK_EXCEPTION
();
field
=
(
*
env
)
->
GetStaticFieldID
(
env
,
clazz
,
"SIZEOF_KEVENT"
,
"S"
);
CHECK_ERROR_AND_EXCEPTION
(
field
);
(
*
env
)
->
SetStaticShortField
(
env
,
clazz
,
field
,
(
short
)
sizeof
(
struct
kevent
));
CHECK_EXCEPTION
();
field
=
(
*
env
)
->
GetStaticFieldID
(
env
,
clazz
,
"FD_OFFSET"
,
"S"
);
CHECK_ERROR_AND_EXCEPTION
(
field
);
(
*
env
)
->
SetStaticShortField
(
env
,
clazz
,
field
,
(
short
)
offsetof
(
struct
kevent
,
ident
));
CHECK_EXCEPTION
();
field
=
(
*
env
)
->
GetStaticFieldID
(
env
,
clazz
,
"FILTER_OFFSET"
,
"S"
);
CHECK_ERROR_AND_EXCEPTION
(
field
);
(
*
env
)
->
SetStaticShortField
(
env
,
clazz
,
field
,
(
short
)
offsetof
(
struct
kevent
,
filter
));
CHECK_EXCEPTION
();
return
;
badField:
return
;
exceptionOccurred:
return
;
#undef CHECK_EXCEPTION
#undef CHECK_ERROR_AND_EXCEPTION
}
JNIEXPORT
jint
JNICALL
Java_sun_nio_ch_KQueueArrayWrapper_init
(
JNIEnv
*
env
,
jobject
this
)
{
int
kq
=
kqueue
();
if
(
kq
<
0
)
{
JNU_ThrowIOExceptionWithLastError
(
env
,
"KQueueArrayWrapper: kqueue() failed"
);
}
return
kq
;
}
JNIEXPORT
void
JNICALL
Java_sun_nio_ch_KQueueArrayWrapper_register0
(
JNIEnv
*
env
,
jobject
this
,
jint
kq
,
jint
fd
,
jint
r
,
jint
w
)
{
struct
kevent
changes
[
2
];
struct
kevent
errors
[
2
];
struct
timespec
dontBlock
=
{
0
,
0
};
// if (r) then { register for read } else { unregister for read }
// if (w) then { register for write } else { unregister for write }
// Ignore errors - they're probably complaints about deleting non-
// added filters - but provide an error array anyway because
// kqueue behaves erratically if some of its registrations fail.
EV_SET
(
&
changes
[
0
],
fd
,
EVFILT_READ
,
r
?
EV_ADD
:
EV_DELETE
,
0
,
0
,
0
);
EV_SET
(
&
changes
[
1
],
fd
,
EVFILT_WRITE
,
w
?
EV_ADD
:
EV_DELETE
,
0
,
0
,
0
);
kevent
(
kq
,
changes
,
2
,
errors
,
2
,
&
dontBlock
);
}
JNIEXPORT
jint
JNICALL
Java_sun_nio_ch_KQueueArrayWrapper_kevent0
(
JNIEnv
*
env
,
jobject
this
,
jint
kq
,
jlong
kevAddr
,
jint
kevCount
,
jlong
timeout
)
{
struct
kevent
*
kevs
=
(
struct
kevent
*
)
jlong_to_ptr
(
kevAddr
);
struct
timespec
ts
;
struct
timespec
*
tsp
;
int
result
;
// Java timeout is in milliseconds. Convert to struct timespec.
// Java timeout == -1 : wait forever : timespec timeout of NULL
// Java timeout == 0 : return immediately : timespec timeout of zero
if
(
timeout
>=
0
)
{
// For some indeterminate reason kevent(2) has been found to fail with
// an EINVAL error for timeout values greater than or equal to
// 100000001000L. To avoid this problem, clamp the timeout arbitrarily
// to the maximum value of a 32-bit signed integer which is
// approximately 25 days in milliseconds.
const
jlong
timeoutMax
=
0x7fffffff
;
// java.lang.Integer.MAX_VALUE
if
(
timeout
>
timeoutMax
)
{
timeout
=
timeoutMax
;
}
ts
.
tv_sec
=
timeout
/
1000
;
ts
.
tv_nsec
=
(
timeout
%
1000
)
*
1000000
;
//nanosec = 1 million millisec
tsp
=
&
ts
;
}
else
{
tsp
=
NULL
;
}
RESTARTABLE
(
kevent
(
kq
,
NULL
,
0
,
kevs
,
kevCount
,
tsp
),
result
);
if
(
result
<
0
)
{
JNU_ThrowIOExceptionWithLastError
(
env
,
"KQueueArrayWrapper: kevent poll failed"
);
}
return
result
;
}
JNIEXPORT
void
JNICALL
Java_sun_nio_ch_KQueueArrayWrapper_interrupt
(
JNIEnv
*
env
,
jclass
cls
,
jint
fd
)
{
char
c
=
1
;
if
(
1
!=
write
(
fd
,
&
c
,
1
))
{
JNU_ThrowIOExceptionWithLastError
(
env
,
"KQueueArrayWrapper: interrupt failed"
);
}
}
src/java.base/macosx/native/libnio/ch/KQueuePort.c
已删除
100644 → 0
浏览文件 @
21b2c57a
/*
* Copyright (c) 2012, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
#include "jni.h"
#include "jni_util.h"
#include "jvm.h"
#include "jlong.h"
#include "nio_util.h"
#include "sun_nio_ch_KQueuePort.h"
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
JNIEXPORT
void
JNICALL
Java_sun_nio_ch_KQueuePort_socketpair
(
JNIEnv
*
env
,
jclass
clazz
,
jintArray
sv
)
{
int
sp
[
2
];
if
(
socketpair
(
PF_UNIX
,
SOCK_STREAM
,
0
,
sp
)
==
-
1
)
{
JNU_ThrowIOExceptionWithLastError
(
env
,
"socketpair failed"
);
}
else
{
jint
res
[
2
];
res
[
0
]
=
(
jint
)
sp
[
0
];
res
[
1
]
=
(
jint
)
sp
[
1
];
(
*
env
)
->
SetIntArrayRegion
(
env
,
sv
,
0
,
2
,
&
res
[
0
]);
}
}
JNIEXPORT
void
JNICALL
Java_sun_nio_ch_KQueuePort_interrupt
(
JNIEnv
*
env
,
jclass
c
,
jint
fd
)
{
int
res
;
int
buf
[
1
];
buf
[
0
]
=
1
;
RESTARTABLE
(
write
(
fd
,
buf
,
1
),
res
);
if
(
res
<
0
)
{
JNU_ThrowIOExceptionWithLastError
(
env
,
"write failed"
);
}
}
JNIEXPORT
void
JNICALL
Java_sun_nio_ch_KQueuePort_drain1
(
JNIEnv
*
env
,
jclass
cl
,
jint
fd
)
{
int
res
;
char
buf
[
1
];
RESTARTABLE
(
read
(
fd
,
buf
,
1
),
res
);
if
(
res
<
0
)
{
JNU_ThrowIOExceptionWithLastError
(
env
,
"drain1 failed"
);
}
}
JNIEXPORT
void
JNICALL
Java_sun_nio_ch_KQueuePort_close0
(
JNIEnv
*
env
,
jclass
c
,
jint
fd
)
{
int
res
;
RESTARTABLE
(
close
(
fd
),
res
);
}
src/java.base/share/classes/sun/nio/ch/IOUtil.java
浏览文件 @
1a2968ae
...
...
@@ -397,7 +397,9 @@ public class IOUtil {
* The read end of the pipe is returned in the high 32 bits,
* while the write end is returned in the low 32 bits.
*/
static
native
long
makePipe
(
boolean
blocking
);
static
native
long
makePipe
(
boolean
blocking
)
throws
IOException
;
static
native
int
write1
(
int
fd
,
byte
b
)
throws
IOException
;
static
native
boolean
drain
(
int
fd
)
throws
IOException
;
...
...
src/java.base/share/classes/sun/nio/ch/SelectionKeyImpl.java
浏览文件 @
1a2968ae
...
...
@@ -33,10 +33,10 @@ import java.nio.channels.spi.AbstractSelectionKey;
/**
* An implementation of SelectionKey
for Solaris
.
* An implementation of SelectionKey.
*/
public
class
SelectionKeyImpl
public
final
class
SelectionKeyImpl
extends
AbstractSelectionKey
{
...
...
@@ -54,12 +54,14 @@ public class SelectionKeyImpl
selector
=
sel
;
}
@Override
public
SelectableChannel
channel
()
{
return
(
SelectableChannel
)
channel
;
}
@Override
public
Selector
selector
()
{
return
selector
;
return
(
Selector
)
selector
;
}
int
getIndex
()
{
// package-private
...
...
@@ -75,16 +77,19 @@ public class SelectionKeyImpl
throw
new
CancelledKeyException
();
}
@Override
public
int
interestOps
()
{
ensureValid
();
return
interestOps
;
}
@Override
public
SelectionKey
interestOps
(
int
ops
)
{
ensureValid
();
return
nioInterestOps
(
ops
);
}
@Override
public
int
readyOps
()
{
ensureValid
();
return
readyOps
;
...
...
@@ -131,4 +136,6 @@ public class SelectionKeyImpl
return
sb
.
toString
();
}
// used by Selector implementations to record when the key was selected
int
lastPolled
;
}
src/java.base/share/classes/sun/nio/ch/SelectorImpl.java
浏览文件 @
1a2968ae
...
...
@@ -78,6 +78,16 @@ public abstract class SelectorImpl
return
publicSelectedKeys
;
}
/**
* Returns the public view of the key sets
*/
protected
final
Set
<
SelectionKey
>
nioKeys
()
{
return
publicKeys
;
}
protected
final
Set
<
SelectionKey
>
nioSelectedKeys
()
{
return
publicSelectedKeys
;
}
protected
abstract
int
doSelect
(
long
timeout
)
throws
IOException
;
private
int
lockAndDoSelect
(
long
timeout
)
throws
IOException
{
...
...
@@ -125,8 +135,6 @@ public abstract class SelectorImpl
protected
abstract
void
implClose
()
throws
IOException
;
public
abstract
void
putEventOps
(
SelectionKeyImpl
sk
,
int
ops
);
@Override
protected
final
SelectionKey
register
(
AbstractSelectableChannel
ch
,
int
ops
,
...
...
@@ -166,4 +174,9 @@ public abstract class SelectorImpl
}
}
}
/**
* Invoked to change the key's interest set
*/
public
abstract
void
putEventOps
(
SelectionKeyImpl
ski
,
int
ops
);
}
src/java.base/share/classes/sun/nio/ch/ServerSocketChannelImpl.java
浏览文件 @
1a2968ae
...
...
@@ -210,8 +210,6 @@ class ServerSocketChannelImpl
@Override
public
ServerSocketChannel
bind
(
SocketAddress
local
,
int
backlog
)
throws
IOException
{
acceptLock
.
lock
();
try
{
synchronized
(
stateLock
)
{
ensureOpen
();
if
(
localAddress
!=
null
)
...
...
@@ -227,9 +225,6 @@ class ServerSocketChannelImpl
Net
.
listen
(
fd
,
backlog
<
1
?
50
:
backlog
);
localAddress
=
Net
.
localAddress
(
fd
);
}
}
finally
{
acceptLock
.
unlock
();
}
return
this
;
}
...
...
src/java.base/solaris/classes/sun/nio/ch/DevPollArrayWrapper.java
浏览文件 @
1a2968ae
...
...
@@ -127,7 +127,7 @@ class DevPollArrayWrapper {
// descriptor is registered with /dev/poll.
private
final
BitSet
registered
=
new
BitSet
();
DevPollArrayWrapper
()
{
DevPollArrayWrapper
()
throws
IOException
{
int
allocationSize
=
NUM_POLLFDS
*
SIZE_POLLFD
;
pollArray
=
new
AllocatedNativeObject
(
allocationSize
,
true
);
pollArrayAddress
=
pollArray
.
address
();
...
...
@@ -136,7 +136,7 @@ class DevPollArrayWrapper {
eventsHigh
=
new
HashMap
<>();
}
void
initInterrupt
(
int
fd0
,
int
fd1
)
{
void
initInterrupt
(
int
fd0
,
int
fd1
)
throws
IOException
{
outgoingInterruptFD
=
fd1
;
incomingInterruptFD
=
fd0
;
register
(
wfd
,
fd0
,
POLLIN
);
...
...
@@ -200,7 +200,7 @@ class DevPollArrayWrapper {
}
}
void
release
(
int
fd
)
{
void
release
(
int
fd
)
throws
IOException
{
synchronized
(
updateLock
)
{
// ignore any pending update for this file descriptor
setUpdateEvents
(
fd
,
IGNORE
);
...
...
@@ -297,7 +297,11 @@ class DevPollArrayWrapper {
boolean
interrupted
=
false
;
public
void
interrupt
()
{
interrupt
(
outgoingInterruptFD
);
try
{
IOUtil
.
write1
(
outgoingInterruptFD
,
(
byte
)
0
);
}
catch
(
IOException
ioe
)
{
throw
new
InternalError
(
ioe
);
}
}
public
int
interruptedIndex
()
{
...
...
@@ -312,13 +316,12 @@ class DevPollArrayWrapper {
interrupted
=
false
;
}
private
native
int
init
();
private
native
void
register
(
int
wfd
,
int
fd
,
int
mask
);
private
native
int
init
()
throws
IOException
;
private
native
void
register
(
int
wfd
,
int
fd
,
int
mask
)
throws
IOException
;
private
native
void
registerMultiple
(
int
wfd
,
long
address
,
int
len
)
throws
IOException
;
private
native
int
poll0
(
long
pollAddress
,
int
numfds
,
long
timeout
,
int
wfd
);
private
static
native
void
interrupt
(
int
fd
);
private
native
int
poll0
(
long
pollAddress
,
int
numfds
,
long
timeout
,
int
wfd
)
throws
IOException
;
static
{
IOUtil
.
load
();
...
...
src/java.base/solaris/classes/sun/nio/ch/DevPollSelectorImpl.java
浏览文件 @
1a2968ae
...
...
@@ -61,7 +61,7 @@ class DevPollSelectorImpl
* Package private constructor called by factory method in
* the abstract superclass Selector.
*/
DevPollSelectorImpl
(
SelectorProvider
sp
)
{
DevPollSelectorImpl
(
SelectorProvider
sp
)
throws
IOException
{
super
(
sp
);
long
pipeFds
=
IOUtil
.
makePipe
(
false
);
fd0
=
(
int
)
(
pipeFds
>>>
32
);
...
...
src/java.base/solaris/classes/sun/nio/ch/EventPortWrapper.java
浏览文件 @
1a2968ae
/*
* Copyright (c) 2012, 201
3
, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 201
8
, 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
...
...
@@ -181,12 +181,26 @@ class EventPortWrapper {
}
// poll for events
int
updated
=
port_getn
(
pfd
,
pollArrayAddress
,
POLL_MAX
,
timeout
);
int
numEntries
;
long
to
=
timeout
;
boolean
timedPoll
=
(
to
>
0
);
do
{
long
startTime
=
timedPoll
?
System
.
currentTimeMillis
()
:
0
;
numEntries
=
port_getn
(
pfd
,
pollArrayAddress
,
POLL_MAX
,
timeout
);
if
(
numEntries
==
IOStatus
.
INTERRUPTED
&&
timedPoll
)
{
// timed poll interrupted so need to adjust timeout
to
-=
System
.
currentTimeMillis
()
-
startTime
;
if
(
to
<=
0
)
{
// timeout also expired so no retry
numEntries
=
0
;
}
}
}
while
(
numEntries
==
IOStatus
.
INTERRUPTED
);
// after polling we need to queue all polled file descriptors as they
// are candidates to register for the next poll.
synchronized
(
updateLock
)
{
for
(
int
i
=
0
;
i
<
updated
;
i
++)
{
for
(
int
i
=
0
;
i
<
numEntries
;
i
++)
{
if
(
getSource
(
i
)
==
PORT_SOURCE_USER
)
{
interrupted
=
true
;
setDescriptor
(
i
,
-
1
);
...
...
@@ -199,7 +213,7 @@ class EventPortWrapper {
}
}
return
updated
;
return
numEntries
;
}
private
void
setInterest
(
int
fd
)
{
...
...
src/java.base/solaris/classes/sun/nio/ch/SolarisEventPort.java
浏览文件 @
1a2968ae
/*
* Copyright (c) 2008, 201
3
, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2008, 201
8
, 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
...
...
@@ -164,7 +164,10 @@ class SolarisEventPort
// A error here is fatal (thread will not be replaced)
replaceMe
=
false
;
try
{
port_get
(
port
,
address
);
int
n
;
do
{
n
=
port_get
(
port
,
address
);
}
while
(
n
==
IOStatus
.
INTERRUPTED
);
}
catch
(
IOException
x
)
{
x
.
printStackTrace
();
return
;
...
...
@@ -240,7 +243,7 @@ class SolarisEventPort
/**
* Retrieves a single event from a port
*/
static
native
void
port_get
(
int
port
,
long
pe
)
throws
IOException
;
static
native
int
port_get
(
int
port
,
long
address
)
throws
IOException
;
/**
* Retrieves at most {@code max} events from a port.
...
...
src/java.base/solaris/native/libnio/ch/DevPollArrayWrapper.c
浏览文件 @
1a2968ae
/*
* Copyright (c) 2001, 201
6
, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2001, 201
8
, 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
...
...
@@ -176,14 +176,3 @@ Java_sun_nio_ch_DevPollArrayWrapper_poll0(JNIEnv *env, jobject this,
}
return
result
;
}
JNIEXPORT
void
JNICALL
Java_sun_nio_ch_DevPollArrayWrapper_interrupt
(
JNIEnv
*
env
,
jclass
this
,
jint
fd
)
{
int
fakebuf
[
1
];
fakebuf
[
0
]
=
1
;
if
(
write
(
fd
,
fakebuf
,
1
)
<
0
)
{
JNU_ThrowIOExceptionWithLastError
(
env
,
"Write to interrupt fd failed"
);
}
}
src/java.base/solaris/native/libnio/ch/SolarisEventPort.c
浏览文件 @
1a2968ae
/*
* Copyright (c) 2008, 201
2
, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2008, 201
8
, 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
...
...
@@ -23,17 +23,18 @@
* questions.
*/
#include <stdlib.h>
#include <dlfcn.h>
#include <sys/types.h>
#include <port.h>
#include "jni.h"
#include "jni_util.h"
#include "jvm.h"
#include "jlong.h"
#include "nio.h"
#include "nio_util.h"
#include <stdlib.h>
#include <dlfcn.h>
#include <sys/types.h>
#include <port.h>
#include "sun_nio_ch_SolarisEventPort.h"
JNIEXPORT
jint
JNICALL
...
...
@@ -51,8 +52,10 @@ JNIEXPORT void JNICALL
Java_sun_nio_ch_SolarisEventPort_port_1close
(
JNIEnv
*
env
,
jclass
clazz
,
jint
port
)
{
int
res
;
RESTARTABLE
(
close
(
port
),
res
);
int
res
=
close
(
port
);
if
(
res
<
0
&&
res
!=
EINTR
)
{
JNU_ThrowIOExceptionWithLastError
(
env
,
"close failed"
);
}
}
JNIEXPORT
jboolean
JNICALL
...
...
@@ -93,17 +96,23 @@ Java_sun_nio_ch_SolarisEventPort_port_1send(JNIEnv* env, jclass clazz,
}
}
JNIEXPORT
void
JNICALL
JNIEXPORT
jint
JNICALL
Java_sun_nio_ch_SolarisEventPort_port_1get
(
JNIEnv
*
env
,
jclass
clazz
,
jint
port
,
jlong
eventAddress
)
{
int
res
;
port_event_t
*
ev
=
(
port_event_t
*
)
jlong_to_ptr
(
eventAddress
);
RESTARTABLE
(
port_get
((
int
)
port
,
ev
,
NULL
),
res
);
res
=
port_get
((
int
)
port
,
ev
,
NULL
);
if
(
res
==
-
1
)
{
JNU_ThrowIOExceptionWithLastError
(
env
,
"port_get"
);
if
(
errno
==
EINTR
)
{
return
IOS_INTERRUPTED
;
}
else
{
JNU_ThrowIOExceptionWithLastError
(
env
,
"port_get failed"
);
return
IOS_THROWN
;
}
}
return
res
;
}
JNIEXPORT
jint
JNICALL
...
...
@@ -125,9 +134,13 @@ Java_sun_nio_ch_SolarisEventPort_port_1getn(JNIEnv* env, jclass clazz,
}
res
=
port_getn
((
int
)
port
,
list
,
(
uint_t
)
max
,
&
n
,
tsp
);
if
(
res
==
-
1
)
{
if
(
errno
!=
ETIME
&&
errno
!=
EINTR
)
JNU_ThrowIOExceptionWithLastError
(
env
,
"port_getn"
);
if
(
res
==
-
1
&&
errno
!=
ETIME
)
{
if
(
errno
==
EINTR
)
{
return
IOS_INTERRUPTED
;
}
else
{
JNU_ThrowIOExceptionWithLastError
(
env
,
"port_getn failed"
);
return
IOS_THROWN
;
}
}
return
(
jint
)
n
;
...
...
src/java.base/unix/classes/sun/nio/ch/PipeImpl.java
浏览文件 @
1a2968ae
/*
* Copyright (c) 2000, 201
0
, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2000, 201
8
, 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
...
...
@@ -38,7 +38,7 @@ class PipeImpl
private
final
SourceChannel
source
;
private
final
SinkChannel
sink
;
PipeImpl
(
SelectorProvider
sp
)
{
PipeImpl
(
SelectorProvider
sp
)
throws
IOException
{
long
pipeFds
=
IOUtil
.
makePipe
(
true
);
int
readFd
=
(
int
)
(
pipeFds
>>>
32
);
int
writeFd
=
(
int
)
pipeFds
;
...
...
src/java.base/unix/classes/sun/nio/ch/PollSelectorImpl.java
浏览文件 @
1a2968ae
/*
* Copyright (c) 2001, 201
6
, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2001, 201
8
, 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
...
...
@@ -51,7 +51,7 @@ class PollSelectorImpl
* Package private constructor called by factory method in
* the abstract superclass Selector.
*/
PollSelectorImpl
(
SelectorProvider
sp
)
{
PollSelectorImpl
(
SelectorProvider
sp
)
throws
IOException
{
super
(
sp
,
1
,
1
);
long
pipeFds
=
IOUtil
.
makePipe
(
false
);
fd0
=
(
int
)
(
pipeFds
>>>
32
);
...
...
src/java.base/unix/classes/sun/nio/ch/SocketDispatcher.java
浏览文件 @
1a2968ae
/*
* Copyright (c) 2000, 20
09
, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2000, 20
18
, 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
...
...
@@ -25,15 +25,15 @@
package
sun.nio.ch
;
import
java.io.*
;
import
java.io.FileDescriptor
;
import
java.io.IOException
;
/**
* Allows different platforms to call different native methods
* for read and write operations.
*/
class
SocketDispatcher
extends
NativeDispatcher
{
class
SocketDispatcher
extends
NativeDispatcher
{
int
read
(
FileDescriptor
fd
,
long
address
,
int
len
)
throws
IOException
{
return
FileDispatcherImpl
.
read0
(
fd
,
address
,
len
);
...
...
src/java.base/unix/native/libnio/ch/IOUtil.c
浏览文件 @
1a2968ae
/*
* Copyright (c) 2000, 201
5
, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2000, 201
8
, 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
...
...
@@ -104,10 +104,19 @@ Java_sun_nio_ch_IOUtil_makePipe(JNIEnv *env, jobject this, jboolean blocking)
return
((
jlong
)
fd
[
0
]
<<
32
)
|
(
jlong
)
fd
[
1
];
}
JNIEXPORT
jint
JNICALL
Java_sun_nio_ch_IOUtil_write1
(
JNIEnv
*
env
,
jclass
cl
,
jint
fd
,
jbyte
b
)
{
char
c
=
(
char
)
b
;
return
convertReturnVal
(
env
,
write
(
fd
,
&
c
,
1
),
JNI_FALSE
);
}
JNIEXPORT
jboolean
JNICALL
Java_sun_nio_ch_IOUtil_drain
(
JNIEnv
*
env
,
jclass
cl
,
jint
fd
)
{
char
buf
[
1
28
];
char
buf
[
1
6
];
int
tn
=
0
;
for
(;;)
{
...
...
test/jdk/java/nio/channels/Selector/CloseWhenKeyIdle.java
浏览文件 @
1a2968ae
/*
* Copyright (c) 2007, 201
0
, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2007, 201
8
, 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
...
...
@@ -62,22 +62,6 @@ public class CloseWhenKeyIdle {
public
static
void
main
(
String
[]
args
)
throws
Exception
{
// Skip test on pre-2.6 kernels until the poll SelectorProvider
// is updated
String
osname
=
System
.
getProperty
(
"os.name"
);
if
(
osname
.
equals
(
"Linux"
))
{
String
[]
ver
=
System
.
getProperty
(
"os.version"
).
split
(
"\\."
,
0
);
if
(
ver
.
length
>=
2
)
{
int
major
=
Integer
.
parseInt
(
ver
[
0
]);
int
minor
=
Integer
.
parseInt
(
ver
[
1
]);
if
(
major
<
2
||
(
major
==
2
&&
minor
<
6
))
{
System
.
out
.
println
(
"Test passing on pre-2.6 kernel"
);
return
;
}
}
}
// establish loopback connection
ServerSocketChannel
ssc
=
ServerSocketChannel
.
open
();
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录