00001 #ifndef TPMCS_LOCK_H 00002 #define TPMCS_LOCK_H 00003 /* -*- mode:C++; c-basic-offset:4 -*- 00004 Shore-MT -- Multi-threaded port of the SHORE storage manager 00005 00006 Copyright (c) 2007-2009 00007 Data Intensive Applications and Systems Labaratory (DIAS) 00008 Ecole Polytechnique Federale de Lausanne 00009 00010 All Rights Reserved. 00011 00012 Permission to use, copy, modify and distribute this software and 00013 its documentation is hereby granted, provided that both the 00014 copyright notice and this permission notice appear in all copies of 00015 the software, derivative works or modified versions, and any 00016 portions thereof, and that both notices appear in supporting 00017 documentation. 00018 00019 This code is distributed in the hope that it will be useful, but 00020 WITHOUT ANY WARRANTY; without even the implied warranty of 00021 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. THE AUTHORS 00022 DISCLAIM ANY LIABILITY OF ANY KIND FOR ANY DAMAGES WHATSOEVER 00023 RESULTING FROM THE USE OF THIS SOFTWARE. 00024 */ 00025 00026 // -*- mode:c++; c-basic-offset:4 -*- 00027 00028 /**\cond skip */ 00029 /**\todo TPMCS locks don't build TODO. Perhaps remove it altogether */ 00030 /** \brief A time-published MCS lock. 00031 * This is a simplified version of the lock 00032 * cited below, and may be used as a drop-in replacement for a normal 00033 * MCS lock. 00034 * 00035 * B He, W Scherer III, M Scott, "Preemption Adaptivity in 00036 * Time-Published Queue-Based Spinlocks." In Proc. HiPC'05. 00037 * Abstract at: http://www.springerlink.com/content/t578363585747371/ 00038 * 00039 * WARNING: This code is debugged but does not quite match the current 00040 * MCS lock; it should be a usable replacement for mcs_lock if updated 00041 * with ext_qnode operations, but (as always) Caveat Emptor. 00042 */ 00043 struct tpmcs_lock 00044 { 00045 struct ext_qnode; // forward 00046 enum status { DEAD=0, WAITING, GRANTED }; 00047 typedef ext_qnode volatile* qnode_ptr; 00048 struct ext_qnode { 00049 qnode_ptr _next; 00050 hrtime_t _touched; 00051 status _status; 00052 // ext_qnode() : _next(NULL), _waiting(false) { } 00053 }; 00054 qnode_ptr volatile _tail; 00055 hrtime_t volatile _cs_start; 00056 #ifndef ARCH_LP64 00057 hrtime_t volatile _acquires; 00058 #endif 00059 hrtime_t _max_cs; 00060 tpmcs_lock(hrtime_t max_cs=0); 00061 00062 void spin_on_waiting(qnode_ptr me); 00063 bool attempt(qnode_ptr me); 00064 void acquire(qnode_ptr me); 00065 qnode_ptr spin_on_next(qnode_ptr me); 00066 void release(qnode_ptr me); 00067 bool is_mine(qnode_ptr me) { return _tail == me; } 00068 }; 00069 00070 /**\endcond skip */ 00071 00072 #endif