about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2022-08-11 23:28:14 +0000
committerbors <bors@rust-lang.org>2022-08-11 23:28:14 +0000
commit403b3f94bbb2717ca7f06cdc5cf79bdaccf6b577 (patch)
tree03545037140a7a1f93f23008720b325956c26b14 /src
parent39ee5747153bf13324870c4a912acbf1f9bfde3f (diff)
parent96049ef88eb38af624134ee465d87eb91717b903 (diff)
downloadrust-403b3f94bbb2717ca7f06cdc5cf79bdaccf6b577.tar.gz
rust-403b3f94bbb2717ca7f06cdc5cf79bdaccf6b577.zip
Auto merge of #2480 - RalfJung:rustup, r=RalfJung
Rustup
Diffstat (limited to 'src')
-rw-r--r--src/shims/time.rs21
-rw-r--r--src/shims/unix/foreign_items.rs11
-rw-r--r--src/shims/unix/fs.rs136
-rw-r--r--src/shims/unix/linux/foreign_items.rs23
-rw-r--r--src/shims/unix/macos/foreign_items.rs24
-rw-r--r--src/shims/unix/sync.rs10
-rw-r--r--src/shims/unix/thread.rs63
-rw-r--r--src/thread.rs25
8 files changed, 140 insertions, 173 deletions
diff --git a/src/shims/time.rs b/src/shims/time.rs
index d9edbe3d7bd..c3eb0161c21 100644
--- a/src/shims/time.rs
+++ b/src/shims/time.rs
@@ -15,7 +15,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
         &mut self,
         clk_id_op: &OpTy<'tcx, Provenance>,
         tp_op: &OpTy<'tcx, Provenance>,
-    ) -> InterpResult<'tcx, i32> {
+    ) -> InterpResult<'tcx, Scalar<Provenance>> {
         // This clock support is deliberately minimal because a lot of clock types have fiddly
         // properties (is it possible for Miri to be suspended independently of the host?). If you
         // have a use for another clock type, please open an issue.
@@ -46,7 +46,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
         } else {
             let einval = this.eval_libc("EINVAL")?;
             this.set_last_error(einval)?;
-            return Ok(-1);
+            return Ok(Scalar::from_i32(-1));
         };
 
         let tv_sec = duration.as_secs();
@@ -54,7 +54,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
 
         this.write_int_fields(&[tv_sec.into(), tv_nsec.into()], &this.deref_operand(tp_op)?)?;
 
-        Ok(0)
+        Ok(Scalar::from_i32(0))
     }
 
     fn gettimeofday(
@@ -160,7 +160,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
         Ok(-1) // Return non-zero on success
     }
 
-    fn mach_absolute_time(&self) -> InterpResult<'tcx, u64> {
+    fn mach_absolute_time(&self) -> InterpResult<'tcx, Scalar<Provenance>> {
         let this = self.eval_context_ref();
 
         this.assert_target_os("macos", "mach_absolute_time");
@@ -169,13 +169,16 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
         // This returns a u64, with time units determined dynamically by `mach_timebase_info`.
         // We return plain nanoseconds.
         let duration = Instant::now().duration_since(this.machine.time_anchor);
-        u64::try_from(duration.as_nanos()).map_err(|_| {
+        let res = u64::try_from(duration.as_nanos()).map_err(|_| {
             err_unsup_format!("programs running longer than 2^64 nanoseconds are not supported")
-                .into()
-        })
+        })?;
+        Ok(Scalar::from_u64(res))
     }
 
