00001 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ 00002 /* 00003 * Copyright (c) 2008 INRIA 00004 * 00005 * This program is free software; you can redistribute it and/or modify 00006 * it under the terms of the GNU General Public License version 2 as 00007 * published by the Free Software Foundation; 00008 * 00009 * This program is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 * GNU General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU General Public License 00015 * along with this program; if not, write to the Free Software 00016 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00017 * 00018 * Author: Mathieu Lacage <mathieu.lacage.inria.fr> 00019 */ 00020 00021 #include <pthread.h> 00022 #include <string.h> 00023 #include <errno.h> 00024 #include "fatal-error.h" 00025 #include "system-mutex.h" 00026 #include "log.h" 00027 00028 NS_LOG_COMPONENT_DEFINE ("SystemMutex"); 00029 00030 namespace ns3 { 00031 00032 class SystemMutexPrivate { 00033 public: 00034 SystemMutexPrivate (); 00035 ~SystemMutexPrivate (); 00036 00037 void Lock (void); 00038 void Unlock (void); 00039 private: 00040 pthread_mutex_t m_mutex; 00041 }; 00042 00043 SystemMutexPrivate::SystemMutexPrivate () 00044 { 00045 NS_LOG_FUNCTION_NOARGS (); 00046 00047 pthread_mutexattr_t attr; 00048 pthread_mutexattr_init (&attr); 00049 // 00050 // Make this an error checking mutex. This will check to see if the current 00051 // thread already owns the mutex before trying to lock it. Instead of 00052 // deadlocking it returns an error. It will also check to make sure a thread 00053 // has previously called pthread_mutex_lock when it calls pthread_mutex_unlock. 00054 // 00055 // Linux and OS X (at least) have, of course chosen different names for the 00056 // error checking flags just to make life difficult. 00057 // 00058 #if defined (PTHREAD_MUTEX_ERRORCHECK_NP) 00059 pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_ERRORCHECK_NP); 00060 #else 00061 pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_ERRORCHECK); 00062 #endif 00063 pthread_mutex_init (&m_mutex, &attr); 00064 } 00065 00066 SystemMutexPrivate::~SystemMutexPrivate() 00067 { 00068 NS_LOG_FUNCTION_NOARGS (); 00069 pthread_mutex_destroy (&m_mutex); 00070 } 00071 00072 void 00073 SystemMutexPrivate::Lock (void) 00074 { 00075 NS_LOG_FUNCTION_NOARGS (); 00076 00077 int rc = pthread_mutex_lock (&m_mutex); 00078 if (rc != 0) 00079 { 00080 NS_FATAL_ERROR ("SystemMutexPrivate::Lock()" 00081 "pthread_mutex_lock failed: " << rc << " = \"" << 00082 strerror(rc) << "\""); 00083 } 00084 } 00085 00086 void 00087 SystemMutexPrivate::Unlock (void) 00088 { 00089 NS_LOG_FUNCTION_NOARGS (); 00090 00091 int rc = pthread_mutex_unlock (&m_mutex); 00092 if (rc != 0) 00093 { 00094 NS_FATAL_ERROR ("SystemMutexPrivate::Unlock()" 00095 "pthread_mutex_unlock failed: " << rc << " = \"" << 00096 strerror(rc) << "\""); 00097 } 00098 } 00099 00100 SystemMutex::SystemMutex() 00101 : m_priv (new SystemMutexPrivate ()) 00102 { 00103 NS_LOG_FUNCTION_NOARGS (); 00104 } 00105 00106 SystemMutex::~SystemMutex() 00107 { 00108 NS_LOG_FUNCTION_NOARGS (); 00109 delete m_priv; 00110 } 00111 00112 void 00113 SystemMutex::Lock() 00114 { 00115 NS_LOG_FUNCTION_NOARGS (); 00116 m_priv->Lock (); 00117 } 00118 00119 void 00120 SystemMutex::Unlock() 00121 { 00122 NS_LOG_FUNCTION_NOARGS (); 00123 m_priv->Unlock (); 00124 } 00125 00126 CriticalSection::CriticalSection (SystemMutex &mutex) 00127 : m_mutex(mutex) 00128 { 00129 NS_LOG_FUNCTION_NOARGS (); 00130 m_mutex.Lock (); 00131 } 00132 00133 CriticalSection::~CriticalSection () 00134 { 00135 NS_LOG_FUNCTION_NOARGS (); 00136 m_mutex.Unlock (); 00137 } 00138 00139 } // namespace ns3