| /* |
| * Copyright (C) 2008 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| /* |
| * Miscellaneous utility functions. |
| */ |
| #ifndef _DALVIK_MISC |
| #define _DALVIK_MISC |
| |
| #include "Inlines.h" |
| |
| #include <stdio.h> |
| #include <sys/types.h> |
| #include <sys/time.h> |
| |
| /* |
| * Used to shut up the compiler when a parameter isn't used. |
| */ |
| #define UNUSED_PARAMETER(p) (void)(p) |
| |
| /* |
| * Floating point conversion functions. These are necessary to avoid |
| * strict-aliasing problems ("dereferencing type-punned pointer will break |
| * strict-aliasing rules"). According to the gcc info page, this usage |
| * is allowed, even with "-fstrict-aliasing". |
| * |
| * The code generated by gcc-4.1.1 appears to be much better than a |
| * type cast dereference ("int foo = *(int*)&myfloat") when the conversion |
| * function is inlined. It also allows us to take advantage of the |
| * optimizations that strict aliasing rules allow. |
| */ |
| INLINE float dvmU4ToFloat(u4 val) { |
| union { u4 in; float out; } conv; |
| conv.in = val; |
| return conv.out; |
| } |
| INLINE u4 dvmFloatToU4(float val) { |
| union { float in; u4 out; } conv; |
| conv.in = val; |
| return conv.out; |
| } |
| |
| /* |
| * Print a hex dump to the log file. |
| * |
| * "local" mode prints a hex dump starting from offset 0 (roughly equivalent |
| * to "xxd -g1"). |
| * |
| * "mem" mode shows the actual memory address, and will offset the start |
| * so that the low nibble of the address is always zero. |
| * |
| * If "tag" is NULL the default tag ("dalvikvm") will be used. |
| */ |
| typedef enum { kHexDumpLocal, kHexDumpMem } HexDumpMode; |
| void dvmPrintHexDumpEx(int priority, const char* tag, const void* vaddr, |
| size_t length, HexDumpMode mode); |
| |
| /* |
| * Print a hex dump, at INFO level. |
| */ |
| INLINE void dvmPrintHexDump(const void* vaddr, size_t length) { |
| dvmPrintHexDumpEx(ANDROID_LOG_INFO, LOG_TAG, |
| vaddr, length, kHexDumpLocal); |
| } |
| |
| /* |
| * Print a hex dump at VERBOSE level. This does nothing in non-debug builds. |
| */ |
| INLINE void dvmPrintHexDumpDbg(const void* vaddr, size_t length,const char* tag) |
| { |
| #if !LOG_NDEBUG |
| dvmPrintHexDumpEx(ANDROID_LOG_VERBOSE, (tag != NULL) ? tag : LOG_TAG, |
| vaddr, length, kHexDumpLocal); |
| #endif |
| } |
| |
| /* |
| * We pass one of these around when we want code to be able to write debug |
| * info to either the log or to a file (or stdout/stderr). |
| */ |
| typedef struct DebugOutputTarget { |
| /* where to? */ |
| enum { |
| kDebugTargetUnknown = 0, |
| kDebugTargetLog, |
| kDebugTargetFile, |
| } which; |
| |
| /* additional bits */ |
| union { |
| struct { |
| int priority; |
| const char* tag; |
| } log; |
| struct { |
| FILE* fp; |
| } file; |
| } data; |
| } DebugOutputTarget; |
| |
| /* |
| * Fill in a DebugOutputTarget struct. |
| */ |
| void dvmCreateLogOutputTarget(DebugOutputTarget* target, int priority, |
| const char* tag); |
| void dvmCreateFileOutputTarget(DebugOutputTarget* target, FILE* fp); |
| |
| /* |
| * Print a debug message. |
| */ |
| void dvmPrintDebugMessage(const DebugOutputTarget* target, const char* format, |
| ...) |
| #if defined(__GNUC__) |
| __attribute__ ((format(printf, 2, 3))) |
| #endif |
| ; |
| |
| |
| /* |
| * Expanding bitmap, used for tracking resources. Bits are numbered starting |
| * from zero. |
| * |
| * All operations on a BitVector are unsynchronized. |
| */ |
| typedef struct BitVector { |
| bool expandable; /* expand bitmap if we run out? */ |
| int storageSize; /* current size, in 32-bit words */ |
| u4* storage; |
| } BitVector; |
| |
| /* allocate a bit vector with enough space to hold "startBits" bits */ |
| BitVector* dvmAllocBitVector(int startBits, bool expandable); |
| void dvmFreeBitVector(BitVector* pBits); |
| |
| /* |
| * dvmAllocBit always allocates the first possible bit. If we run out of |
| * space in the bitmap, and it's not marked expandable, dvmAllocBit |
| * returns -1. |
| * |
| * dvmSetBit sets the specified bit, expanding the vector if necessary |
| * (and possible). |
| * |
| * dvmIsBitSet returns "true" if the bit is set. |
| */ |
| int dvmAllocBit(BitVector* pBits); |
| bool dvmSetBit(BitVector* pBits, int num); |
| void dvmClearBit(BitVector* pBits, int num); |
| void dvmClearAllBits(BitVector* pBits); |
| bool dvmIsBitSet(const BitVector* pBits, int num); |
| |
| /* count the number of bits that have been set */ |
| int dvmCountSetBits(const BitVector* pBits); |
| |
| /* copy one vector to the other compatible one */ |
| bool dvmCopyBitVector(BitVector *dest, const BitVector *src); |
| |
| /* |
| * Intersect two bit vectores and merge the result on top of the pre-existing |
| * value in the dest vector. |
| */ |
| bool dvmIntersectBitVectors(BitVector *dest, const BitVector *src1, |
| const BitVector *src2); |
| |
| #define kBitVectorGrowth 4 /* increase by 4 u4s when limit hit */ |
| |
| |
| /* |
| * Return a newly-allocated string in which all occurrences of '.' have |
| * been changed to '/'. If we find a '/' in the original string, NULL |
| * is returned to avoid ambiguity. |
| */ |
| char* dvmDotToSlash(const char* str); |
| |
| /* |
| * Return a newly-allocated string for the "dot version" of the class |
| * name for the given type descriptor. That is, The initial "L" and |
| * final ";" (if any) have been removed and all occurrences of '/' |
| * have been changed to '.'. |
| */ |
| char* dvmDescriptorToDot(const char* str); |
| |
| /* |
| * Return a newly-allocated string for the type descriptor |
| * corresponding to the "dot version" of the given class name. That |
| * is, non-array names are surrounde by "L" and ";", and all |
| * occurrences of '.' have been changed to '/'. |
| */ |
| char* dvmDotToDescriptor(const char* str); |
| |
| /* |
| * Return a newly-allocated string for the internal-form class name for |
| * the given type descriptor. That is, the initial "L" and final ";" (if |
| * any) have been removed. |
| */ |
| char* dvmDescriptorToName(const char* str); |
| |
| /* |
| * Return a newly-allocated string for the type descriptor for the given |
| * internal-form class name. That is, a non-array class name will get |
| * surrounded by "L" and ";", while array names are left as-is. |
| */ |
| char* dvmNameToDescriptor(const char* str); |
| |
| /* |
| * Get the current time, in nanoseconds. This is "relative" time, meaning |
| * it could be wall-clock time or a monotonic counter, and is only suitable |
| * for computing time deltas. |
| */ |
| u8 dvmGetRelativeTimeNsec(void); |
| |
| /* |
| * Get the current time, in microseconds. This is "relative" time, meaning |
| * it could be wall-clock time or a monotonic counter, and is only suitable |
| * for computing time deltas. |
| */ |
| INLINE u8 dvmGetRelativeTimeUsec(void) { |
| return dvmGetRelativeTimeNsec() / 1000; |
| } |
| |
| /* |
| * Get the current per-thread CPU time. This clock increases monotonically |
| * when the thread is running, but not when it's sleeping or blocked on a |
| * synchronization object. |
| * |
| * The absolute value of the clock may not be useful, so this should only |
| * be used for time deltas. |
| * |
| * If the thread CPU clock is not available, this always returns (u8)-1. |
| */ |
| u8 dvmGetThreadCpuTimeNsec(void); |
| |
| /* |
| * Per-thread CPU time, in micros. |
| */ |
| INLINE u8 dvmGetThreadCpuTimeUsec(void) { |
| return dvmGetThreadCpuTimeNsec() / 1000; |
| } |
| |
| /* |
| * Like dvmGetThreadCpuTimeNsec, but for a different thread. |
| */ |
| u8 dvmGetOtherThreadCpuTimeNsec(pthread_t thread); |
| INLINE u8 dvmGetOtherThreadCpuTimeUsec(pthread_t thread) { |
| return dvmGetOtherThreadCpuTimeNsec(thread) / 1000; |
| } |
| |
| /* |
| * Sleep for increasingly longer periods, until "maxTotalSleep" microseconds |
| * have elapsed. Pass in the start time, which must be a value returned by |
| * dvmGetRelativeTimeUsec(). |
| * |
| * Returns "false" if we were unable to sleep because our time is up. |
| */ |
| bool dvmIterativeSleep(int iteration, int maxTotalSleep, u8 relStartTime); |
| |
| /* |
| * Set the "close on exec" flag on a file descriptor. |
| */ |
| bool dvmSetCloseOnExec(int fd); |
| |
| /* |
| * Unconditionally abort the entire VM. Try not to use this. |
| */ |
| void dvmAbort(void) |
| #if defined(__GNUC__) |
| __attribute__ ((noreturn)) |
| #endif |
| ; |
| |
| #if (!HAVE_STRLCPY) |
| /* Implementation of strlcpy() for platforms that don't already have it. */ |
| size_t strlcpy(char *dst, const char *src, size_t size); |
| #endif |
| |
| #endif /*_DALVIK_MISC*/ |