Home | History | Annotate | Download | only in vm
      1 /*
      2  * Copyright (C) 2008 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 /*
     18  * Miscellaneous utility functions.
     19  */
     20 #ifndef _DALVIK_MISC
     21 #define _DALVIK_MISC
     22 
     23 #include "Inlines.h"
     24 
     25 #include <stdio.h>
     26 #include <sys/types.h>
     27 #include <sys/time.h>
     28 
     29 /*
     30  * Used to shut up the compiler when a parameter isn't used.
     31  */
     32 #define UNUSED_PARAMETER(p)     (void)(p)
     33 
     34 /*
     35  * Floating point conversion functions.  These are necessary to avoid
     36  * strict-aliasing problems ("dereferencing type-punned pointer will break
     37  * strict-aliasing rules").  According to the gcc info page, this usage
     38  * is allowed, even with "-fstrict-aliasing".
     39  *
     40  * The code generated by gcc-4.1.1 appears to be much better than a
     41  * type cast dereference ("int foo = *(int*)&myfloat") when the conversion
     42  * function is inlined.  It also allows us to take advantage of the
     43  * optimizations that strict aliasing rules allow.
     44  */
     45 INLINE float dvmU4ToFloat(u4 val) {
     46     union { u4 in; float out; } conv;
     47     conv.in = val;
     48     return conv.out;
     49 }
     50 INLINE u4 dvmFloatToU4(float val) {
     51     union { float in; u4 out; } conv;
     52     conv.in = val;
     53     return conv.out;
     54 }
     55 
     56 /*
     57  * Print a hex dump to the log file.
     58  *
     59  * "local" mode prints a hex dump starting from offset 0 (roughly equivalent
     60  * to "xxd -g1").
     61  *
     62  * "mem" mode shows the actual memory address, and will offset the start
     63  * so that the low nibble of the address is always zero.
     64  *
     65  * If "tag" is NULL the default tag ("dalvikvm") will be used.
     66  */
     67 typedef enum { kHexDumpLocal, kHexDumpMem } HexDumpMode;
     68 void dvmPrintHexDumpEx(int priority, const char* tag, const void* vaddr,
     69     size_t length, HexDumpMode mode);
     70 
     71 /*
     72  * Print a hex dump, at INFO level.
     73  */
     74 INLINE void dvmPrintHexDump(const void* vaddr, size_t length) {
     75     dvmPrintHexDumpEx(ANDROID_LOG_INFO, LOG_TAG,
     76         vaddr, length, kHexDumpLocal);
     77 }
     78 
     79 /*
     80  * Print a hex dump at VERBOSE level. This does nothing in non-debug builds.
     81  */
     82 INLINE void dvmPrintHexDumpDbg(const void* vaddr, size_t length,const char* tag)
     83 {
     84 #if !LOG_NDEBUG
     85     dvmPrintHexDumpEx(ANDROID_LOG_VERBOSE, (tag != NULL) ? tag : LOG_TAG,
     86         vaddr, length, kHexDumpLocal);
     87 #endif
     88 }
     89 
     90 /*
     91  * We pass one of these around when we want code to be able to write debug
     92  * info to either the log or to a file (or stdout/stderr).
     93  */
     94 typedef struct DebugOutputTarget {
     95     /* where to? */
     96     enum {
     97         kDebugTargetUnknown = 0,
     98         kDebugTargetLog,
     99         kDebugTargetFile,
    100     } which;
    101 
    102     /* additional bits */
    103     union {
    104         struct {
    105             int priority;
    106             const char* tag;
    107         } log;
    108         struct {
    109             FILE* fp;
    110         } file;
    111     } data;
    112 } DebugOutputTarget;
    113 
    114 /*
    115  * Fill in a DebugOutputTarget struct.
    116  */
    117 void dvmCreateLogOutputTarget(DebugOutputTarget* target, int priority,
    118     const char* tag);
    119 void dvmCreateFileOutputTarget(DebugOutputTarget* target, FILE* fp);
    120 
    121 /*
    122  * Print a debug message.
    123  */
    124 void dvmPrintDebugMessage(const DebugOutputTarget* target, const char* format,
    125     ...)
    126 #if defined(__GNUC__)
    127     __attribute__ ((format(printf, 2, 3)))
    128 #endif
    129     ;
    130 
    131 
    132 /*
    133  * Expanding bitmap, used for tracking resources.  Bits are numbered starting
    134  * from zero.
    135  *
    136  * All operations on a BitVector are unsynchronized.
    137  */
    138 typedef struct BitVector {
    139     bool    expandable;     /* expand bitmap if we run out? */
    140     int     storageSize;    /* current size, in 32-bit words */
    141     u4*     storage;
    142 } BitVector;
    143 
    144 /* allocate a bit vector with enough space to hold "startBits" bits */
    145 BitVector* dvmAllocBitVector(int startBits, bool expandable);
    146 void dvmFreeBitVector(BitVector* pBits);
    147 
    148 /*
    149  * dvmAllocBit always allocates the first possible bit.  If we run out of
    150  * space in the bitmap, and it's not marked expandable, dvmAllocBit
    151  * returns -1.
    152  *
    153  * dvmSetBit sets the specified bit, expanding the vector if necessary
    154  * (and possible).
    155  *
    156  * dvmIsBitSet returns "true" if the bit is set.
    157  */
    158 int dvmAllocBit(BitVector* pBits);
    159 bool dvmSetBit(BitVector* pBits, int num);
    160 void dvmClearBit(BitVector* pBits, int num);
    161 void dvmClearAllBits(BitVector* pBits);
    162 bool dvmIsBitSet(const BitVector* pBits, int num);
    163 
    164 /* count the number of bits that have been set */
    165 int dvmCountSetBits(const BitVector* pBits);
    166 
    167 /* copy one vector to the other compatible one */
    168 bool dvmCopyBitVector(BitVector *dest, const BitVector *src);
    169 
    170 /*
    171  * Intersect two bit vectores and merge the result on top of the pre-existing
    172  * value in the dest vector.
    173  */
    174 bool dvmIntersectBitVectors(BitVector *dest, const BitVector *src1,
    175                             const BitVector *src2);
    176 
    177 #define kBitVectorGrowth    4   /* increase by 4 u4s when limit hit */
    178 
    179 
    180 /*
    181  * Return a newly-allocated string in which all occurrences of '.' have
    182  * been changed to '/'.  If we find a '/' in the original string, NULL
    183  * is returned to avoid ambiguity.
    184  */
    185 char* dvmDotToSlash(const char* str);
    186 
    187 /*
    188  * Return a newly-allocated string for the "dot version" of the class
    189  * name for the given type descriptor. That is, The initial "L" and
    190  * final ";" (if any) have been removed and all occurrences of '/'
    191  * have been changed to '.'.
    192  */
    193 char* dvmDescriptorToDot(const char* str);
    194 
    195 /*
    196  * Return a newly-allocated string for the type descriptor
    197  * corresponding to the "dot version" of the given class name. That
    198  * is, non-array names are surrounde by "L" and ";", and all
    199  * occurrences of '.' have been changed to '/'.
    200  */
    201 char* dvmDotToDescriptor(const char* str);
    202 
    203 /*
    204  * Return a newly-allocated string for the internal-form class name for
    205  * the given type descriptor. That is, the initial "L" and final ";" (if
    206  * any) have been removed.
    207  */
    208 char* dvmDescriptorToName(const char* str);
    209 
    210 /*
    211  * Return a newly-allocated string for the type descriptor for the given
    212  * internal-form class name. That is, a non-array class name will get
    213  * surrounded by "L" and ";", while array names are left as-is.
    214  */
    215 char* dvmNameToDescriptor(const char* str);
    216 
    217 /*
    218  * Get the current time, in nanoseconds.  This is "relative" time, meaning
    219  * it could be wall-clock time or a monotonic counter, and is only suitable
    220  * for computing time deltas.
    221  */
    222 u8 dvmGetRelativeTimeNsec(void);
    223 
    224 /*
    225  * Get the current time, in microseconds.  This is "relative" time, meaning
    226  * it could be wall-clock time or a monotonic counter, and is only suitable
    227  * for computing time deltas.
    228  */
    229 INLINE u8 dvmGetRelativeTimeUsec(void) {
    230     return dvmGetRelativeTimeNsec() / 1000;
    231 }
    232 
    233 /*
    234  * Get the current time, in milliseconds.  This is "relative" time,
    235  * meaning it could be wall-clock time or a monotonic counter, and is
    236  * only suitable for computing time deltas.  The value returned from
    237  * this function is a u4 and should only be used for debugging
    238  * messages.  TODO: make this value relative to the start-up time of
    239  * the VM.
    240  */
    241 INLINE u4 dvmGetRelativeTimeMsec(void) {
    242     return (u4)(dvmGetRelativeTimeUsec() / 1000);
    243 }
    244 
    245 /*
    246  * Get the current per-thread CPU time.  This clock increases monotonically
    247  * when the thread is running, but not when it's sleeping or blocked on a
    248  * synchronization object.
    249  *
    250  * The absolute value of the clock may not be useful, so this should only
    251  * be used for time deltas.
    252  *
    253  * If the thread CPU clock is not available, this always returns (u8)-1.
    254  */
    255 u8 dvmGetThreadCpuTimeNsec(void);
    256 
    257 /*
    258  * Per-thread CPU time, in micros.
    259  */
    260 INLINE u8 dvmGetThreadCpuTimeUsec(void) {
    261     return dvmGetThreadCpuTimeNsec() / 1000;
    262 }
    263 
    264 /*
    265  * Like dvmGetThreadCpuTimeNsec, but for a different thread.
    266  */
    267 u8 dvmGetOtherThreadCpuTimeNsec(pthread_t thread);
    268 INLINE u8 dvmGetOtherThreadCpuTimeUsec(pthread_t thread) {
    269     return dvmGetOtherThreadCpuTimeNsec(thread) / 1000;
    270 }
    271 
    272 /*
    273  * Sleep for increasingly longer periods, until "maxTotalSleep" microseconds
    274  * have elapsed.  Pass in the start time, which must be a value returned by
    275  * dvmGetRelativeTimeUsec().
    276  *
    277  * Returns "false" if we were unable to sleep because our time is up.
    278  */
    279 bool dvmIterativeSleep(int iteration, int maxTotalSleep, u8 relStartTime);
    280 
    281 /*
    282  * Set the "close on exec" flag on a file descriptor.
    283  */
    284 bool dvmSetCloseOnExec(int fd);
    285 
    286 /*
    287  * Unconditionally abort the entire VM.  Try not to use this.
    288  *
    289  * NOTE: if this is marked ((noreturn)), gcc will merge multiple dvmAbort()
    290  * calls in a single function together.  This is good, in that it reduces
    291  * code size slightly, but also bad, because the native stack trace we
    292  * get from the abort may point at the wrong call site.  Best to leave
    293  * it undecorated.
    294  */
    295 void dvmAbort(void);
    296 
    297 #if (!HAVE_STRLCPY)
    298 /* Implementation of strlcpy() for platforms that don't already have it. */
    299 size_t strlcpy(char *dst, const char *src, size_t size);
    300 #endif
    301 
    302 /*
    303  *  Allocates a memory region using ashmem and mmap, initialized to
    304  *  zero.  Actual allocation rounded up to page multiple.  Returns
    305  *  NULL on failure.
    306  */
    307 void *dvmAllocRegion(size_t size, int prot, const char *name);
    308 
    309 /*
    310  * Returns the pointer to the "absolute path" part of the given path
    311  * string, treating first (if any) instance of "/./" as a sentinel
    312  * indicating the start of the absolute path. If the path isn't absolute
    313  * in the usual way (i.e., starts with "/") and doesn't have the sentinel,
    314  * then this returns NULL.
    315  *
    316  * For example:
    317  *     "/foo/bar/baz" returns "/foo/bar/baz"
    318  *     "foo/./bar/baz" returns "/bar/baz"
    319  *     "foo/bar/baz" returns NULL
    320  *
    321  * The sentinel is used specifically to aid in cross-optimization, where
    322  * a host is processing dex files in a build tree, and where we don't want
    323  * the build tree's directory structure to be baked into the output (such
    324  * as, for example, in the dependency paths of optimized dex files).
    325  */
    326 const char* dvmPathToAbsolutePortion(const char* path);
    327 
    328 #endif /*_DALVIK_MISC*/
    329