Skip to content

Commit

Permalink
review: added assert to get_pending_threads; added suggested coverage…
Browse files Browse the repository at this point in the history
… to test objmonusage003
  • Loading branch information
sspitsyn committed Feb 14, 2024
1 parent 674da98 commit 1ab5b34
Show file tree
Hide file tree
Showing 2 changed files with 132 additions and 26 deletions.
1 change: 1 addition & 0 deletions src/hotspot/share/runtime/threads.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1185,6 +1185,7 @@ void Threads::metadata_handles_do(void f(Metadata*)) {
GrowableArray<JavaThread*>* Threads::get_pending_threads(ThreadsList * t_list,
int count,
address monitor) {
assert(Thread::current()->is_VM_thread(), "Must be the VM thread");
GrowableArray<JavaThread*>* result = new GrowableArray<JavaThread*>(count);

int i = 0;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,9 @@
public class objmonusage003 {

final static int JCK_STATUS_BASE = 95;
final static int NUMBER_OF_ENTERER_THREADS = 4;
final static int NUMBER_OF_WAITER_THREADS = 4;
final static int NUMBER_OF_THREADS = NUMBER_OF_ENTERER_THREADS + NUMBER_OF_WAITER_THREADS;
final static int NUMBER_OF_ENTERING_THREADS = 4;
final static int NUMBER_OF_WAITING_THREADS = 4;
final static int NUMBER_OF_THREADS = NUMBER_OF_ENTERING_THREADS + NUMBER_OF_WAITING_THREADS;

static {
try {
Expand All @@ -44,48 +44,137 @@ public class objmonusage003 {
}

static Object lockCheck = new Object();
static TestThread thr[] = new TestThread[NUMBER_OF_THREADS];

native static int getRes();
native static void check(Object obj, Thread owner,
int entryCount, int waiterCount, int notifyWaiterCount);

public static void main(String args[]) {
args = nsk.share.jvmti.JVMTITest.commonInit(args);
/* Scenario #1:
* - non-zero entering threads
* - zero re-entering threads
* - zero threads waiting to be notified
*/
static void test1() throws Error {
synchronized (lockCheck) {
// entry count: 1
// count of threads waiting to enter: 0
// count of threads waiting to re-enter: 0
// count of threads waiting to be notified: 0
check(lockCheck, Thread.currentThread(), 1, 0, 0);

// produce JCK-like exit status.
System.exit(run(args, System.out) + JCK_STATUS_BASE);
for (int i = 0; i < NUMBER_OF_ENTERING_THREADS; i++) {
thr[i] = new EnteringThread();
thr[i].start();
// this EnteringThread has to be blocked on the lockCheck enter
thr[i].waitReady();
}
// entry count: 1
// count of threads waiting to enter: NUMBER_OF_ENTERING_THREADS
// count of threads waiting to re-enter: 0
// count of threads waiting to be notified: 0
check(lockCheck, Thread.currentThread(), 1,
NUMBER_OF_ENTERING_THREADS,
0 /* count of threads waiting to be notified: 0 */);
}
for (int i = 0; i < NUMBER_OF_ENTERING_THREADS; i++) {
try {
thr[i].join();
} catch (InterruptedException e) {
throw new Error("Unexpected " + e);
}
}
}

public static int run(String args[], PrintStream out) {
check(lockCheck, null, 0, 0, 0);

/* Scenario #2:
* - non-zero entering threads
* - zero re-entering threads
* - non-zero waiting to be notified
*/
static void test2() throws Error {
for (int i = NUMBER_OF_ENTERING_THREADS; i < NUMBER_OF_THREADS; i++) {
thr[i] = new WaitingThread();
thr[i].start();
thr[i].waitReady(); // the WaitingThread has to wait to be notified in a lockCheck.wait()
}
synchronized (lockCheck) {
check(lockCheck, Thread.currentThread(), 1, 0, 0);
for (int i = 0; i < NUMBER_OF_ENTERING_THREADS; i++) {
thr[i] = new EnteringThread();
thr[i].start();
thr[i].waitReady(); // the EnteringThread has to block on monitor enter
}
// entry count: 1
// count of threads waiting to enter: NUMBER_OF_ENTERING_THREADS
// count of threads waiting to re-enter: 0
// count of threads waiting to be notified: NUMBER_OF_WAITING_THREADS
check(lockCheck, Thread.currentThread(), 1,
NUMBER_OF_ENTERING_THREADS,
NUMBER_OF_WAITING_THREADS);

lockCheck.notifyAll();
}
for (int i = 0; i < NUMBER_OF_THREADS; i++) {
try {
thr[i].join();
} catch (InterruptedException e) {
throw new Error("Unexpected " + e);
}
}
}

TestThread thr[] = new TestThread[NUMBER_OF_THREADS];
for (int i = NUMBER_OF_ENTERER_THREADS; i < NUMBER_OF_THREADS; i++) {
thr[i] = new WaiterThread();
/* Scenario #3:
* Initially we have:
* - zero entering threads
* - zero re-entering threads
* - non-zero threads waiting to be notified
*
* The threads waiting to be notified are being notified one-by-one
* until all threads are blocked on re-entering the monitor.
* The numbers of entering/re-entering and waiting threads are checked
* for correctness after each notification.
*/
static void test3() throws Error {
for (int i = NUMBER_OF_ENTERING_THREADS; i < NUMBER_OF_THREADS; i++) {
thr[i] = new WaitingThread();
thr[i].start();
// the WaiterThread has to wait to be notified in a lockCheck.wait()
// the WaitingThread has to wait to be notified in a lockCheck.wait()
thr[i].waitReady();
}
synchronized (lockCheck) {
for (int i = 0; i < NUMBER_OF_ENTERER_THREADS; i++) {
thr[i] = new EntererThread();
// entry count: 1
// count of threads waiting to enter: 0
// count of threads waiting to re-enter: 0
// count of threads waiting to be notified: NUMBER_OF_WAITING_THREADS
check(lockCheck, Thread.currentThread(), 1,
0, // number of threads waiting to enter or re-enter
NUMBER_OF_WAITING_THREADS);

for (int i = 0; i < NUMBER_OF_ENTERING_THREADS; i++) {
thr[i] = new EnteringThread();
thr[i].start();
// the EntererThread has to be blocked on the lockCheck enter
// this EnteringThread has to be blocked on the lockCheck enter
thr[i].waitReady();
}

// entry count: 1
// count of threads waiting to enter: NUMBER_OF_ENTERING_THREADS
// count of threads waiting to re-enter: 0
// count of threads waiting to be notified: NUMBER_OF_WAITING_THREADS
check(lockCheck, Thread.currentThread(), 1,
NUMBER_OF_ENTERER_THREADS,
NUMBER_OF_WAITER_THREADS);
for (int i = 0; i < NUMBER_OF_WAITER_THREADS; i++) {
NUMBER_OF_ENTERING_THREADS,
NUMBER_OF_WAITING_THREADS);

for (int i = 0; i < NUMBER_OF_WAITING_THREADS; i++) {
lockCheck.notify();
// now the notified WaiterThread has to be blocked on the lockCheck re-enter
// now the notified WaitingThread has to be blocked on the lockCheck re-enter

// entry count: 1
// count of threads waiting to enter: NUMBER_OF_ENTERING_THREADS
// count of threads waiting to re-enter: i + 1
// count of threads waiting to be notified: NUMBER_OF_WAITING_THREADS - i - 1
check(lockCheck, Thread.currentThread(), 1,
NUMBER_OF_ENTERER_THREADS + i + 1,
NUMBER_OF_WAITER_THREADS - i - 1);
NUMBER_OF_ENTERING_THREADS + i + 1,
NUMBER_OF_WAITING_THREADS - i - 1);
}
}
for (int i = 0; i < NUMBER_OF_THREADS; i++) {
Expand All @@ -95,6 +184,22 @@ public static int run(String args[], PrintStream out) {
throw new Error("Unexpected " + e);
}
}
}

public static void main(String args[]) {
args = nsk.share.jvmti.JVMTITest.commonInit(args);

// produce JCK-like exit status.
System.exit(run(args, System.out) + JCK_STATUS_BASE);
}

public static int run(String args[], PrintStream out) {
check(lockCheck, null, 0, 0, 0);

test1();
test2();
test3();

check(lockCheck, null, 0, 0, 0);
return getRes();
}
Expand All @@ -112,15 +217,15 @@ public void waitReady() {
}
}

static class EntererThread extends TestThread {
static class EnteringThread extends TestThread {
public void run() {
ready = true;
synchronized (lockCheck) {
}
}
}

static class WaiterThread extends TestThread {
static class WaitingThread extends TestThread {
public void run() {
synchronized (lockCheck) {
try {
Expand Down

0 comments on commit 1ab5b34

Please sign in to comment.