Skip to content
Permalink
Browse files
Merge branch 'fibers' of https://github.com/openjdk/loom into fibers
  • Loading branch information
lmesnik committed Mar 12, 2021
2 parents 923370d + a9b7b05 commit c623197aba63b4db0310ff4bd086a1db20d874ef
Show file tree
Hide file tree
Showing 4 changed files with 76 additions and 35 deletions.
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1998, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1998, 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -876,7 +876,9 @@ printUsage(void)
"onthrow=<exception name> debug on throw none\n"
"onuncaught=y|n debug on any uncaught? n\n"
"timeout=<timeout value> for listen/attach in milliseconds n\n"
"virtualthreads=y|n|all support debugging virtual threads y\n"
"trackvthreads=some|all track some or all vthreads some\n"
"enumeratevthreads=y|n thread lists include vthreads y\n"
"fakevthreadstartevent=y|n send fake start event when needed y\n"
"mutf8=y|n output modified utf-8 n\n"
"quiet=y|n control over terminal messages n\n"));

@@ -1025,7 +1027,9 @@ parseOptions(char *options)

/* Set vthread debugging level. */
gdata->vthreadsSupported = JNI_TRUE;
gdata->notifyDebuggerOfAllVThreads = JNI_FALSE;
gdata->trackAllVThreads = JNI_FALSE;
gdata->enumerateVThreads = JNI_TRUE;
gdata->fakeVThreadStartEvent = JNI_TRUE;

