Tue, 06 Jan 2015 21:39:09 +0100
Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 *
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #ifndef spacetrace_h__
8 #define spacetrace_h__
10 /*
11 ** spacetrace.h
12 **
13 ** SpaceTrace is meant to take the output of trace-malloc and present
14 ** a picture of allocations over the run of the application.
15 */
17 /*
18 ** Required includes.
19 */
20 #include <stdint.h>
21 #include "nspr.h"
22 #include "prlock.h"
23 #include "prrwlock.h"
24 #include "nsTraceMalloc.h"
25 #include "tmreader.h"
26 #include "formdata.h"
28 /*
29 ** Turn on to attempt adding support for graphs on your platform.
30 */
31 #if defined(HAVE_BOUTELL_GD)
32 #define ST_WANT_GRAPHS 1
33 #endif /* HAVE_BOUTELL_GD */
34 #if !defined(ST_WANT_GRAPHS)
35 #define ST_WANT_GRAPHS 0
36 #endif
38 /*
39 ** REPORT_ERROR
40 ** REPORT_INFO
41 **
42 ** Just report errors and stuff in a consistent manner.
43 */
44 #define REPORT_ERROR(code, function) \
45 PR_fprintf(PR_STDERR, "error(%d):\t%s\n", code, #function)
46 #define REPORT_ERROR_MSG(code, msg) \
47 PR_fprintf(PR_STDERR, "error(%d):\t%s\n", code, msg)
48 #define REPORT_INFO(msg) \
49 PR_fprintf(PR_STDOUT, "%s: %s\n", globals.mProgramName, (msg))
51 #if defined(DEBUG_blythe) && 1
52 #define REPORT_blythe(code, msg) \
53 PR_fprintf(PR_STDOUT, "gab(%d):\t%s\n", code, msg)
54 #else
55 #define REPORT_blythe(code, msg)
56 #endif /* DEBUG_blythe */
58 /*
59 ** CALLSITE_RUN
60 **
61 ** How to get a callsite run.
62 ** Allows for further indirection if needed later.
63 */
64 #define CALLSITE_RUN(callsite) \
65 ((STRun*)((callsite)->data))
67 /*
68 ** ST_PERMS
69 ** ST_FLAGS
70 **
71 ** File permissions we desire.
72 ** 0644
73 */
74 #define ST_PERMS (PR_IRUSR | PR_IWUSR | PR_IRGRP | PR_IROTH)
75 #define ST_FLAGS (PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE)
77 /*
78 ** Sorting order
79 */
80 #define ST_WEIGHT 0 /* size * timeval */
81 #define ST_SIZE 1
82 #define ST_TIMEVAL 2
83 #define ST_COUNT 3
84 #define ST_HEAPCOST 4
86 /*
87 ** Callsite loop direction flags.
88 */
89 #define ST_FOLLOW_SIBLINGS 0
90 #define ST_FOLLOW_PARENTS 1
92 /*
93 ** Graph data.
94 */
95 #define STGD_WIDTH 640
96 #define STGD_HEIGHT 480
97 #define STGD_MARGIN 75
98 #define STGD_SPACE_X (STGD_WIDTH - (2 * STGD_MARGIN))
99 #define STGD_SPACE_Y (STGD_HEIGHT - (2 * STGD_MARGIN))
101 /*
102 ** Minimum lifetime default, in seconds.
103 */
104 #define ST_DEFAULT_LIFETIME_MIN 10
106 /*
107 ** Allocations fall to this boundry size by default.
108 ** Overhead is taken after alignment.
109 **
110 ** The msvcrt malloc has an alignment of 16 with an overhead of 8.
111 ** The win32 HeapAlloc has an alignment of 8 with an overhead of 8.
112 */
113 #define ST_DEFAULT_ALIGNMENT_SIZE 16
114 #define ST_DEFAULT_OVERHEAD_SIZE 8
116 /*
117 ** Numer of substring match specifications to allow.
118 */
119 #define ST_SUBSTRING_MATCH_MAX 5
121 /*
122 ** Max Number of patterns per rule
123 */
124 #define ST_MAX_PATTERNS_PER_RULE 16
126 /*
127 ** Rule pointers and child pointers are allocated in steps of ST_ALLOC_STEP
128 */
129 #define ST_ALLOC_STEP 16
131 /*
132 ** Name of the root category. Appears in UI.
133 */
134 #define ST_ROOT_CATEGORY_NAME "All"
136 /*
137 ** Size of our option string buffers.
138 */
139 #define ST_OPTION_STRING_MAX 256
141 /*
142 ** Set the desired resolution of the timevals.
143 ** The resolution is just mimicking what is recorded in the trace-malloc
144 ** output, and that is currently milliseconds.
145 */
146 #define ST_TIMEVAL_RESOLUTION 1000
147 #define ST_TIMEVAL_FORMAT "%.3f"
148 #define ST_TIMEVAL_PRINTABLE(timeval) ((double)(timeval) / (double)ST_TIMEVAL_RESOLUTION)
149 #define ST_TIMEVAL_PRINTABLE64(timeval) ((double)((int64_t)(timeval)) / (double)ST_TIMEVAL_RESOLUTION)
150 #define ST_TIMEVAL_MAX ((uint32_t)-1 - ((uint32_t)-1 % ST_TIMEVAL_RESOLUTION))
152 #define ST_MICROVAL_RESOLUTION 1000000
153 #define ST_MICROVAL_FORMAT "%.6f"
154 #define ST_MICROVAL_PRINTABLE(timeval) ((double)(timeval) / (double)ST_MICROVAL_RESOLUTION)
155 #define ST_MICROVAL_PRINTABLE64(timeval) ((double)((int64_t)(timeval)) / (double)ST_MICROVAL_RESOLUTION)
156 #define ST_MICROVAL_MAX ((uint32_t)-1 - ((uint32_t)-1 % ST_MICROVAL_RESOLUTION))
158 /*
159 ** Forward Declaration
160 */
161 typedef struct __struct_STCategoryNode STCategoryNode;
162 typedef struct __struct_STCategoryRule STCategoryRule;
165 /*
166 ** STAllocEvent
167 **
168 ** An event that happens to an allocation (malloc, free, et. al.)
169 */
170 typedef struct __struct_STAllocEvent
171 {
172 /*
173 ** The type of allocation event.
174 ** This maps directly to the trace malloc events (i.e. TM_EVENT_MALLOC)
175 */
176 char mEventType;
178 /*
179 ** Each event, foremost, has a chronologically increasing ID in
180 ** relation to other allocation events. This is a time stamp
181 ** of sorts.
182 */
183 uint32_t mTimeval;
185 /*
186 ** Every event has a heap ID (pointer).
187 ** In the event of a realloc, this is the new heap ID.
188 ** In the event of a free, this is the previous heap ID value.
189 */
190 uint32_t mHeapID;
192 /*
193 ** Every event, along with the heap ID, tells of the size.
194 ** In the event of a realloc, this is the new size.
195 ** In th event of a free, this is the previous size.
196 */
197 uint32_t mHeapSize;
199 /*
200 ** Every event has a callsite/stack backtrace.
201 ** In the event of a realloc, this is the new callsite.
202 ** In the event of a free, this is the previous call site.
203 */
204 tmcallsite* mCallsite;
205 } STAllocEvent;
207 /*
208 ** STAllocation
209 **
210 ** An allocation is a temporal entity in the heap.
211 ** It possibly lives under different heap IDs (pointers) and different
212 ** sizes during its given time.
213 ** An allocation is defined by the events during its lifetime.
214 ** An allocation's lifetime is defined by the range of event IDs it holds.
215 */
216 typedef struct __struct_STAllocation
217 {
218 /*
219 ** The array of events.
220 */
221 uint32_t mEventCount;
222 STAllocEvent* mEvents;
224 /*
225 ** The lifetime/lifespan of the allocation.
226 */
227 uint32_t mMinTimeval;
228 uint32_t mMaxTimeval;
230 /*
231 ** Index of this allocation in the global run.
232 */
233 uint32_t mRunIndex;
235 /*
236 ** The runtime cost of heap events in this allocation.
237 ** The cost is defined as the number of time units recorded as being
238 ** spent in heap code (time of malloc, free, et al.).
239 ** We do not track individual event cost in order to save space.
240 */
241 uint32_t mHeapRuntimeCost;
242 } STAllocation;
244 /*
245 ** STCallsiteStats
246 **
247 ** Stats regarding a run, kept mainly for callsite runs.
248 */
249 typedef struct __struct_STCallsiteStats
250 {
251 /*
252 ** Sum timeval of the allocations.
253 ** Callsite runs total all allocations below the callsite.
254 */
255 uint64_t mTimeval64;
257 /*
258 ** Sum weight of the allocations.
259 ** Callsite runs total all allocations below the callsite.
260 */
261 uint64_t mWeight64;
263 /*
264 ** Sum size of the allocations.
265 ** Callsite runs total all allocations below the callsite.
266 */
267 uint32_t mSize;
269 /*
270 ** A stamp, indicated the relevance of the run.
271 ** If the stamp does not match the origin value, the
272 ** data contained here-in is considered invalid.
273 */
274 uint32_t mStamp;
276 /*
277 ** A sum total of allocations (note, not sizes) below the callsite.
278 ** This is NOT the same as STRun::mAllocationCount which
279 ** tracks the STRun::mAllocations array size.
280 */
281 uint32_t mCompositeCount;
283 /*
284 ** A sum total runtime cost of heap operations below the calliste.
285 ** The cost is defined as the number of time units recorded as being
286 ** spent in heap code (time of malloc, free, et al.).
287 */
288 uint32_t mHeapRuntimeCost;
289 } STCallsiteStats;
291 /*
292 ** STRun
293 **
294 ** A run is a closed set of allocations.
295 ** Given a run, we can deduce information about the contained allocations.
296 ** We can also determine if an allocation lives beyond a run (leak).
297 **
298 ** A run might be used to represent allocations for an entire application.
299 ** A run might also be used to represent allocations from a single callstack.
300 */
301 typedef struct __struct_STRun
302 {
303 /*
304 ** The array of allocations.
305 */
306 uint32_t mAllocationCount;
307 STAllocation** mAllocations;
309 /*
310 ** Callsites like to keep some information.
311 ** As callsites are possibly shared between all contexts, each
312 ** different context needs to keep different stats.
313 */
314 STCallsiteStats *mStats;
316 } STRun;
318 /*
319 ** Categorize allocations
320 **
321 ** The objective is to have a tree of categories with each leaf node of the tree
322 ** matching a set of callsites that belong to the category. Each category can
323 ** signify a functional area like say css and hence the user can browse this
324 ** tree looking for how much of each of these are live at an instant.
325 */
327 /*
328 ** STCategoryNode
329 */
331 struct __struct_STCategoryNode
332 {
333 /*
334 ** Category name
335 */
336 const char *categoryName;
338 /*
339 ** Pointer to parent node. NULL for Root.
340 */
341 STCategoryNode *parent;
343 /*
344 ** For non-leaf nodes, an array of children node pointers.
345 ** NULL if leaf node.
346 */
347 STCategoryNode** children;
348 uint32_t nchildren;
350 /*
351 ** The Run(s). Valid for both leaf and parent nodes.
352 ** One run per --Context to handle multiple data sets.
353 ** The relevant index for the particular request will be
354 ** mIndex stored by the mContext of the request.
355 */
356 STRun **runs;
357 };
360 struct __struct_STCategoryRule
361 {
362 /*
363 ** The pattern for the rule. Patterns are an array of strings.
364 ** A callsite needs to pass substring match for all the strings.
365 */
366 char* pats[ST_MAX_PATTERNS_PER_RULE];
367 uint32_t patlen[ST_MAX_PATTERNS_PER_RULE];
368 uint32_t npats;
370 /*
371 ** Category name that this rule belongs to
372 */
373 const char* categoryName;
375 /*
376 ** The node this should be categorized into
377 */
378 STCategoryNode* node;
379 };
382 /*
383 ** CategoryName to Node mapping table
384 */
385 typedef struct __struct_STCategoryMapEntry {
386 STCategoryNode* node;
387 const char * categoryName;
388 } STCategoryMapEntry;
390 /*
391 ** Option genres.
392 **
393 ** This helps to determine what functionality each option effects.
394 ** In specific, this will help use determine when and when not to
395 ** totally recaclulate the sorted run and categories.
396 ** Be very aware that adding things to a particular genre, or adding a genre,
397 ** may completely screw up the caching algorithms of SpaceTrace.
398 ** See contextLookup() or ask someone that knows if you are in doubt.
399 */
400 typedef enum __enum_STOptionGenre
401 {
402 CategoryGenre = 0,
403 DataSortGenre,
404 DataSetGenre,
405 DataSizeGenre,
406 UIGenre,
407 ServerGenre,
408 BatchModeGenre,
410 /*
411 ** Last one please.
412 */
413 MaxGenres
414 }
415 STOptionGenre;
417 /*
418 ** STOptions
419 **
420 ** Structure containing the varios options for the code.
421 ** The definition of these options exists in a different file.
422 ** We access that definition via macros to inline our structure definition.
423 */
424 #define ST_CMD_OPTION_BOOL(option_name, option_genre, option_help) PRBool m##option_name;
425 #define ST_CMD_OPTION_STRING(option_name, option_genre, default_value, option_help) char m##option_name[ST_OPTION_STRING_MAX];
426 #define ST_CMD_OPTION_STRING_ARRAY(option_name, option_genre, array_size, option_help) char m##option_name[array_size][ST_OPTION_STRING_MAX];
427 #define ST_CMD_OPTION_STRING_PTR_ARRAY(option_name, option_genre, option_help) const char** m##option_name; uint32_t m##option_name##Count;
428 #define ST_CMD_OPTION_UINT32(option_name, option_genre, default_value, multiplier, option_help) uint32_t m##option_name;
429 #define ST_CMD_OPTION_UINT64(option_name, option_genre, default_value, multiplier, option_help) uint64_t m##option_name##64;
431 typedef struct __struct_STOptions
432 {
433 #include "stoptions.h"
434 }
435 STOptions;
437 typedef struct __struct_STContext
438 /*
439 ** A per request, thread safe, manner of accessing the contained members.
440 ** A reader/writer lock ensures that the data is properly initialized before
441 ** readers of the data begin their work.
442 **
443 ** mRWLock reader/writer lock.
444 ** writer lock is held to ensure initialization, though
445 ** others can be attempting to acquire read locks
446 ** at that time.
447 ** writer lock is also used in destruction to make sure
448 ** there are no more readers of data contained herein.
449 ** reader lock is to allow multiple clients to read the
450 ** data at the same time; implies is they must not
451 ** write anything.
452 ** mIndex Consider this much like thread private data or thread
453 ** local storage in a few places.
454 ** The index is specifically reserved for this context's
455 ** usage in other data structure array's provided
456 ** for the particular thread/client/context.
457 ** This should not be modified after initialization.
458 ** mSortedRun A pre sorted run taken from the global run, with our
459 ** options applied.
460 ** mImageLock An overly simplistic locking mechanism to protect the
461 ** shared image cache.
462 ** The proper implementation would have a reader/writer
463 ** lock per cached image data.
464 ** However, this will prove to be simpler for the time
465 ** being.
466 ** mFootprintCached Whether or not YData contains something useful.
467 ** mTimevalCached Whether or not YData contains something useful.
468 ** mLifespanCached Whether or not YData contains something useful.
469 ** mWeightCached Whether or not YData contains something useful.
470 ** mFootprintYData Precomputed cached graph data.
471 ** mTimevalYData Precomputed cached graph data.
472 ** mLifespanYData Precomputed cached graph data.
473 ** mWeightYData Precomputed cached graph data.
474 */
475 {
476 PRRWLock* mRWLock;
477 uint32_t mIndex;
478 STRun* mSortedRun;
479 #if ST_WANT_GRAPHS
480 PRLock* mImageLock;
481 PRBool mFootprintCached;
482 PRBool mTimevalCached;
483 PRBool mLifespanCached;
484 PRBool mWeightCached;
485 uint32_t mFootprintYData[STGD_SPACE_X];
486 uint32_t mTimevalYData[STGD_SPACE_X];
487 uint32_t mLifespanYData[STGD_SPACE_X];
488 uint64_t mWeightYData64[STGD_SPACE_X];
489 #endif
490 }
491 STContext;
494 typedef struct __struct_STContextCacheItem
495 /*
496 ** This basically pools the common items that the context cache will
497 ** want to track on a per context basis.
498 **
499 ** mOptions What options this item represents.
500 ** mContext State/data this cache item is wrapping.
501 ** mReferenceCount A count of clients currently using this item.
502 ** Should this item be 0, then the cache might
503 ** decide to evict this context.
504 ** Should this item not be 0, once it reaches
505 ** zero a condition variable in the context cache
506 ** will be signaled to notify the availability.
507 ** mLastAccessed A timestamp of when this item was last accessed/released.
508 ** Ignore this unless the reference count is 0,
509 ** This is used to evict the oldest unused item from
510 ** the context cache.
511 ** mInUse Mainly PR_FALSE only at the beginning of the process,
512 ** but this indicates that the item has not yet been
513 ** used at all, and thus shouldn't be evaluated for
514 ** a cache hit.
515 */
516 {
517 STOptions mOptions;
518 STContext mContext;
519 int32_t mReferenceCount;
520 PRIntervalTime mLastAccessed;
521 PRBool mInUse;
522 }
523 STContextCacheItem;
526 typedef struct __struct_STContextCache
527 /*
528 ** A thread safe, possibly blocking, cache of context items.
529 **
530 ** mLock Must hold the lock to read/access/write to this struct, as
531 ** well as any items it holds.
532 ** mCacheMiss All items are busy and there were no cache matches.
533 ** This condition variable is used to wait until an item becomes
534 ** "available" to be evicted from the cache.
535 ** mItems Array of items.
536 ** mItemCount Number of items in array.
537 ** This is generally the same as the global option's command line
538 ** mContexts....
539 */
540 {
541 PRLock* mLock;
542 PRCondVar* mCacheMiss;
543 STContextCacheItem* mItems;
544 uint32_t mItemCount;
545 }
546 STContextCache;
549 /*
550 ** STRequest
551 **
552 ** Things specific to a request.
553 */
554 typedef struct __struct_STRequest
555 {
556 /*
557 ** Sink/where to output.
558 */
559 PRFileDesc* mFD;
561 /*
562 ** The filename requested.
563 */
564 const char* mGetFileName;
566 /*
567 ** The GET form data, if any.
568 */
569 const FormData* mGetData;
571 /*
572 ** Options specific to this request.
573 */
574 STOptions mOptions;
576 /*
577 ** The context/data/state of the request.
578 */
579 STContext* mContext;
580 } STRequest;
583 /*
584 ** STGlobals
585 **
586 ** Various globals we keep around.
587 */
588 typedef struct __struct_STGlobals
589 {
590 /*
591 ** The string which identifies this program.
592 */
593 const char* mProgramName;
595 /*
596 ** Options derived from the command line.
597 ** These are used as defaults, and should remain static during
598 ** the run of the application.
599 */
600 STOptions mCommandLineOptions;
602 /*
603 ** Context cache.
604 ** As clients come in, based on their options, a different context
605 ** will be used to service them.
606 */
607 STContextCache mContextCache;
609 /*
610 ** Various counters for different types of events.
611 */
612 uint32_t mMallocCount;
613 uint32_t mCallocCount;
614 uint32_t mReallocCount;
615 uint32_t mFreeCount;
617 /*
618 ** Total events, operation counter.
619 */
620 uint32_t mOperationCount;
622 /*
623 ** The "run" of the input.
624 */
625 STRun mRun;
627 /*
628 ** Operation minimum/maximum timevals.
629 ** So that we can determine the overall timeval of the run.
630 ** NOTE: These are NOT the options to control the data set.
631 */
632 uint32_t mMinTimeval;
633 uint32_t mMaxTimeval;
635 /*
636 ** Calculates peak allocation overall for all allocations.
637 */
638 uint32_t mPeakMemoryUsed;
639 uint32_t mMemoryUsed;
641 /*
642 ** A list of rules for categorization read in from the mCategoryFile
643 */
644 STCategoryRule** mCategoryRules;
645 uint32_t mNRules;
647 /*
648 ** CategoryName to Node mapping table
649 */
650 STCategoryMapEntry** mCategoryMap;
651 uint32_t mNCategoryMap;
653 /*
654 ** Categorized allocations. For now we support only one tree.
655 */
656 STCategoryNode mCategoryRoot;
658 /*
659 ** tmreader hash tables.
660 ** Moved into globals since we need to destroy these only after all
661 ** client threads are finishes (after PR_Cleanup).
662 */
663 tmreader* mTMR;
664 } STGlobals;
667 /*
668 ** Function prototypes
669 */
670 extern STRun* createRun(STContext* inContext, uint32_t aStamp);
671 extern void freeRun(STRun* aRun);
672 extern int initCategories(STGlobals* g);
673 extern int categorizeRun(STOptions* inOptions, STContext* inContext, const STRun* aRun, STGlobals* g);
674 extern STCategoryNode* findCategoryNode(const char *catName, STGlobals *g);
675 extern int freeCategories(STGlobals* g);
676 extern int displayCategoryReport(STRequest* inRequest, STCategoryNode *root, int depth);
678 extern int recalculateAllocationCost(STOptions* inOptions, STContext* inContext, STRun* aRun, STAllocation* aAllocation, PRBool updateParent);
679 extern void htmlHeader(STRequest* inRequest, const char* aTitle);
680 extern void htmlFooter(STRequest* inRequest);
681 extern void htmlAnchor(STRequest* inRequest,
682 const char* aHref,
683 const char* aText,
684 const char* aTarget,
685 const char* aClass,
686 STOptions* inOptions);
687 extern char *FormatNumber(int32_t num);
689 /*
690 ** shared globals
691 */
692 extern STGlobals globals;
694 #endif /* spacetrace_h__ */