1 /* Copyright 2008 Sun Microsystems, Inc. 2 All rights reserved. Use is subject to license terms. 3 4 This program is free software; you can redistribute it and/or modify 5 it under the terms of the GNU General Public License, version 2.0, 6 as published by the Free Software Foundation. 7 8 This program is also distributed with certain software (including 9 but not limited to OpenSSL) that is licensed under separate terms, 10 as designated in a particular file or component or in included license 11 documentation. The authors of MySQL hereby grant you an additional 12 permission to link the program and your derivative works with the 13 separately licensed software that they have included with MySQL. 14 15 This program is distributed in the hope that it will be useful, 16 but WITHOUT ANY WARRANTY; without even the implied warranty of 17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 GNU General Public License, version 2.0, for more details. 19 20 You should have received a copy of the GNU General Public License 21 along with this program; if not, write to the Free Software 22 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ 23 24 #ifndef NDB_SAFE_MUTEX_HPP 25 #define NDB_SAFE_MUTEX_HPP 26 27 #ifdef __WIN__ 28 #include <ndb_global.h> 29 #include <my_pthread.h> 30 #else 31 #include <pthread.h> 32 #endif 33 #include <assert.h> 34 #include <ndb_types.h> 35 #include <NdbOut.hpp> 36 37 /* 38 * Recursive mutex with recursion limit >= 1. Intended for debugging. 39 * One should rewrite caller code until limit 1 works. 40 * 41 * The implementation uses a default mutex. If limit is > 1 or debug 42 * is specified then a recursive mutex is simulated. Operating system 43 * recursive mutex (if any) is not used. The simulation is several 44 * times slower. There is a unit test testSafeMutex. 45 * 46 * The caller currently is multi-threaded disk data. Here it is easy 47 * to verify that the mutex is released within a time-slice. 48 */ 49 50 class SafeMutex { 51 const char* const m_name; 52 const Uint32 m_limit; // error if usage exceeds this 53 const bool m_debug; // use recursive implementation even for limit 1 54 const bool m_simple; 55 pthread_mutex_t m_mutex; 56 pthread_cond_t m_cond; 57 pthread_t m_owner; 58 bool m_initdone; 59 Uint32 m_level; 60 Uint32 m_usage; // max level used so far 61 int m_errcode; 62 int m_errline; 63 int err(int errcode, int errline); 64 friend class NdbOut& operator<<(NdbOut&, const SafeMutex&); 65 66 public: SafeMutex(const char * name,Uint32 limit,bool debug)67 SafeMutex(const char* name, Uint32 limit, bool debug) : 68 m_name(name), 69 m_limit(limit), 70 m_debug(debug), 71 m_simple(!(limit > 1 || debug)) 72 { 73 assert(m_limit >= 1), 74 m_owner = 0; // wl4391_todo assuming numeric non-zero 75 m_initdone = false; 76 m_level = 0; 77 m_usage = 0; 78 m_errcode = 0; 79 m_errline = 0; 80 }; ~SafeMutex()81 ~SafeMutex() { 82 if (m_initdone) 83 (void)destroy(); 84 } 85 86 enum { 87 // caller must crash on any error - recovery is not possible 88 ErrState = -101, // user error 89 ErrLevel = -102, // level exceeded limit 90 ErrOwner = -103, // unlock when not owner 91 ErrNolock = -104 // unlock when no lock 92 }; 93 int create(); 94 int destroy(); 95 int lock(); 96 int unlock(); 97 98 private: 99 int lock_impl(); 100 int unlock_impl(); 101 }; 102 103 #endif 104