Skip to content

Commit 3bfa32f

Browse files
committed
runtime/native: transition some java.lang.Thread natives to JNI
Only moved over a few methods needed for early boot.
1 parent ac6dd6f commit 3bfa32f

File tree

3 files changed

+72
-98
lines changed

3 files changed

+72
-98
lines changed

runtime/src/native/java/lang/Thread.rs

Lines changed: 1 addition & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,10 @@ use crate::thread::pool::ThreadPool;
77
use crate::thread::{JavaThread, JavaThreadBuilder};
88

99
use std::cmp;
10-
use std::sync::atomic::AtomicUsize;
1110

1211
use ::jni::env::JniEnv;
13-
use ::jni::sys::{jboolean, jint, jlong};
12+
use ::jni::sys::{jboolean, jlong};
1413

15-
include_generated!("native/java/lang/def/Thread.registerNatives.rs");
1614
include_generated!("native/java/lang/def/Thread.definitions.rs");
1715

1816
pub fn findScopedValueBindings(_env: JniEnv, _class: ClassPtr) -> Reference /* java.lang.Object */
@@ -25,14 +23,6 @@ pub fn currentCarrierThread(_env: JniEnv, _class: ClassPtr) -> Reference /* java
2523
unimplemented!("java.lang.Thread#currentCarrierThread");
2624
}
2725

28-
pub fn currentThread(env: JniEnv, _class: ClassPtr) -> Reference /* java.lang.Thread */
29-
{
30-
unsafe {
31-
let thread = JavaThread::for_env(env.raw().cast_const());
32-
(*thread).obj().expect("current thread should exist")
33-
}
34-
}
35-
3626
pub fn setCurrentThread(
3727
_env: JniEnv,
3828
_this: Reference, // java.lang.Thread
@@ -54,14 +44,6 @@ pub fn setScopedValueCache(
5444
unimplemented!("java.lang.Thread#setScopedValueCache");
5545
}
5646

57-
pub fn ensureMaterializedForStackWalk(
58-
_env: JniEnv,
59-
_class: ClassPtr,
60-
_o: Reference, // java.lang.Object
61-
) {
62-
// Nothing to do
63-
}
64-
6547
pub fn yield0(_env: JniEnv, _class: ClassPtr) {
6648
std::thread::yield_now();
6749
}
@@ -71,35 +53,6 @@ pub fn sleepNanos0(_env: JniEnv, _class: ClassPtr, _nanos: jlong) {
7153
unimplemented!("java.lang.Thread#sleepNanos0");
7254
}
7355

74-
pub fn start0(_env: JniEnv, this: Reference /* java.lang.Thread */) {
75-
{
76-
if let Some(existing_thread) = ThreadPool::find_from_obj(this) {
77-
throw!(existing_thread, IllegalThreadStateException);
78-
}
79-
}
80-
81-
let holder = classes::java::lang::Thread::holder(this.extract_class());
82-
let stack_size_raw = classes::java::lang::Thread::holder::stackSize(holder.extract_class());
83-
84-
let mut thread_builder = JavaThreadBuilder::new()
85-
.obj(this)
86-
.entry_point(JavaThread::default_entry_point);
87-
88-
if stack_size_raw > 0 {
89-
let stack_size = cmp::min(stack_size_raw as usize, u32::MAX as usize);
90-
thread_builder = thread_builder.stack_size(stack_size);
91-
}
92-
93-
let thread = thread_builder.finish();
94-
95-
let obj = thread.obj().expect("current thread object should exist");
96-
let holder = classes::java::lang::Thread::holder(obj.extract_class());
97-
classes::java::lang::Thread::holder::set_threadStatus(
98-
holder.extract_class(),
99-
ThreadStatus::Runnable,
100-
);
101-
}
102-
10356
pub fn holdsLock(
10457
_env: JniEnv,
10558
_class: ClassPtr,
@@ -130,23 +83,6 @@ pub fn getThreads(_env: JniEnv, _class: ClassPtr) -> Reference /* []java.lang.Th
13083
unimplemented!("java.lang.Thread#getThreads");
13184
}
13285

133-
pub fn setPriority0(
134-
_env: JniEnv,
135-
this: Reference, // java.lang.Thread
136-
new_priority: jint,
137-
) {
138-
let holder = classes::java::lang::Thread::holder(this.extract_class());
139-
classes::java::lang::Thread::holder::set_priority(holder.extract_class(), new_priority);
140-
141-
let java_thread = ThreadPool::find_from_obj(this);
142-
let Some(_thread) = java_thread else {
143-
return;
144-
};
145-
146-
// Thread is alive...
147-
todo!("Set priority on JavaThread?")
148-
}
149-
15086
pub fn interrupt0(_env: JniEnv, _this: Reference /* java.lang.Thread */) {
15187
unimplemented!("java.lang.Thread#interrupt");
15288
}
@@ -162,11 +98,3 @@ pub fn setNativeName(
16298
) {
16399
unimplemented!("java.lang.Thread#setNativeName");
164100
}
165-
166-
pub fn getNextThreadIdOffset(_env: JniEnv, _class: ClassPtr) -> jlong {
167-
// https://github.com/openjdk/jdk/blob/a3b58ee5cd1ec0ea78649d4128d272458b05eb13/src/java.base/share/classes/java/lang/Thread.java#L624-L627
168-
const INITIAL_THREAD_ID: usize = 3;
169-
static NEXT_THREAD_ID: AtomicUsize = AtomicUsize::new(INITIAL_THREAD_ID);
170-
171-
NEXT_THREAD_ID.as_ptr() as jlong
172-
}

runtime/src/native/java/lang/def/Thread.def

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,12 @@ import java.lang.StackTraceElement;
33
import java.lang.String;
44

55
public class Thread {
6-
private static native void registerNatives();
7-
86
@IntrinsicCandidate
97
static native Object findScopedValueBindings();
108

119
@IntrinsicCandidate
1210
static native Thread currentCarrierThread();
1311

14-
@IntrinsicCandidate
15-
public static native Thread currentThread();
16-
1712
@IntrinsicCandidate
1813
native void setCurrentThread(Thread thread);
1914

@@ -23,27 +18,18 @@ public class Thread {
2318
@IntrinsicCandidate
2419
static native void setScopedValueCache(Object[] cache);
2520

26-
@IntrinsicCandidate
27-
static native void ensureMaterializedForStackWalk(Object o);
28-
2921
private static native void yield0();
3022

3123
private static native void sleepNanos0(long nanos) throws InterruptedException;
3224

33-
private native void start0();
34-
3525
public static native boolean holdsLock(Object obj);
3626

3727
private native Object getStackTrace0();
3828

3929
private static native StackTraceElement[][] dumpThreads(Thread[] threads);
4030
private static native Thread[] getThreads();
4131

42-
private native void setPriority0(int newPriority);
4332
private native void interrupt0();
4433
private static native void clearInterruptEvent();
4534
private native void setNativeName(String name);
46-
47-
// The address of the next thread identifier, see ThreadIdentifiers.
48-
private static native long getNextThreadIdOffset();
4935
}

runtime/src/native/jvm/threads.rs

Lines changed: 71 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,70 @@
11
#![native_macros::jni_fn_module]
22

3-
use jni::env::JniEnv;
4-
use jni::objects::{JClass, JObject, JObjectArray, JString};
5-
use jni::sys::{jboolean, jint, jlong};
3+
use crate::classes;
4+
use crate::classes::java::lang::Thread::ThreadStatus;
5+
use crate::native::jni::{IntoJni, reference_from_jobject};
6+
use crate::thread::exceptions::throw;
7+
use crate::thread::pool::ThreadPool;
8+
use crate::thread::{JavaThread, JavaThreadBuilder};
9+
10+
use std::cmp;
11+
use std::sync::atomic::AtomicUsize;
12+
13+
use ::jni::env::JniEnv;
14+
use ::jni::objects::{JClass, JObject, JObjectArray, JString};
15+
use ::jni::sys::{jboolean, jint, jlong};
616
use native_macros::jni_call;
717

818
#[jni_call]
9-
pub extern "C" fn JVM_StartThread(_env: JniEnv, _thread: JObject) {
10-
todo!()
19+
pub extern "C" fn JVM_StartThread(_env: JniEnv, this: JObject) {
20+
let Some(this) = (unsafe { reference_from_jobject(this.raw()) }) else {
21+
return; // TODO: Exception?
22+
};
23+
24+
{
25+
if let Some(existing_thread) = ThreadPool::find_from_obj(this) {
26+
throw!(existing_thread, IllegalThreadStateException);
27+
}
28+
}
29+
30+
let holder = classes::java::lang::Thread::holder(this.extract_class());
31+
let stack_size_raw = classes::java::lang::Thread::holder::stackSize(holder.extract_class());
32+
33+
let mut thread_builder = JavaThreadBuilder::new()
34+
.obj(this)
35+
.entry_point(JavaThread::default_entry_point);
36+
37+
if stack_size_raw > 0 {
38+
let stack_size = cmp::min(stack_size_raw as usize, u32::MAX as usize);
39+
thread_builder = thread_builder.stack_size(stack_size);
40+
}
41+
42+
let thread = thread_builder.finish();
43+
44+
let obj = thread.obj().expect("current thread object should exist");
45+
let holder = classes::java::lang::Thread::holder(obj.extract_class());
46+
classes::java::lang::Thread::holder::set_threadStatus(
47+
holder.extract_class(),
48+
ThreadStatus::Runnable,
49+
);
1150
}
1251

1352
#[jni_call]
14-
pub extern "C" fn JVM_SetThreadPriority(_env: JniEnv, _thread: JObject, _priority: jint) {
15-
todo!()
53+
pub extern "C" fn JVM_SetThreadPriority(_env: JniEnv, this: JObject, priority: jint) {
54+
let Some(this) = (unsafe { reference_from_jobject(this.raw()) }) else {
55+
return; // TODO: Exception?
56+
};
57+
58+
let holder = classes::java::lang::Thread::holder(this.extract_class());
59+
classes::java::lang::Thread::holder::set_priority(holder.extract_class(), priority);
60+
61+
let java_thread = ThreadPool::find_from_obj(this);
62+
let Some(_thread) = java_thread else {
63+
return;
64+
};
65+
66+
// Thread is alive...
67+
todo!("Set priority on JavaThread?")
1668
}
1769

1870
#[jni_call]
@@ -31,8 +83,12 @@ pub extern "C" fn JVM_CurrentCarrierThread(_env: JniEnv, _class: JClass) -> JObj
3183
}
3284

3385
#[jni_call]
34-
pub extern "C" fn JVM_CurrentThread(_env: JniEnv, _class: JClass) -> JObject {
35-
todo!()
86+
pub extern "C" fn JVM_CurrentThread(env: JniEnv, _class: JClass) -> JObject {
87+
let thread = unsafe { &*JavaThread::for_env(env.raw().cast_const()) };
88+
thread
89+
.obj()
90+
.expect("current thread should exist")
91+
.into_jni_safe()
3692
}
3793

3894
#[jni_call]
@@ -42,7 +98,11 @@ pub extern "C" fn JVM_SetCurrentThread(_env: JniEnv, _this: JObject, _thread: JO
4298

4399
#[jni_call]
44100
pub extern "C" fn JVM_GetNextThreadIdOffset(_env: JniEnv, _class: JClass) -> jlong {
45-
todo!()
101+
// https://github.com/openjdk/jdk/blob/a3b58ee5cd1ec0ea78649d4128d272458b05eb13/src/java.base/share/classes/java/lang/Thread.java#L624-L627
102+
const INITIAL_THREAD_ID: usize = 3;
103+
static NEXT_THREAD_ID: AtomicUsize = AtomicUsize::new(INITIAL_THREAD_ID);
104+
105+
NEXT_THREAD_ID.as_ptr() as jlong
46106
}
47107

48108
#[jni_call]
@@ -135,5 +195,5 @@ pub extern "C" fn JVM_EnsureMaterializedForStackWalk_func(
135195
_vthread: JObject,
136196
_value: JObject,
137197
) {
138-
todo!()
198+
// Nothing to do
139199
}

0 commit comments

Comments
 (0)