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 */
dvmU4ToFloat(u4 val)45 INLINE float dvmU4ToFloat(u4 val) {
46 union { u4 in; float out; } conv;
47 conv.in = val;
48 return conv.out;
49 }
dvmFloatToU4(float val)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 */
dvmPrintHexDump(const void * vaddr,size_t length)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 */
dvmPrintHexDumpDbg(const void * vaddr,size_t length,const char * tag)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 */
dvmGetRelativeTimeUsec(void)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 */
dvmGetRelativeTimeMsec(void)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 */
dvmGetThreadCpuTimeUsec(void)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);
dvmGetOtherThreadCpuTimeUsec(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