46 #include "jlong.h" |
46 #include "jlong.h" |
47 #include "nio.h" |
47 #include "nio.h" |
48 #include "nio_util.h" |
48 #include "nio_util.h" |
49 #include "sun_nio_ch_FileChannelImpl.h" |
49 #include "sun_nio_ch_FileChannelImpl.h" |
50 #include "java_lang_Integer.h" |
50 #include "java_lang_Integer.h" |
|
51 #include <assert.h> |
51 |
52 |
52 static jfieldID chan_fd; /* jobject 'fd' in sun.nio.ch.FileChannelImpl */ |
53 static jfieldID chan_fd; /* jobject 'fd' in sun.nio.ch.FileChannelImpl */ |
53 |
54 |
54 JNIEXPORT jlong JNICALL |
55 JNIEXPORT jlong JNICALL |
55 Java_sun_nio_ch_FileChannelImpl_initIDs(JNIEnv *env, jclass clazz) |
56 Java_sun_nio_ch_FileChannelImpl_initIDs(JNIEnv *env, jclass clazz) |
71 } |
72 } |
72 |
73 |
73 |
74 |
74 JNIEXPORT jlong JNICALL |
75 JNIEXPORT jlong JNICALL |
75 Java_sun_nio_ch_FileChannelImpl_map0(JNIEnv *env, jobject this, |
76 Java_sun_nio_ch_FileChannelImpl_map0(JNIEnv *env, jobject this, |
76 jint prot, jlong off, jlong len) |
77 jint prot, jlong off, jlong len, jboolean map_sync) |
77 { |
78 { |
78 void *mapAddress = 0; |
79 void *mapAddress = 0; |
79 jobject fdo = (*env)->GetObjectField(env, this, chan_fd); |
80 jobject fdo = (*env)->GetObjectField(env, this, chan_fd); |
80 jint fd = fdval(env, fdo); |
81 jint fd = fdval(env, fdo); |
81 int protections = 0; |
82 int protections = 0; |
82 int flags = 0; |
83 int flags = 0; |
|
84 |
|
85 // should never be called with map_sync and prot == PRIVATE |
|
86 assert((prot != sun_nio_ch_FileChannelImpl_MAP_PV) || !map_sync); |
83 |
87 |
84 if (prot == sun_nio_ch_FileChannelImpl_MAP_RO) { |
88 if (prot == sun_nio_ch_FileChannelImpl_MAP_RO) { |
85 protections = PROT_READ; |
89 protections = PROT_READ; |
86 flags = MAP_SHARED; |
90 flags = MAP_SHARED; |
87 } else if (prot == sun_nio_ch_FileChannelImpl_MAP_RW) { |
91 } else if (prot == sun_nio_ch_FileChannelImpl_MAP_RW) { |
90 } else if (prot == sun_nio_ch_FileChannelImpl_MAP_PV) { |
94 } else if (prot == sun_nio_ch_FileChannelImpl_MAP_PV) { |
91 protections = PROT_WRITE | PROT_READ; |
95 protections = PROT_WRITE | PROT_READ; |
92 flags = MAP_PRIVATE; |
96 flags = MAP_PRIVATE; |
93 } |
97 } |
94 |
98 |
|
99 // if MAP_SYNC and MAP_SHARED_VALIDATE are not defined then it is |
|
100 // best to define them here. This ensures the code compiles on old |
|
101 // OS releases which do not provide the relevant headers. If run |
|
102 // on the same machine then it will work if the kernel contains |
|
103 // the necessary support otherwise mmap should fail with an |
|
104 // invalid argument error |
|
105 |
|
106 #ifndef MAP_SYNC |
|
107 #define MAP_SYNC 0x80000 |
|
108 #endif |
|
109 #ifndef MAP_SHARED_VALIDATE |
|
110 #define MAP_SHARED_VALIDATE 0x03 |
|
111 #endif |
|
112 |
|
113 if (map_sync) { |
|
114 // ensure |
|
115 // 1) this is Linux on AArch64 or x86_64 |
|
116 // 2) the mmap APIs are available/ at compile time |
|
117 #if !defined(LINUX) || ! (defined(aarch64) || (defined(amd64) && defined(_LP64))) |
|
118 // TODO - implement for solaris/AIX/BSD/WINDOWS and for 32 bit |
|
119 JNU_ThrowInternalError(env, "should never call map on platform where MAP_SYNC is unimplemented"); |
|
120 return IOS_THROWN; |
|
121 #else |
|
122 flags |= MAP_SYNC | MAP_SHARED_VALIDATE; |
|
123 #endif |
|
124 } |
|
125 |
95 mapAddress = mmap64( |
126 mapAddress = mmap64( |
96 0, /* Let OS decide location */ |
127 0, /* Let OS decide location */ |
97 len, /* Number of bytes to map */ |
128 len, /* Number of bytes to map */ |
98 protections, /* File permissions */ |
129 protections, /* File permissions */ |
99 flags, /* Changes are shared */ |
130 flags, /* Changes are shared */ |
100 fd, /* File descriptor of mapped file */ |
131 fd, /* File descriptor of mapped file */ |
101 off); /* Offset into file */ |
132 off); /* Offset into file */ |
102 |
133 |
103 if (mapAddress == MAP_FAILED) { |
134 if (mapAddress == MAP_FAILED) { |
|
135 if (map_sync && errno == ENOTSUP) { |
|
136 JNU_ThrowIOExceptionWithLastError(env, "map with mode MAP_SYNC unsupported"); |
|
137 return IOS_THROWN; |
|
138 } |
|
139 |
104 if (errno == ENOMEM) { |
140 if (errno == ENOMEM) { |
105 JNU_ThrowOutOfMemoryError(env, "Map failed"); |
141 JNU_ThrowOutOfMemoryError(env, "Map failed"); |
106 return IOS_THROWN; |
142 return IOS_THROWN; |
107 } |
143 } |
108 return handle(env, -1, "Map failed"); |
144 return handle(env, -1, "Map failed"); |