1/* 2 * Copyright (c) 2000-2001,2004,2009 Apple Inc. All Rights Reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. Please obtain a copy of the License at 10 * http://www.opensource.apple.com/apsl/ and read it before using this 11 * file. 12 * 13 * The Original Code and all software distributed under the License are 14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 * Please see the License for the specific language governing rights and 19 * limitations under the License. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 */ 23 24 25// 26// structure - structural framework for securityd objects 27// 28#include "structure.h" 29 30 31// 32// NodeCore always has a destructor (because it's virtual), 33// but its dump support is conditionally included. 34// 35NodeCore::~NodeCore() 36{ 37#if defined(DEBUGDUMP) 38 StLock<Mutex> _(mCoreLock); 39 mCoreNodes.erase(this); 40#endif //DEBUGDUMP 41} 42 43 44// 45// Basic object mesh maintainance 46// 47void NodeCore::parent(NodeCore &p) 48{ 49 StLock<Mutex> _(*this); 50 mParent = &p; 51} 52 53void NodeCore::referent(NodeCore &r) 54{ 55 StLock<Mutex> _(*this); 56 assert(!mReferent); 57 mReferent = &r; 58} 59 60void NodeCore::clearReferent() 61{ 62 StLock<Mutex> _(*this); 63 if (mReferent) 64 assert(!mReferent->hasReference(*this)); 65 mReferent = NULL; 66} 67 68 69void NodeCore::addReference(NodeCore &p) 70{ 71 StLock<Mutex> _(*this); 72 assert(p.mReferent == this); 73 mReferences.insert(&p); 74} 75 76void NodeCore::removeReference(NodeCore &p) 77{ 78 StLock<Mutex> _(*this); 79 assert(hasReference(p)); 80 mReferences.erase(&p); 81} 82 83#if !defined(NDEBUG) 84 85bool NodeCore::hasReference(NodeCore &p) 86{ 87 assert(p.refCountForDebuggingOnly() > 0); 88 return mReferences.find(&p) != mReferences.end(); 89} 90 91#endif //NDEBUG 92 93 94// 95// ClearReferences clears the reference set but does not propagate 96// anything; it is NOT recursive. 97// 98void NodeCore::clearReferences() 99{ 100 StLock<Mutex> _(*this); 101 secdebug("ssnode", "%p clearing all %d references", 102 this, int(mReferences.size())); 103 mReferences.erase(mReferences.begin(), mReferences.end()); 104} 105 106 107// 108// Kill should be overloaded by Nodes to implement any cleanup and release 109// operations that should happen at LOGICAL death of the represented object. 110// This is where you should release ports, close files, etc. 111// This default behavior, which you MUST include in your override, 112// propagates kills to all active references, recursively. 113// 114void NodeCore::kill() 115{ 116 StLock<Mutex> _(*this); 117 for (ReferenceSet::const_iterator it = mReferences.begin(); it != mReferences.end(); it++) 118 (*it)->kill(); 119 clearReferences(); 120} 121 122 123void NodeCore::kill(NodeCore &ref) 124{ 125 StLock<Mutex> _(*this); 126 assert(hasReference(ref)); 127 ref.kill(); 128 removeReference(ref); 129} 130 131 132// 133// NodeCore-level support for state dumping. 134// Call NodeCore::dumpAll() to debug-dump all nodes. 135// Note that enabling DEBUGDUMP serializes all node creation/destruction 136// operations, and thus may cause significant shifts in thread interactions. 137// 138#if defined(DEBUGDUMP) 139 140// The (uncounted) set of all known NodeCores in existence, with protective lock 141set<NodeCore *> NodeCore::mCoreNodes; 142Mutex NodeCore::mCoreLock; 143 144// add a new NodeCore to the known set 145NodeCore::NodeCore() 146 : Mutex(Mutex::recursive) 147{ 148 StLock<Mutex> _(mCoreLock); 149 mCoreNodes.insert(this); 150} 151 152// partial-line common dump text for any NodeCore 153// override this to add text to your Node type's state dump output 154void NodeCore::dumpNode() 155{ 156 Debug::dump("%s@%p rc=%u", Debug::typeName(*this).c_str(), this, unsigned(refCountForDebuggingOnly())); 157 if (mParent) 158 Debug::dump(" parent=%p", mParent.get()); 159 if (mReferent) 160 Debug::dump(" referent=%p", mReferent.get()); 161} 162 163// full-line dump of a NodeCore 164// override this to completely re-implement the dump format for your Node type 165void NodeCore::dump() 166{ 167 dumpNode(); 168 if (!mReferences.empty()) { 169 Debug::dump(" {"); 170 for (ReferenceSet::const_iterator it = mReferences.begin(); it != mReferences.end(); it++) { 171 Debug::dump(" %p", it->get()); 172 if ((*it)->mReferent != this) 173 Debug::dump("!*INVALID*"); 174 } 175 Debug::dump(" }"); 176 } 177 Debug::dump("\n"); 178} 179 180// dump all known nodes 181void NodeCore::dumpAll() 182{ 183 StLock<Mutex> _(mCoreLock); 184 time_t now; time(&now); 185 Debug::dump("\nNODE DUMP (%24.24s)\n", ctime(&now)); 186 for (set<NodeCore *>::const_iterator it = mCoreNodes.begin(); it != mCoreNodes.end(); it++) 187 (*it)->dump(); 188 Debug::dump("END NODE DUMP\n\n"); 189} 190 191#endif //DEBUGDUMP 192