blob: bd6fece98249e29d23a892d8e60e9ea7819d9ca3 [file] [log] [blame]
The Android Open Source Projectf6c38712009-03-03 19:28:47 -08001/*
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 */
The Android Open Source Project99409882009-03-18 22:20:24 -070016
The Android Open Source Projectf6c38712009-03-03 19:28:47 -080017/*
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#if 0
56INLINE float dvmU8ToFloat(u8 val) {
57 union { u8 in; float out; } conv;
58 conv.in = val;
59 return conv.out;
60}
61INLINE u8 dvmFloatToU8(float val) {
62 union { float in; u8 out; } conv;
63 conv.in = val;
64 return conv.out;
65}
66INLINE double dvmU8ToDouble(u8 val) {
67 union { u8 in; double out; } conv;
68 conv.in = val;
69 return conv.out;
70}
71INLINE u8 dvmDoubleToU8(double val) {
72 union { double in; u8 out; } conv;
73 conv.in = val;
74 return conv.out;
75}
76#endif
77
78/*
79 * Print a hex dump to the log file.
80 *
81 * "local" mode prints a hex dump starting from offset 0 (roughly equivalent
82 * to "xxd -g1").
83 *
84 * "mem" mode shows the actual memory address, and will offset the start
85 * so that the low nibble of the address is always zero.
86 *
87 * If "tag" is NULL the default tag ("dalvikvm") will be used.
88 */
89typedef enum { kHexDumpLocal, kHexDumpMem } HexDumpMode;
90void dvmPrintHexDumpEx(int priority, const char* tag, const void* vaddr,
91 size_t length, HexDumpMode mode);
92
93/*
94 * Print a hex dump, at INFO level.
95 */
96INLINE void dvmPrintHexDump(const void* vaddr, size_t length) {
97 dvmPrintHexDumpEx(ANDROID_LOG_INFO, LOG_TAG,
98 vaddr, length, kHexDumpLocal);
99}
100
101/*
102 * Print a hex dump at VERBOSE level. This does nothing in non-debug builds.
103 */
104INLINE void dvmPrintHexDumpDbg(const void* vaddr, size_t length,const char* tag)
105{
106#if !LOG_NDEBUG
107 dvmPrintHexDumpEx(ANDROID_LOG_VERBOSE, (tag != NULL) ? tag : LOG_TAG,
108 vaddr, length, kHexDumpLocal);
109#endif
110}
111
112/*
113 * We pass one of these around when we want code to be able to write debug
114 * info to either the log or to a file (or stdout/stderr).
115 */
116typedef struct DebugOutputTarget {
117 /* where to? */
118 enum {
119 kDebugTargetUnknown = 0,
120 kDebugTargetLog,
121 kDebugTargetFile,
122 } which;
123
124 /* additional bits */
125 union {
126 struct {
127 int priority;
128 const char* tag;
129 } log;
130 struct {
131 FILE* fp;
132 } file;
133 } data;
134} DebugOutputTarget;
135
136/*
137 * Fill in a DebugOutputTarget struct.
138 */
139void dvmCreateLogOutputTarget(DebugOutputTarget* target, int priority,
140 const char* tag);
141void dvmCreateFileOutputTarget(DebugOutputTarget* target, FILE* fp);
142
143/*
144 * Print a debug message.
145 */
146void dvmPrintDebugMessage(const DebugOutputTarget* target, const char* format,
The Android Open Source Project99409882009-03-18 22:20:24 -0700147 ...)
148#if defined(__GNUC__)
149 __attribute__ ((format(printf, 2, 3)))
150#endif
151 ;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800152
153
154/*
155 * Expanding bitmap, used for tracking resources. Bits are numbered starting
156 * from zero.
157 *
158 * All operations on a BitVector are unsynchronized.
159 */
160typedef struct BitVector {
161 bool expandable; /* expand bitmap if we run out? */
162 int storageSize; /* current size, in 32-bit words */
163 u4* storage;
164} BitVector;
165
166/* allocate a bit vector with enough space to hold "startBits" bits */
167BitVector* dvmAllocBitVector(int startBits, bool expandable);
168void dvmFreeBitVector(BitVector* pBits);
169
170/*
171 * dvmAllocBit always allocates the first possible bit. If we run out of
172 * space in the bitmap, and it's not marked expandable, dvmAllocBit
173 * returns -1.
174 *
175 * dvmSetBit sets the specified bit, expanding the vector if necessary
176 * (and possible).
177 *
178 * dvmIsBitSet returns "true" if the bit is set.
179 */
180int dvmAllocBit(BitVector* pBits);
181bool dvmSetBit(BitVector* pBits, int num);
182void dvmClearBit(BitVector* pBits, int num);
183bool dvmIsBitSet(const BitVector* pBits, int num);
184
185/* count the number of bits that have been set */
186int dvmCountSetBits(const BitVector* pBits);
187
188#define kBitVectorGrowth 4 /* increase by 4 u4s when limit hit */
189
190
191/*
192 * Return a newly-allocated string in which all occurrences of '.' have
193 * been changed to '/'. If we find a '/' in the original string, NULL
194 * is returned to avoid ambiguity.
195 */
196char* dvmDotToSlash(const char* str);
197
198/*
199 * Return a newly-allocated string for the "dot version" of the class
200 * name for the given type descriptor. That is, The initial "L" and
201 * final ";" (if any) have been removed and all occurrences of '/'
202 * have been changed to '.'.
203 */
204char* dvmDescriptorToDot(const char* str);
205
206/*
207 * Return a newly-allocated string for the type descriptor
208 * corresponding to the "dot version" of the given class name. That
209 * is, non-array names are surrounde by "L" and ";", and all
210 * occurrences of '.' have been changed to '/'.
211 */
212char* dvmDotToDescriptor(const char* str);
213
214/*
215 * Return a newly-allocated string for the internal-form class name for
216 * the given type descriptor. That is, the initial "L" and final ";" (if
217 * any) have been removed.
218 */
219char* dvmDescriptorToName(const char* str);
220
221/*
222 * Return a newly-allocated string for the type descriptor for the given
223 * internal-form class name. That is, a non-array class name will get
224 * surrounded by "L" and ";", while array names are left as-is.
225 */
226char* dvmNameToDescriptor(const char* str);
227
228/*
229 * Get the current time, in nanoseconds. This is "relative" time, meaning
230 * it could be wall-clock time or a monotonic counter, and is only suitable
231 * for computing time deltas.
232 */
233u8 dvmGetRelativeTimeNsec(void);
234
235/*
236 * Get the current time, in microseconds. This is "relative" time, meaning
237 * it could be wall-clock time or a monotonic counter, and is only suitable
238 * for computing time deltas.
239 */
240INLINE u8 dvmGetRelativeTimeUsec(void) {
241 return dvmGetRelativeTimeNsec() / 1000;
242}
243
244/*
245 * Get the current per-thread CPU time. This clock increases monotonically
246 * when the thread is running, but not when it's sleeping or blocked on a
247 * synchronization object.
248 *
249 * The absolute value of the clock may not be useful, so this should only
250 * be used for time deltas.
251 *
252 * If the thread CPU clock is not available, this always returns (u8)-1.
253 */
254u8 dvmGetThreadCpuTimeNsec(void);
255
256/*
257 * Per-thread CPU time, in micros.
258 */
259INLINE u8 dvmGetThreadCpuTimeUsec(void) {
260 return dvmGetThreadCpuTimeNsec() / 1000;
261}
262
263/*
264 * Like dvmGetThreadCpuTimeNsec, but for a different thread.
265 */
266u8 dvmGetOtherThreadCpuTimeNsec(pthread_t thread);
267INLINE u8 dvmGetOtherThreadCpuTimeUsec(pthread_t thread) {
268 return dvmGetOtherThreadCpuTimeNsec(thread) / 1000;
269}
270
271/*
272 * Sleep for increasingly longer periods, until "maxTotalSleep" microseconds
273 * have elapsed. Pass in the start time, which must be a value returned by
274 * dvmGetRelativeTimeUsec().
275 *
276 * Returns "false" if we were unable to sleep because our time is up.
277 */
278bool dvmIterativeSleep(int iteration, int maxTotalSleep, u8 relStartTime);
279
280/*
281 * Set the "close on exec" flag on a file descriptor.
282 */
283bool dvmSetCloseOnExec(int fd);
284
The Android Open Source Project99409882009-03-18 22:20:24 -0700285/*
286 * Unconditionally abort the entire VM. Try not to use this.
287 */
288void dvmAbort(void)
289#if defined(__GNUC__)
290 __attribute__ ((noreturn))
291#endif
292 ;
293
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800294#if (!HAVE_STRLCPY)
295/* Implementation of strlcpy() for platforms that don't already have it. */
296size_t strlcpy(char *dst, const char *src, size_t size);
297#endif
298
299#endif /*_DALVIK_MISC*/