-    fn mach_timebase_info(&mut self, info_op: &OpTy<'tcx, Provenance>) -> InterpResult<'tcx, i32> {
+    fn mach_timebase_info(
+        &mut self,
+        info_op: &OpTy<'tcx, Provenance>,
+    ) -> InterpResult<'tcx, Scalar<Provenance>> {
         let this = self.eval_context_mut();
 
         this.assert_target_os("macos", "mach_timebase_info");
@@ -188,7 +191,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
         let (numer, denom) = (1, 1);
         this.write_int_fields(&[numer.into(), denom.into()], &info)?;
 
-        Ok(0) // KERN_SUCCESS
+        Ok(Scalar::from_i32(0)) // KERN_SUCCESS
     }
 
     fn nanosleep(
diff --git a/src/shims/unix/foreign_items.rs b/src/shims/unix/foreign_items.rs
index 6ea10de0b8a..3dea8f203bb 100644
--- a/src/shims/unix/foreign_items.rs
+++ b/src/shims/unix/foreign_items.rs
@@ -63,7 +63,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
             "close" => {
                 let [fd] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
                 let result = this.close(fd)?;
-                this.write_scalar(Scalar::from_i32(result), dest)?;
+                this.write_scalar(result, dest)?;
             }
             "fcntl" => {
                 // `fcntl` is variadic. The argument count is checked based on the first argument
@@ -128,13 +128,13 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
             "lseek64" => {
                 let [fd, offset, whence] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
                 let result = this.lseek64(fd, offset, whence)?;
-                this.write_scalar(Scalar::from_i64(result), dest)?;
+                this.write_scalar(result, dest)?;
             }
             "ftruncate64" => {
                 let [fd, length] =
                     this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
                 let result = this.ftruncate64(fd, length)?;
-                this.write_scalar(Scalar::from_i32(result), dest)?;
+                this.write_scalar(result, dest)?;
             }
             "fsync" => {
                 let [fd] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
@@ -164,7 +164,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
             "realpath" => {
                 let [path, resolved_path] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
                 let result = this.realpath(path, resolved_path)?;
-                this.write_pointer(result, dest)?;
+                this.write_scalar(result, dest)?;
             }
             "mkstemp" => {
                 let [template] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
@@ -437,7 +437,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
             }
             "pthread_self" => {
                 let [] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
-                this.pthread_self(dest)?;
+                let res = this.pthread_self()?;
+                this.write_scalar(res, dest)?;
             }
             "sched_yield" => {
                 let [] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
diff --git a/src/shims/unix/fs.rs b/src/shims/unix/fs.rs
index 951ddae2c14..2a6499ce999 100644
--- a/src/shims/unix/fs.rs
+++ b/src/shims/unix/fs.rs
@@ -664,17 +664,19 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
         }
     }
 
-    fn close(&mut self, fd_op: &OpTy<'tcx, Provenance>) -> InterpResult<'tcx, i32> {
+    fn close(&mut self, fd_op: &OpTy<'tcx, Provenance>) -> InterpResult<'tcx, Scalar<Provenance>> {
         let this = self.eval_context_mut();
 
         let fd = this.read_scalar(fd_op)?.to_i32()?;
 
-        if let Some(file_descriptor) = this.machine.file_handler.handles.remove(&fd) {
-            let result = file_descriptor.close(this.machine.communicate())?;
-            this.try_unwrap_io_result(result)
-        } else {
-            this.handle_not_found()
-        }
+        Ok(Scalar::from_i32(
+            if let Some(file_descriptor) = this.machine.file_handler.handles.remove(&fd) {
+                let result = file_descriptor.close(this.machine.communicate())?;
+                this.try_unwrap_io_result(result)?
+            } else {
+                this.handle_not_found()?
+            },
+        ))
     }
 
     fn read(
@@ -772,7 +774,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
         fd_op: &OpTy<'tcx, Provenance>,
         offset_op: &OpTy<'tcx, Provenance>,
         whence_op: &OpTy<'tcx, Provenance>,
-    ) -> InterpResult<'tcx, i64> {
+    ) -> InterpResult<'tcx, Scalar<Provenance>> {
         let this = self.eval_context_mut();
 
         // Isolation check is done via `FileDescriptor` trait.
@@ -790,18 +792,20 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
         } else {
             let einval = this.eval_libc("EINVAL")?;
             this.set_last_error(einval)?;
-            return Ok(-1);
+            return Ok(Scalar::from_i64(-1));
         };
 
         let communicate = this.machine.communicate();
-        if let Some(file_descriptor) = this.machine.file_handler.handles.get_mut(&fd) {
-            let result = file_descriptor
-                .seek(communicate, seek_from)?
-                .map(|offset| i64::try_from(offset).unwrap());
-            this.try_unwrap_io_result(result)
-        } else {
-            this.handle_not_found()
-        }
+        Ok(Scalar::from_i64(
+            if let Some(file_descriptor) = this.machine.file_handler.handles.get_mut(&fd) {
+                let result = file_descriptor
+                    .seek(communicate, seek_from)?
+                    .map(|offset| i64::try_from(offset).unwrap());
+                this.try_unwrap_io_result(result)?
+            } else {
+                this.handle_not_found()?
+            },
+        ))
     }
 
     fn unlink(&mut self, path_op: &OpTy<'tcx, Provenance>) -> InterpResult<'tcx, i32> {
@@ -855,7 +859,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
         &mut self,
         path_op: &OpTy<'tcx, Provenance>,
         buf_op: &OpTy<'tcx, Provenance>,
-    ) -> InterpResult<'tcx, i32> {
+    ) -> InterpResult<'tcx, Scalar<Provenance>> {
         let this = self.eval_context_mut();
         this.assert_target_os("macos", "stat");
 
@@ -867,16 +871,16 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
             this.reject_in_isolation("`stat`", reject_with)?;
             let eacc = this.eval_libc("EACCES")?;
             this.set_last_error(eacc)?;
-            return Ok(-1);
+            return Ok(Scalar::from_i32(-1));
         }
 
         // `stat` always follows symlinks.
         let metadata = match FileMetadata::from_path(this, &path, true)? {
             Some(metadata) => metadata,
-            None => return Ok(-1),
+            None => return Ok(Scalar::from_i32(-1)), // `FileMetadata` has set errno
         };
 
-        this.macos_stat_write_buf(metadata, buf_op)
+        Ok(Scalar::from_i32(this.macos_stat_write_buf(metadata, buf_op)?))
     }
 
     // `lstat` is used to get symlink metadata.
@@ -884,7 +888,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
         &mut self,
         path_op: &OpTy<'tcx, Provenance>,
         buf_op: &OpTy<'tcx, Provenance>,
-    ) -> InterpResult<'tcx, i32> {
+    ) -> InterpResult<'tcx, Scalar<Provenance>> {
         let this = self.eval_context_mut();
         this.assert_target_os("macos", "lstat");
 
