#!/bin/awk

#  memps
#
# Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
#
# Contact: Wonil Choi <wonil22.choi@samsung.com>
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

BEGIN{
	rss_total = 0
	pss_total = 0
	private_dirty_total = 0
	private_clean_total = 0
	shared_dirty_total = 0
	shared_clean_total = 0

	lib_pss_data_total = 0
	lib_pss_code_total = 0
	exe_pss_total = 0
	edj_pss_total = 0
	font_pss_total = 0
	locale_pss_total = 0
	stack_pss_total = 0
	small_heap_pss_total = 0
	bss_other_total = 0
	SYSV_total = 0
	un_calculatable_total = 0

	uidev_rss = 0
	uidev_pss = 0
	uidev_nonormal = 0

	if(show_all){
		rss_all = 0
		pss_all = 0
		priv_all = 0
		priv_dirty = 0
		ui_rss_all = 0
		ui_pss_all = 0
		ui_pfn_all = 0
	}

	if(detail_view){
		print cmd_line"("pid")"
		printf "RSS\tPSS\tCLEAN\tTYPE\tNAME  ----  TOP (over PSS 100 KB ) vma (except PVR)\n"
		print "--------------------------------------------------------------------"
	}
}

{
	if(meminfo){
		if($1 == "MemTotal:")
			memtotal = $2
		else if($1 == "MemFree:")
			memfree = $2
		else if($1 == "Shmem:")
			shmem = $2
		else if($1 == "Slab:")
			slab = $2
		else if($1 == "KernelStack:")
			kernelstack = $2
		else if($1 == "PageTables:")
			pagetable = $2
		next
	}

	if(show_all){
		print
		rss_all += $1
		pss_all += $2
		priv_all += $3
		priv_dirty += $4
		ui_rss_all += $5
		ui_pss_all += $6
		ui_pfn_all += $7
		next
	}

	if(NF > 4){
		name = $6
		type = $2
		ino = $5
		next
	}

	if($1 == "Size:")
		size = $2
	else if($1 == "Rss:")
		rss = $2
	else if($1 == "Pss:")
		pss = $2
	else if($1 == "Shared_Clean:")
		sc = $2
	else if($1 == "Shared_Dirty:")
		sd = $2
	else if($1 == "Private_Clean:")
		pc = $2
	else if($1 == "Private_Dirty:")
		pd = $2

	# process total
	if($1 == "MMUPageSize:"){
		# calculate uidev or fb3 driver memory
		# dev/uidev vma is special region which is mapped by kernel driver
		if(name == "/dev/pvrsrvkm" || name ~ "/dev/fb" ||
				name ==	"/dev/ump" || name == "/dev/mali"){
			if (rss != 0)
				uidev_rss += rss
			else
				uidev_rss += size
			uidev_pss += pss
			if((rss != 0) && (pss == 0) && (sc+sd+pc+pd == 0) )
				uidev_nonormal += rss
			next
		}

		# check memory region mmaped by kernel driver (executed by remap_pfn_page() call)
		if((rss != 0) && (pss == 0) && (sc+sd+pc+pd == 0) && (ino != 0)){
			printf "<<WARNING>> %s: %d KB may mmaped by driver %s. Check\n", cmd_line, rss, name
			next
		}

		# check memory region pss=0 by many sharing, so many sharing may make pss 0
		if(pss == 0 && (sc+sd != 0) ){
			un_calculatable_total += rss
			next
		}

		# calculate rss total(except ui dev)
		rss_total += rss

		# calculate pss total
		pss_total += pss

		# calculate private total(never reclaimable if doesn't have swap)
		private_dirty_total += pd

		# calculate private clean(reclaimable, fast) total
		private_clean_total += pc

		# calculate shared dirty total
		shared_dirty_total += sd

		# calculate shared clean(reclaimable, but slow) total
		shared_clean_total += sc

		if(!detail_view)
			next

		if(pss >= 32)
			printf "%d\t%d\t%d\t%s\t%s\n",rss,pss,pc+sc,type,name

		# check memory by library(*.so)
		if(name ~ ".so"){
			if( type ~ "w")
				lib_pss_data_total += pss
			else
				lib_pss_code_total += pss
		}

		# check memory by executable
		else if(name == cmd_line)	# TODO : this support full path name
			exe_pss_total += pss

		# check memory by edj
		else if(name ~ ".edj")
			edj_pss_total += pss

		# check memory by font(ttf)
		else if(name ~ ".ttf" || name ~ "fontconfig")
			font_pss_total += pss

		# check memory by locale	# TODO : all locale at locale directory?
		else if(name ~ "/locale/")
			locale_pss_total += pss

		else if(name ~ "stack" && ino == 0)
			stack_pss_total += pss

		else if(name ~ "heap" && ino == 0)
			small_heap_pss_total += pss

		else if(name == "" && ino == 0 && type ~ "w"){
			bss_other_total += pss
		}
		else if(name ~ "SYSV"){
			SYSV_total += pss
		}
#		else
#			print name
	}
}

