staticvoid__mutex_lock(structmutex*m,constchar*fname,int lineno){assert_have_no_spinlock();assert(thread_get_id_may_fail()!= THREAD_ID_INVALID);assert(thread_is_in_normal_mode());mutex_lock_check(m);while(true){uint32_t old_itr_status;bool can_lock;structwait_queue_elem wqe;/** If the mutex is locked we need to initialize the wqe* before releasing the spinlock to guarantee that we don't* miss the wakeup from mutex_unlock().** If the mutex is unlocked we don't need to use the wqe at* all.*/old_itr_status =cpu_spin_lock_xsave(&m->spin_lock);can_lock =!m->state;if(!can_lock){wq_wait_init(&m->wq,&wqe, false /* wait_read */);}else{m->state =-1;/* write locked */}cpu_spin_unlock_xrestore(&m->spin_lock, old_itr_status);if(!can_lock){/** Someone else is holding the lock, wait in normal* world for the lock to become available.*/wq_wait_final(&m->wq,&wqe, m, fname, lineno);}elsereturn;}}staticvoid__mutex_unlock(structmutex*m,constchar*fname,int lineno){uint32_t old_itr_status;assert_have_no_spinlock();assert(thread_get_id_may_fail()!= THREAD_ID_INVALID);mutex_unlock_check(m);old_itr_status =cpu_spin_lock_xsave(&m->spin_lock);if(!m->state)panic();m->state =0;cpu_spin_unlock_xrestore(&m->spin_lock, old_itr_status);wq_wake_next(&m->wq, m, fname, lineno);}