Skip to content

Commit 070a94a

Browse files
committed
make MutexKind an enum
1 parent f0c2c4f commit 070a94a

File tree

2 files changed

+81
-77
lines changed

2 files changed

+81
-77
lines changed

src/concurrency/sync.rs

+7-10
Original file line numberDiff line numberDiff line change
@@ -69,16 +69,13 @@ declare_id!(MutexId);
6969
/// The mutex kind.
7070
/// The meaning of this type is defined by concrete mutex implementations.
7171
#[derive(Debug, Clone, Copy)]
72-
pub struct MutexKind(i32);
73-
74-
impl MutexKind {
75-
pub fn new(k: i32) -> Self {
76-
Self(k)
77-
}
78-
79-
pub fn to_i32(&self) -> i32 {
80-
self.0
81-
}
72+
#[non_exhaustive]
73+
pub enum MutexKind {
74+
Invalid,
75+
Normal,
76+
Default,
77+
Recursive,
78+
ErrorCheck,
8279
}
8380

8481
#[derive(Debug)]

src/shims/unix/sync.rs

+74-67
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ fn mutex_create<'tcx>(
9999
// FIXME: might be worth changing mutex_create to take the mplace
100100
// rather than the `OpTy`.
101101
let address = ecx.read_pointer(mutex_op)?.addr().bytes();
102-
let kind = MutexKind::new(kind);
102+
let kind = translate_kind(ecx, kind)?;
103103
let data = Some(AdditionalMutexData { address, kind });
104104
ecx.mutex_create(mutex_op, ecx.libc_ty_layout("pthread_mutex_t"), mutex_id_offset(ecx)?, data)?;
105105
Ok(())
@@ -145,21 +145,37 @@ fn kind_from_static_initializer<'tcx>(
145145
mutex_op: &OpTy<'tcx>,
146146
) -> InterpResult<'tcx, MutexKind> {
147147
// Only linux has static initializers other than PTHREAD_MUTEX_DEFAULT.
148-
let offset = match &*ecx.tcx.sess.target.os {
149-
"linux" => if ecx.pointer_size().bytes() == 8 { 16 } else { 12 },
150-
| "illumos" | "solaris" | "macos" => return Ok(MutexKind::new(ecx.eval_libc_i32("PTHREAD_MUTEX_DEFAULT"))),
148+
let kind = match &*ecx.tcx.sess.target.os {
149+
"linux" => {
150+
let offset = if ecx.pointer_size().bytes() == 8 { 16 } else { 12 };
151+
152+
ecx.deref_pointer_and_read(
153+
mutex_op,
154+
offset,
155+
ecx.libc_ty_layout("pthread_mutex_t"),
156+
ecx.machine.layouts.i32,
157+
)?
158+
.to_i32()?
159+
}
160+
| "illumos" | "solaris" | "macos" => ecx.eval_libc_i32("PTHREAD_MUTEX_DEFAULT"),
151161
os => throw_unsup_format!("`pthread_mutex` is not supported on {os}"),
152162
};
153163

154-
let kind = ecx
155-
.deref_pointer_and_read(
156-
mutex_op,
157-
offset,
158-
ecx.libc_ty_layout("pthread_mutex_t"),
159-
ecx.machine.layouts.i32,
160-
)?
161-
.to_i32()?;
162-
return Ok(MutexKind::new(kind));
164+
translate_kind(ecx, kind)
165+
}
166+
167+
fn translate_kind<'tcx>(ecx: &MiriInterpCx<'tcx>, kind: i32) -> InterpResult<'tcx, MutexKind> {
168+
Ok(if is_mutex_kind_default(ecx, kind)? {
169+
MutexKind::Default
170+
} else if is_mutex_kind_normal(ecx, kind)? {
171+
MutexKind::Normal
172+
} else if kind == ecx.eval_libc_i32("PTHREAD_MUTEX_ERRORCHECK") {
173+
MutexKind::ErrorCheck
174+
} else if kind == ecx.eval_libc_i32("PTHREAD_MUTEX_RECURSIVE") {
175+
MutexKind::Recursive
176+
} else {
177+
throw_unsup_format!("unsupported type of mutex: {kind}");
178+
})
163179
}
164180

165181
// pthread_rwlock_t is between 32 and 56 bytes, depending on the platform.
@@ -462,11 +478,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
462478
let this = self.eval_context_mut();
463479

464480
let id = mutex_get_id(this, mutex_op)?;
465-
let kind = this
466-
.mutex_get_data(id)
467-
.expect("data should always exist for pthread mutexes")
468-
.kind
469-
.to_i32();
481+
let kind =
482+
this.mutex_get_data(id).expect("data should always exist for pthread mutexes").kind;
470483

