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