Misc.h revision 5016966b91f1bc36b2bd52ec13ecfd8de1c68209
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 */ 45INLINE float dvmU4ToFloat(u4 val) { 46 union { u4 in; float out; } conv; 47 conv.in = val; 48 return conv.out; 49} 50INLINE 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 */ 67typedef enum { kHexDumpLocal, kHexDumpMem } HexDumpMode; 68void 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 */ 74INLINE 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 */ 82INLINE 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 */ 94typedef 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 */ 117void dvmCreateLogOutputTarget(DebugOutputTarget* target, int priority, 118 const char* tag); 119void dvmCreateFileOutputTarget(DebugOutputTarget* target, FILE* fp); 120 121/* 122 * Print a debug message. 123 */ 124void 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 */ 138typedef 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 */ 145BitVector* dvmAllocBitVector(int startBits, bool expandable); 146void 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 */ 158int dvmAllocBit(BitVector* pBits); 159bool dvmSetBit(BitVector* pBits, int num); 160void dvmClearBit(BitVector* pBits, int num); 161void dvmClearAllBits(BitVector* pBits); 162bool dvmIsBitSet(const BitVector* pBits, int num); 163 164/* count the number of bits that have been set */ 165int dvmCountSetBits(const BitVector* pBits); 166 167/* copy one vector to the other compatible one */ 168bool 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 */ 174bool 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 */ 185char* dvmDotToSlash(const char* str); 186 187/* 188 * Return a newly-allocated string containing a human-readable equivalent 189 * of 'descriptor'. So "I" would be "int", "[[I" would be "int[][]", 190 * "[Ljava/lang/String;" would be "java.lang.String[]", and so forth. 191 */ 192char* dvmHumanReadableDescriptor(const char* descriptor); 193 194/* 195 * Return a newly-allocated string for the "dot version" of the class 196 * name for the given type descriptor. That is, The initial "L" and 197 * final ";" (if any) have been removed and all occurrences of '/' 198 * have been changed to '.'. 199 * 200 * "Dot version" names are used in the class loading machinery. 201 * See also dvmHumanReadableDescriptor. 202 */ 203char* dvmDescriptorToDot(const char* str); 204 205/* 206 * Return a newly-allocated string for the type descriptor 207 * corresponding to the "dot version" of the given class name. That 208 * is, non-array names are surrounded by "L" and ";", and all 209 * occurrences of '.' have been changed to '/'. 210 * 211 * "Dot version" names are used in the class loading machinery. 212 */ 213char* dvmDotToDescriptor(const char* str); 214 215/* 216 * Return a newly-allocated string for the internal-form class name for 217 * the given type descriptor. That is, the initial "L" and final ";" (if 218 * any) have been removed. 219 */ 220char* dvmDescriptorToName(const char* str); 221 222/* 223 * Return a newly-allocated string for the type descriptor for the given 224 * internal-form class name. That is, a non-array class name will get 225 * surrounded by "L" and ";", while array names are left as-is. 226 */ 227char* dvmNameToDescriptor(const char* str); 228 229/* 230 * Get the current time, in nanoseconds. This is "relative" time, meaning 231 * it could be wall-clock time or a monotonic counter, and is only suitable 232 * for computing time deltas. 233 */ 234u8 dvmGetRelativeTimeNsec(void); 235 236/* 237 * Get the current time, in microseconds. This is "relative" time, meaning 238 * it could be wall-clock time or a monotonic counter, and is only suitable 239 * for computing time deltas. 240 */ 241INLINE u8 dvmGetRelativeTimeUsec(void) { 242 return dvmGetRelativeTimeNsec() / 1000; 243} 244 245/* 246 * Get the current time, in milliseconds. This is "relative" time, 247 * meaning it could be wall-clock time or a monotonic counter, and is 248 * only suitable for computing time deltas. The value returned from 249 * this function is a u4 and should only be used for debugging 250 * messages. TODO: make this value relative to the start-up time of 251 * the VM. 252 */ 253INLINE u4 dvmGetRelativeTimeMsec(void) { 254 return (u4)(dvmGetRelativeTimeUsec() / 1000); 255} 256 257/* 258 * Get the current per-thread CPU time. This clock increases monotonically 259 * when the thread is running, but not when it's sleeping or blocked on a 260 * synchronization object. 261 * 262 * The absolute value of the clock may not be useful, so this should only 263 * be used for time deltas. 264 * 265 * If the thread CPU clock is not available, this always returns (u8)-1. 266 */ 267u8 dvmGetThreadCpuTimeNsec(void); 268 269/* 270 * Per-thread CPU time, in micros. 271 */ 272INLINE u8 dvmGetThreadCpuTimeUsec(void) { 273 return dvmGetThreadCpuTimeNsec() / 1000; 274} 275 276/* 277 * Like dvmGetThreadCpuTimeNsec, but for a different thread. 278 */ 279u8 dvmGetOtherThreadCpuTimeNsec(pthread_t thread); 280INLINE u8 dvmGetOtherThreadCpuTimeUsec(pthread_t thread) { 281 return dvmGetOtherThreadCpuTimeNsec(thread) / 1000; 282} 283 284/* 285 * Sleep for increasingly longer periods, until "maxTotalSleep" microseconds 286 * have elapsed. Pass in the start time, which must be a value returned by 287 * dvmGetRelativeTimeUsec(). 288 * 289 * Returns "false" if we were unable to sleep because our time is up. 290 */ 291bool dvmIterativeSleep(int iteration, int maxTotalSleep, u8 relStartTime); 292 293/* 294 * Set the "close on exec" flag on a file descriptor. 295 */ 296bool dvmSetCloseOnExec(int fd); 297 298/* 299 * Unconditionally abort the entire VM. Try not to use this. 300 * 301 * NOTE: if this is marked ((noreturn)), gcc will merge multiple dvmAbort() 302 * calls in a single function together. This is good, in that it reduces 303 * code size slightly, but also bad, because the native stack trace we 304 * get from the abort may point at the wrong call site. Best to leave 305 * it undecorated. 306 */ 307void dvmAbort(void); 308 309#if (!HAVE_STRLCPY) 310/* Implementation of strlcpy() for platforms that don't already have it. */ 311size_t strlcpy(char *dst, const char *src, size_t size); 312#endif 313 314/* 315 * Allocates a memory region using ashmem and mmap, initialized to 316 * zero. Actual allocation rounded up to page multiple. Returns 317 * NULL on failure. 318 */ 319void *dvmAllocRegion(size_t size, int prot, const char *name); 320 321/* 322 * Get some per-thread stats from /proc/self/task/N/stat. 323 */ 324typedef struct { 325 unsigned long utime; /* number of jiffies scheduled in user mode */ 326 unsigned long stime; /* number of jiffies scheduled in kernel mode */ 327 int processor; /* number of CPU that last executed thread */ 328} ProcStatData; 329bool dvmGetThreadStats(ProcStatData* pData, pid_t tid); 330 331/* 332 * Returns the pointer to the "absolute path" part of the given path 333 * string, treating first (if any) instance of "/./" as a sentinel 334 * indicating the start of the absolute path. If the path isn't absolute 335 * in the usual way (i.e., starts with "/") and doesn't have the sentinel, 336 * then this returns NULL. 337 * 338 * For example: 339 * "/foo/bar/baz" returns "/foo/bar/baz" 340 * "foo/./bar/baz" returns "/bar/baz" 341 * "foo/bar/baz" returns NULL 342 * 343 * The sentinel is used specifically to aid in cross-optimization, where 344 * a host is processing dex files in a build tree, and where we don't want 345 * the build tree's directory structure to be baked into the output (such 346 * as, for example, in the dependency paths of optimized dex files). 347 */ 348const char* dvmPathToAbsolutePortion(const char* path); 349 350#endif /*_DALVIK_MISC*/ 351