001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: package org.apache.harmony.luni.platform;
019:
020: import java.io.IOException;
021:
022: /**
023: * This class enables direct access to OS memory.
024: * <p>
025: * Methods that take OS addresses define such parameters as a Java
026: * <code>long</code>. The <code>long</code> value is interpreted based on
027: * the underlying platform pointer size, such that only the lowest significant
028: * <code>POINTER_SIZE</code> bytes of the <code>long</code> value are used.
029: * In practice this means that methods on 64-bit platforms use the full eight
030: * bytes of the address parameter, and on 32-bit platforms the same methods are
031: * truncated to use only the low four bytes.
032: * </p>
033: * <p>
034: * Methods that return OS addresses define the return type to be a Java
035: * <code>long</code>. If the platform pointer size is less than eight bytes
036: * the OS address value is zero-extended to an eight-byte int to correspond to
037: * the subsequent interpretation of that jlong as an OS address as defined
038: * above.
039: * </p>
040: */
041: final class OSMemory extends OSComponent implements IMemorySystem {
042:
043: /**
044: * Defines the size, in bytes, of a native pointer type for the underlying
045: * platform. This will be 4 (for 32-bit machines) or 8 (for 64-bit
046: * machines).
047: */
048: public static final int POINTER_SIZE;
049:
050: /**
051: * Defines the natural byte order for this machine.
052: */
053: public static final Endianness NATIVE_ORDER;
054:
055: private static final OSMemory singleton = new OSMemory();
056:
057: static {
058: POINTER_SIZE = getPointerSizeImpl();
059:
060: if (isLittleEndianImpl()) {
061: NATIVE_ORDER = Endianness.LITTLE_ENDIAN;
062: } else {
063: NATIVE_ORDER = Endianness.BIG_ENDIAN;
064: }
065: }
066:
067: public static OSMemory getOSMemory() {
068: return singleton;
069: }
070:
071: /**
072: * This class is not designed to be publically instantiated.
073: *
074: * @see #getOSMemory()
075: */
076: OSMemory() {
077: super ();
078: }
079:
080: /**
081: * Answers whether the byte order of this machine is little endian or not..
082: *
083: * @return <code>false</code> for Big Endian, and
084: * <code>true</code. for Little Endian.
085: */
086: public static native boolean isLittleEndianImpl();
087:
088: public boolean isLittleEndian() {
089: return isLittleEndianImpl();
090: }
091:
092: /**
093: * Answers the natural byte order for this machine.
094: *
095: * @return the native byte order for the current platform.
096: */
097: public Endianness getNativeOrder() {
098: return NATIVE_ORDER;
099: }
100:
101: /**
102: * Answers the size of a native pointer type for the underlying platform.
103: *
104: * @return the size of a pointer, in bytes.
105: */
106: private static native int getPointerSizeImpl();
107:
108: public int getPointerSize() {
109: return POINTER_SIZE;
110: }
111:
112: /**
113: * Allocates and returns a pointer to space for a memory block of
114: * <code>length</code> bytes. The space is uninitialized and may be larger
115: * than the number of bytes requested; however, the guaranteed usable memory
116: * block is exactly <code>length</code> bytes long.
117: *
118: * @param length
119: * number of bytes requested.
120: * @return the address of the start of the memory block.
121: * @throws OutOfMemoryError
122: * if the request cannot be satisfied.
123: */
124: public long malloc(long length) throws OutOfMemoryError {
125: OSResourcesMonitor.ensurePhysicalMemoryCapacity();
126: return mallocNative(length);
127: }
128:
129: private native long mallocNative(long length)
130: throws OutOfMemoryError;
131:
132: /**
133: * Deallocates space for a memory block that was previously allocated by a
134: * call to {@link #malloc(long) malloc(long)}. The number of bytes freed is
135: * identical to the number of bytes acquired when the memory block was
136: * allocated. If <code>address</code> is zero the method does nothing.
137: * <p>
138: * Freeing a pointer to a memory block that was not allocated by
139: * <code>malloc()</code> has unspecified effect.
140: * </p>
141: *
142: * @param address
143: * the address of the memory block to deallocate.
144: */
145: public native void free(long address);
146:
147: /**
148: * Places <code>value</code> into first <code>length</code> bytes of the
149: * memory block starting at <code>address</code>.
150: * <p>
151: * The behavior is unspecified if
152: * <code>(address ... address + length)</code> is not wholly within the
153: * range that was previously allocated using <code>malloc()</code>.
154: * </p>
155: *
156: * @param address
157: * the address of the first memory location.
158: * @param value
159: * the byte value to set at each location.
160: * @param length
161: * the number of byte-length locations to set.
162: */
163: public native void memset(long address, byte value, long length);
164:
165: /**
166: * Copies <code>length</code> bytes from <code>srcAddress</code> to
167: * <code>destAddress</code>. Where any part of the source memory block
168: * and the destination memory block overlap <code>memmove()</code> ensures
169: * that the original source bytes in the overlapping region are copied
170: * before being overwritten.
171: * <p>
172: * The behavior is unspecified if
173: * <code>(srcAddress ... srcAddress + length)</code> and
174: * <code>(destAddress ... destAddress + length)</code> are not both wholly
175: * within the range that was previously allocated using
176: * <code>malloc()</code>.
177: * </p>
178: *
179: * @param destAddress
180: * the address of the destination memory block.
181: * @param srcAddress
182: * the address of the source memory block.
183: * @param length
184: * the number of bytes to move.
185: */
186: public native void memmove(long destAddress, long srcAddress,
187: long length);
188:
189: /**
190: * Copies <code>length</code> bytes from the memory block at
191: * <code>address</code> into the byte array <code>bytes</code> starting
192: * at element <code>offset</code> within the byte array.
193: * <p>
194: * The behavior of this method is undefined if the range
195: * <code>(address ... address + length)</code> is not within a memory
196: * block that was allocated using {@link #malloc(long) malloc(long)}.
197: * </p>
198: *
199: * @param address
200: * the address of the OS memory block from which to copy bytes.
201: * @param bytes
202: * the byte array into which to copy the bytes.
203: * @param offset
204: * the index of the first element in <code>bytes</code> that
205: * will be overwritten.
206: * @param length
207: * the total number of bytes to copy into the byte array.
208: * @throws NullPointerException
209: * if <code>bytes</code> is <code>null</code>.
210: * @throws IndexOutOfBoundsException
211: * if <code>offset + length > bytes.length</code>.
212: */
213: public native void getByteArray(long address, byte[] bytes,
214: int offset, int length) throws NullPointerException,
215: IndexOutOfBoundsException;
216:
217: /**
218: * Copies <code>length</code> bytes from the byte array <code>bytes</code>
219: * into the memory block at <code>address</code>, starting at element
220: * <code>offset</code> within the byte array.
221: * <p>
222: * The behavior of this method is undefined if the range
223: * <code>(address ... address + length)</code> is not within a memory
224: * block that was allocated using {@link #malloc(long) malloc(long)}.
225: * </p>
226: *
227: * @param address
228: * the address of the OS memory block into which to copy the
229: * bytes.
230: * @param bytes
231: * the byte array from which to copy the bytes.
232: * @param offset
233: * the index of the first element in <code>bytes</code> that
234: * will be read.
235: * @param length
236: * the total number of bytes to copy from <code>bytes</code>
237: * into the memory block.
238: * @throws NullPointerException
239: * if <code>bytes</code> is <code>null</code>.
240: * @throws IndexOutOfBoundsException
241: * if <code>offset + length > bytes.length</code>.
242: */
243: public native void setByteArray(long address, byte[] bytes,
244: int offset, int length) throws NullPointerException,
245: IndexOutOfBoundsException;
246:
247: // Primitive get & set methods
248:
249: /**
250: * Gets the value of the single byte at the given address.
251: * <p>
252: * The behavior is unspecified if <code>address</code> is not in the range
253: * that was previously allocated using <code>malloc()</code>.
254: * </p>
255: *
256: * @param address
257: * the platform address of the byte.
258: * @return the byte value.
259: */
260: public native byte getByte(long address);
261:
262: /**
263: * Sets the given single byte value at the given address.
264: * <p>
265: * The behavior is unspecified if <code>address</code> is not in the range
266: * that was previously allocated using <code>malloc()</code>.
267: * </p>
268: *
269: * @param address
270: * the address at which to set the byte value.
271: * @param value
272: * the value to set.
273: */
274: public native void setByte(long address, byte value);
275:
276: /**
277: * Gets the value of the signed two-byte integer stored in platform byte
278: * order at the given address.
279: * <p>
280: * The behavior is unspecified if <code>(address ... address + 2)</code>
281: * is not wholly within the range that was previously allocated using
282: * <code>malloc()</code>.
283: * </p>
284: *
285: * @param address
286: * the platform address of the start of the two-byte value.
287: * @return the value of the two-byte integer as a Java <code>short</code>.
288: */
289: public native short getShort(long address);
290:
291: public short getShort(long address, Endianness endianness) {
292: return (endianness == NATIVE_ORDER) ? getShort(address)
293: : swap(getShort(address));
294: }
295:
296: /**
297: * Sets the value of the signed two-byte integer at the given address in
298: * platform byte order.
299: * <p>
300: * The behavior is unspecified if <code>(address ... address + 2)</code>
301: * is not wholly within the range that was previously allocated using
302: * <code>malloc()</code>.
303: * </p>
304: *
305: * @param address
306: * the platform address of the start of the two-byte value.
307: * @param value
308: * the value of the two-byte integer as a Java <code>short</code>.
309: */
310: public native void setShort(long address, short value);
311:
312: public void setShort(long address, short value,
313: Endianness endianness) {
314: if (endianness == NATIVE_ORDER) {
315: setShort(address, value);
316: } else {
317: setShort(address, swap(value));
318: }
319: }
320:
321: /**
322: * Gets the value of the signed four-byte integer stored in platform
323: * byte-order at the given address.
324: * <p>
325: * The behavior is unspecified if <code>(address ... address + 4)</code>
326: * is not wholly within the range that was previously allocated using
327: * <code>malloc()</code>.
328: * </p>
329: *
330: * @param address
331: * the platform address of the start of the four-byte value.
332: * @return the value of the four-byte integer as a Java <code>int</code>.
333: */
334: public native int getInt(long address);
335:
336: public int getInt(long address, Endianness endianness) {
337: return (endianness == NATIVE_ORDER) ? getInt(address)
338: : swap(getInt(address));
339: }
340:
341: /**
342: * Sets the value of the signed four-byte integer at the given address in
343: * platform byte order.
344: * <p>
345: * The behavior is unspecified if <code>(address ... address + 4)</code>
346: * is not wholly within the range that was previously allocated using
347: * <code>malloc()</code>.
348: * </p>
349: *
350: * @param address
351: * the platform address of the start of the four-byte value.
352: * @param value
353: * the value of the four-byte integer as a Java <code>int</code>.
354: */
355: public native void setInt(long address, int value);
356:
357: public void setInt(long address, int value, Endianness endianness) {
358: if (endianness == NATIVE_ORDER) {
359: setInt(address, value);
360: } else {
361: setInt(address, swap(value));
362: }
363: }
364:
365: /**
366: * Gets the value of the signed eight-byte integer stored in platform byte
367: * order at the given address.
368: * <p>
369: * The behavior is unspecified if <code>(address ... address + 8)</code>
370: * is not wholly within the range that was previously allocated using
371: * <code>malloc()</code>.
372: * </p>
373: *
374: * @param address
375: * the platform address of the start of the eight-byte value.
376: * @return the value of the eight-byte integer as a Java <code>long</code>.
377: */
378: public native long getLong(long address);
379:
380: public long getLong(long address, Endianness endianness) {
381: return (endianness == NATIVE_ORDER) ? getLong(address)
382: : swap(getLong(address));
383: }
384:
385: /**
386: * Sets the value of the signed eight-byte integer at the given address in
387: * the platform byte order.
388: * <p>
389: * The behavior is unspecified if <code>(address ... address + 8)</code>
390: * is not wholly within the range that was previously allocated using
391: * <code>malloc()</code>.
392: * </p>
393: *
394: * @param address
395: * the platform address of the start of the eight-byte value.
396: * @param value
397: * the value of the eight-byte integer as a Java
398: * <code>long</code>.
399: */
400: public native void setLong(long address, long value);
401:
402: public void setLong(long address, long value, Endianness endianness) {
403: if (endianness == NATIVE_ORDER) {
404: setLong(address, value);
405: } else {
406: setLong(address, swap(value));
407: }
408: }
409:
410: /**
411: * Gets the value of the IEEE754-format four-byte float stored in platform
412: * byte order at the given address.
413: * <p>
414: * The behavior is unspecified if <code>(address ... address + 4)</code>
415: * is not wholly within the range that was previously allocated using
416: * <code>malloc()</code>.
417: * </p>
418: *
419: * @param address
420: * the platform address of the start of the eight-byte value.
421: * @return the value of the four-byte float as a Java <code>float</code>.
422: */
423: public native float getFloat(long address);
424:
425: public float getFloat(long address, Endianness endianness) {
426: if (endianness == NATIVE_ORDER) {
427: return getFloat(address);
428: }
429: int floatBits = swap(getInt(address));
430: return Float.intBitsToFloat(floatBits);
431: }
432:
433: /**
434: * Sets the value of the IEEE754-format four-byte float stored in platform
435: * byte order at the given address.
436: * <p>
437: * The behavior is unspecified if <code>(address ... address + 4)</code>
438: * is not wholly within the range that was previously allocated using
439: * <code>malloc()</code>.
440: * </p>
441: *
442: * @param address
443: * the platform address of the start of the eight-byte value.
444: * @param value
445: * the value of the four-byte float as a Java <code>float</code>.
446: */
447: public native void setFloat(long address, float value);
448:
449: public void setFloat(long address, float value,
450: Endianness endianness) {
451: if (endianness == NATIVE_ORDER) {
452: setFloat(address, value);
453: } else {
454: int floatBits = Float.floatToIntBits(value);
455: setInt(address, swap(floatBits));
456: }
457: }
458:
459: /**
460: * Gets the value of the IEEE754-format eight-byte float stored in platform
461: * byte order at the given address.
462: * <p>
463: * The behavior is unspecified if <code>(address ... address + 8)</code>
464: * is not wholly within the range that was previously allocated using
465: * <code>malloc()</code>.
466: * </p>
467: *
468: * @param address
469: * the platform address of the start of the eight-byte value.
470: * @return the value of the eight-byte float as a Java <code>double</code>.
471: */
472: public native double getDouble(long address);
473:
474: public double getDouble(long address, Endianness endianness) {
475: if (endianness == NATIVE_ORDER) {
476: return getDouble(address);
477: }
478: long doubleBits = swap(getLong(address));
479: return Double.longBitsToDouble(doubleBits);
480: }
481:
482: /**
483: * Sets the value of the IEEE754-format eight-byte float store in platform
484: * byte order at the given address.
485: * <p>
486: * The behavior is unspecified if <code>(address ... address + 8)</code>
487: * is not wholly within the range that was previously allocated using
488: * <code>malloc()</code>.
489: * </p>
490: *
491: * @param address
492: * the platform address of the start of the eight-byte value.
493: * @param value
494: * the value of the eight-byte float as a Java
495: * <code>double</code>.
496: */
497: public native void setDouble(long address, double value);
498:
499: public void setDouble(long address, double value,
500: Endianness endianness) {
501: if (endianness == NATIVE_ORDER) {
502: setDouble(address, value);
503: } else {
504: long doubleBits = Double.doubleToLongBits(value);
505: setLong(address, swap(doubleBits));
506: }
507: }
508:
509: /**
510: * Gets the value of the platform pointer at the given address.
511: * <p>
512: * The length of the platform pointer is defined by
513: * <code>POINTER_SIZE</code>.
514: * </p>
515: * The behavior is unspecified if
516: * <code>(address ... address + POINTER_SIZE)</code> is not wholly within
517: * the range that was previously allocated using <code>malloc()</code>.
518: * </p>
519: *
520: * @param address
521: * the platform address of the start of the platform pointer.
522: * @return the value of the platform pointer as a Java <code>long</code>.
523: */
524: public native long getAddress(long address);
525:
526: /**
527: * Sets the value of the platform pointer at the given address.
528: * <p>
529: * The length of the platform pointer is defined by
530: * <code>POINTER_SIZE</code>. This method only sets
531: * <code>POINTER_SIZE</code> bytes at the given address.
532: * </p>
533: * The behavior is unspecified if
534: * <code>(address ... address + POINTER_SIZE)</code> is not wholly within
535: * the range that was previously allocated using <code>malloc()</code>.
536: * </p>
537: *
538: * @param address
539: * the platform address of the start of the platform pointer.
540: * @param value
541: * the value of the platform pointer as a Java <code>long</code>.
542: */
543: public native void setAddress(long address, long value);
544:
545: /*
546: * Memory mapped file
547: */
548: private native long mmapImpl(long fileDescriptor, long alignment,
549: long size, int mapMode);
550:
551: public long mmap(long fileDescriptor, long alignment, long size,
552: int mapMode) throws IOException {
553: long address = mmapImpl(fileDescriptor, alignment, size,
554: mapMode);
555: if (address == -1) {
556: throw new IOException();
557: }
558: return address;
559: }
560:
561: private native void unmapImpl(long addr, long size);
562:
563: public void unmap(long addr, long size) {
564: unmapImpl(addr, size);
565: }
566:
567: public void load(long addr, long size) {
568: loadImpl(addr, size);
569: }
570:
571: private native int loadImpl(long l, long size);
572:
573: public boolean isLoaded(long addr, long size) {
574: return size == 0 ? true : isLoadedImpl(addr, size);
575: }
576:
577: private native boolean isLoadedImpl(long l, long size);
578:
579: public void flush(long addr, long size) {
580: flushImpl(addr, size);
581: }
582:
583: private native int flushImpl(long l, long size);
584:
585: /*
586: * Helper methods to change byte order.
587: */
588: private short swap(short value) {
589: int topEnd = value << 8;
590: int btmEnd = (value >> 8) & 0xFF;
591: return (short) (topEnd | btmEnd);
592: }
593:
594: private int swap(int value) {
595: short left = (short) (value >> 16);
596: short right = (short) value;
597: int topEnd = swap(right) << 16;
598: int btmEnd = swap(left) & 0xFFFF;
599: return topEnd | btmEnd;
600: }
601:
602: private long swap(long value) {
603: int left = (int) (value >> 32);
604: int right = (int) value;
605: long topEnd = ((long) swap(right)) << 32;
606: long btmEnd = swap(left) & 0xFFFFFFFFL;
607: return topEnd | btmEnd;
608: }
609: }
|