Misc.cpp revision fe7f2b3920bf5d66eda262e643245b03df3e57c8
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#include "Dalvik.h" 21 22#include <stdlib.h> 23#include <stddef.h> 24#include <string.h> 25#include <strings.h> 26#include <ctype.h> 27#include <time.h> 28#include <sys/time.h> 29#include <fcntl.h> 30#include <cutils/ashmem.h> 31#include <sys/mman.h> 32 33/* 34 * Print a hex dump in this format: 35 * 3601234567: 00 11 22 33 44 55 66 77 88 99 aa bb cc dd ee ff 0123456789abcdef\n 37 * 38 * If "mode" is kHexDumpLocal, we start at offset zero, and show a full 39 * 16 bytes on the first line. If it's kHexDumpMem, we make this look 40 * like a memory dump, using the actual address, outputting a partial line 41 * if "vaddr" isn't aligned on a 16-byte boundary. 42 * 43 * "priority" and "tag" determine the values passed to the log calls. 44 * 45 * Does not use printf() or other string-formatting calls. 46 */ 47void dvmPrintHexDumpEx(int priority, const char* tag, const void* vaddr, 48 size_t length, HexDumpMode mode) 49{ 50 static const char gHexDigit[] = "0123456789abcdef"; 51 const unsigned char* addr = (const unsigned char*)vaddr; 52 char out[77]; /* exact fit */ 53 unsigned int offset; /* offset to show while printing */ 54 char* hex; 55 char* asc; 56 int gap; 57 //int trickle = 0; 58 59 if (mode == kHexDumpLocal) 60 offset = 0; 61 else 62 offset = (int) addr; 63 64 memset(out, ' ', sizeof(out)-1); 65 out[8] = ':'; 66 out[sizeof(out)-2] = '\n'; 67 out[sizeof(out)-1] = '\0'; 68 69 gap = (int) offset & 0x0f; 70 while (length) { 71 unsigned int lineOffset = offset & ~0x0f; 72 int i, count; 73 74 hex = out; 75 asc = out + 59; 76 77 for (i = 0; i < 8; i++) { 78 *hex++ = gHexDigit[lineOffset >> 28]; 79 lineOffset <<= 4; 80 } 81 hex++; 82 hex++; 83 84 count = ((int)length > 16-gap) ? 16-gap : (int)length; /* cap length */ 85 assert(count != 0); 86 assert(count+gap <= 16); 87 88 if (gap) { 89 /* only on first line */ 90 hex += gap * 3; 91 asc += gap; 92 } 93 94 for (i = gap ; i < count+gap; i++) { 95 *hex++ = gHexDigit[*addr >> 4]; 96 *hex++ = gHexDigit[*addr & 0x0f]; 97 hex++; 98 if (*addr >= 0x20 && *addr < 0x7f /*isprint(*addr)*/) 99 *asc++ = *addr; 100 else 101 *asc++ = '.'; 102 addr++; 103 } 104 for ( ; i < 16; i++) { 105 /* erase extra stuff; only happens on last line */ 106 *hex++ = ' '; 107 *hex++ = ' '; 108 hex++; 109 *asc++ = ' '; 110 } 111 112 LOG_PRI(priority, tag, "%s", out); 113#if 0 //def HAVE_ANDROID_OS 114 /* 115 * We can overrun logcat easily by writing at full speed. On the 116 * other hand, we can make Eclipse time out if we're showing 117 * packet dumps while debugging JDWP. 118 */ 119 { 120 if (trickle++ == 8) { 121 trickle = 0; 122 usleep(20000); 123 } 124 } 125#endif 126 127 gap = 0; 128 length -= count; 129 offset += count; 130 } 131} 132 133 134/* 135 * Fill out a DebugOutputTarget, suitable for printing to the log. 136 */ 137void dvmCreateLogOutputTarget(DebugOutputTarget* target, int priority, 138 const char* tag) 139{ 140 assert(target != NULL); 141 assert(tag != NULL); 142 143 target->which = kDebugTargetLog; 144 target->data.log.priority = priority; 145 target->data.log.tag = tag; 146} 147 148/* 149 * Fill out a DebugOutputTarget suitable for printing to a file pointer. 150 */ 151void dvmCreateFileOutputTarget(DebugOutputTarget* target, FILE* fp) 152{ 153 assert(target != NULL); 154 assert(fp != NULL); 155 156 target->which = kDebugTargetFile; 157 target->data.file.fp = fp; 158} 159 160/* 161 * Free "target" and any associated data. 162 */ 163void dvmFreeOutputTarget(DebugOutputTarget* target) 164{ 165 free(target); 166} 167 168/* 169 * Print a debug message, to either a file or the log. 170 */ 171void dvmPrintDebugMessage(const DebugOutputTarget* target, const char* format, 172 ...) 173{ 174 va_list args; 175 176 va_start(args, format); 177 178 switch (target->which) { 179 case kDebugTargetLog: 180 LOG_PRI_VA(target->data.log.priority, target->data.log.tag, 181 format, args); 182 break; 183 case kDebugTargetFile: 184 vfprintf(target->data.file.fp, format, args); 185 break; 186 default: 187 LOGE("unexpected 'which' %d", target->which); 188 break; 189 } 190 191 va_end(args); 192} 193 194 195/* 196 * Return a newly-allocated string in which all occurrences of '.' have 197 * been changed to '/'. If we find a '/' in the original string, NULL 198 * is returned to avoid ambiguity. 199 */ 200char* dvmDotToSlash(const char* str) 201{ 202 char* newStr = strdup(str); 203 char* cp = newStr; 204 205 if (newStr == NULL) 206 return NULL; 207 208 while (*cp != '\0') { 209 if (*cp == '/') { 210 assert(false); 211 return NULL; 212 } 213 if (*cp == '.') 214 *cp = '/'; 215 cp++; 216 } 217 218 return newStr; 219} 220 221std::string dvmHumanReadableDescriptor(const char* descriptor) { 222 // Count the number of '['s to get the dimensionality. 223 const char* c = descriptor; 224 size_t dim = 0; 225 while (*c == '[') { 226 dim++; 227 c++; 228 } 229 230 // Reference or primitive? 231 if (*c == 'L') { 232 // "[[La/b/C;" -> "a.b.C[][]". 233 c++; // Skip the 'L'. 234 } else { 235 // "[[B" -> "byte[][]". 236 // To make life easier, we make primitives look like unqualified 237 // reference types. 238 switch (*c) { 239 case 'B': c = "byte;"; break; 240 case 'C': c = "char;"; break; 241 case 'D': c = "double;"; break; 242 case 'F': c = "float;"; break; 243 case 'I': c = "int;"; break; 244 case 'J': c = "long;"; break; 245 case 'S': c = "short;"; break; 246 case 'Z': c = "boolean;"; break; 247 default: return descriptor; 248 } 249 } 250 251 // At this point, 'c' is a string of the form "fully/qualified/Type;" 252 // or "primitive;". Rewrite the type with '.' instead of '/': 253 std::string result; 254 const char* p = c; 255 while (*p != ';') { 256 char ch = *p++; 257 if (ch == '/') { 258 ch = '.'; 259 } 260 result.push_back(ch); 261 } 262 // ...and replace the semicolon with 'dim' "[]" pairs: 263 while (dim--) { 264 result += "[]"; 265 } 266 return result; 267} 268 269std::string dvmHumanReadableType(const Object* obj) 270{ 271 if (obj == NULL) { 272 return "(null)"; 273 } 274 if (obj->clazz == NULL) { 275 /* should only be possible right after a plain dvmMalloc() */ 276 return "(raw)"; 277 } 278 std::string result(dvmHumanReadableDescriptor(obj->clazz->descriptor)); 279 if (dvmIsClassObject(obj)) { 280 const ClassObject* clazz = reinterpret_cast<const ClassObject*>(obj); 281 result += "<" + dvmHumanReadableDescriptor(clazz->descriptor) + ">"; 282 } 283 return result; 284} 285 286/* 287 * Return a newly-allocated string for the "dot version" of the class 288 * name for the given type descriptor. That is, The initial "L" and 289 * final ";" (if any) have been removed and all occurrences of '/' 290 * have been changed to '.'. 291 * 292 * "Dot version" names are used in the class loading machinery. 293 * See also dvmHumanReadableDescriptor. 294 */ 295char* dvmDescriptorToDot(const char* str) 296{ 297 size_t at = strlen(str); 298 char* newStr; 299 300 if ((at >= 2) && (str[0] == 'L') && (str[at - 1] == ';')) { 301 at -= 2; /* Two fewer chars to copy. */ 302 str++; /* Skip the 'L'. */ 303 } 304 305 newStr = (char*)malloc(at + 1); /* Add one for the '\0'. */ 306 if (newStr == NULL) 307 return NULL; 308 309 newStr[at] = '\0'; 310 311 while (at > 0) { 312 at--; 313 newStr[at] = (str[at] == '/') ? '.' : str[at]; 314 } 315 316 return newStr; 317} 318 319/* 320 * Return a newly-allocated string for the type descriptor 321 * corresponding to the "dot version" of the given class name. That 322 * is, non-array names are surrounded by "L" and ";", and all 323 * occurrences of '.' have been changed to '/'. 324 * 325 * "Dot version" names are used in the class loading machinery. 326 */ 327char* dvmDotToDescriptor(const char* str) 328{ 329 size_t length = strlen(str); 330 int wrapElSemi = 0; 331 char* newStr; 332 char* at; 333 334 if (str[0] != '[') { 335 length += 2; /* for "L" and ";" */ 336 wrapElSemi = 1; 337 } 338 339 newStr = at = (char*)malloc(length + 1); /* + 1 for the '\0' */ 340 341 if (newStr == NULL) { 342 return NULL; 343 } 344 345 if (wrapElSemi) { 346 *(at++) = 'L'; 347 } 348 349 while (*str) { 350 char c = *(str++); 351 if (c == '.') { 352 c = '/'; 353 } 354 *(at++) = c; 355 } 356 357 if (wrapElSemi) { 358 *(at++) = ';'; 359 } 360 361 *at = '\0'; 362 return newStr; 363} 364 365/* 366 * Return a newly-allocated string for the internal-form class name for 367 * the given type descriptor. That is, the initial "L" and final ";" (if 368 * any) have been removed. 369 */ 370char* dvmDescriptorToName(const char* str) 371{ 372 if (str[0] == 'L') { 373 size_t length = strlen(str) - 1; 374 char* newStr = (char*)malloc(length); 375 376 if (newStr == NULL) { 377 return NULL; 378 } 379 380 strlcpy(newStr, str + 1, length); 381 return newStr; 382 } 383 384 return strdup(str); 385} 386 387/* 388 * Return a newly-allocated string for the type descriptor for the given 389 * internal-form class name. That is, a non-array class name will get 390 * surrounded by "L" and ";", while array names are left as-is. 391 */ 392char* dvmNameToDescriptor(const char* str) 393{ 394 if (str[0] != '[') { 395 size_t length = strlen(str); 396 char* descriptor = (char*)malloc(length + 3); 397 398 if (descriptor == NULL) { 399 return NULL; 400 } 401 402 descriptor[0] = 'L'; 403 strcpy(descriptor + 1, str); 404 descriptor[length + 1] = ';'; 405 descriptor[length + 2] = '\0'; 406 407 return descriptor; 408 } 409 410 return strdup(str); 411} 412 413/* 414 * Get a notion of the current time, in nanoseconds. This is meant for 415 * computing durations (e.g. "operation X took 52nsec"), so the result 416 * should not be used to get the current date/time. 417 */ 418u8 dvmGetRelativeTimeNsec() 419{ 420#ifdef HAVE_POSIX_CLOCKS 421 struct timespec now; 422 clock_gettime(CLOCK_MONOTONIC, &now); 423 return (u8)now.tv_sec*1000000000LL + now.tv_nsec; 424#else 425 struct timeval now; 426 gettimeofday(&now, NULL); 427 return (u8)now.tv_sec*1000000000LL + now.tv_usec * 1000LL; 428#endif 429} 430 431/* 432 * Get the per-thread CPU time, in nanoseconds. 433 * 434 * Only useful for time deltas. 435 */ 436u8 dvmGetThreadCpuTimeNsec() 437{ 438#ifdef HAVE_POSIX_CLOCKS 439 struct timespec now; 440 clock_gettime(CLOCK_THREAD_CPUTIME_ID, &now); 441 return (u8)now.tv_sec*1000000000LL + now.tv_nsec; 442#else 443 return (u8) -1; 444#endif 445} 446 447/* 448 * Get the per-thread CPU time, in nanoseconds, for the specified thread. 449 */ 450u8 dvmGetOtherThreadCpuTimeNsec(pthread_t thread) 451{ 452#if 0 /*def HAVE_POSIX_CLOCKS*/ 453 int clockId; 454 455 if (pthread_getcpuclockid(thread, &clockId) != 0) 456 return (u8) -1; 457 458 struct timespec now; 459 clock_gettime(clockId, &now); 460 return (u8)now.tv_sec*1000000000LL + now.tv_nsec; 461#else 462 return (u8) -1; 463#endif 464} 465 466 467/* 468 * Call this repeatedly, with successively higher values for "iteration", 469 * to sleep for a period of time not to exceed "maxTotalSleep". 470 * 471 * For example, when called with iteration==0 we will sleep for a very 472 * brief time. On the next call we will sleep for a longer time. When 473 * the sum total of all sleeps reaches "maxTotalSleep", this returns false. 474 * 475 * The initial start time value for "relStartTime" MUST come from the 476 * dvmGetRelativeTimeUsec call. On the device this must come from the 477 * monotonic clock source, not the wall clock. 478 * 479 * This should be used wherever you might be tempted to call sched_yield() 480 * in a loop. The problem with sched_yield is that, for a high-priority 481 * thread, the kernel might not actually transfer control elsewhere. 482 * 483 * Returns "false" if we were unable to sleep because our time was up. 484 */ 485bool dvmIterativeSleep(int iteration, int maxTotalSleep, u8 relStartTime) 486{ 487 const int minSleep = 10000; 488 u8 curTime; 489 int curDelay; 490 491 /* 492 * Get current time, and see if we've already exceeded the limit. 493 */ 494 curTime = dvmGetRelativeTimeUsec(); 495 if (curTime >= relStartTime + maxTotalSleep) { 496 LOGVV("exsl: sleep exceeded (start=%llu max=%d now=%llu)", 497 relStartTime, maxTotalSleep, curTime); 498 return false; 499 } 500 501 /* 502 * Compute current delay. We're bounded by "maxTotalSleep", so no 503 * real risk of overflow assuming "usleep" isn't returning early. 504 * (Besides, 2^30 usec is about 18 minutes by itself.) 505 * 506 * For iteration==0 we just call sched_yield(), so the first sleep 507 * at iteration==1 is actually (minSleep * 2). 508 */ 509 curDelay = minSleep; 510 while (iteration-- > 0) 511 curDelay *= 2; 512 assert(curDelay > 0); 513 514 if (curTime + curDelay >= relStartTime + maxTotalSleep) { 515 LOGVV("exsl: reduced delay from %d to %d", 516 curDelay, (int) ((relStartTime + maxTotalSleep) - curTime)); 517 curDelay = (int) ((relStartTime + maxTotalSleep) - curTime); 518 } 519 520 if (iteration == 0) { 521 LOGVV("exsl: yield"); 522 sched_yield(); 523 } else { 524 LOGVV("exsl: sleep for %d", curDelay); 525 usleep(curDelay); 526 } 527 return true; 528} 529 530 531/* 532 * Set the "close on exec" flag so we don't expose our file descriptors 533 * to processes launched by us. 534 */ 535bool dvmSetCloseOnExec(int fd) 536{ 537 int flags; 538 539 /* 540 * There's presently only one flag defined, so getting the previous 541 * value of the fd flags is probably unnecessary. 542 */ 543 flags = fcntl(fd, F_GETFD); 544 if (flags < 0) { 545 LOGW("Unable to get fd flags for fd %d", fd); 546 return false; 547 } 548 if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) < 0) { 549 LOGW("Unable to set close-on-exec for fd %d", fd); 550 return false; 551 } 552 return true; 553} 554 555#if (!HAVE_STRLCPY) 556/* Implementation of strlcpy() for platforms that don't already have it. */ 557size_t strlcpy(char *dst, const char *src, size_t size) { 558 size_t srcLength = strlen(src); 559 size_t copyLength = srcLength; 560 561 if (srcLength > (size - 1)) { 562 copyLength = size - 1; 563 } 564 565 if (size != 0) { 566 strncpy(dst, src, copyLength); 567 dst[copyLength] = '\0'; 568 } 569 570 return srcLength; 571} 572#endif 573 574/* 575 * Allocates a memory region using ashmem and mmap, initialized to 576 * zero. Actual allocation rounded up to page multiple. Returns 577 * NULL on failure. 578 */ 579void *dvmAllocRegion(size_t byteCount, int prot, const char *name) { 580 void *base; 581 int fd, ret; 582 583 byteCount = ALIGN_UP_TO_PAGE_SIZE(byteCount); 584 fd = ashmem_create_region(name, byteCount); 585 if (fd == -1) { 586 return NULL; 587 } 588 base = mmap(NULL, byteCount, prot, MAP_PRIVATE, fd, 0); 589 ret = close(fd); 590 if (base == MAP_FAILED) { 591 return NULL; 592 } 593 if (ret == -1) { 594 return NULL; 595 } 596 return base; 597} 598 599/* 600 * Get some per-thread stats. 601 * 602 * This is currently generated by opening the appropriate "stat" file 603 * in /proc and reading the pile of stuff that comes out. 604 */ 605bool dvmGetThreadStats(ProcStatData* pData, pid_t tid) 606{ 607 /* 608 int pid; 609 char comm[128]; 610 char state; 611 int ppid, pgrp, session, tty_nr, tpgid; 612 unsigned long flags, minflt, cminflt, majflt, cmajflt, utime, stime; 613 long cutime, cstime, priority, nice, zero, itrealvalue; 614 unsigned long starttime, vsize; 615 long rss; 616 unsigned long rlim, startcode, endcode, startstack, kstkesp, kstkeip; 617 unsigned long signal, blocked, sigignore, sigcatch, wchan, nswap, cnswap; 618 int exit_signal, processor; 619 unsigned long rt_priority, policy; 620 621 scanf("%d %s %c %d %d %d %d %d %lu %lu %lu %lu %lu %lu %lu %ld %ld %ld " 622 "%ld %ld %ld %lu %lu %ld %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu " 623 "%lu %lu %lu %d %d %lu %lu", 624 &pid, comm, &state, &ppid, &pgrp, &session, &tty_nr, &tpgid, 625 &flags, &minflt, &cminflt, &majflt, &cmajflt, &utime, &stime, 626 &cutime, &cstime, &priority, &nice, &zero, &itrealvalue, 627 &starttime, &vsize, &rss, &rlim, &startcode, &endcode, 628 &startstack, &kstkesp, &kstkeip, &signal, &blocked, &sigignore, 629 &sigcatch, &wchan, &nswap, &cnswap, &exit_signal, &processor, 630 &rt_priority, &policy); 631 632 (new: delayacct_blkio_ticks %llu (since Linux 2.6.18)) 633 */ 634 635 char nameBuf[64]; 636 int i, fd; 637 638 /* 639 * Open and read the appropriate file. This is expected to work on 640 * Linux but will fail on other platforms (e.g. Mac sim). 641 */ 642 sprintf(nameBuf, "/proc/self/task/%d/stat", (int) tid); 643 fd = open(nameBuf, O_RDONLY); 644 if (fd < 0) { 645 LOGV("Unable to open '%s': %s", nameBuf, strerror(errno)); 646 return false; 647 } 648 649 char lineBuf[512]; /* > 2x typical */ 650 int cc = read(fd, lineBuf, sizeof(lineBuf)-1); 651 if (cc <= 0) { 652 const char* msg = (cc == 0) ? "unexpected EOF" : strerror(errno); 653 LOGI("Unable to read '%s': %s", nameBuf, msg); 654 close(fd); 655 return false; 656 } 657 close(fd); 658 lineBuf[cc] = '\0'; 659 660 /* 661 * Skip whitespace-separated tokens. For the most part we can assume 662 * that tokens do not contain spaces, and are separated by exactly one 663 * space character. The only exception is the second field ("comm") 664 * which may contain spaces but is surrounded by parenthesis. 665 */ 666 char* cp = strchr(lineBuf, ')'); 667 if (cp == NULL) 668 goto parse_fail; 669 cp++; 670 for (i = 2; i < 13; i++) { 671 cp = strchr(cp+1, ' '); 672 if (cp == NULL) 673 goto parse_fail; 674 } 675 676 /* 677 * Grab utime/stime. 678 */ 679 char* endp; 680 pData->utime = strtoul(cp+1, &endp, 10); 681 if (endp == cp+1) 682 LOGI("Warning: strtoul failed on utime ('%.30s...')", cp); 683 684 cp = strchr(cp+1, ' '); 685 if (cp == NULL) 686 goto parse_fail; 687 688 pData->stime = strtoul(cp+1, &endp, 10); 689 if (endp == cp+1) 690 LOGI("Warning: strtoul failed on stime ('%.30s...')", cp); 691 692 /* 693 * Skip more stuff we don't care about. 694 */ 695 for (i = 14; i < 38; i++) { 696 cp = strchr(cp+1, ' '); 697 if (cp == NULL) 698 goto parse_fail; 699 } 700 701 /* 702 * Grab processor number. 703 */ 704 pData->processor = strtol(cp+1, &endp, 10); 705 if (endp == cp+1) 706 LOGI("Warning: strtoul failed on processor ('%.30s...')", cp); 707 708 return true; 709 710parse_fail: 711 LOGI("stat parse failed (%s)", lineBuf); 712 return false; 713} 714 715/* documented in header file */ 716const char* dvmPathToAbsolutePortion(const char* path) { 717 if (path == NULL) { 718 return NULL; 719 } 720 721 if (path[0] == '/') { 722 /* It's a regular absolute path. Return it. */ 723 return path; 724 } 725 726 const char* sentinel = strstr(path, "/./"); 727 728 if (sentinel != NULL) { 729 /* It's got the sentinel. Return a pointer to the second slash. */ 730 return sentinel + 2; 731 } 732 733 return NULL; 734} 735 736// From RE2. 737static void StringAppendV(std::string* dst, const char* format, va_list ap) { 738 // First try with a small fixed size buffer 739 char space[1024]; 740 741 // It's possible for methods that use a va_list to invalidate 742 // the data in it upon use. The fix is to make a copy 743 // of the structure before using it and use that copy instead. 744 va_list backup_ap; 745 va_copy(backup_ap, ap); 746 int result = vsnprintf(space, sizeof(space), format, backup_ap); 747 va_end(backup_ap); 748 749 if ((result >= 0) && ((size_t) result < sizeof(space))) { 750 // It fit 751 dst->append(space, result); 752 return; 753 } 754 755 // Repeatedly increase buffer size until it fits 756 int length = sizeof(space); 757 while (true) { 758 if (result < 0) { 759 // Older behavior: just try doubling the buffer size 760 length *= 2; 761 } else { 762 // We need exactly "result+1" characters 763 length = result+1; 764 } 765 char* buf = new char[length]; 766 767 // Restore the va_list before we use it again 768 va_copy(backup_ap, ap); 769 result = vsnprintf(buf, length, format, backup_ap); 770 va_end(backup_ap); 771 772 if ((result >= 0) && (result < length)) { 773 // It fit 774 dst->append(buf, result); 775 delete[] buf; 776 return; 777 } 778 delete[] buf; 779 } 780} 781 782std::string dvmStringPrintf(const char* fmt, ...) { 783 va_list ap; 784 va_start(ap, fmt); 785 std::string result; 786 StringAppendV(&result, fmt, ap); 787 va_end(ap); 788 return result; 789} 790