]> git.saurik.com Git - apple/security.git/blob - securityd/src/structure.cpp
Security-57337.40.85.tar.gz
[apple/security.git] / securityd / src / structure.cpp
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 //
35 NodeCore::~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 //
47 void NodeCore::parent(NodeCore &p)
48 {
49 StLock<Mutex> _(*this);
50 mParent = &p;
51 }
52
53 void NodeCore::referent(NodeCore &r)
54 {
55 StLock<Mutex> _(*this);
56 assert(!mReferent);
57 mReferent = &r;
58 }
59
60 void NodeCore::clearReferent()
61 {
62 StLock<Mutex> _(*this);
63 if (mReferent)
64 assert(!mReferent->hasReference(*this));
65 mReferent = NULL;
66 }
67
68
69 void NodeCore::addReference(NodeCore &p)
70 {
71 StLock<Mutex> _(*this);
72 assert(p.mReferent == this);
73 mReferences.insert(&p);
74 }
75
76 void NodeCore::removeReference(NodeCore &p)
77 {
78 StLock<Mutex> _(*this);
79 assert(hasReference(p));
80 mReferences.erase(&p);
81 }
82
83 #if !defined(NDEBUG)
84
85 bool 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 //
98 void 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 //
114 void 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
123 void 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
141 set<NodeCore *> NodeCore::mCoreNodes;
142 Mutex NodeCore::mCoreLock;
143
144 // add a new NodeCore to the known set
145 NodeCore::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
154 void 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
165 void 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
181 void 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