@@ -896,22 +900,22 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
             this.reject_in_isolation("`lstat`", reject_with)?;
             let eacc = this.eval_libc("EACCES")?;
             this.set_last_error(eacc)?;
-            return Ok(-1);
+            return Ok(Scalar::from_i32(-1));
         }
 
         let metadata = match FileMetadata::from_path(this, &path, false)? {
             Some(metadata) => metadata,
-            None => return Ok(-1),
+            None => return Ok(Scalar::from_i32(-1)), // `FileMetadata` has set errno
         };
 
-        this.macos_stat_write_buf(metadata, buf_op)
+        Ok(Scalar::from_i32(this.macos_stat_write_buf(metadata, buf_op)?))
     }
 
     fn macos_fstat(
         &mut self,
         fd_op: &OpTy<'tcx, Provenance>,
         buf_op: &OpTy<'tcx, Provenance>,
-    ) -> InterpResult<'tcx, i32> {
+    ) -> InterpResult<'tcx, Scalar<Provenance>> {
         let this = self.eval_context_mut();
 
         this.assert_target_os("macos", "fstat");
@@ -922,14 +926,14 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
         if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op {
             this.reject_in_isolation("`fstat`", reject_with)?;
             // Set error code as "EBADF" (bad fd)
-            return this.handle_not_found();
+            return Ok(Scalar::from_i32(this.handle_not_found()?));
         }
 
         let metadata = match FileMetadata::from_fd(this, fd)? {
             Some(metadata) => metadata,
-            None => return Ok(-1),
+            None => return Ok(Scalar::from_i32(-1)),
         };
-        this.macos_stat_write_buf(metadata, buf_op)
+        Ok(Scalar::from_i32(this.macos_stat_write_buf(metadata, buf_op)?))
     }
 
     fn linux_statx(
@@ -1343,7 +1347,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
         dirp_op: &OpTy<'tcx, Provenance>,
         entry_op: &OpTy<'tcx, Provenance>,
         result_op: &OpTy<'tcx, Provenance>,
-    ) -> InterpResult<'tcx, i32> {
+    ) -> InterpResult<'tcx, Scalar<Provenance>> {
         let this = self.eval_context_mut();
 
         this.assert_target_os("macos", "readdir_r");
