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 per-thread CPU time.  This clock increases monotonically
    235  * when the thread is running, but not when it's sleeping or blocked on a
    236  * synchronization object.
    237  *
    238  * The absolute value of the clock may not be useful, so this should only
    239  * be used for time deltas.
    240  *
    241  * If the thread CPU clock is not available, this always returns (u8)-1.
    242  */
    243 u8 dvmGetThreadCpuTimeNsec(void);
    244 
    245 /*
    246  * Per-thread CPU time, in micros.
    247  */
    248 INLINE u8 dvmGetThreadCpuTimeUsec(void) {
    249     return dvmGetThreadCpuTimeNsec() / 1000;
    250 }
    251 
    252 /*
    253  * Like dvmGetThreadCpuTimeNsec, but for a different thread.
    254  */
    255 u8 dvmGetOtherThreadCpuTimeNsec(pthread_t thread);
    256 INLINE u8 dvmGetOtherThreadCpuTimeUsec(pthread_t thread) {
    257     return dvmGetOtherThreadCpuTimeNsec(thread) / 1000;
    258 }
    259 
    260 /*
    261  * Sleep for increasingly longer periods, until "maxTotalSleep" microseconds
    262  * have elapsed.  Pass in the start time, which must be a value returned by
    263  * dvmGetRelativeTimeUsec().
    264  *
    265  * Returns "false" if we were unable to sleep because our time is up.
    266  */
    267 bool dvmIterativeSleep(int iteration, int maxTotalSleep, u8 relStartTime);
    268 
    269 /*
    270  * Set the "close on exec" flag on a file descriptor.
    271  */
    272 bool dvmSetCloseOnExec(int fd);
    273 
    274 /*
    275  * Unconditionally abort the entire VM.  Try not to use this.
    276  *
    277  * NOTE: if this is marked ((noreturn)), gcc will merge multiple dvmAbort()
    278  * calls in a single function together.  This is good, in that it reduces
    279  * code size slightly, but also bad, because the native stack trace we
    280  * get from the abort may point at the wrong call site.  Best to leave
    281  * it undecorated.
    282  */
    283 void dvmAbort(void);
    284 
    285 #if (!HAVE_STRLCPY)
    286 /* Implementation of strlcpy() for platforms that don't already have it. */
    287 size_t strlcpy(char *dst, const char *src, size_t size);
    288 #endif
    289 
    290 #endif /*_DALVIK_MISC*/
    291