using the sendfile system call on Darwin
msa at allman.ms
Thu Jan 28 00:14:15 PST 2010
On Wed, 27 Jan 2010, Greg Lewis wrote:
> On Tue, Jan 26, 2010 at 01:33:06AM -0800, Michael Allman wrote:
>> I would like to update jdk/src/solaris/native/sun/nio/ch/FileChannelImpl.c
>> so that the Java_sun_nio_ch_FileChannelImpl_transferTo0 function calls the
>> sendfile system call on Darwin. I have a few questions:
>> 1. Is there a cpp #define for Darwin? If not, how do I tell cpp whether
>> the system is Darwin or not?
> The rest of the code uses
> #ifdef __APPLE__
>> 2. Are there tests that exercise
>> Java_sun_nio_ch_FileChannelImpl_transferTo0 or the java method
> Some of the tests in jdk/test/java/nio/channels/FileChannel/ may be useful,
> I haven't looked them over though.
Oh yeah. I remember these. I have have an old copy on my machine. I
>> 3. Why doesn't the existing BSD code just return IOS_UNSUPPORTED? For
>> instance, look at lines 223 and 224. If there's no sendfile function on
>> Solaris, the function just returns IOS_UNSUPPORTED. The caller handles
>> that return value gracefully. The existing BSD code looks needlessly
>> complex to me.
> All of the BSDs have sendfile, its just limited to only sending the file to
> a stream socket rather than any file descriptor, which Solaris and Linux
> allow. It's fairly easy to implement code that will do that though, so
> that's what was done rather than throwing errors when a non-socket file
> descriptor was used.
> Note that MacOS X seems to have the same limitations as all the other BSDs
> in terms of what type of file descriptor can be used as the destination:
I think sun.nio.ch.FileChannelImpl can handle this limitation gracefully.
The new Java_sun_nio_ch_FileChannelImpl_transferTo0 method will look
something like this: (starting at _ALLBSD_SOURCE_)
result = sendfile(srcFD, dstFD, position, &count);
if (result == 0)
if (errno == ENOTSOCK)
/* Handle more errno's here... */
/* Return of last resort */
JNU_ThrowIOExceptionWithLastError(env, "Transfer failed");
FileChannelImpl's transferToDirectly method tries
Java_sun_nio_ch_FileChannelImpl_transferTo0 at least once. If
Java_sun_nio_ch_FileChannelImpl_transferTo0 returns IOS_UNSUPPORTED, it
won't call it again. If Java_sun_nio_ch_FileChannelImpl_transferTo0
returns IOS_UNSUPPORTED_CASE and the destination file descriptor is a
file, then transferToDirectly just won't call
Java_sun_nio_ch_FileChannelImpl_transferTo0 again for transfers to files.
But it will still call it for transfers to sockets. The details are in
the FileChannelImpl.java source code.
Using this approach, we can still take advantage of BSDs' support for
file->socket transfer without emulating support for file->file transfer.
Also, though this patch will be targeted at Darwin only, I believe it will
be easily adaptable to other BSD systems. I just looked up FreeBSD's
sendfile call and it looks very similar.
> If NIO in general interests you, then a project we really need someone to
> work on is porting NIO2 to BSD. None of the BSDs have the epoll mechanism
> used on Linux or whatever Solaris uses (which I can't recall off the top of
> my head right now). The suggestion is to use kqueue(2) on BSD.
A kqueue-based selector would be nice for NIO 1. Both of these would be
I might be able to do the Java side of this effort if a kqueue developer
does the native side. I don't have the C/C++ programming skills to do the
More information about the bsd-port-dev