📄 mutex.cxx
字号:
//==========================================================================//// sync/mutex.cxx//// Mutex and condition variable implementation////==========================================================================//####COPYRIGHTBEGIN####//// -------------------------------------------// The contents of this file are subject to the Cygnus eCos Public License// Version 1.0 (the "License"); you may not use this file except in// compliance with the License. You may obtain a copy of the License at// http://sourceware.cygnus.com/ecos// // Software distributed under the License is distributed on an "AS IS"// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the// License for the specific language governing rights and limitations under// the License.// // The Original Code is eCos - Embedded Cygnus Operating System, released// September 30, 1998.// // The Initial Developer of the Original Code is Cygnus. Portions created// by Cygnus are Copyright (C) 1998,1999 Cygnus Solutions. All Rights Reserved.// -------------------------------------------////####COPYRIGHTEND####//==========================================================================//#####DESCRIPTIONBEGIN####//// Author(s): nickg// Contributors: nickg, jlarmour// Date: 1999-02-17// Purpose: Mutex implementation// Description: This file contains the implementations of the mutex// and condition variable classes.////####DESCRIPTIONEND####////==========================================================================#include <pkgconf/kernel.h>#include <cyg/kernel/ktypes.h> // base kernel types#include <cyg/infra/cyg_trac.h> // tracing macros#include <cyg/infra/cyg_ass.h> // assertion macros#include <cyg/kernel/instrmnt.h> // instrumentation#include <cyg/kernel/mutex.hxx> // our header#include <cyg/kernel/thread.inl> // thread inlines#include <cyg/kernel/sched.inl> // scheduler inlines#include <cyg/kernel/clock.inl> // clock inlines// -------------------------------------------------------------------------// ConstructorCyg_Mutex::Cyg_Mutex(){ CYG_REPORT_FUNCTION(); locked = false; owner = NULL; CYG_REPORT_RETURN();}// -------------------------------------------------------------------------// DestructorCyg_Mutex::~Cyg_Mutex(){ CYG_REPORT_FUNCTION(); CYG_ASSERT( owner == NULL, "Deleting mutex with owner"); CYG_ASSERT( queue.empty(), "Deleting mutex with waiting threads"); CYG_REPORT_RETURN();}// -------------------------------------------------------------------------#ifdef CYGDBG_USE_ASSERTSboolCyg_Mutex::check_this( cyg_assert_class_zeal zeal) const{// CYG_REPORT_FUNCTION(); // check that we have a non-NULL pointer first if( this == NULL ) return false; switch( zeal ) { case cyg_system_test: case cyg_extreme: case cyg_thorough: case cyg_quick: case cyg_trivial: if( locked && owner == NULL ) return false; if( !locked && owner != NULL ) return false; case cyg_none: default: break; }; return true;}#endif// -------------------------------------------------------------------------// Lock and/or waitcyg_boolCyg_Mutex::lock(void){ CYG_REPORT_FUNCTYPE("returning %d"); cyg_bool result = true; Cyg_Thread *self = Cyg_Thread::self(); // Prevent preemption Cyg_Scheduler::lock(); CYG_ASSERTCLASS( this, "Bad this pointer"); CYG_INSTRUMENT_MUTEX(LOCK, this, 0); // Loop while the mutex is locked, sleeping each time around // the loop. This copes with the possibility of a higher priority // thread grabbing the mutex between the wakeup in unlock() and // this thread actually starting. while( locked && result ) { CYG_ASSERT( self != owner, "Locking mutex I already own"); self->set_sleep_reason( Cyg_Thread::WAIT ); self->sleep(); queue.enqueue( self );#ifdef CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INHERITANCE owner->inherit_priority(self); #endif CYG_INSTRUMENT_MUTEX(WAIT, this, 0); CYG_ASSERT( Cyg_Scheduler::get_sched_lock() == 1, "Called with non-zero scheduler lock"); // Unlock scheduler and allow other threads // to run Cyg_Scheduler::unlock(); Cyg_Scheduler::lock(); CYG_ASSERTCLASS( this, "Bad this pointer"); switch( self->get_wake_reason() ) { case Cyg_Thread::DESTRUCT: case Cyg_Thread::BREAK: result = false; break; case Cyg_Thread::EXIT: self->exit(); break; default: break; } } if( result ) { locked = true; owner = self;#ifdef CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INHERITANCE self->count_mutex();#endif CYG_INSTRUMENT_MUTEX(LOCKED, this, 0); } // Unlock the scheduler and maybe switch threads Cyg_Scheduler::unlock(); CYG_ASSERTCLASS( this, "Bad this pointer"); CYG_REPORT_RETVAL(result); return result;}// -------------------------------------------------------------------------// Try to lock and return successcyg_boolCyg_Mutex::trylock(void){ CYG_REPORT_FUNCTYPE("returning %d"); CYG_ASSERTCLASS( this, "Bad this pointer"); cyg_bool result = true; // Prevent preemption Cyg_Scheduler::lock(); // If the mutex is not locked, grab it // for ourself. Otherwise return failure. if( !locked ) { Cyg_Thread *self = Cyg_Thread::self(); locked = true; owner = self;#ifdef CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INHERITANCE self->count_mutex();#endif } else result = false; CYG_INSTRUMENT_MUTEX(TRY, this, result); // Unlock the scheduler and maybe switch threads Cyg_Scheduler::unlock(); CYG_REPORT_RETVAL(result); return result; }// -------------------------------------------------------------------------// unlockvoidCyg_Mutex::unlock(void){ CYG_REPORT_FUNCTION(); // Prevent preemption Cyg_Scheduler::lock(); CYG_INSTRUMENT_MUTEX(UNLOCK, this, 0); CYG_ASSERTCLASS( this, "Bad this pointer"); CYG_ASSERT( locked, "Unlock mutex that is not locked"); CYG_ASSERT( owner == Cyg_Thread::self(), "Unlock mutex I do not own"); #ifdef CYGSEM_KERNEL_SYNCH_MUTEX_PRIORITY_INHERITANCE owner->uncount_mutex(); owner->disinherit_priority(); #endif locked = false; owner = NULL; if( !queue.empty() ) { // The queue is non-empty, so grab the next // thread from it and wake it up. Cyg_Thread *thread = queue.dequeue(); CYG_ASSERTCLASS( thread, "Bad thread pointer"); thread->set_wake_reason( Cyg_Thread::DONE ); thread->wake(); CYG_INSTRUMENT_MUTEX(WAKE, this, thread); } CYG_ASSERTCLASS( this, "Bad this pointer"); // Unlock the scheduler and maybe switch threads Cyg_Scheduler::unlock(); CYG_REPORT_RETURN();}// -------------------------------------------------------------------------// Release all waiting threads.void Cyg_Mutex::release(){ CYG_REPORT_FUNCTION(); // Prevent preemption Cyg_Scheduler::lock(); CYG_INSTRUMENT_MUTEX(RELEASE, this, 0); CYG_ASSERTCLASS( this, "Bad this pointer"); while( !queue.empty() ) { // The queue is non-empty, so grab each // thread from it and release it. Cyg_Thread *thread = queue.dequeue(); CYG_ASSERTCLASS( thread, "Bad thread pointer"); thread->release(); CYG_INSTRUMENT_MUTEX(RELEASED, this, thread); } CYG_ASSERTCLASS( this, "Bad this pointer");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -