-
Notifications
You must be signed in to change notification settings - Fork 389
Add shims for gettid
-esque functions
#4397
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
7fcf49f
5f12c71
1d57f0a
75a94a0
4a0a2f0
c5770b9
c4fc629
de427c1
90695e4
6f960f3
64f2447
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -274,15 +274,50 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { | |||||
interp_ok(Scalar::from_u32(this.get_pid())) | ||||||
} | ||||||
|
||||||
fn linux_gettid(&mut self) -> InterpResult<'tcx, Scalar> { | ||||||
/// The `gettid`-like function for Unix platforms that take no parameters and return a 32-bit | ||||||
/// integer. It is not always named "gettid". | ||||||
fn unix_gettid(&mut self, link_name: &str) -> InterpResult<'tcx, Scalar> { | ||||||
let this = self.eval_context_ref(); | ||||||
this.assert_target_os("linux", "gettid"); | ||||||
this.assert_target_os_is_unix(link_name.as_ref()); | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
This should also work, doesn't it? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Indeed, I don't know why I thought it didn't like that... |
||||||
|
||||||
let index = this.machine.threads.active_thread().to_u32(); | ||||||
// For most platforms the return type is an `i32`, but some are unsigned. The TID | ||||||
// will always be positive so we don't need to differentiate. | ||||||
interp_ok(Scalar::from_u32(this.get_current_tid())) | ||||||
} | ||||||
|
||||||
/// The Apple-specific `int pthread_threadid_np(pthread_t thread, uint64_t *thread_id)`, which | ||||||
/// allows querying the ID for arbitrary threads, identified by their pthread_t. | ||||||
fn apple_pthread_threadip_np( | ||||||
&mut self, | ||||||
thread_op: &OpTy<'tcx>, | ||||||
tid_op: &OpTy<'tcx>, | ||||||
) -> InterpResult<'tcx, Scalar> { | ||||||
let this = self.eval_context_mut(); | ||||||
this.assert_target_os("macos", "pthread_threadip_np"); | ||||||
|
||||||
let tid_dest = this.read_pointer(tid_op)?; | ||||||
if this.ptr_is_null(tid_dest)? { | ||||||
// If NULL is passed, an error is immediately returned | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this documented behavior or just observed? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The possible error codes are documented https://www.manpagez.com/man/3/pthread_threadid_np/, the priority (null check before valid thread check) is observed There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That's apparently a BSD manpage, not an Apple one... but it's better than no reference. Would be good to have some sort of link somewhere in the function for what we used as reference. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It is from MacOS (see the table at the very bottom). Source for reference https://github.com/apple-oss-distributions/libpthread/blob/1ebf56b3a702df53213c2996e5e128a535d2577e/src/pthread.c#L1118-L1146 (there is also a manpage in that repo) |
||||||
return interp_ok(this.eval_libc("EINVAL")); | ||||||
} | ||||||
|
||||||
let thread = this.read_scalar(thread_op)?.to_int(this.libc_ty_layout("pthread_t").size)?; | ||||||
let thread = if thread == 0 { | ||||||
// Null thread ID indicates that we are querying the active thread. | ||||||
this.machine.threads.active_thread() | ||||||
} else { | ||||||
// Our pthread_t is just the raw ThreadId. | ||||||
let Ok(thread) = this.thread_id_try_from(thread) else { | ||||||
tgross35 marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
return interp_ok(this.eval_libc("ESRCH")); | ||||||
}; | ||||||
thread | ||||||
}; | ||||||
|
||||||
// Compute a TID for this thread, ensuring that the main thread has PID == TID. | ||||||
let tid = this.get_pid().strict_add(index); | ||||||
let tid = this.get_tid(thread); | ||||||
let tid_dest = this.deref_pointer_as(tid_op, this.machine.layouts.u64)?; | ||||||
this.write_int(tid, &tid_dest)?; | ||||||
|
||||||
interp_ok(Scalar::from_u32(tid)) | ||||||
// Never an error if we only ever check the current thread. | ||||||
interp_ok(Scalar::from_u32(0)) | ||||||
} | ||||||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -9,6 +9,7 @@ use rustc_target::callconv::FnAbi; | |
|
||
use self::shims::windows::handle::{Handle, PseudoHandle}; | ||
use crate::shims::os_str::bytes_to_os_str; | ||
use crate::shims::windows::handle::HandleError; | ||
use crate::shims::windows::*; | ||
use crate::*; | ||
|
||
|
@@ -629,6 +630,29 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { | |
this.write_scalar(name, &name_ptr)?; | ||
this.write_scalar(res, dest)?; | ||
} | ||
"GetThreadId" => { | ||
let [handle] = this.check_shim(abi, sys_conv, link_name, args)?; | ||
|
||
let handle = this.read_scalar(handle)?; | ||
let tid = match Handle::try_from_scalar(handle, this)? { | ||
Comment on lines
+636
to
+637
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The expectation is that you'll usually call read_handle instead (so There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is to match the documented behavior of returning 0 on failure https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-getthreadid. But with #4397 (comment), this can be dropped. |
||
Ok(Handle::Thread(thread)) => this.get_tid(thread), | ||
Ok(Handle::Pseudo(PseudoHandle::CurrentThread)) => { | ||
let thread = this.active_thread(); | ||
this.get_tid(thread) | ||
} | ||
// Unknown threads return 0 | ||
Ok(_) => 0, | ||
Err(HandleError::InvalidHandle | HandleError::ThreadNotFound(_)) => 0, | ||
}; | ||
|
||
this.write_scalar(Scalar::from_u32(tid), dest)?; | ||
} | ||
"GetCurrentThreadId" => { | ||
let [] = this.check_shim(abi, sys_conv, link_name, args)?; | ||
let thread = this.active_thread(); | ||
let tid = this.get_tid(thread); | ||
this.write_scalar(Scalar::from_u32(tid), dest)?; | ||
} | ||
|
||
// Miscellaneous | ||
"ExitProcess" => { | ||
|
Uh oh!
There was an error while loading. Please reload this page.