• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <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  *
33 01234567: 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  */
dvmPrintHexDumpEx(int priority,const char * tag,const void * vaddr,size_t length,HexDumpMode mode)44 void 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  */
dvmCreateLogOutputTarget(DebugOutputTarget * target,int priority,const char * tag)134 void 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  */
dvmCreateFileOutputTarget(DebugOutputTarget * target,FILE * fp)148 void 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  */
dvmFreeOutputTarget(DebugOutputTarget * target)160 void dvmFreeOutputTarget(DebugOutputTarget* target)
161 {
162     free(target);
163 }
164 
165 /*
166  * Print a debug message, to either a file or the log.
167  */
dvmPrintDebugMessage(const DebugOutputTarget * target,const char * format,...)168 void 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  */
dvmAllocBitVector(int startBits,bool expandable)196 BitVector* 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  */
dvmFreeBitVector(BitVector * pBits)218 void 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  */
dvmAllocBit(BitVector * pBits)234 int dvmAllocBit(BitVector* pBits)
235 {
236     int word, bit;
237 
238 retry:
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  */
dvmSetBit(BitVector * pBits,int num)271 bool 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));
283     }
284 
285     pBits->storage[num >> 5] |= 1 << (num & 0x1f);
286     return true;
287 }
288 
289 /*
290  * Mark the specified bit as "clear".
291  */
dvmClearBit(BitVector * pBits,int num)292 void dvmClearBit(BitVector* pBits, int num)
293 {
294     assert(num >= 0 && num < (int) pBits->storageSize * (int)sizeof(u4) * 8);
295 
296     pBits->storage[num >> 5] &= ~(1 << (num & 0x1f));
297 }
298 
299 /*
300  * Determine whether or not the specified bit is set.
301  */
dvmIsBitSet(const BitVector * pBits,int num)302 bool dvmIsBitSet(const BitVector* pBits, int num)
303 {
304     assert(num >= 0 && num < (int) pBits->storageSize * (int)sizeof(u4) * 8);
305 
306     int val = pBits->storage[num >> 5] & (1 << (num & 0x1f));
307     return (val != 0);
308 }
309 
310 /*
311  * Count the number of bits that are set.
312  */
dvmCountSetBits(const BitVector * pBits)313 int dvmCountSetBits(const BitVector* pBits)
314 {
315     int word, bit;
316     int count = 0;
317 
318     for (word = 0; word < pBits->storageSize; word++) {
319         u4 val = pBits->storage[word];
320 
321         if (val != 0) {
322             if (val == 0xffffffff) {
323                 count += 32;
324             } else {
325                 /* count the number of '1' bits */
326                 while (val != 0) {
327                     val &= val - 1;
328                     count++;
329                 }
330             }
331         }
332     }
333 
334     return count;
335 }
336 
337 
338 /*
339  * Return a newly-allocated string in which all occurrences of '.' have
340  * been changed to '/'.  If we find a '/' in the original string, NULL
341  * is returned to avoid ambiguity.
342  */
dvmDotToSlash(const char * str)343 char* dvmDotToSlash(const char* str)
344 {
345     char* newStr = strdup(str);
346     char* cp = newStr;
347 
348     while (*cp != '\0') {
349         if (*cp == '/') {
350             assert(false);
351             return NULL;
352         }
353         if (*cp == '.')
354             *cp = '/';
355         cp++;
356     }
357 
358     return newStr;
359 }
360 
361 /*
362  * Return a newly-allocated string for the "dot version" of the class
363  * name for the given type descriptor. That is, The initial "L" and
364  * final ";" (if any) have been removed and all occurrences of '/'
365  * have been changed to '.'.
366  */
dvmDescriptorToDot(const char * str)367 char* dvmDescriptorToDot(const char* str)
368 {
369     size_t at = strlen(str);
370     char* newStr;
371 
372     if ((at >= 2) && (str[0] == 'L') && (str[at - 1] == ';')) {
373         at -= 2; /* Two fewer chars to copy. */
374         str++; /* Skip the 'L'. */
375     }
376 
377     newStr = malloc(at + 1); /* Add one for the '\0'. */
378     newStr[at] = '\0';
379 
380     while (at > 0) {
381         at--;
382         newStr[at] = (str[at] == '/') ? '.' : str[at];
383     }
384 
385     return newStr;
386 }
387 
388 /*
389  * Return a newly-allocated string for the type descriptor
390  * corresponding to the "dot version" of the given class name. That
391  * is, non-array names are surrounded by "L" and ";", and all
392  * occurrences of '.' are changed to '/'.
393  */
dvmDotToDescriptor(const char * str)394 char* dvmDotToDescriptor(const char* str)
395 {
396     size_t length = strlen(str);
397     int wrapElSemi = 0;
398     char* newStr;
399     char* at;
400 
401     if (str[0] != '[') {
402         length += 2; /* for "L" and ";" */
403         wrapElSemi = 1;
404     }
405 
406     newStr = at = malloc(length + 1); /* + 1 for the '\0' */
407 
408     if (newStr == NULL) {
409         return NULL;
410     }
411 
412     if (wrapElSemi) {
413         *(at++) = 'L';
414     }
415 
416     while (*str) {
417         char c = *(str++);
418         if (c == '.') {
419             c = '/';
420         }
421         *(at++) = c;
422     }
423 
424     if (wrapElSemi) {
425         *(at++) = ';';
426     }
427 
428     *at = '\0';
429     return newStr;
430 }
431 
432 /*
433  * Return a newly-allocated string for the internal-form class name for
434  * the given type descriptor. That is, the initial "L" and final ";" (if
435  * any) have been removed.
436  */
dvmDescriptorToName(const char * str)437 char* dvmDescriptorToName(const char* str)
438 {
439     if (str[0] == 'L') {
440         size_t length = strlen(str) - 1;
441         char* newStr = malloc(length);
442 
443         if (newStr == NULL) {
444             return NULL;
445         }
446 
447         strlcpy(newStr, str + 1, length);
448         return newStr;
449     }
450 
451     return strdup(str);
452 }
453 
454 /*
455  * Return a newly-allocated string for the type descriptor for the given
456  * internal-form class name. That is, a non-array class name will get
457  * surrounded by "L" and ";", while array names are left as-is.
458  */
dvmNameToDescriptor(const char * str)459 char* dvmNameToDescriptor(const char* str)
460 {
461     if (str[0] != '[') {
462         size_t length = strlen(str);
463         char* descriptor = malloc(length + 3);
464 
465         if (descriptor == NULL) {
466             return NULL;
467         }
468 
469         descriptor[0] = 'L';
470         strcpy(descriptor + 1, str);
471         descriptor[length + 1] = ';';
472         descriptor[length + 2] = '\0';
473 
474         return descriptor;
475     }
476 
477     return strdup(str);
478 }
479 
480 /*
481  * Get a notion of the current time, in nanoseconds.  This is meant for
482  * computing durations (e.g. "operation X took 52nsec"), so the result
483  * should not be used to get the current date/time.
484  */
dvmGetRelativeTimeNsec(void)485 u8 dvmGetRelativeTimeNsec(void)
486 {
487 #ifdef HAVE_POSIX_CLOCKS
488     struct timespec now;
489     clock_gettime(CLOCK_MONOTONIC, &now);
490     return (u8)now.tv_sec*1000000000LL + now.tv_nsec;
491 #else
492     struct timeval now;
493     gettimeofday(&now, NULL);
494     return (u8)now.tv_sec*1000000000LL + now.tv_usec * 1000LL;
495 #endif
496 }
497 
498 /*
499  * Get the per-thread CPU time, in nanoseconds.
500  *
501  * Only useful for time deltas.
502  */
dvmGetThreadCpuTimeNsec(void)503 u8 dvmGetThreadCpuTimeNsec(void)
504 {
505 #ifdef HAVE_POSIX_CLOCKS
506     struct timespec now;
507     clock_gettime(CLOCK_THREAD_CPUTIME_ID, &now);
508     return (u8)now.tv_sec*1000000000LL + now.tv_nsec;
509 #else
510     return (u8) -1;
511 #endif
512 }
513 
514 /*
515  * Get the per-thread CPU time, in nanoseconds, for the specified thread.
516  */
dvmGetOtherThreadCpuTimeNsec(pthread_t thread)517 u8 dvmGetOtherThreadCpuTimeNsec(pthread_t thread)
518 {
519 #if 0 /*def HAVE_POSIX_CLOCKS*/
520     int clockId;
521 
522     if (pthread_getcpuclockid(thread, &clockId) != 0)
523         return (u8) -1;
524 
525     struct timespec now;
526     clock_gettime(clockId, &now);
527     return (u8)now.tv_sec*1000000000LL + now.tv_nsec;
528 #else
529     return (u8) -1;
530 #endif
531 }
532 
533 
534 /*
535  * Call this repeatedly, with successively higher values for "iteration",
536  * to sleep for a period of time not to exceed "maxTotalSleep".
537  *
538  * For example, when called with iteration==0 we will sleep for a very
539  * brief time.  On the next call we will sleep for a longer time.  When
540  * the sum total of all sleeps reaches "maxTotalSleep", this returns false.
541  *
542  * The initial start time value for "relStartTime" MUST come from the
543  * dvmGetRelativeTimeUsec call.  On the device this must come from the
544  * monotonic clock source, not the wall clock.
545  *
546  * This should be used wherever you might be tempted to call sched_yield()
547  * in a loop.  The problem with sched_yield is that, for a high-priority
548  * thread, the kernel might not actually transfer control elsewhere.
549  *
550  * Returns "false" if we were unable to sleep because our time was up.
551  */
dvmIterativeSleep(int iteration,int maxTotalSleep,u8 relStartTime)552 bool dvmIterativeSleep(int iteration, int maxTotalSleep, u8 relStartTime)
553 {
554     const int minSleep = 10000;
555     u8 curTime;
556     int curDelay;
557 
558     /*
559      * Get current time, and see if we've already exceeded the limit.
560      */
561     curTime = dvmGetRelativeTimeUsec();
562     if (curTime >= relStartTime + maxTotalSleep) {
563         LOGVV("exsl: sleep exceeded (start=%llu max=%d now=%llu)\n",
564             relStartTime, maxTotalSleep, curTime);
565         return false;
566     }
567 
568     /*
569      * Compute current delay.  We're bounded by "maxTotalSleep", so no
570      * real risk of overflow assuming "usleep" isn't returning early.
571      * (Besides, 2^30 usec is about 18 minutes by itself.)
572      *
573      * For iteration==0 we just call sched_yield(), so the first sleep
574      * at iteration==1 is actually (minSleep * 2).
575      */
576     curDelay = minSleep;
577     while (iteration-- > 0)
578         curDelay *= 2;
579     assert(curDelay > 0);
580 
581     if (curTime + curDelay >= relStartTime + maxTotalSleep) {
582         LOGVV("exsl: reduced delay from %d to %d\n",
583             curDelay, (int) ((relStartTime + maxTotalSleep) - curTime));
584         curDelay = (int) ((relStartTime + maxTotalSleep) - curTime);
585     }
586 
587     if (iteration == 0) {
588         LOGVV("exsl: yield\n");
589         sched_yield();
590     } else {
591         LOGVV("exsl: sleep for %d\n", curDelay);
592         usleep(curDelay);
593     }
594     return true;
595 }
596 
597 
598 /*
599  * Set the "close on exec" flag so we don't expose our file descriptors
600  * to processes launched by us.
601  */
dvmSetCloseOnExec(int fd)602 bool dvmSetCloseOnExec(int fd)
603 {
604     int flags;
605 
606     /*
607      * There's presently only one flag defined, so getting the previous
608      * value of the fd flags is probably unnecessary.
609      */
610     flags = fcntl(fd, F_GETFD);
611     if (flags < 0) {
612         LOGW("Unable to get fd flags for fd %d\n", fd);
613         return false;
614     }
615     if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) < 0) {
616         LOGW("Unable to set close-on-exec for fd %d\n", fd);
617         return false;
618     }
619     return true;
620 }
621 
622 #if (!HAVE_STRLCPY)
623 /* Implementation of strlcpy() for platforms that don't already have it. */
strlcpy(char * dst,const char * src,size_t size)624 size_t strlcpy(char *dst, const char *src, size_t size) {
625     size_t srcLength = strlen(src);
626     size_t copyLength = srcLength;
627 
628     if (srcLength > (size - 1)) {
629         copyLength = size - 1;
630     }
631 
632     if (size != 0) {
633         strncpy(dst, src, copyLength);
634         dst[copyLength] = '\0';
635     }
636 
637     return srcLength;
638 }
639 #endif
640