fn pthread_rwlock_unlock(&mut self, rwlock_op: OpTy<'tcx, Tag>) -> InterpResult<'tcx, i32> {
        let this = self.eval_context_mut();

        let readers = rwlock_get_readers(this, rwlock_op)?.to_u32()?;
        let writers = rwlock_get_writers(this, rwlock_op)?.to_u32()?;
        let writer_blockset = rwlock_get_or_create_writer_blockset(this, rwlock_op)?;
        if let Some(new_readers) = readers.checked_sub(1) {
            assert_eq!(writers, 0);
            rwlock_set_readers(this, rwlock_op, Scalar::from_u32(new_readers))?;
            if new_readers == 0 {
                if let Some(_writer) = this.unblock_some_thread(writer_blockset)? {
                    rwlock_set_writers(this, rwlock_op, Scalar::from_u32(1))?;
                }
            }
            Ok(0)
        } else if writers != 0 {
            let reader_blockset = rwlock_get_or_create_reader_blockset(this, rwlock_op)?;
            // We are prioritizing writers here against the readers. As a
            // result, not only readers can starve writers, but also writers can
            // starve readers.
            if let Some(_writer) = this.unblock_some_thread(writer_blockset)? {
                assert_eq!(writers, 1);
            } else {
                rwlock_set_writers(this, rwlock_op, Scalar::from_u32(0))?;
                let mut readers = 0;
                while let Some(_reader) = this.unblock_some_thread(reader_blockset)? {
                    readers += 1;
                }
                rwlock_set_readers(this, rwlock_op, Scalar::from_u32(readers))?
            }
            Ok(0)
        } else {
            throw_ub_format!("unlocked an rwlock that was not locked");
        }
    }
// FIXME: We should check that this lock was locked by the active thread.
We should check that this lock was locked by the active thread.
We should check that this lock was locked by the active thread .
fn pthread_rwlock_unlock(&mut self, rwlock_op: OpTy<'tcx, Tag>) -> InterpResult<'tcx, i32> {
        let this = self.eval_context_mut();
        let readers = rwlock_get_readers(this, rwlock_op)?.to_u32()?;
        let writers = rwlock_get_writers(this, rwlock_op)?.to_u32()?;
        let writer_blockset = rwlock_get_or_create_writer_blockset(this, rwlock_op)?;
        if let Some(new_readers) = readers.checked_sub(1) {
            assert_eq!(writers, 0);
            rwlock_set_readers(this, rwlock_op, Scalar::from_u32(new_readers))?;
            if new_readers == 0 {
                if let Some(_writer) = this.unblock_some_thread(writer_blockset)? {
                    rwlock_set_writers(this, rwlock_op, Scalar::from_u32(1))?;
                }
            }
            Ok(0)
        } else if writers != 0 {
            let reader_blockset = rwlock_get_or_create_reader_blockset(this, rwlock_op)?;
            // We are prioritizing writers here against the readers. As a
            // result, not only readers can starve writers, but also writers can
            // starve readers.
            if let Some(_writer) = this.unblock_some_thread(writer_blockset)? {
                assert_eq!(writers, 1);
            } else {
                rwlock_set_writers(this, rwlock_op, Scalar::from_u32(0))?;
                let mut readers = 0;
                while let Some(_reader) = this.unblock_some_thread(reader_blockset)? {
                    readers += 1;
                }
                rwlock_set_readers(this, rwlock_op, Scalar::from_u32(readers))?
            }
            Ok(0)
        } else {
            throw_ub_format!("unlocked an rwlock that was not locked");
        }
    }
fn pthread_rwlock_unlock ( & mut self , rwlock_op : OpTy < ' tcx , Tag > ) -> InterpResult < ' tcx , i32 > { let this = self . eval_context_mut ( ) ; let readers = rwlock_get_readers ( this , rwlock_op ) ? . to_u32 ( ) ? ; let writers = rwlock_get_writers ( this , rwlock_op ) ? . to_u32 ( ) ? ; let writer_blockset = rwlock_get_or_create_writer_blockset ( this , rwlock_op ) ? ; if let Some ( new_readers ) = readers . checked_sub ( 1 ) { assert_eq ! ( writers 0 ) ; rwlock_set_readers ( this , rwlock_op , Scalar :: from_u32 ( new_readers ) ) ? ; if new_readers == 0 { if let Some ( _writer ) = this . unblock_some_thread ( writer_blockset ) ? { rwlock_set_writers ( this , rwlock_op , Scalar :: from_u32 ( 1 ) ) ? ; } } Ok ( 0 ) } else if writers != 0 { let reader_blockset = rwlock_get_or_create_reader_blockset ( this , rwlock_op ) ? ; // We are prioritizing writers here against the readers. As a // result, not only readers can starve writers, but also writers can // starve readers. if let Some ( _writer ) = this . unblock_some_thread ( writer_blockset ) ? { assert_eq ! ( writers 1 ) ; } else { rwlock_set_writers ( this , rwlock_op , Scalar :: from_u32 ( 0 ) ) ? ; let mut readers = 0 ; while let Some ( _reader ) = this . unblock_some_thread ( reader_blockset ) ? { readers += 1 ; } rwlock_set_readers ( this , rwlock_op , Scalar :: from_u32 ( readers ) ) ? } Ok ( 0 ) } else { throw_ub_format ! ( " " ) ; } }
FIXME: We should check that this lock was locked by the active thread.
FIXME : We should check that this lock was locked by the active thread .
&mut self
rwlock_op
OpTy<'tcx, Tag>
&mut self
rwlock_op
OpTy<'tcx, Tag>