Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2fd40f7c authored by Puranam V G Tejaswi's avatar Puranam V G Tejaswi
Browse files

msm: kgsl: make stats updation atomic



There is a chance of messing up per process stats if something
like a free and allocation happen at the same time for memory
belonging to the same process. Similarly mapsize of memdesc can
also go bad because of concurrent access. So make per process
stats and mapsize of memdesc atomic. Also use scnprintf()
instead of snprintf().

Change-Id: I5da1cf368d523768d0b267b314394612934a620d
Signed-off-by: default avatarPuranam V G Tejaswi <pvgtejas@codeaurora.org>
parent defa0305
Loading
Loading
Loading
Loading
+5 −4
Original line number Diff line number Diff line
@@ -529,7 +529,8 @@ static void kgsl_mem_entry_detach_process(struct kgsl_mem_entry *entry)
		idr_remove(&entry->priv->mem_idr, entry->id);
	entry->id = 0;

	entry->priv->gpumem_mapped -= entry->memdesc.mapsize;
	atomic64_sub(atomic64_read(&entry->memdesc.mapsize),
			&entry->priv->gpumem_mapped);

	spin_unlock(&entry->priv->mem_lock);

@@ -4388,7 +4389,7 @@ kgsl_gpumem_vm_fault(struct vm_fault *vmf)

	ret = entry->memdesc.ops->vmfault(&entry->memdesc, vmf->vma, vmf);
	if ((ret == 0) || (ret == VM_FAULT_NOPAGE))
		entry->priv->gpumem_mapped += PAGE_SIZE;
		atomic64_add(PAGE_SIZE, &entry->priv->gpumem_mapped);

	return ret;
}
@@ -4768,8 +4769,8 @@ static int kgsl_mmap(struct file *file, struct vm_area_struct *vma)
			vm_insert_page(vma, addr, page);
			addr += PAGE_SIZE;
		}
		m->mapsize = m->size;
		entry->priv->gpumem_mapped += m->mapsize;
		atomic64_add(m->size, &m->mapsize);
		atomic64_add(m->size, &entry->priv->gpumem_mapped);
	}

	vma->vm_file = file;
+1 −1
Original line number Diff line number Diff line
@@ -233,7 +233,7 @@ struct kgsl_memdesc {
	uint64_t gpuaddr;
	phys_addr_t physaddr;
	uint64_t size;
	uint64_t mapsize;
	atomic64_t mapsize;
	uint64_t pad_to;
	unsigned int priv;
	struct sg_table *sgt;
+3 −2
Original line number Diff line number Diff line
/* Copyright (c) 2002,2008-2017, The Linux Foundation. All rights reserved.
/* Copyright (c) 2002, 2008-2017, 2019 The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -168,7 +168,8 @@ static int print_mem_entry(void *data, void *ptr)
			(unsigned long *) m->useraddr,
			m->size, entry->id, flags,
			memtype_str(usermem_type),
			usage, (m->sgt ? m->sgt->nents : 0), m->mapsize,
			usage, (m->sgt ? m->sgt->nents : 0),
			(u64)atomic64_read(&m->mapsize),
			egl_surface_count, egl_image_count);

	if (entry->metadata[0] != 0)
+8 −7
Original line number Diff line number Diff line
@@ -474,10 +474,10 @@ struct kgsl_process_private {
	struct kobject kobj;
	struct dentry *debug_root;
	struct {
		uint64_t cur;
		uint64_t max;
		atomic64_t cur;
		atomic64_t max;
	} stats[KGSL_MEM_ENTRY_MAX];
	uint64_t gpumem_mapped;
	atomic64_t gpumem_mapped;
	struct idr syncsource_idr;
	spinlock_t syncsource_lock;
	int fd_count;
@@ -571,9 +571,10 @@ struct kgsl_device *kgsl_get_device(int dev_idx);
static inline void kgsl_process_add_stats(struct kgsl_process_private *priv,
	unsigned int type, uint64_t size)
{
	priv->stats[type].cur += size;
	if (priv->stats[type].max < priv->stats[type].cur)
		priv->stats[type].max = priv->stats[type].cur;
	u64 ret = atomic64_add_return(size, &priv->stats[type].cur);

	if (ret > atomic64_read(&priv->stats[type].max))
		atomic64_set(&priv->stats[type].max, ret);
	add_mm_counter(current->mm, MM_UNRECLAIMABLE, (size >> PAGE_SHIFT));
}

@@ -584,7 +585,7 @@ static inline void kgsl_process_sub_stats(struct kgsl_process_private *priv,
	struct task_struct *task;
	struct mm_struct *mm;

	priv->stats[type].cur -= size;
	atomic64_sub(size, &priv->stats[type].cur);
	pid_struct = find_get_pid(priv->pid);
	if (pid_struct) {
		task = get_pid_task(pid_struct, PIDTYPE_PID);
+12 −7
Original line number Diff line number Diff line
@@ -146,17 +146,20 @@ gpumem_mapped_show(struct kgsl_process_private *priv,
				int type, char *buf)
{
	return scnprintf(buf, PAGE_SIZE, "%llu\n",
			priv->gpumem_mapped);
			(u64)atomic64_read(&priv->gpumem_mapped));
}

static ssize_t
gpumem_unmapped_show(struct kgsl_process_private *priv, int type, char *buf)
{
	if (priv->gpumem_mapped > priv->stats[type].cur)
	u64 gpumem_total = atomic64_read(&priv->stats[type].cur);
	u64 gpumem_mapped = atomic64_read(&priv->gpumem_mapped);

	if (gpumem_mapped > gpumem_total)
		return -EIO;

	return scnprintf(buf, PAGE_SIZE, "%llu\n",
			priv->stats[type].cur - priv->gpumem_mapped);
			gpumem_total - gpumem_mapped);
}

static struct kgsl_mem_entry_attribute debug_memstats[] = {
@@ -173,7 +176,8 @@ static struct kgsl_mem_entry_attribute debug_memstats[] = {
static ssize_t
mem_entry_show(struct kgsl_process_private *priv, int type, char *buf)
{
	return snprintf(buf, PAGE_SIZE, "%llu\n", priv->stats[type].cur);
	return scnprintf(buf, PAGE_SIZE, "%llu\n",
			(u64)atomic64_read(&priv->stats[type].cur));
}

/**
@@ -184,7 +188,8 @@ mem_entry_show(struct kgsl_process_private *priv, int type, char *buf)
static ssize_t
mem_entry_max_show(struct kgsl_process_private *priv, int type, char *buf)
{
	return snprintf(buf, PAGE_SIZE, "%llu\n", priv->stats[type].max);
	return scnprintf(buf, PAGE_SIZE, "%llu\n",
			(u64)atomic64_read(&priv->stats[type].max));
}

static ssize_t mem_entry_sysfs_show(struct kobject *kobj,
@@ -448,7 +453,7 @@ static int kgsl_page_alloc_vmfault(struct kgsl_memdesc *memdesc,
		get_page(page);
		vmf->page = page;

		memdesc->mapsize += PAGE_SIZE;
		atomic64_add(PAGE_SIZE, &memdesc->mapsize);

		return 0;
	}
@@ -619,7 +624,7 @@ static int kgsl_contiguous_vmfault(struct kgsl_memdesc *memdesc,
	else if (ret == -EFAULT)
		return VM_FAULT_SIGBUS;

	memdesc->mapsize += PAGE_SIZE;
	atomic64_add(PAGE_SIZE, &memdesc->mapsize);

	return VM_FAULT_NOPAGE;
}