예제 #1
0
/*
 * Send a notification when a thread's name changes.
 */
void dvmDdmSendThreadNameChange(int threadId, StringObject* newName)
{
    if (!gDvm.ddmThreadNotification)
        return;

    size_t stringLen = dvmStringLen(newName);
    const u2* chars = dvmStringChars(newName);

    /*
     * Output format:
     *  (4b) thread ID
     *  (4b) stringLen
     *  (xb) string chars
     */
    int bufLen = 4 + 4 + (stringLen * 2);
    u1 buf[bufLen];

    set4BE(&buf[0x00], threadId);
    set4BE(&buf[0x04], stringLen);
    u2* outChars = (u2*) &buf[0x08];
    while (stringLen--)
        set2BE((u1*) (outChars++), *chars++);

    dvmDbgDdmSendChunk(CHUNK_TYPE("THNM"), bufLen, buf);
}
예제 #2
0
/*
 * Generate the contents of a THST chunk.  The data encompasses all known
 * threads.
 *
 * Response has:
 *  (1b) header len
 *  (1b) bytes per entry
 *  (2b) thread count
 * Then, for each thread:
 *  (4b) threadId
 *  (1b) thread status
 *  (4b) tid
 *  (4b) utime 
 *  (4b) stime 
 *  (1b) is daemon?
 *
 * The length fields exist in anticipation of adding additional fields
 * without wanting to break ddms or bump the full protocol version.  I don't
 * think it warrants full versioning.  They might be extraneous and could
 * be removed from a future version.
 *
 * Returns a new byte[] with the data inside, or NULL on failure.  The
 * caller must call dvmReleaseTrackedAlloc() on the array.
 */
ArrayObject* dvmDdmGenerateThreadStats(void)
{
    const int kHeaderLen = 4;
    const int kBytesPerEntry = 18;

    dvmLockThreadList(NULL);

    Thread* thread;
    int threadCount = 0;
    for (thread = gDvm.threadList; thread != NULL; thread = thread->next)
        threadCount++;

    /*
     * Create a temporary buffer.  We can't perform heap allocation with
     * the thread list lock held (could cause a GC).  The output is small
     * enough to sit on the stack.
     */
    int bufLen = kHeaderLen + threadCount * kBytesPerEntry;
    u1 tmpBuf[bufLen];
    u1* buf = tmpBuf;

    set1(buf+0, kHeaderLen);
    set1(buf+1, kBytesPerEntry);
    set2BE(buf+2, (u2) threadCount);
    buf += kHeaderLen;

    pid_t pid = getpid();
    for (thread = gDvm.threadList; thread != NULL; thread = thread->next) {
        unsigned long utime, stime;
        bool isDaemon;

        if (!getThreadStats(pid, thread->systemTid, &utime, &stime)) {
            // failed; drop in empty values
            utime = stime = 0;
        }

        isDaemon = dvmGetFieldBoolean(thread->threadObj,
                        gDvm.offJavaLangThread_daemon);

        set4BE(buf+0, thread->threadId);
        set1(buf+4, thread->status);
        set4BE(buf+5, thread->systemTid);
        set4BE(buf+9, utime);
        set4BE(buf+13, stime);
        set1(buf+17, isDaemon);

        buf += kBytesPerEntry;
    }
    dvmUnlockThreadList();


    /*
     * Create a byte array to hold the data.
     */
    ArrayObject* arrayObj = dvmAllocPrimitiveArray('B', bufLen, ALLOC_DEFAULT);
    if (arrayObj != NULL)
        memcpy(arrayObj->contents, tmpBuf, bufLen);
    return arrayObj;
}
예제 #3
0
/*
 * Send a notification when a thread starts or stops.
 *
 * Because we broadcast the full set of threads when the notifications are
 * first enabled, it's possible for "thread" to be actively executing.
 */
void dvmDdmSendThreadNotification(Thread* thread, bool started)
{
    if (!gDvm.ddmThreadNotification)
        return;

    StringObject* nameObj = NULL;
    Object* threadObj = thread->threadObj;

    if (threadObj != NULL) {
        nameObj = (StringObject*)
            dvmGetFieldObject(threadObj, gDvm.offJavaLangThread_name);
    }

    int type, len;
    u1 buf[256];

    if (started) {
        const u2* chars;
        u2* outChars;
        size_t stringLen;

        type = CHUNK_TYPE("THCR");

        if (nameObj != NULL) {
            stringLen = dvmStringLen(nameObj);
            chars = dvmStringChars(nameObj);
        } else {
            stringLen = 0;
            chars = NULL;
        }

        /* leave room for the two integer fields */
        if (stringLen > (sizeof(buf) - sizeof(u4)*2) / 2)
            stringLen = (sizeof(buf) - sizeof(u4)*2) / 2;
        len = stringLen*2 + sizeof(u4)*2;

        set4BE(&buf[0x00], thread->threadId);
        set4BE(&buf[0x04], stringLen);

        /* copy the UTF-16 string, transforming to big-endian */
        outChars = (u2*) &buf[0x08];
        while (stringLen--)
            set2BE((u1*) (outChars++), *chars++);
    } else {
        type = CHUNK_TYPE("THDE");

        len = 4;

        set4BE(&buf[0x00], thread->threadId);
    }

    dvmDbgDdmSendChunk(type, len, buf);
}
예제 #4
0
파일: ExpandBuf.cpp 프로젝트: hhhaiai/JNI
/*
 * Append two big-endian bytes.
 */
void expandBufAdd2BE(ExpandBuf *pBuf, u2 val) {
    ensureSpace(pBuf, sizeof(val));
    set2BE(pBuf->storage + pBuf->curLen, val);
    pBuf->curLen += sizeof(val);
}