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