used dictionary find() to achieve some speedup
[dyninst.git] / paradynd / src / resource.C
1 /*
2  * Copyright (c) 1996 Barton P. Miller
3  * 
4  * We provide the Paradyn Parallel Performance Tools (below
5  * described as Paradyn") on an AS IS basis, and do not warrant its
6  * validity or performance.  We reserve the right to update, modify,
7  * or discontinue this software at any time.  We shall have no
8  * obligation to supply such updates or modifications or any other
9  * form of support to you.
10  * 
11  * This license is for research uses.  For such uses, there is no
12  * charge. We define "research use" to mean you may freely use it
13  * inside your organization for whatever purposes you see fit. But you
14  * may not re-distribute Paradyn or parts of Paradyn, in any form
15  * source or binary (including derivatives), electronic or otherwise,
16  * to any other organization or entity without our permission.
17  * 
18  * (for other uses, please contact us at paradyn@cs.wisc.edu)
19  * 
20  * All warranties, including without limitation, any warranty of
21  * merchantability or fitness for a particular purpose, are hereby
22  * excluded.
23  * 
24  * By your use of Paradyn, you understand and agree that we (or any
25  * other person or entity with proprietary rights in Paradyn) are
26  * under no obligation to provide either maintenance services,
27  * update services, notices of latent defects, or correction of
28  * defects for Paradyn.
29  * 
30  * Even if advised of the possibility of such damages, under no
31  * circumstances shall we (or any other person or entity with
32  * proprietary rights in the software licensed hereunder) be liable
33  * to you or any third party for direct, indirect, or consequential
34  * damages of any character regardless of type of action, including,
35  * without limitation, loss of profits, loss of use, loss of good
36  * will, or computer failure or malfunction.  You agree to indemnify
37  * us (and any other person or entity with proprietary rights in the
38  * software licensed hereunder) for any and all liability it may
39  * incur to third parties resulting from your use of Paradyn.
40  */
41
42 /*
43  * resource.C - handle resource creation and queries.
44  *
45  * $Log: resource.C,v $
46  * Revision 1.28  1997/06/23 17:04:36  tamches
47  * used dictionary find() to achieve some speedup
48  *
49  * Revision 1.27  1997/04/29 23:17:44  mjrg
50  * Changes for WindowsNT port
51  * Delayed check for DYNINST symbols to allow linking libdyninst dynamically
52  * Changed way paradyn and paradynd generate resource ids
53  * Changes to instPoint class in inst-x86.C to reduce size of objects
54  * Added initialization for process->threads to fork and attach constructors
55  *
56  * Revision 1.26  1997/04/14 20:08:03  zhichen
57  * Added   enum index { machine, procedure, process, sync_object, memory };
58  *         resource *memoryRoot; // shared-memory resource
59  *         resource *memoryResource; // shared-memory resource
60  *         resource *resource::newResource_ncb(...)
61  * changed void resource::make_canonical...)
62  *
63  * Revision 1.25  1997/03/29 02:11:06  sec
64  * Debugging stuff
65  *
66  * Revision 1.24  1997/02/26 23:46:48  mjrg
67  * First part of WindowsNT port: changes for compiling with Visual C++;
68  * moved unix specific code to unix.C file
69  *
70  * Revision 1.23  1997/02/21 20:16:03  naim
71  * Moving files from paradynd to dyninstAPI + eliminating references to
72  * dataReqNode from the ast class. This is the first pre-dyninstAPI commit! - naim
73  *
74  * Revision 1.22  1997/01/15 00:30:18  tamches
75  * added some uses of dictionary find() method
76  *
77  * Revision 1.21  1996/09/26 18:59:12  newhall
78  * added support for instrumenting dynamic executables on sparc-solaris
79  * platform
80  *
81  * Revision 1.20  1996/08/16 21:19:46  tamches
82  * updated copyright for release 1.1
83  *
84  * Revision 1.19  1996/06/01 00:04:10  tamches
85  * const and refs added in appropriate places to enhance speed and compile
86  * time error checking
87  *
88  * Revision 1.18  1996/03/01 22:35:57  mjrg
89  * Added a type to resources.
90  * Changes to the MDL to handle the resource hierarchy better.
91  *
92  * Revision 1.17  1995/12/20 16:10:23  tamches
93  * minor changes for the new vector class (no constructor taking in T&)
94  *
95  * Revision 1.16  1995/07/24 03:53:13  tamches
96  * The Procedure -- > Code commit
97  *
98  * Revision 1.15  1995/05/18  10:41:49  markc
99  * Cache global ids supplied by paradyn
100  * have a canonical form for the resource list
101  *
102  */
103
104 #include <limits.h>
105 #include "dyninstAPI/src/symtab.h"
106 #include "dyninstAPI/src/process.h"
107 #include "dyninstAPI/src/dyninstP.h"
108 #include "dyninstAPI/src/util.h"
109 #include "paradynd/src/comm.h"
110 #include "util/h/String.h"
111 #include "util/h/Dictionary.h"
112 #include "paradynd/src/main.h"
113
114 u_int resource::num_outstanding_creates = 0;
115 dictionary_hash<string, resource*> resource::allResources(string::hash);
116 dictionary_hash<unsigned, resource*> resource::res_dict(uiHash);
117
118 /*
119  * handle the notification of resource creation and deletion.
120  *
121  */
122
123 resource *rootResource;
124 resource *machineRoot;
125 resource *machineResource;
126 resource *processResource;
127 resource *moduleRoot;
128 resource *syncRoot;
129 resource *memoryRoot; // shared-memory resource
130 resource *memoryResource; // shared-memory resource
131
132
133 resource *resource::newResource(resource *parent, const string& name, unsigned id, 
134                                 unsigned type) {
135   assert (name != (char*) NULL);
136   assert ((name.string_of())[0] != '/');
137
138   string res_string = parent->full_name() + slashStr + name;
139
140   // first check to see if the resource has already been defined 
141   resource *ret;
142   if (allResources.find(res_string, ret)) // writes to ret if found
143      return ret;
144
145   string abs;
146
147   
148   //ret = new resource(abs, name, 0.0, NULL, false, parent, v_names, type);
149   ret = new resource(abs, name, 0.0, NULL, false, parent, type);
150   assert(ret);
151
152   allResources[res_string] = ret;
153   res_dict[id] = ret;
154   return(ret);
155 }
156
157 resource *resource::newResource(resource *parent, void *handle,
158                                 const string &abstraction, 
159                                 const string &name, timeStamp creation,
160                                 const string &unique,
161                                 unsigned type)
162 {
163   assert (name != (char*) NULL);
164   assert ((name.string_of())[0] != '/');
165   static const string leftBracket = "{";
166   static const string rightBracket = "}";
167
168   string unique_string(name);
169   if (unique.length()) 
170     unique_string += leftBracket + unique + rightBracket;
171
172   string res_string = parent->full_name() + slashStr + unique_string;
173
174   // Has this resource already been defined?
175   if (allResources.defines(res_string))
176     return (allResources[res_string]);
177
178   // The components of this resource's name equals that of its parent, plus
179   // the extra level not included with the parent.
180   vector<string> res_components = parent->names();
181   res_components += unique_string;
182
183   resource *ret = new resource(abstraction, unique_string, creation, handle,
184                                false, parent, type);
185   assert(ret);
186   allResources[res_string] = ret;
187
188   // TODO -- use pid here
189   //logLine("newResource:  ");
190   //logLine(P_strdup(name.string_of()));
191   //logLine("\n");
192
193   // generate a unique Id for this resource. Each daemon generates its own id
194   // for the resource and report it to paradyn. If there are any conflicts
195   // between ids generated by two daemons, paradyn will pick a new id and
196   // send a resourceInfoResponse message to the daemons with the new id.
197   // We generate Id's on the range 0..INT_MAX. Values from INT_MAX to UINT_MAX
198   // are used by paradyn when there are conflicts
199   unsigned id = string::hash(res_string) % ((unsigned)INT_MAX);
200   while (res_dict.defines(id)) {
201     id = (id + 1) % ((unsigned)INT_MAX);
202   }
203   res_dict[id] = ret;
204
205   tp->resourceInfoCallback(id, res_components, abstraction, type); 
206   return(ret);
207 }
208
209 resource *resource::newResource_ncb(resource *parent, void *handle,
210                                 const string &abstraction, 
211                                 const string &name, timeStamp creation,
212                                 const string &unique,
213                                 unsigned type)
214 {
215   assert (name != (char*) NULL);
216   assert ((name.string_of())[0] != '/');
217
218   string unique_string(name);
219   if (unique.length()) 
220     unique_string += string("{") + unique + string("}");
221
222   string res_string = parent->full_name() + "/" + unique_string;
223
224   // Has this resource already been defined?
225   if (allResources.defines(res_string))
226     return (allResources[res_string]);
227
228   // The components of this resource's name equals that of its parent, plus
229   // the extra level not included with the parent.
230   vector<string> res_components = parent->names();
231   res_components += unique_string;
232
233   resource *ret = new resource(abstraction, unique_string, creation, handle,
234                                false, parent, type);
235   assert(ret);
236   allResources[res_string] = ret;
237
238   return(ret);
239 }
240
241 bool resource::foc_to_strings(vector< vector<string> >& string_foc,
242                               const vector<u_int>& ids,
243                               bool print_err_msg) {
244   unsigned id_size = ids.size();
245   for (unsigned i=0; i<id_size; i++) {
246     resource *r;
247     if (!res_dict.find(ids[i], r)) { // writes to "r" if found
248        if (print_err_msg) {
249          cerr << "resource::foc_to_strings -- could not find resource entry for id " << ids[i] << endl;
250        }
251        return false;
252     }
253
254     string_foc += r->names();
255   }
256
257   return true;
258 }
259
260 // Other parts of the system depend on this order (mdl.C)
261 // Assume that there are 4 top level resources
262 void resource::make_canonical(const vector< vector<string> >& focus,
263                               vector< vector<string> >& ret) {
264   unsigned size = focus.size();
265   bool machine=false, procedure=false, process=false, sync=false, memory = false;
266   ret.resize(5); //changed from 4 to 5 Zhichen for resource::memory
267   for (unsigned f=0; f<size; f++) {
268     assert(focus[f].size() > 0);
269     if (focus[f][0] == "Machine") {
270       machine = true;
271       ret[resource::machine] = focus[f];
272     } else if (focus[f][0] == "Code") {      
273       procedure = true;
274       ret[resource::procedure] = focus[f];
275     } else if (focus[f][0] == "Process") {
276       process = true;
277       ret[resource::process] = focus[f];
278     } else if (focus[f][0] == "SyncObject") {
279       sync = true;
280       ret[resource::sync_object] = focus[f];
281     } else if (focus[f][0] == "Memory") {
282       memory = true ;
283       ret[resource::memory] = focus[f] ;
284     }
285   }
286
287   vector<string> temp(1); // 1 entry vector
288
289   if (!machine) {temp[0]="Machine"; ret[resource::machine] = temp;}
290   if (!procedure) {temp[0]="Code"; ret[resource::procedure] = temp;}
291   if (!process) {temp[0]="Process"; ret[resource::process] = temp;}
292   if (!sync) {temp[0]="SyncObject"; ret[resource::sync_object] = temp;}
293   if (!memory) {temp[0]="Memory"; ret[resource::memory] = temp; }
294 }