>> Index: sys/kern/kern_malloc.c >> =================================================================== >> RCS file: /cvs/src/sys/kern/kern_malloc.c,v >> retrieving revision 1.128 >> diff -u -p -r1.128 kern_malloc.c >> --- sys/kern/kern_malloc.c 14 Mar 2015 03:38:50 -0000 1.128 >> +++ sys/kern/kern_malloc.c 9 Dec 2015 16:50:57 -0000 >> @@ -158,6 +158,8 @@ malloc(size_t size, int type, int flags) >> char *savedtype; >> #endif >> #ifdef KMEMSTATS >> + int i; >> + struct ktopcount *kftop; >> struct kmemstats *ksp = &kmemstats[type]; >> >> if (((unsigned long)type) <= 1 || ((unsigned long)type) >= M_LAST) >> @@ -338,6 +340,29 @@ out: >> ksp->ks_calls++; >> if (ksp->ks_memuse > ksp->ks_maxused) >> ksp->ks_maxused = ksp->ks_memuse; >> + >> + void *from = __builtin_return_address(0); >> + from = __builtin_extract_return_addr(from); >> + if (!from) >> + goto topout; > > Dropping gcc extensions into the middle of the kernel isn't recommended. Also, > this mixes code and declarations.
Ted, thanks for your comments once again! I didn't know about it. I looked at db_stack_dump() as an example, it uses __builtin_frame_address. >> + >> + kftop = &ksp->ks_top[0]; >> + for (i = 0; i < KMEMSTATS_TOPCOUNT; ++i) >> + { >> + if (ksp->ks_top[i].kt_from == from) { >> + ksp->ks_top[i].kt_calls++; >> + ksp->ks_top[i].kt_memuse += allocsize; >> + goto topout; >> + } >> + else if (ksp->ks_top[i].kt_memuse < kftop->kt_memuse) >> + kftop = &ksp->ks_top[i]; >> + } >> + >> + kftop->kt_calls = 1; >> + kftop->kt_memuse = allocsize; >> + kftop->kt_from = from; > > I'm not sure what you're trying to do here. The replacement policy seems to > overwrite the first entry every time. I think you'd have to get pretty lucky > for this to actually track the biggest user. The replacement policy looks like this: I take the first entry and assume that it has a min value of kt_kmemuse. Then I loop through kt_top structs and search for a minimum. At the first iteration it checks ks_top[0] with ks_top[0], but I need it due to first if (kt_from == from).