The browser makes memory leaks easy to notice, through the memory-consumption bar graphs in the main browser window: if the allocated portion of memory grows continually, you have a problem. The memory-consumption graph in Figure 6-21 corresponds to a memory leak in an application that has run long enough to almost completely run out of memory.
When a task exceeds its stack size, the resulting problem is often hard to trace, because the initial symptom may be in some other task altogether. The browser's stack-check window is useful when faced with behavior that is hard to explain: if the problem is a stack overflow, you can spot it immediately. The affected task's stack display shows a high-water mark at the right edge, as in the example in Figure 6-22.
A more subtle memory-management problem occurs when small blocks of memory that are not freed for long periods are allocated interleaved with moderate-sized blocks of memory that are freed more frequently: memory can become fragmented, because the calls to free( ) for the large blocks cannot coalesce the free memory back into a single large available-memory pool. This problem is easily observed by examining the affected memory partition (in simple applications this is the VxWorks system memory partition, memSysPartId) with the browser. Figure 6-23 shows an example of a growing free-list with many small blocks, characteristic of memory fragmentation.
The browser's displays are most useful when they complement each other. For example, suppose you notice in the main browser window (as in Figure 6-24) that a task expected to be high priority is blocked while two other tasks are ready to run.
An immediate thing to check is whether the three tasks really have the expected priority relationship (in this example, the names are chosen to suggest the intended priorities: uHi is supposed to have highest priority, uMed medium priority, and uLow the lowest). You can check this immediately by clicking on each task's summary line, thus bringing up the windows shown in Figure 6-25.
Unfortunately, that turns out not to be the explanation; the priorities (shown for each task under Attributes) are indeed as expected. Examining the CPU allocations with the spy window (Figure 6-26) reveals that the observed situation is ongoing; uMed is monopolizing the target CPU. It should certainly execute by preference to the low-priority uLow, but why is uHi not getting to run?
At this point examining the code (not shown) may seem worthwhile. Doing so, you notice that uMed uses no shared resources, but uHi and uLow synchronize their work with a semaphore.
Examining the semaphore with the browser (Figure 6-27) confirms the dawning suspicion: uHi is indeed blocking on the semaphore, which uLow cannot release because uMed has preempted it.
Having diagnosed the problem as a classic priority inversion, the fix is straightforward. As described in VxWorks Programmer's Guide: Basic OS, you can revise the application to synchronize uLow and uHi with a mutual-exclusion semaphore created with the SEM_INVERSION_SAFE option.