@@ -1354,13 +1358,13 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
         if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op {
             this.reject_in_isolation("`readdir_r`", reject_with)?;
             // Set error code as "EBADF" (bad fd)
-            return this.handle_not_found();
+            return Ok(Scalar::from_i32(this.handle_not_found()?));
         }
 
         let open_dir = this.machine.dir_handler.streams.get_mut(&dirp).ok_or_else(|| {
             err_unsup_format!("the DIR pointer passed to readdir_r did not come from opendir")
         })?;
-        match open_dir.read_dir.next() {
+        Ok(Scalar::from_i32(match open_dir.read_dir.next() {
             Some(Ok(dir_entry)) => {
                 // Write into entry, write pointer to result, return 0 on success.
                 // The name is written with write_os_str_to_c_str, while the rest of the
@@ -1417,17 +1421,17 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
                 let result_place = this.deref_operand(result_op)?;
                 this.write_scalar(this.read_scalar(entry_op)?, &result_place.into())?;
 
-                Ok(0)
+                0
             }
             None => {
                 // end of stream: return 0, assign *result=NULL
                 this.write_null(&this.deref_operand(result_op)?.into())?;
-                Ok(0)
+                0
             }
             Some(Err(e)) =>
                 match e.raw_os_error() {
                     // return positive error number on error
-                    Some(error) => Ok(error),
+                    Some(error) => error,
                     None => {
                         throw_unsup_format!(
                             "the error {} couldn't be converted to a return value",
@@ -1435,7 +1439,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
                         )
                     }
                 },
-        }
+        }))
     }
 
     fn closedir(&mut self, dirp_op: &OpTy<'tcx, Provenance>) -> InterpResult<'tcx, i32> {
@@ -1463,7 +1467,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
         &mut self,
         fd_op: &OpTy<'tcx, Provenance>,
         length_op: &OpTy<'tcx, Provenance>,
-    ) -> InterpResult<'tcx, i32> {
+    ) -> InterpResult<'tcx, Scalar<Provenance>> {
         let this = self.eval_context_mut();
 
         let fd = this.read_scalar(fd_op)?.to_i32()?;
@@ -1473,30 +1477,32 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
         if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op {
             this.reject_in_isolation("`ftruncate64`", reject_with)?;
             // Set error code as "EBADF" (bad fd)
-            return this.handle_not_found();
+            return Ok(Scalar::from_i32(this.handle_not_found()?));
         }
 
-        if let Some(file_descriptor) = this.machine.file_handler.handles.get_mut(&fd) {
-            // FIXME: Support ftruncate64 for all FDs
-            let FileHandle { file, writable } = file_descriptor.as_file_handle()?;
-            if *writable {
-                if let Ok(length) = length.try_into() {
-                    let result = file.set_len(length);
-                    this.try_unwrap_io_result(result.map(|_| 0i32))
+        Ok(Scalar::from_i32(
+            if let Some(file_descriptor) = this.machine.file_handler.handles.get_mut(&fd) {
+                // FIXME: Support ftruncate64 for all FDs
+                let FileHandle { file, writable } = file_descriptor.as_file_handle()?;
+                if *writable {
+                    if let Ok(length) = length.try_into() {
+                        let result = file.set_len(length);
+                        this.try_unwrap_io_result(result.map(|_| 0i32))?
+                    } else {
+                        let einval = this.eval_libc("EINVAL")?;
+                        this.set_last_error(einval)?;
+                        -1
+                    }
                 } else {
+                    // The file is not writable
                     let einval = this.eval_libc("EINVAL")?;
                     this.set_last_error(einval)?;
-                    Ok(-1)
+                    -1
                 }
             } else {
-                // The file is not writable
-                let einval = this.eval_libc("EINVAL")?;
-                this.set_last_error(einval)?;
-                Ok(-1)
-            }
-        } else {
-            this.handle_not_found()
-        }
+                this.handle_not_found()?
+            },
+        ))
     }
 
     fn fsync(&mut self, fd_op: &OpTy<'tcx, Provenance>) -> InterpResult<'tcx, i32> {
@@ -1554,7 +1560,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
         offset_op: &OpTy<'tcx, Provenance>,
         nbytes_op: &OpTy<'tcx, Provenance>,
         flags_op: &OpTy<'tcx, Provenance>,
-    ) -> InterpResult<'tcx, i32> {
+    ) -> InterpResult<'tcx, Scalar<Provenance>> {
         let this = self.eval_context_mut();
 
         let fd = this.read_scalar(fd_op)?.to_i32()?;
