blob: 61c13f0142727975a7fc0e83b871eec68f8985e1 [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 */
16/*
17 * Miscellaneous utility functions.
18 */
19#include "Dalvik.h"
20
21#include <stdlib.h>
22#include <stddef.h>
23#include <string.h>
24#include <ctype.h>
25#include <time.h>
26#include <sys/time.h>
27#include <fcntl.h>
28
29
30/*
31 * Print a hex dump in this format:
32 *
3301234567: 00 11 22 33 44 55 66 77 88 99 aa bb cc dd ee ff 0123456789abcdef\n
34 *
35 * If "mode" is kHexDumpLocal, we start at offset zero, and show a full
36 * 16 bytes on the first line. If it's kHexDumpMem, we make this look
37 * like a memory dump, using the actual address, outputting a partial line
38 * if "vaddr" isn't aligned on a 16-byte boundary.
39 *
40 * "priority" and "tag" determine the values passed to the log calls.
41 *
42 * Does not use printf() or other string-formatting calls.
43 */
44void dvmPrintHexDumpEx(int priority, const char* tag, const void* vaddr,
45 size_t length, HexDumpMode mode)
46{
47 static const char gHexDigit[] = "0123456789abcdef";
48 const unsigned char* addr = vaddr;
49 char out[77]; /* exact fit */
50 unsigned int offset; /* offset to show while printing */
51 char* hex;
52 char* asc;
53 int gap;
54 //int trickle = 0;
55
56 if (mode == kHexDumpLocal)
57 offset = 0;
58 else
59 offset = (int) addr;
60
61 memset(out, ' ', sizeof(out)-1);
62 out[8] = ':';
63 out[sizeof(out)-2] = '\n';
64 out[sizeof(out)-1] = '\0';
65
66 gap = (int) offset & 0x0f;
67 while (length) {
68 unsigned int lineOffset = offset & ~0x0f;
69 int i, count;
70
71 hex = out;
72 asc = out + 59;
73
74 for (i = 0; i < 8; i++) {
75 *hex++ = gHexDigit[lineOffset >> 28];
76 lineOffset <<= 4;
77 }
78 hex++;
79 hex++;
80
81 count = ((int)length > 16-gap) ? 16-gap : (int)length; /* cap length */
82 assert(count != 0);
83 assert(count+gap <= 16);
84
85 if (gap) {
86 /* only on first line */
87 hex += gap * 3;
88 asc += gap;
89 }
90
91 for (i = gap ; i < count+gap; i++) {
92 *hex++ = gHexDigit[*addr >> 4];
93 *hex++ = gHexDigit[*addr & 0x0f];
94 hex++;
95 if (*addr >= 0x20 && *addr < 0x7f /*isprint(*addr)*/)
96 *asc++ = *addr;
97 else
98 *asc++ = '.';
99 addr++;
100 }
101 for ( ; i < 16; i++) {
102 /* erase extra stuff; only happens on last line */
103 *hex++ = ' ';
104 *hex++ = ' ';
105 hex++;
106 *asc++ = ' ';
107 }
108
109 LOG_PRI(priority, tag, "%s", out);
110#if 0 //def HAVE_ANDROID_OS
111 /*
112 * We can overrun logcat easily by writing at full speed. On the
113 * other hand, we can make Eclipse time out if we're showing
114 * packet dumps while debugging JDWP.
115 */
116 {
117 if (trickle++ == 8) {
118 trickle = 0;
119 usleep(20000);
120 }
121 }
122#endif
123
124 gap = 0;
125 length -= count;
126 offset += count;
127 }
128}
129
130
131/*
132 * Fill out a DebugOutputTarget, suitable for printing to the log.
133 */
134void dvmCreateLogOutputTarget(DebugOutputTarget* target, int priority,
135 const char* tag)
136{
137 assert(target != NULL);
138 assert(tag != NULL);
139
140 target->which = kDebugTargetLog;
141 target->data.log.priority = priority;
142 target->data.log.tag = tag;
143}
144
145/*
146 * Fill out a DebugOutputTarget suitable for printing to a file pointer.
147 */
148void dvmCreateFileOutputTarget(DebugOutputTarget* target, FILE* fp)
149{
150 assert(target != NULL);
151 assert(fp != NULL);
152
153 target->which = kDebugTargetFile;
154 target->data.file.fp = fp;
155}
156
157/*
158 * Free "target" and any associated data.
159 */
160void dvmFreeOutputTarget(DebugOutputTarget* target)
161{
162 free(target);
163}
164
165/*
166 * Print a debug message, to either a file or the log.
167 */
168void dvmPrintDebugMessage(const DebugOutputTarget* target, const char* format,
169 ...)
170{
171 va_list args;
172
173 va_start(args, format);
174
175 switch (target->which) {
176 case kDebugTargetLog:
177 LOG_PRI_VA(target->data.log.priority, target->data.log.tag,
178 format, args);
179 break;
180 case kDebugTargetFile:
181 vfprintf(target->data.file.fp, format, args);
182 break;
183 default:
184 LOGE("unexpected 'which' %d\n", target->which);
185 break;
186 }
187
188 va_end(args);
189}
190
191
192/*
193 * Allocate a bit vector with enough space to hold at least the specified
194 * number of bits.
195 */
196BitVector* dvmAllocBitVector(int startBits, bool expandable)
197{
198 BitVector* bv;
199 int count;
200
201 assert(sizeof(bv->storage[0]) == 4); /* assuming 32-bit units */
202 assert(startBits >= 0);
203
204 bv = (BitVector*) malloc(sizeof(BitVector));
205
206 count = (startBits + 31) >> 5;
207
208 bv->storageSize = count;
209 bv->expandable = expandable;
210 bv->storage = (u4*) malloc(count * sizeof(u4));
211 memset(bv->storage, 0x00, count * sizeof(u4));
212 return bv;
213}
214
215/*
216 * Free a BitVector.
217 */
218void dvmFreeBitVector(BitVector* pBits)
219{
220 if (pBits == NULL)
221 return;
222
223 free(pBits->storage);
224 free(pBits);
225}
226
227/*
228 * "Allocate" the first-available bit in the bitmap.
229 *
230 * This is not synchronized. The caller is expected to hold some sort of
231 * lock that prevents multiple threads from executing simultaneously in
232 * dvmAllocBit/dvmFreeBit.
233 */
234int dvmAllocBit(BitVector* pBits)
235{
236 int word, bit;
237
238retry:
239 for (word = 0; word < pBits->storageSize; word++) {
240 if (pBits->storage[word] != 0xffffffff) {
241 /*
242 * There are unallocated bits in this word. Return the first.
243 */
244 bit = ffs(~(pBits->storage[word])) -1;
245 assert(bit >= 0 && bit < 32);
246 pBits->storage[word] |= 1 << bit;
247 return (word << 5) | bit;
248 }
249 }
250
251 /*
252 * Ran out of space, allocate more if we're allowed to.
253 */
254 if (!pBits->expandable)
255 return -1;
256
257 pBits->storage = realloc(pBits->storage,
258 (pBits->storageSize + kBitVectorGrowth) * sizeof(u4));
259 memset(&pBits->storage[pBits->storageSize], 0x00,
260 kBitVectorGrowth * sizeof(u4));
261 pBits->storageSize += kBitVectorGrowth;
262 goto retry;
263}
264
265/*
266 * Mark the specified bit as "set".
267 *
268 * Returns "false" if the bit is outside the range of the vector and we're
269 * not allowed to expand.
270 */
271bool dvmSetBit(BitVector* pBits, int num)
272{
273 assert(num >= 0);
274 if (num >= pBits->storageSize * (int)sizeof(u4) * 8) {
275 if (!pBits->expandable)
276 return false;
277
278 int newSize = (num + 31) >> 5;
279 assert(newSize > pBits->storageSize);
280 pBits->storage = realloc(pBits->storage, newSize * sizeof(u4));
281 memset(&pBits->storage[pBits->storageSize], 0x00,
282 (newSize - pBits->storageSize) * sizeof(u4));
Andy McFadden01651b42009-08-19 10:32:01 -0700283 pBits->storageSize = newSize;
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800284 }
285
286 pBits->storage[num >> 5] |= 1 << (num & 0x1f);
287 return true;
288}
289
290/*
291 * Mark the specified bit as "clear".
292 */
293void dvmClearBit(BitVector* pBits, int num)
294{
295 assert(num >= 0 && num < (int) pBits->storageSize * (int)sizeof(u4) * 8);
296
297 pBits->storage[num >> 5] &= ~(1 << (num & 0x1f));
298}
299
300/*
Ben Chenge9695e52009-06-16 16:11:47 -0700301 * Mark all bits bit as "clear".
302 */
303void dvmClearAllBits(BitVector* pBits)
304{
305 int count = pBits->storageSize;
306 memset(pBits->storage, 0, count * sizeof(u4));
307}
308
309/*
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800310 * Determine whether or not the specified bit is set.
311 */
312bool dvmIsBitSet(const BitVector* pBits, int num)
313{
314 assert(num >= 0 && num < (int) pBits->storageSize * (int)sizeof(u4) * 8);
315
316 int val = pBits->storage[num >> 5] & (1 << (num & 0x1f));
317 return (val != 0);
318}
319
320/*
321 * Count the number of bits that are set.
322 */
323int dvmCountSetBits(const BitVector* pBits)
324{
325 int word, bit;
326 int count = 0;
327
328 for (word = 0; word < pBits->storageSize; word++) {
329 u4 val = pBits->storage[word];
330
331 if (val != 0) {
332 if (val == 0xffffffff) {
333 count += 32;
334 } else {
335 /* count the number of '1' bits */
336 while (val != 0) {
337 val &= val - 1;
338 count++;
339 }
340 }
341 }
342 }
343
344 return count;
345}
346
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800347/*
Ben Cheng4238ec22009-08-24 16:32:22 -0700348 * Copy a whole vector to the other. Only do that when the both vectors have
349 * the same size and attribute.
350 */
351bool dvmCopyBitVector(BitVector *dest, const BitVector *src)
352{
353 if (dest->storageSize != src->storageSize ||
354 dest->expandable != src->expandable)
355 return false;
356 memcpy(dest->storage, src->storage, sizeof(u4) * dest->storageSize);
357 return true;
358}
359
360/*
361 * Intersect two bit vectores and merge the result on top of the pre-existing
362 * value in the dest vector.
363 */
364bool dvmIntersectBitVectors(BitVector *dest, const BitVector *src1,
365 const BitVector *src2)
366{
367 if (dest->storageSize != src1->storageSize ||
368 dest->storageSize != src2->storageSize ||
369 dest->expandable != src1->expandable ||
370 dest->expandable != src2->expandable)
371 return false;
372
373 int i;
374 for (i = 0; i < dest->storageSize; i++) {
375 dest->storage[i] |= src1->storage[i] & src2->storage[i];
376 }
377 return true;
378}
379
380/*
The Android Open Source Projectf6c38712009-03-03 19:28:47 -0800381 * Return a newly-allocated string in which all occurrences of '.' have
382 * been changed to '/'. If we find a '/' in the original string, NULL
383 * is returned to avoid ambiguity.
384 */
385char* dvmDotToSlash(const char* str)
386{
387 char* newStr = strdup(str);
388 char* cp = newStr;
389
390 while (*cp != '\0') {
391 if (*cp == '/') {
392 assert(false);
393 return NULL;
394 }
395 if (*cp == '.')
396 *cp = '/';
397 cp++;
398 }
399
400 return newStr;
401}
402
403/*
404 * Return a newly-allocated string for the "dot version" of the class
405 * name for the given type descriptor. That is, The initial "L" and
406 * final ";" (if any) have been removed and all occurrences of '/'
407 * have been changed to '.'.
408 */
409char* dvmDescriptorToDot(const char* str)
410{
411 size_t at = strlen(str);
412 char* newStr;
413
414 if ((at >= 2) && (str[0] == 'L') && (str[at - 1] == ';')) {
415 at -= 2; /* Two fewer chars to copy. */
416 str++; /* Skip the 'L'. */
417 }
418
419 newStr = malloc(at + 1); /* Add one for the '\0'. */
420 newStr[at] = '\0';
421
422 while (at > 0) {
423 at--;
424 newStr[at] = (str[at] == '/') ? '.' : str[at];
425 }
426
427 return newStr;
428}
429
430/*
431 * Return a newly-allocated string for the type descriptor
432 * corresponding to the "dot version" of the given class name. That
433 * is, non-array names are surrounded by "L" and ";", and all
434 * occurrences of '.' are changed to '/'.
435 */
436char* dvmDotToDescriptor(const char* str)
437{
438 size_t length = strlen(str);
439 int wrapElSemi = 0;
440 char* newStr;
441 char* at;
442
443 if (str[0] != '[') {
444 length += 2; /* for "L" and ";" */
445 wrapElSemi = 1;
446 }
447
448 newStr = at = malloc(length + 1); /* + 1 for the '\0' */
449
450 if (newStr == NULL) {
451 return NULL;
452 }
453
454 if (wrapElSemi) {
455 *(at++) = 'L';
456 }
457
458 while (*str) {
459 char c = *(str++);
460 if (c == '.') {
461 c = '/';
462 }
463 *(at++) = c;
464 }
465
466 if (wrapElSemi) {
467 *(at++) = ';';
468 }
469
470 *at = '\0';
471 return newStr;
472}
473
474/*
475 * Return a newly-allocated string for the internal-form class name for
476 * the given type descriptor. That is, the initial "L" and final ";" (if
477 * any) have been removed.
478 */
479char* dvmDescriptorToName(const char* str)
480{
481 if (str[0] == 'L') {
482 size_t length = strlen(str) - 1;
483 char* newStr = malloc(length);
484
485 if (newStr == NULL) {
486 return NULL;
487 }
488
489 strlcpy(newStr, str + 1, length);
490 return newStr;
491 }
492
493 return strdup(str);
494}
495
496/*
497 * Return a newly-allocated string for the type descriptor for the given
498 * internal-form class name. That is, a non-array class name will get
499 * surrounded by "L" and ";", while array names are left as-is.
500 */
501char* dvmNameToDescriptor(const char* str)
502{
503 if (str[0] != '[') {
504 size_t length = strlen(str);
505 char* descriptor = malloc(length + 3);
506
507 if (descriptor == NULL) {
508 return NULL;
509 }
510
511 descriptor[0] = 'L';
512 strcpy(descriptor + 1, str);
513 descriptor[length + 1] = ';';
514 descriptor[length + 2] = '\0';
515
516 return descriptor;
517 }
518
519 return strdup(str);
520}
521
522/*
523 * Get a notion of the current time, in nanoseconds. This is meant for
524 * computing durations (e.g. "operation X took 52nsec"), so the result
525 * should not be used to get the current date/time.
526 */
527u8 dvmGetRelativeTimeNsec(void)
528{
529#ifdef HAVE_POSIX_CLOCKS
530 struct timespec now;
531 clock_gettime(CLOCK_MONOTONIC, &now);
532 return (u8)now.tv_sec*1000000000LL + now.tv_nsec;
533#else
534 struct timeval now;
535 gettimeofday(&now, NULL);
536 return (u8)now.tv_sec*1000000000LL + now.tv_usec * 1000LL;
537#endif
538}
539
540/*
541 * Get the per-thread CPU time, in nanoseconds.
542 *
543 * Only useful for time deltas.
544 */
545u8 dvmGetThreadCpuTimeNsec(void)
546{
547#ifdef HAVE_POSIX_CLOCKS
548 struct timespec now;
549 clock_gettime(CLOCK_THREAD_CPUTIME_ID, &now);
550 return (u8)now.tv_sec*1000000000LL + now.tv_nsec;
551#else
552 return (u8) -1;
553#endif
554}
555
556/*
557 * Get the per-thread CPU time, in nanoseconds, for the specified thread.
558 */
559u8 dvmGetOtherThreadCpuTimeNsec(pthread_t thread)
560{
561#if 0 /*def HAVE_POSIX_CLOCKS*/
562 int clockId;
563
564 if (pthread_getcpuclockid(thread, &clockId) != 0)
565 return (u8) -1;
566
567 struct timespec now;
568 clock_gettime(clockId, &now);
569 return (u8)now.tv_sec*1000000000LL + now.tv_nsec;
570#else
571 return (u8) -1;
572#endif
573}
574
575
576/*
577 * Call this repeatedly, with successively higher values for "iteration",
578 * to sleep for a period of time not to exceed "maxTotalSleep".
579 *
580 * For example, when called with iteration==0 we will sleep for a very
581 * brief time. On the next call we will sleep for a longer time. When
582 * the sum total of all sleeps reaches "maxTotalSleep", this returns false.
583 *
584 * The initial start time value for "relStartTime" MUST come from the
585 * dvmGetRelativeTimeUsec call. On the device this must come from the
586 * monotonic clock source, not the wall clock.
587 *
588 * This should be used wherever you might be tempted to call sched_yield()
589 * in a loop. The problem with sched_yield is that, for a high-priority
590 * thread, the kernel might not actually transfer control elsewhere.
591 *
592 * Returns "false" if we were unable to sleep because our time was up.
593 */
594bool dvmIterativeSleep(int iteration, int maxTotalSleep, u8 relStartTime)
595{
596 const int minSleep = 10000;
597 u8 curTime;
598 int curDelay;
599
600 /*
601 * Get current time, and see if we've already exceeded the limit.
602 */
603 curTime = dvmGetRelativeTimeUsec();
604 if (curTime >= relStartTime + maxTotalSleep) {
605 LOGVV("exsl: sleep exceeded (start=%llu max=%d now=%llu)\n",
606 relStartTime, maxTotalSleep, curTime);
607 return false;
608 }
609
610 /*
611 * Compute current delay. We're bounded by "maxTotalSleep", so no
612 * real risk of overflow assuming "usleep" isn't returning early.
613 * (Besides, 2^30 usec is about 18 minutes by itself.)
614 *
615 * For iteration==0 we just call sched_yield(), so the first sleep
616 * at iteration==1 is actually (minSleep * 2).
617 */
618 curDelay = minSleep;
619 while (iteration-- > 0)
620 curDelay *= 2;
621 assert(curDelay > 0);
622
623 if (curTime + curDelay >= relStartTime + maxTotalSleep) {
624 LOGVV("exsl: reduced delay from %d to %d\n",
625 curDelay, (int) ((relStartTime + maxTotalSleep) - curTime));
626 curDelay = (int) ((relStartTime + maxTotalSleep) - curTime);
627 }
628
629 if (iteration == 0) {
630 LOGVV("exsl: yield\n");
631 sched_yield();
632 } else {
633 LOGVV("exsl: sleep for %d\n", curDelay);
634 usleep(curDelay);
635 }
636 return true;
637}
638
639
640/*
641 * Set the "close on exec" flag so we don't expose our file descriptors
642 * to processes launched by us.
643 */
644bool dvmSetCloseOnExec(int fd)
645{
646 int flags;
647
648 /*
649 * There's presently only one flag defined, so getting the previous
650 * value of the fd flags is probably unnecessary.
651 */
652 flags = fcntl(fd, F_GETFD);
653 if (flags < 0) {
654 LOGW("Unable to get fd flags for fd %d\n", fd);
655 return false;
656 }
657 if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) < 0) {
658 LOGW("Unable to set close-on-exec for fd %d\n", fd);
659 return false;
660 }
661 return true;
662}
663
664#if (!HAVE_STRLCPY)
665/* Implementation of strlcpy() for platforms that don't already have it. */
666size_t strlcpy(char *dst, const char *src, size_t size) {
667 size_t srcLength = strlen(src);
668 size_t copyLength = srcLength;
669
670 if (srcLength > (size - 1)) {
671 copyLength = size - 1;
672 }
673
674 if (size != 0) {
675 strncpy(dst, src, copyLength);
676 dst[copyLength] = '\0';
677 }
678
679 return srcLength;
680}
681#endif