471484
let ret = if this.mutex_is_locked(id) {
472485
let owner_thread = this.mutex_get_owner(id);
@@ -475,19 +488,19 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
475488
return Ok(());
476489
} else {
477490
// Trying to acquire the same mutex again.
478-
if is_mutex_kind_default(this, kind)? {
479-
throw_ub_format!("trying to acquire already locked default mutex");
480-
} else if is_mutex_kind_normal(this, kind)? {
481-
throw_machine_stop!(TerminationInfo::Deadlock);
482-
} else if kind == this.eval_libc_i32("PTHREAD_MUTEX_ERRORCHECK") {
483-
this.eval_libc_i32("EDEADLK")
484-
} else if kind == this.eval_libc_i32("PTHREAD_MUTEX_RECURSIVE") {
485-
this.mutex_lock(id);
486-
0
487-
} else {
488-
throw_unsup_format!(
489-
"called pthread_mutex_lock on an unsupported type of mutex"
490-
);
491+
match kind {
492+
MutexKind::Default =>
493+
throw_ub_format!("trying to acquire already locked default mutex"),
494+
MutexKind::Normal => throw_machine_stop!(TerminationInfo::Deadlock),
495+
MutexKind::ErrorCheck => this.eval_libc_i32("EDEADLK"),
496+
MutexKind::Recursive => {
497+
this.mutex_lock(id);
498+
0
499+
}
500+
_ =>
501+
throw_unsup_format!(
502+
"called pthread_mutex_lock on an unsupported type of mutex"
503+
),
491504
}
492505
}
493506
} else {
@@ -503,29 +516,25 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
503516
let this = self.eval_context_mut();
504517

505518
let id = mutex_get_id(this, mutex_op)?;
506-
let kind = this
507-
.mutex_get_data(id)
508-
.expect("data should always exist for pthread mutexes")
509-
.kind
510-
.to_i32();
519+
let kind =
520+
this.mutex_get_data(id).expect("data should always exist for pthread mutexes").kind;
511521

512522
Ok(Scalar::from_i32(if this.mutex_is_locked(id) {
513523
let owner_thread = this.mutex_get_owner(id);
514524
if owner_thread != this.active_thread() {
515525
this.eval_libc_i32("EBUSY")
516526
} else {
517-
if is_mutex_kind_default(this, kind)?
518-
|| is_mutex_kind_normal(this, kind)?
519-
|| kind == this.eval_libc_i32("PTHREAD_MUTEX_ERRORCHECK")
520-
{
521-
this.eval_libc_i32("EBUSY")
522-
} else if kind == this.eval_libc_i32("PTHREAD_MUTEX_RECURSIVE") {
523-
this.mutex_lock(id);
524-
0
525-
} else {
526-
throw_unsup_format!(
527-
"called pthread_mutex_trylock on an unsupported type of mutex"
528-
);
527+
match kind {
528+
MutexKind::Default | MutexKind::Normal | MutexKind::ErrorCheck =>
529+
this.eval_libc_i32("EBUSY"),
530+
MutexKind::Recursive => {
531+
this.mutex_lock(id);
532+
0
533+
}
534+
_ =>
535+
throw_unsup_format!(
536+
"called pthread_mutex_trylock on an unsupported type of mutex"
537+
),
529538
}
530539
}
531540
} else {
@@ -539,11 +548,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
539548
let this = self.eval_context_mut();
540549

541550
let id = mutex_get_id(this, mutex_op)?;
542-
let kind = this
543-
.mutex_get_data(id)
544-
.expect("data should always exist for pthread mutexes")
545-
.kind
546-
.to_i32();
551+
let kind =
552+
this.mutex_get_data(id).expect("data should always exist for pthread mutexes").kind;
547553

548554
if let Some(_old_locked_count) = this.mutex_unlock(id)? {
549555
// The mutex was locked by the current thread.
@@ -552,20 +558,21 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
552558
// The mutex was locked by another thread or not locked at all. See
553559
// the “Unlock When Not Owner” column in
554560
// https://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_mutex_unlock.html.
555-
if is_mutex_kind_default(this, kind)? {
556-
throw_ub_format!(
557-
"unlocked a default mutex that was not locked by the current thread"
558-
);
559-
} else if is_mutex_kind_normal(this, kind)? {
560-
throw_ub_format!(
561-
"unlocked a PTHREAD_MUTEX_NORMAL mutex that was not locked by the current thread"
562-
);
563-
} else if kind == this.eval_libc_i32("PTHREAD_MUTEX_ERRORCHECK")
564-
|| kind == this.eval_libc_i32("PTHREAD_MUTEX_RECURSIVE")
565-
{
566-
Ok(Scalar::from_i32(this.eval_libc_i32("EPERM")))
567-
} else {
568-
throw_unsup_format!("called pthread_mutex_unlock on an unsupported type of mutex");
561+
match kind {
562+
MutexKind::Default =>
563+
throw_ub_format!(
564+
"unlocked a default mutex that was not locked by the current thread"
565+
),
566+
MutexKind::Normal =>
567+
throw_ub_format!(
568+
"unlocked a PTHREAD_MUTEX_NORMAL mutex that was not locked by the current thread"
569+
),
570+
MutexKind::ErrorCheck | MutexKind::Recursive =>
571+
Ok(Scalar::from_i32(this.eval_libc_i32("EPERM"))),
572+
_ =>
573+
throw_unsup_format!(
574+
"called pthread_mutex_unlock on an unsupported type of mutex"
575+
),
569576
}
570577
}
571578
}

0 commit comments

Comments
 (0)