/* Options being NULL will end up being an error. */
if (options == NULL) {
@@ -1129,19 +1133,38 @@ parseOptions(char *options)
}
currentTransport->timeout = atol(current);
current += strlen(current) + 1;
} else if (strcmp(buf, "virtualthreads") == 0) {
} else if (strcmp(buf, "trackvthreads") == 0) {
if (!get_tok(&str, current, (int)(end - current), ',')) {
goto syntax_error;
}
if (strcmp(current, "y") == 0) {
gdata->vthreadsSupported = JNI_TRUE;
gdata->notifyDebuggerOfAllVThreads = JNI_FALSE;
if (strcmp(current, "some") == 0) {
gdata->trackAllVThreads = JNI_FALSE;
} else if (strcmp(current, "all") == 0) {
gdata->vthreadsSupported = JNI_TRUE;
gdata->notifyDebuggerOfAllVThreads = JNI_TRUE;
gdata->trackAllVThreads = JNI_TRUE;
} else {
goto syntax_error;
}
current += strlen(current) + 1;
} else if (strcmp(buf, "enumeratevthreads") == 0) {
if (!get_tok(&str, current, (int)(end - current), ',')) {
goto syntax_error;
}
if (strcmp(current, "y") == 0) {
gdata->enumerateVThreads = JNI_TRUE;
} else if (strcmp(current, "n") == 0) {
gdata->enumerateVThreads = JNI_FALSE;
} else {
goto syntax_error;
}
current += strlen(current) + 1;
} else if (strcmp(buf, "fakevthreadstartevent") == 0) {
if (!get_tok(&str, current, (int)(end - current), ',')) {
goto syntax_error;
}
if (strcmp(current, "y") == 0) {
gdata->fakeVThreadStartEvent = JNI_TRUE;
} else if (strcmp(current, "n") == 0) {
gdata->vthreadsSupported = JNI_FALSE;
gdata->notifyDebuggerOfAllVThreads = JNI_FALSE;
gdata->fakeVThreadStartEvent = JNI_FALSE;
} else {
goto syntax_error;
}
@@ -647,25 +647,29 @@ filterAndAddVThread(JNIEnv *env, EventInfo *evinfo, EventIndex ei, jbyte eventSe
/* Make sure this vthread gets added to the vthreads list. */
threadControl_addVThread(vthread);

/*
* When the VIRTUAL_THREAD_SCHEDULED event arrived for this vthread, we ignored it since we don't
* want to notify the debugger about vthreads until there is a non-vthread event that
* arrives on it (like a breakpoint). Now that this has happened, we need to send
* a VIRTUAL_THREAD_SCHEDULED event (which will be converted into a THREAD_START event) so
* the debugger will know about the vthread. Otherwise it will be unhappy when it gets
* an event for a vthread that it never got a THREAD_START event for.
*/
EventInfo info;
struct bag *eventBag = eventHelper_createEventBag();

(void)memset(&info,0,sizeof(info));
info.ei = EI_VIRTUAL_THREAD_SCHEDULED;
info.thread = vthread;

/* Note: filterAndHandleEvent() expects EI_THREAD_START instead of EI_VIRTUAL_THREAD_SCHEDULED. */
filterAndHandleEvent(env, &info, EI_THREAD_START, eventBag, eventSessionID);
JDI_ASSERT(bagSize(eventBag) == 0);
bagDestroyBag(eventBag);
if (gdata->fakeVThreadStartEvent) {
/* vthread fixme: this shouldn't be needed if ei == EI_THREAD_START. */
/*
* When the VIRTUAL_THREAD_SCHEDULED event arrived for this vthread, we ignored it since we don't
* want to notify the debugger about vthreads until there is a non-vthread event that
* arrives on it (like a breakpoint). Now that this has happened, we need to send
* a VIRTUAL_THREAD_SCHEDULED event (which will be converted into a THREAD_START event) so
* the debugger will know about the vthread. Otherwise it will be unhappy when it gets
* an event for a vthread that it never got a THREAD_START event for.
*/
EventInfo info;
struct bag *eventBag = eventHelper_createEventBag();

(void)memset(&info,0,sizeof(info));
info.ei = EI_VIRTUAL_THREAD_SCHEDULED;
info.thread = vthread;

/* Note: filterAndHandleEvent() expects EI_THREAD_START instead of EI_VIRTUAL_THREAD_SCHEDULED
* in order for getHandlerChain(ei) to work properly. */
filterAndHandleEvent(env, &info, EI_THREAD_START, eventBag, eventSessionID);
JDI_ASSERT(bagSize(eventBag) == 0);
bagDestroyBag(eventBag);
}
}
}

@@ -784,9 +788,13 @@ event_callback(JNIEnv *env, EventInfo *evinfo)
if (gdata->vthreadsSupported) {
/* Add the vthread if we haven't added it before. */
if (evinfo->is_vthread && !threadControl_isKnownVThread(thread)) {
if (gdata->notifyDebuggerOfAllVThreads) {
if (gdata->trackAllVThreads) {
/* Make sure this vthread gets added to the vthreads list. */
threadControl_addVThread(thread);
/* vthread fixme: we need to fake a THREAD_START event here just like
* filterAndAddVThread() does. This is needed when the debug
* agent is started after some vthreads have already been started.
*/
} else {
/* Add this vthread if it passes the event filters. */
filterAndAddVThread(env, evinfo, ei, eventSessionID);
@@ -1448,6 +1456,11 @@ cbVThreadScheduled(jvmtiEnv *jvmti_env, JNIEnv *env,
}
}

/* Ignore VIRTUAL_THREAD_SCHEDULED events unless we are notifying the debugger of all vthreads. */
if (!gdata->trackAllVThreads || !gdata->enumerateVThreads) {
return;
}

BEGIN_CALLBACK() {
(void)memset(&info,0,sizeof(info));
info.ei = EI_THREAD_START;
@@ -2691,6 +2691,11 @@ threadControl_allVThreads(jint *numVThreads)
ThreadNode *node;
jthread* vthreads;

if (!gdata->enumerateVThreads) {
*numVThreads = 0;
return NULL;
}

env = getEnv();
debugMonitorEnter(threadLock);

@@ -83,10 +83,10 @@ typedef struct {
volatile jboolean vmDead; /* Once VM is dead it stays that way - don't put in init */
jboolean assertOn;
jboolean assertFatal;
jboolean vthreadsSupported; /* If true, debugging support for vthreads is enabled.*/
jboolean notifyDebuggerOfAllVThreads; /* If true, the debugger will be notified of all known vthreads.
* If false the debugger is only notified of vthreads for which
* certain events have been received. */
jboolean vthreadsSupported; /* If true, debugging support for vthreads is enabled.*/
jboolean trackAllVThreads; /* If true, track all vthreads. Otherwise just ones we get events on. */
jboolean enumerateVThreads; /* If true, JDWP APIs return tracked vthreads in thread lists. Otherwise they don't. */
jboolean fakeVThreadStartEvent; /* If true, send a fake THREAD_START event the first time we get an event on a vthread. */
jboolean doerrorexit;
jboolean modifiedUtf8;
jboolean quiet;

0 comments on commit c623197

Please sign in to comment.