]>
Commit | Line | Data |
---|---|---|
d8f41ccd A |
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 |