END{
	if(show_all){
		print "-------------------------------------------------------------------"
		printf("%d\t%d\t%d\t%d\t%d\t%d\t%d\n",
			rss_all,pss_all,priv_all,priv_dirty,ui_rss_all,ui_pss_all,ui_pfn_all)
		print "\t"
		print "Assuming Total memory used by Application and Daemon (except uncalculatable region)"
		print "\tPRIVATE(all) = " priv_all
		print "\tSHARED(all) = " pss_all - priv_all
		print "\tUIDEV_PSS+UIDEV_PFN(all) = " ui_pss_all + ui_pfn_all
	       	print "\tTOTAL = " pss_all + ui_pss_all + ui_pfn_all " KB"
		exit
	}
	if(meminfo){
		print "\t"
		print "Assuming Total memory used by shmem/pagetable/kernelstack/.. by meminfo"
		print "\tSHMEM = " shmem
		print "\tSLAB = " slab
		print "\tKERNELSTACK = " kernelstack
		print "\tPAGETABLE = " pagetable
		print "\tTOTAL = " shmem + slab + kernelstack + pagetable " KB"
		print "\t"
		print "USED TOTAL by meminfo"
		print "\t USED TOTAL " memtotal - memfree " KB"
		exit
	}

	if(detail_view){
		print "-------------------------------------------------------------------"
		print "RSS Total(except UI device memory) : " rss_total " KB"
		print "\tPrivate dirty Total : " private_dirty_total " KB"
		print "\tPrivate clean Total(reclaimable) : " private_clean_total " KB"
		print "\tShared dirty Total : " shared_dirty_total " KB"
		print "\tShared clean Total(reclaimable,but maybe almost library) : " shared_clean_total " KB"
		print "\t"
		print "PSS Total(except UI device memory) : " pss_total " KB"
		print "\tExecutable("cmd_line") PSS Total : " exe_pss_total " KB"
		print "\tShared library(code) PSS Total : " lib_pss_code_total " KB"
		print "\tShared library(data) PSS Total : " lib_pss_data_total " KB"
		print "\tStack PSS Total : " stack_pss_total " KB"
		print "\tSmall Heap PSS Total : " small_heap_pss_total " KB"
		print "\tBSS(include BIG Heap) PSS Total : " bss_other_total " KB"
		print "\tEDJ file PSS Total : " edj_pss_total " KB"
		print "\tFONT file PSS Total : " font_pss_total " KB"
		print "\tLOCALE file PSS Total : " locale_pss_total " KB"
		print "\tSYSV(shared memory) PSS Total : " SYSV_total " KB"
		print "\tOther PSS : " pss_total - exe_pss_total - lib_pss_code_total - lib_pss_data_total - stack_pss_total - small_heap_pss_total -  bss_other_total - edj_pss_total - font_pss_total - locale_pss_total - SYSV_total " KB"
		print "\t"
		print "Device(related UI) memory (3D and /dev/fb#)  : "
		print "\tRSS : " uidev_rss " KB"
		print "\tPSS : " uidev_pss " KB"
		print "\tNO normal page : " uidev_nonormal " KB"
		print "\t"
		print "Un-calculatable page size (RSS): " un_calculatable_total " KB"
		print "-------------------------------------------------------------------"
	}
	else{
		printf("%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%s(%s)\n",
			rss_total,pss_total,private_dirty_total+private_clean_total,
			private_dirty_total,uidev_rss,uidev_pss,uidev_nonormal, un_calculatable_total,cmd_line,pid)
	}
}

