2 * Copyright (C) 2008 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 * Miscellaneous utility functions.
30 #include <cutils/ashmem.h>
34 * Print a hex dump in this format:
36 01234567: 00 11 22 33 44 55 66 77 88 99 aa bb cc dd ee ff 0123456789abcdef\n
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.
43 * "priority" and "tag" determine the values passed to the log calls.
45 * Does not use printf() or other string-formatting calls.
47 void dvmPrintHexDumpEx(int priority, const char* tag, const void* vaddr,
48 size_t length, HexDumpMode mode)
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 */
59 if (mode == kHexDumpLocal)
64 memset(out, ' ', sizeof(out)-1);
66 out[sizeof(out)-2] = '\n';
67 out[sizeof(out)-1] = '\0';
69 gap = (int) offset & 0x0f;
71 unsigned int lineOffset = offset & ~0x0f;
77 for (i = 0; i < 8; i++) {
78 *hex++ = gHexDigit[lineOffset >> 28];
84 count = ((int)length > 16-gap) ? 16-gap : (int)length; /* cap length */
86 assert(count+gap <= 16);
89 /* only on first line */
94 for (i = gap ; i < count+gap; i++) {
95 *hex++ = gHexDigit[*addr >> 4];
96 *hex++ = gHexDigit[*addr & 0x0f];
98 if (*addr >= 0x20 && *addr < 0x7f /*isprint(*addr)*/)
104 for ( ; i < 16; i++) {
105 /* erase extra stuff; only happens on last line */
112 LOG_PRI(priority, tag, "%s", out);
113 #if 0 //def HAVE_ANDROID_OS
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.
120 if (trickle++ == 8) {
135 * Fill out a DebugOutputTarget, suitable for printing to the log.
137 void dvmCreateLogOutputTarget(DebugOutputTarget* target, int priority,
140 assert(target != NULL);
143 target->which = kDebugTargetLog;
144 target->data.log.priority = priority;
145 target->data.log.tag = tag;
149 * Fill out a DebugOutputTarget suitable for printing to a file pointer.
151 void dvmCreateFileOutputTarget(DebugOutputTarget* target, FILE* fp)
153 assert(target != NULL);
156 target->which = kDebugTargetFile;
157 target->data.file.fp = fp;
161 * Free "target" and any associated data.
163 void dvmFreeOutputTarget(DebugOutputTarget* target)
169 * Print a debug message, to either a file or the log.
171 void dvmPrintDebugMessage(const DebugOutputTarget* target, const char* format,
176 va_start(args, format);
178 switch (target->which) {
179 case kDebugTargetLog:
180 LOG_PRI_VA(target->data.log.priority, target->data.log.tag,
183 case kDebugTargetFile:
184 vfprintf(target->data.file.fp, format, args);
187 LOGE("unexpected 'which' %d\n", target->which);
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.
200 char* dvmDotToSlash(const char* str)
202 char* newStr = strdup(str);
208 while (*cp != '\0') {
221 char* dvmHumanReadableDescriptor(const char* descriptor)
223 // Count the number of '['s to get the dimensionality.
224 const char* c = descriptor;
231 // Work out how large the result will be.
234 // "[[La/b/C;" -> "a.b.C[][]".
235 resultLength = strlen(c) - 2 + 2*dim;
236 c++; // Skip the 'L'.
238 // "[[B" -> "byte[][]".
239 // To make life easier, we make primitives look like unqualified
242 case 'B': c = "byte;"; break;
243 case 'C': c = "char;"; break;
244 case 'D': c = "double;"; break;
245 case 'F': c = "float;"; break;
246 case 'I': c = "int;"; break;
247 case 'J': c = "long;"; break;
248 case 'S': c = "short;"; break;
249 case 'Z': c = "boolean;"; break;
250 default: return strdup(descriptor);
252 resultLength = strlen(c) - 1 + 2*dim;
255 // Allocate enough space.
256 char* result = (char*)malloc(resultLength + 1);
257 if (result == NULL) {
261 // At this point, 'c' is a string of the form "fully/qualified/Type;"
262 // or "primitive;". Rewrite the type with '.' instead of '/':
272 // ...and replace the semicolon with 'dim' "[]" pairs:
282 * Return a newly-allocated string for the "dot version" of the class
283 * name for the given type descriptor. That is, The initial "L" and
284 * final ";" (if any) have been removed and all occurrences of '/'
285 * have been changed to '.'.
287 * "Dot version" names are used in the class loading machinery.
288 * See also dvmHumanReadableDescriptor.
290 char* dvmDescriptorToDot(const char* str)
292 size_t at = strlen(str);
295 if ((at >= 2) && (str[0] == 'L') && (str[at - 1] == ';')) {
296 at -= 2; /* Two fewer chars to copy. */
297 str++; /* Skip the 'L'. */
300 newStr = (char*)malloc(at + 1); /* Add one for the '\0'. */
308 newStr[at] = (str[at] == '/') ? '.' : str[at];
315 * Return a newly-allocated string for the type descriptor
316 * corresponding to the "dot version" of the given class name. That
317 * is, non-array names are surrounded by "L" and ";", and all
318 * occurrences of '.' have been changed to '/'.
320 * "Dot version" names are used in the class loading machinery.
322 char* dvmDotToDescriptor(const char* str)
324 size_t length = strlen(str);
330 length += 2; /* for "L" and ";" */
334 newStr = at = (char*)malloc(length + 1); /* + 1 for the '\0' */
336 if (newStr == NULL) {
361 * Return a newly-allocated string for the internal-form class name for
362 * the given type descriptor. That is, the initial "L" and final ";" (if
363 * any) have been removed.
365 char* dvmDescriptorToName(const char* str)
368 size_t length = strlen(str) - 1;
369 char* newStr = (char*)malloc(length);
371 if (newStr == NULL) {
375 strlcpy(newStr, str + 1, length);
383 * Return a newly-allocated string for the type descriptor for the given
384 * internal-form class name. That is, a non-array class name will get
385 * surrounded by "L" and ";", while array names are left as-is.
387 char* dvmNameToDescriptor(const char* str)
390 size_t length = strlen(str);
391 char* descriptor = (char*)malloc(length + 3);
393 if (descriptor == NULL) {
398 strcpy(descriptor + 1, str);
399 descriptor[length + 1] = ';';
400 descriptor[length + 2] = '\0';
409 * Get a notion of the current time, in nanoseconds. This is meant for
410 * computing durations (e.g. "operation X took 52nsec"), so the result
411 * should not be used to get the current date/time.
413 u8 dvmGetRelativeTimeNsec()
415 #ifdef HAVE_POSIX_CLOCKS
417 clock_gettime(CLOCK_MONOTONIC, &now);
418 return (u8)now.tv_sec*1000000000LL + now.tv_nsec;
421 gettimeofday(&now, NULL);
422 return (u8)now.tv_sec*1000000000LL + now.tv_usec * 1000LL;
427 * Get the per-thread CPU time, in nanoseconds.
429 * Only useful for time deltas.
431 u8 dvmGetThreadCpuTimeNsec()
433 #ifdef HAVE_POSIX_CLOCKS
435 clock_gettime(CLOCK_THREAD_CPUTIME_ID, &now);
436 return (u8)now.tv_sec*1000000000LL + now.tv_nsec;
443 * Get the per-thread CPU time, in nanoseconds, for the specified thread.
445 u8 dvmGetOtherThreadCpuTimeNsec(pthread_t thread)
447 #if 0 /*def HAVE_POSIX_CLOCKS*/
450 if (pthread_getcpuclockid(thread, &clockId) != 0)
454 clock_gettime(clockId, &now);
455 return (u8)now.tv_sec*1000000000LL + now.tv_nsec;
463 * Call this repeatedly, with successively higher values for "iteration",
464 * to sleep for a period of time not to exceed "maxTotalSleep".
466 * For example, when called with iteration==0 we will sleep for a very
467 * brief time. On the next call we will sleep for a longer time. When
468 * the sum total of all sleeps reaches "maxTotalSleep", this returns false.
470 * The initial start time value for "relStartTime" MUST come from the
471 * dvmGetRelativeTimeUsec call. On the device this must come from the
472 * monotonic clock source, not the wall clock.
474 * This should be used wherever you might be tempted to call sched_yield()
475 * in a loop. The problem with sched_yield is that, for a high-priority
476 * thread, the kernel might not actually transfer control elsewhere.
478 * Returns "false" if we were unable to sleep because our time was up.
480 bool dvmIterativeSleep(int iteration, int maxTotalSleep, u8 relStartTime)
482 const int minSleep = 10000;
487 * Get current time, and see if we've already exceeded the limit.
489 curTime = dvmGetRelativeTimeUsec();
490 if (curTime >= relStartTime + maxTotalSleep) {
491 LOGVV("exsl: sleep exceeded (start=%llu max=%d now=%llu)\n",
492 relStartTime, maxTotalSleep, curTime);
497 * Compute current delay. We're bounded by "maxTotalSleep", so no
498 * real risk of overflow assuming "usleep" isn't returning early.
499 * (Besides, 2^30 usec is about 18 minutes by itself.)
501 * For iteration==0 we just call sched_yield(), so the first sleep
502 * at iteration==1 is actually (minSleep * 2).
505 while (iteration-- > 0)
507 assert(curDelay > 0);
509 if (curTime + curDelay >= relStartTime + maxTotalSleep) {
510 LOGVV("exsl: reduced delay from %d to %d\n",
511 curDelay, (int) ((relStartTime + maxTotalSleep) - curTime));
512 curDelay = (int) ((relStartTime + maxTotalSleep) - curTime);
515 if (iteration == 0) {
516 LOGVV("exsl: yield\n");
519 LOGVV("exsl: sleep for %d\n", curDelay);
527 * Set the "close on exec" flag so we don't expose our file descriptors
528 * to processes launched by us.
530 bool dvmSetCloseOnExec(int fd)
535 * There's presently only one flag defined, so getting the previous
536 * value of the fd flags is probably unnecessary.
538 flags = fcntl(fd, F_GETFD);
540 LOGW("Unable to get fd flags for fd %d\n", fd);
543 if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) < 0) {
544 LOGW("Unable to set close-on-exec for fd %d\n", fd);
551 /* Implementation of strlcpy() for platforms that don't already have it. */
552 size_t strlcpy(char *dst, const char *src, size_t size) {
553 size_t srcLength = strlen(src);
554 size_t copyLength = srcLength;
556 if (srcLength > (size - 1)) {
557 copyLength = size - 1;
561 strncpy(dst, src, copyLength);
562 dst[copyLength] = '\0';
570 * Allocates a memory region using ashmem and mmap, initialized to
571 * zero. Actual allocation rounded up to page multiple. Returns
574 void *dvmAllocRegion(size_t byteCount, int prot, const char *name) {
578 byteCount = ALIGN_UP_TO_PAGE_SIZE(byteCount);
579 fd = ashmem_create_region(name, byteCount);
583 base = mmap(NULL, byteCount, prot, MAP_PRIVATE, fd, 0);
585 if (base == MAP_FAILED) {
595 * Get some per-thread stats.
597 * This is currently generated by opening the appropriate "stat" file
598 * in /proc and reading the pile of stuff that comes out.
600 bool dvmGetThreadStats(ProcStatData* pData, pid_t tid)
606 int ppid, pgrp, session, tty_nr, tpgid;
607 unsigned long flags, minflt, cminflt, majflt, cmajflt, utime, stime;
608 long cutime, cstime, priority, nice, zero, itrealvalue;
609 unsigned long starttime, vsize;
611 unsigned long rlim, startcode, endcode, startstack, kstkesp, kstkeip;
612 unsigned long signal, blocked, sigignore, sigcatch, wchan, nswap, cnswap;
613 int exit_signal, processor;
614 unsigned long rt_priority, policy;
616 scanf("%d %s %c %d %d %d %d %d %lu %lu %lu %lu %lu %lu %lu %ld %ld %ld "
617 "%ld %ld %ld %lu %lu %ld %lu %lu %lu %lu %lu %lu %lu %lu %lu %lu "
618 "%lu %lu %lu %d %d %lu %lu",
619 &pid, comm, &state, &ppid, &pgrp, &session, &tty_nr, &tpgid,
620 &flags, &minflt, &cminflt, &majflt, &cmajflt, &utime, &stime,
621 &cutime, &cstime, &priority, &nice, &zero, &itrealvalue,
622 &starttime, &vsize, &rss, &rlim, &startcode, &endcode,
623 &startstack, &kstkesp, &kstkeip, &signal, &blocked, &sigignore,
624 &sigcatch, &wchan, &nswap, &cnswap, &exit_signal, &processor,
625 &rt_priority, &policy);
627 (new: delayacct_blkio_ticks %llu (since Linux 2.6.18))
634 * Open and read the appropriate file. This is expected to work on
635 * Linux but will fail on other platforms (e.g. Mac sim).
637 sprintf(nameBuf, "/proc/self/task/%d/stat", (int) tid);
638 fd = open(nameBuf, O_RDONLY);
640 LOGV("Unable to open '%s': %s\n", nameBuf, strerror(errno));
644 char lineBuf[512]; /* > 2x typical */
645 int cc = read(fd, lineBuf, sizeof(lineBuf)-1);
647 const char* msg = (cc == 0) ? "unexpected EOF" : strerror(errno);
648 LOGI("Unable to read '%s': %s\n", nameBuf, msg);
656 * Skip whitespace-separated tokens. For the most part we can assume
657 * that tokens do not contain spaces, and are separated by exactly one
658 * space character. The only exception is the second field ("comm")
659 * which may contain spaces but is surrounded by parenthesis.
661 char* cp = strchr(lineBuf, ')');
665 for (i = 2; i < 13; i++) {
666 cp = strchr(cp+1, ' ');
675 pData->utime = strtoul(cp+1, &endp, 10);
677 LOGI("Warning: strtoul failed on utime ('%.30s...')\n", cp);
679 cp = strchr(cp+1, ' ');
683 pData->stime = strtoul(cp+1, &endp, 10);
685 LOGI("Warning: strtoul failed on stime ('%.30s...')\n", cp);
688 * Skip more stuff we don't care about.
690 for (i = 14; i < 38; i++) {
691 cp = strchr(cp+1, ' ');
697 * Grab processor number.
699 pData->processor = strtol(cp+1, &endp, 10);
701 LOGI("Warning: strtoul failed on processor ('%.30s...')\n", cp);
706 LOGI("stat parse failed (%s)\n", lineBuf);
710 /* documented in header file */
711 const char* dvmPathToAbsolutePortion(const char* path) {
716 if (path[0] == '/') {
717 /* It's a regular absolute path. Return it. */
721 const char* sentinel = strstr(path, "/./");
723 if (sentinel != NULL) {
724 /* It's got the sentinel. Return a pointer to the second slash. */