@@ -1565,7 +1571,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
         if offset < 0 || nbytes < 0 {
             let einval = this.eval_libc("EINVAL")?;
             this.set_last_error(einval)?;
-            return Ok(-1);
+            return Ok(Scalar::from_i32(-1));
         }
         let allowed_flags = this.eval_libc_i32("SYNC_FILE_RANGE_WAIT_BEFORE")?
             | this.eval_libc_i32("SYNC_FILE_RANGE_WRITE")?
@@ -1573,23 +1579,23 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
         if flags & allowed_flags != flags {
             let einval = this.eval_libc("EINVAL")?;
             this.set_last_error(einval)?;
-            return Ok(-1);
+            return Ok(Scalar::from_i32(-1));
         }
 
         // Reject if isolation is enabled.
         if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op {
             this.reject_in_isolation("`sync_file_range`", reject_with)?;
             // Set error code as "EBADF" (bad fd)
-            return this.handle_not_found();
+            return Ok(Scalar::from_i32(this.handle_not_found()?));
         }
 
         if let Some(file_descriptor) = this.machine.file_handler.handles.get(&fd) {
             // FIXME: Support sync_data_range for all FDs
             let FileHandle { file, writable } = file_descriptor.as_file_handle()?;
             let io_result = maybe_sync_file(file, *writable, File::sync_data);
-            this.try_unwrap_io_result(io_result)
+            Ok(Scalar::from_i32(this.try_unwrap_io_result(io_result)?))
         } else {
-            this.handle_not_found()
+            Ok(Scalar::from_i32(this.handle_not_found()?))
         }
     }
 
@@ -1674,7 +1680,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
         &mut self,
         path_op: &OpTy<'tcx, Provenance>,
         processed_path_op: &OpTy<'tcx, Provenance>,
-    ) -> InterpResult<'tcx, Pointer<Option<Provenance>>> {
+    ) -> InterpResult<'tcx, Scalar<Provenance>> {
         let this = self.eval_context_mut();
         this.assert_target_os_is_unix("realpath");
 
@@ -1686,7 +1692,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
             this.reject_in_isolation("`realpath`", reject_with)?;
             let eacc = this.eval_libc("EACCES")?;
             this.set_last_error(eacc)?;
-            return Ok(Pointer::null());
+            return Ok(Scalar::from_machine_usize(0, this));
         }
 
         let result = std::fs::canonicalize(pathname);
@@ -1717,16 +1723,16 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
                         // seems like a bit of a mess anyway: <https://eklitzke.org/path-max-is-tricky>.
                         let enametoolong = this.eval_libc("ENAMETOOLONG")?;
                         this.set_last_error(enametoolong)?;
-                        return Ok(Pointer::null());
+                        return Ok(Scalar::from_machine_usize(0, this));
                     }
                     processed_ptr
                 };
 
-                Ok(dest)
+                Ok(Scalar::from_maybe_pointer(dest, this))
             }
             Err(e) => {
                 this.set_last_error_from_io_error(e.kind())?;
-                Ok(Pointer::null())
+                Ok(Scalar::from_machine_usize(0, this))
             }
         }
     }
diff --git a/src/shims/unix/linux/foreign_items.rs b/src/shims/unix/linux/foreign_items.rs
index bae3780b460..6881d829c15 100644
--- a/src/shims/unix/linux/foreign_items.rs
+++ b/src/shims/unix/linux/foreign_items.rs
@@ -38,7 +38,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
                 let [fd, offset, nbytes, flags] =
                     this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
                 let result = this.sync_file_range(fd, offset, nbytes, flags)?;
-                this.write_scalar(Scalar::from_i32(result), dest)?;
+                this.write_scalar(result, dest)?;
             }
 
             // Time related shims
