1 /* -*- mode: C; c-file-style: "linux" -*- */
3 /* MemProf -- memory profiler and leak detector
4 * Copyright 2006 Carsten Haitzler
5 * Copyright 2009 Holger Hans Peter Freyther
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
38 #include <glade/glade.h>
45 dw_draw_memstats(ProcessWindow
*pwin
)
49 gint64 i
, j
, x
, y
, w
, h
, hh
;
51 widget
= pwin
->time_graph
;
52 w
= widget
->allocation
.width
;
53 h
= widget
->allocation
.height
;
54 if (!widget
->window
) return;
55 pixmap
= gdk_pixmap_new(widget
->window
, w
, h
, -1);
56 gdk_draw_rectangle(pixmap
,
57 widget
->style
->base_gc
[GTK_STATE_NORMAL
],
60 for (i
= 0; i
< MEMSTATS
; i
++)
64 if (pwin
->usage_high
> 0)
65 hh
= (h
* pwin
->memstats
[i
][1]) / pwin
->usage_high
;
69 gdk_draw_rectangle(pixmap
,
70 widget
->style
->base_gc
[GTK_STATE_SELECTED
],
73 if (pwin
->usage_high
> 0)
74 hh
= (h
* pwin
->memstats
[i
][0]) / pwin
->usage_high
;
78 gdk_draw_rectangle(pixmap
,
79 widget
->style
->text_gc
[GTK_STATE_NORMAL
],
83 if (pwin
->usage_high
> 0)
87 gc
= gdk_gc_new(pixmap
);
88 gdk_gc_copy(gc
, widget
->style
->dark_gc
[GTK_STATE_NORMAL
]);
89 gdk_gc_set_line_attributes(gc
, 0, GDK_LINE_ON_OFF_DASH
,
90 GDK_CAP_BUTT
, GDK_JOIN_MITER
);
91 for (j
= 0, i
= 0; i
< pwin
->usage_high
; i
+= (256 * 1024), j
++)
94 y
= h
- ((i
* h
) / pwin
->usage_high
);
96 gdk_draw_line(pixmap
, widget
->style
->dark_gc
[GTK_STATE_NORMAL
],
99 gdk_draw_line(pixmap
, gc
,
104 gdk_draw_pixmap(widget
->window
,
105 widget
->style
->fg_gc
[GTK_WIDGET_STATE(widget
)],
106 pixmap
, 0, 0, 0, 0, w
, h
);
107 gdk_pixmap_unref(pixmap
);
119 typedef struct _MemReg
127 dw_draw_memmap_foreach(gpointer key
, gpointer value
, gpointer data
)
143 addr
= (gulong
)block
->addr
;
144 for (i
= 0, l
= mem
->regs
; l
; l
= l
->next
, i
++)
147 if ((addr
>= (gulong
)reg
->start
) &&
148 (addr
< (gulong
)(reg
->start
+ reg
->size
)))
153 addr
= addr
- (gulong
)reg
->start
;
154 w
= (gulong
)(addr
+ block
->size
+ (bpp
/ 2)) / bpp
;
155 x
= (gulong
)(addr
) / bpp
;
158 y
= reg
->y
+ (x
/ memw
);
160 pixmap
= mem
->pixmap
;
162 gc
= mem
->widget
->style
->fg_gc
[GTK_STATE_PRELIGHT
];
164 gc
= mem
->widget
->style
->fg_gc
[GTK_STATE_NORMAL
];
165 gdk_draw_rectangle(pixmap
, gc
, TRUE
, x
, y
, w
, 1);
166 if ((x
+ w
) > mem
->w
)
167 gdk_draw_rectangle(pixmap
, gc
, TRUE
, 0, y
+ 1, w
- (memw
- x
), 1);
171 dw_draw_memmap(ProcessWindow
*pwin
)
175 guint w
, h
, y
, bpl
, i
;
179 widget
= pwin
->mem_map
;
180 w
= widget
->allocation
.width
;
181 h
= widget
->allocation
.height
;
182 if (!widget
->window
) return;
183 pixmap
= gdk_pixmap_new(widget
->window
, w
, h
, -1);
184 gdk_draw_rectangle(pixmap
,
185 widget
->style
->base_gc
[GTK_STATE_NORMAL
],
200 guint major
, minor
, inode
;
202 snprintf(buffer
, 1023, "/proc/%d/maps", pwin
->process
->pid
);
204 in
= fopen(buffer
, "r");
207 g_warning("Failed to open: '%s'", buffer
);
211 while (fgets(buffer
, 1023, in
))
214 int count
= sscanf(buffer
, "%lx-%lx %15s %*x %u:%u %u %255s",
215 &start
, &end
, perms
, &major
, &minor
, &inode
,
219 if ((!strcmp(perms
, "rw-p")) && (inode
== 0))
223 reg
= g_malloc(sizeof(MemReg
));
224 reg
->start
= GSIZE_TO_POINTER(start
);
225 reg
->size
= end
- start
;
226 mem
.mtotal
+= reg
->size
;
227 mem
.regs
= g_list_append(mem
.regs
, reg
);
233 bpl
= (mem
.mtotal
+ h
- 1) / h
;
235 for (i
= 0, l
= mem
.regs
; l
; l
= l
->next
, i
++)
240 reg
->h
= ((reg
->size
* h
) + bpl
- 1) / mem
.mtotal
;
244 gdk_draw_rectangle(pixmap
,
245 widget
->style
->base_gc
[GTK_STATE_INSENSITIVE
],
247 0, reg
->y
, w
, reg
->h
);
249 mem
.bpp
= (bpl
+ w
- 1) / w
;
250 if (mem
.bpp
< 1) mem
.bpp
= 1;
252 g_hash_table_foreach(pwin
->process
->block_table
,
253 dw_draw_memmap_foreach
,
256 for (l
= mem
.regs
; l
; l
= l
->next
) g_free(l
->data
);
257 g_list_free(mem
.regs
);
259 gdk_draw_pixmap(widget
->window
,
260 widget
->style
->fg_gc
[GTK_WIDGET_STATE(widget
)],
261 pixmap
, 0, 0, 0, 0, w
, h
);
262 gdk_pixmap_unref(pixmap
);
266 time_graph_expose_event(GtkWidget
*widget
, GdkEventExpose
*event
, ProcessWindow
*pwin
)
268 if (!pwin
->process
) return FALSE
;
269 dw_draw_memstats(pwin
);
274 mem_map_expose_event(GtkWidget
*widget
, GdkEventExpose
*event
, ProcessWindow
*pwin
)
276 if (!pwin
->process
) return FALSE
;
277 dw_draw_memmap(pwin
);
282 dw_update(ProcessWindow
*pwin
)
285 if (!pwin
->process
) return;
286 for (i
= MEMSTATS
- 1; i
> 0; i
--)
288 pwin
->memstats
[i
][0] = pwin
->memstats
[i
- 1][0];
289 pwin
->memstats
[i
][1] = pwin
->memstats
[i
- 1][1];
291 pwin
->memstats
[0][0] = pwin
->process
->bytes_used
;
292 pwin
->memstats
[0][1] = pwin
->usage_high
;
293 dw_draw_memstats(pwin
);
294 dw_draw_memmap(pwin
);