1. 程式人生 > >高通平臺採用gpu-mmu的時候發生視訊記憶體耗完而整個系統記憶體尚有的情況導致crash和重啟

高通平臺採用gpu-mmu的時候發生視訊記憶體耗完而整個系統記憶體尚有的情況導致crash和重啟

原因在於kgsl_mmu.c中,定義了gpu使用的記憶體大小,7x30中限定了256MB,當視訊記憶體耗光而記憶體尚剩餘很多的時候就會發生問題:不能觸發LMK或OOM來釋放記憶體,而又沒有視訊記憶體可用,進而可能引起各程序watchdogtimeout,如果系統程序發生watchdogtimeout,會導致system serverrestart,而restart之後也不能釋放gpu視訊記憶體,會一直反覆重啟:

unsigned int kgsl_mmu_get_ptsize(void)
{
	/*
	 * For IOMMU, we could do up to 4G virtual range if we wanted to, but
	 * it makes more sense to return a smaller range and leave the rest of
	 * the virtual range for future improvements
	 */

	if (KGSL_MMU_TYPE_GPU == kgsl_mmu_type)
		return CONFIG_MSM_KGSL_PAGE_TABLE_SIZE;
	else if (KGSL_MMU_TYPE_IOMMU == kgsl_mmu_type)
		return SZ_2G - KGSL_PAGETABLE_BASE;
	else
		return 0;
}

Lowmemorykiller.c 新增一個新函式


void lowmem_shrink_gpu(void)
{
	struct task_struct *tsk;
	struct task_struct *selected = NULL;
	int tasksize;
	int selected_tasksize = 0;

	rcu_read_lock();
	for_each_process(tsk) {
		struct task_struct *p;

		if (tsk->flags & PF_KTHREAD)
			continue;

		p = find_lock_task_mm(tsk);
		if (!p)
			continue;

		if (test_tsk_thread_flag(p, TIF_MEMDIE) &&
		    time_before_eq(jiffies, lowmem_deathpending_timeout)) {
			task_unlock(p);
			rcu_read_unlock();
			return ;
		}
		tasksize = get_mm_rss(p->mm);
		task_unlock(p);
		if ((tasksize <= 0) || (p->signal->oom_score_adj <= 1))
			continue;
		if (selected) {
			if (tasksize <= selected_tasksize)
				continue;
		}
		selected = p;
		selected_tasksize = tasksize;
		lowmem_print(2, "AKeywordSE select %d (%s), size %d, to kill\n",
			     p->pid, p->comm, tasksize);
	}
	if (selected) {
		lowmem_print(1, "AKeywordSE send sigkill to %d (%s), size %d\n",
			     selected->pid, selected->comm,selected_tasksize);
		lowmem_deathpending_timeout = jiffies + HZ;
		send_sig(SIGKILL, selected, 0);
		set_tsk_thread_flag(selected, TIF_MEMDIE);
	}
	rcu_read_unlock();
	return ;
}

Kgs_mmu.c中宣告

extern void lowmem_shrink_gpu(void );

並在kgsl_mmu_map中呼叫


if (memdesc->gpuaddr == 0) {
		lowmem_shrink_gpu();
		KGSL_CORE_ERR("gen_pool_alloc(%d) failed from pool: %s\n",
			size,
			(pool == pagetable->kgsl_pool) ?
			"kgsl_pool" : "general_pool");
		KGSL_CORE_ERR(" [%d] allocated=%d, entries=%d\n",
				pagetable->name, pagetable->stats.mapped,
				pagetable->stats.entries);
		return -ENOMEM;
	}