@@ -47,27 +47,30 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
                 let [clk_id, tp] =
                     this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
                 let result = this.clock_gettime(clk_id, tp)?;
-                this.write_scalar(Scalar::from_i32(result), dest)?;
+                this.write_scalar(result, dest)?;
             }
 
             // Threading
-            "prctl" => {
-                // prctl is variadic. (It is not documented like that in the manpage, but defined like that in the libc crate.)
-                this.check_abi_and_shim_symbol_clash(abi, Abi::C { unwind: false }, link_name)?;
-                let result = this.prctl(args)?;
-                this.write_scalar(Scalar::from_i32(result), dest)?;
-            }
             "pthread_condattr_setclock" => {
                 let [attr, clock_id] =
                     this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
                 let result = this.pthread_condattr_setclock(attr, clock_id)?;
-                this.write_scalar(Scalar::from_i32(result), dest)?;
+                this.write_scalar(result, dest)?;
             }
             "pthread_condattr_getclock" => {
                 let [attr, clock_id] =
                     this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
                 let result = this.pthread_condattr_getclock(attr, clock_id)?;
-                this.write_scalar(Scalar::from_i32(result), dest)?;
+                this.write_scalar(result, dest)?;
+            }
+            "pthread_setname_np" => {
+                let [thread, name] =
+                    this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
+                let res = this.pthread_setname_np(
+                    this.read_scalar(thread)?.check_init()?,
+                    this.read_scalar(name)?.check_init()?,
+                )?;
+                this.write_scalar(res, dest)?;
             }
 
             // Dynamically invoked syscalls
diff --git a/src/shims/unix/macos/foreign_items.rs b/src/shims/unix/macos/foreign_items.rs
index 35751d5818a..fd7d5fb763e 100644
--- a/src/shims/unix/macos/foreign_items.rs
+++ b/src/shims/unix/macos/foreign_items.rs
@@ -29,24 +29,24 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
             "close$NOCANCEL" => {
                 let [result] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
                 let result = this.close(result)?;
-                this.write_scalar(Scalar::from_i32(result), dest)?;
+                this.write_scalar(result, dest)?;
             }
             "stat" | "stat64" | "stat$INODE64" => {
                 let [path, buf] =
                     this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
                 let result = this.macos_stat(path, buf)?;
-                this.write_scalar(Scalar::from_i32(result), dest)?;
+                this.write_scalar(result, dest)?;
             }
             "lstat" | "lstat64" | "lstat$INODE64" => {
                 let [path, buf] =
                     this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
                 let result = this.macos_lstat(path, buf)?;
-                this.write_scalar(Scalar::from_i32(result), dest)?;
+                this.write_scalar(result, dest)?;
             }
             "fstat" | "fstat64" | "fstat$INODE64" => {
                 let [fd, buf] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
                 let result = this.macos_fstat(fd, buf)?;
-                this.write_scalar(Scalar::from_i32(result), dest)?;
+                this.write_scalar(result, dest)?;
             }
             "opendir$INODE64" => {
                 let [name] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
@@ -57,27 +57,27 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
                 let [dirp, entry, result] =
                     this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
                 let result = this.macos_readdir_r(dirp, entry, result)?;
-                this.write_scalar(Scalar::from_i32(result), dest)?;
+                this.write_scalar(result, dest)?;
             }
             "lseek" => {
                 let [fd, offset, whence] =
                     this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
                 // macOS is 64bit-only, so this is lseek64
                 let result = this.lseek64(fd, offset, whence)?;
-                this.write_scalar(Scalar::from_i64(result), dest)?;
+                this.write_scalar(result, dest)?;
             }
             "ftruncate" => {
                 let [fd, length] =
                     this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
                 // macOS is 64bit-only, so this is ftruncate64
                 let result = this.ftruncate64(fd, length)?;
-                this.write_scalar(Scalar::from_i32(result), dest)?;
+                this.write_scalar(result, dest)?;
             }
             "realpath$DARWIN_EXTSN" => {
                 let [path, resolved_path] =
                     this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
                 let result = this.realpath(path, resolved_path)?;
-                this.write_pointer(result, dest)?;
+                this.write_scalar(result, dest)?;
             }
 
             // Environment related shims
@@ -93,13 +93,13 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
             "mach_absolute_time" => {
                 let [] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
                 let result = this.mach_absolute_time()?;
-                this.write_scalar(Scalar::from_u64(result), dest)?;
+                this.write_scalar(result, dest)?;
             }
 
             "mach_timebase_info" => {
                 let [info] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
                 let result = this.mach_timebase_info(info)?;
-                this.write_scalar(Scalar::from_i32(result), dest)?;
+                this.write_scalar(result, dest)?;
             }
 
             // Access to command-line arguments
@@ -173,8 +173,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
             // Threading
             "pthread_setname_np" => {
                 let [name] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
-                let name = this.read_pointer(name)?;
-                this.pthread_setname_np(name)?;
+                let thread = this.pthread_self()?;
+                this.pthread_setname_np(thread, this.read_scalar(name)?.check_init()?)?;
             }
 
             // Incomplete shims that we "stub out" just to get pre-main initialization code to work.
diff --git a/src/shims/unix/sync.rs b/src/shims/unix/sync.rs
index 18226c2b8cf..69e632915b1 100644
--- a/src/shims/unix/sync.rs
+++ b/src/shims/unix/sync.rs
@@ -723,7 +723,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
         &mut self,
         attr_op: &OpTy<'tcx, Provenance>,
         clock_id_op: &OpTy<'tcx, Provenance>,
-    ) -> InterpResult<'tcx, i32> {
+    ) -> InterpResult<'tcx, Scalar<Provenance>> {
         let this = self.eval_context_mut();
 
         let clock_id = this.read_scalar(clock_id_op)?.check_init()?;
@@ -733,23 +733,23 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
             condattr_set_clock_id(this, attr_op, clock_id)?;
         } else {
             let einval = this.eval_libc_i32("EINVAL")?;
-            return Ok(einval);
+            return Ok(Scalar::from_i32(einval));
         }
 
-        Ok(0)
+        Ok(Scalar::from_i32(0))
     }
 
     fn pthread_condattr_getclock(
         &mut self,
         attr_op: &OpTy<'tcx, Provenance>,
         clk_id_op: &OpTy<'tcx, Provenance>,
-    ) -> InterpResult<'tcx, i32> {
+    ) -> InterpResult<'tcx, Scalar<Provenance>> {
         let this = self.eval_context_mut();
 
         let clock_id = condattr_get_clock_id(this, attr_op)?;
         this.write_scalar(clock_id, &this.deref_operand(clk_id_op)?.into())?;
 
-        Ok(0)
+        Ok(Scalar::from_i32(0))
     }
 
     fn pthread_condattr_destroy(
diff --git a/src/shims/unix/thread.rs b/src/shims/unix/thread.rs
index 1a8531e8804..0df70543fac 100644
--- a/src/shims/unix/thread.rs
+++ b/src/shims/unix/thread.rs
@@ -84,68 +84,27 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
         Ok(0)
     }
 
-    fn pthread_self(&mut self, dest: &PlaceTy<'tcx, Provenance>) -> InterpResult<'tcx> {
+    fn pthread_self(&mut self) -> InterpResult<'tcx, Scalar<Provenance>> {
         let this = self.eval_context_mut();
 
         let thread_id = this.get_active_thread();
-        this.write_scalar(Scalar::from_uint(thread_id.to_u32(), dest.layout.size), dest)
+        Ok(Scalar::from_machine_usize(thread_id.into(), this))
     }
 
-    fn prctl(&mut self, args: &[OpTy<'tcx, Provenance>]) -> InterpResult<'tcx, i32> {
+    fn pthread_setname_np(
+        &mut self,
+        thread: Scalar<Provenance>,
+        name: Scalar<Provenance>,
+    ) -> InterpResult<'tcx, Scalar<Provenance>> {
         let this = self.eval_context_mut();
-        this.assert_target_os("linux", "prctl");
-
-        if args.is_empty() {
-            throw_ub_format!(
-                "incorrect number of arguments for `prctl`: got {}, expected at least 1",
-                args.len()
-            );
-        }
-
-        let option = this.read_scalar(&args[0])?.to_i32()?;
-        if option == this.eval_libc_i32("PR_SET_NAME")? {
-            if args.len() < 2 {
-                throw_ub_format!(
-                    "incorrect number of arguments for `prctl` with `PR_SET_NAME`: got {}, expected at least 2",
-                    args.len()
-                );
-            }
-
-            let address = this.read_pointer(&args[1])?;
-            let mut name = this.read_c_str(address)?.to_owned();
-            // The name should be no more than 16 bytes, including the null
-            // byte. Since `read_c_str` returns the string without the null
-            // byte, we need to truncate to 15.
-            name.truncate(15);
-            this.set_active_thread_name(name);
-        } else if option == this.eval_libc_i32("PR_GET_NAME")? {
-            if args.len() < 2 {
-                throw_ub_format!(
-                    "incorrect number of arguments for `prctl` with `PR_SET_NAME`: got {}, expected at least 2",
-                    args.len()
-                );
-            }
-
-            let address = this.read_pointer(&args[1])?;
-            let mut name = this.get_active_thread_name().to_vec();
-            name.push(0u8);
-            assert!(name.len() <= 16);
-            this.write_bytes_ptr(address, name)?;
-        } else {
-            throw_unsup_format!("unsupported prctl option {}", option);
-        }
 
-        Ok(0)
-    }
-
-    fn pthread_setname_np(&mut self, name: Pointer<Option<Provenance>>) -> InterpResult<'tcx> {
-        let this = self.eval_context_mut();
-        this.assert_target_os("macos", "pthread_setname_np");
+        let thread = ThreadId::try_from(thread.to_machine_usize(this)?).unwrap();
+        let name = name.to_pointer(this)?;
 
         let name = this.read_c_str(name)?.to_owned();
-        this.set_active_thread_name(name);
+        this.set_thread_name(thread, name);
 
-        Ok(())
+        Ok(Scalar::from_u32(0))
     }
 
     fn sched_yield(&mut self) -> InterpResult<'tcx, i32> {
diff --git a/src/thread.rs b/src/thread.rs
index 683694f482e..6f394fa42fc 100644
--- a/src/thread.rs
+++ b/src/thread.rs
@@ -69,9 +69,9 @@ impl From<u32> for ThreadId {
     }
 }
 
-impl ThreadId {
-    pub fn to_u32_scalar(&self) -> Scalar<Provenance> {
-        Scalar::from_u32(self.0)
+impl From<ThreadId> for u64 {
+    fn from(t: ThreadId) -> Self {
+        t.0.into()
     }
 }
 
@@ -394,14 +394,9 @@ impl<'mir, 'tcx: 'mir> ThreadManager<'mir, 'tcx> {
         Ok(())
     }
 
-    /// Set the name of the active thread.
-    fn set_active_thread_name(&mut self, new_thread_name: Vec<u8>) {
-        self.active_thread_mut().thread_name = Some(new_thread_name);
-    }
-
-    /// Get the name of the active thread.
-    pub fn get_active_thread_name(&self) -> &[u8] {
-        self.active_thread_ref().thread_name()
+    /// Set the name of the given thread.
+    pub fn set_thread_name(&mut self, thread: ThreadId, new_thread_name: Vec<u8>) {
+        self.threads[thread].thread_name = Some(new_thread_name);
     }
 
     /// Get the name of the given thread.
@@ -704,18 +699,18 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
     }
 
     #[inline]
-    fn set_active_thread_name(&mut self, new_thread_name: Vec<u8>) {
+    fn set_thread_name(&mut self, thread: ThreadId, new_thread_name: Vec<u8>) {
         let this = self.eval_context_mut();
-        this.machine.threads.set_active_thread_name(new_thread_name);
+        this.machine.threads.set_thread_name(thread, new_thread_name);
     }
 
     #[inline]
-    fn get_active_thread_name<'c>(&'c self) -> &'c [u8]
+    fn get_thread_name<'c>(&'c self, thread: ThreadId) -> &'c [u8]
     where
         'mir: 'c,
     {
         let this = self.eval_context_ref();
-        this.machine.threads.get_active_thread_name()
+        this.machine.threads.get_thread_name(thread)
     }
 
     #[inline]