Re: mm/memory.c: Add update local tlb for smp race

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 




On 05/16/2020 05:34 PM, maobibo wrote:
> 
> 
> On 05/15/2020 09:50 PM, David Hildenbrand wrote:
>> On 14.05.20 08:50, Bibo Mao wrote:
>>> If there are two threads hitting page fault at the address, one
>>> thread updates pte entry and local tlb, the other thread can update
>>> local tlb also, rather than give up and let page fault happening
>>> again.
>>
>> Let me suggest
>>
>> "mm/memory: optimize concurrent page faults at same address
>>
>> If two threads concurrently fault at the same address, the thread that
>> won the race updates the PTE and its local TLB. For now, the other
>> thread gives up, simply does nothing, and continues.
>>
>> It could happen that this second thread triggers another fault, whereby
>> it only updates its local TLB while handling the fault. Instead of
>> triggering another fault, let's directly update the local TLB of the
>> second thread.
>> "
>>
>> If I got the intention of this patch correctly.
>>
>> Are there any performance numbers to support this patch?
>>
>> (I can't say too much about the correctness and/or usefulness of this patch)
> 
> yes, that is the situation. On MIPS platform software can update TLB,
> so update_mmu_cache is used here. This does not happen frequently, and with the three series patches in later mail. I test lat_pagefault in lmbench, here is is result:
> 
> with these three series patches, 
> # ./lat_pagefault  -N 10  /tmp/1 
> Pagefaults on /tmp/1: 1.4973 microseconds
> # ./lat_pagefault -P 4 -N 10  /tmp/1 
> Pagefaults on /tmp/1: 1.5716 microseconds
> 
> original version, without these three series patch
> #  ./lat_pagefault  -N 10  /tmp/1 
> Pagefaults on /tmp/1: 1.6489 microseconds
> # ./lat_pagefault -P 4 -N 10  /tmp/1
> Pagefaults on /tmp/1: 1.7214 microseconds
> 

I tested the three patches one by one, there is no obvious improvement with
lat_pagefault case, I guess that it happens seldom where multiple threads access
the same page at the same time. 

The improvement is because of another modification where pte_mkyoung is added
to get readable privilege on MIPS system.

regards
bibo, mao

>>>
>>> 	modified:   mm/memory.c
>>
>> This does not belong into a patch description.
> 
> well, I will modify the patch description.
> 
> regards
> bibo,mao
> 
> 
>>
>>
>>> Signed-off-by: Bibo Mao <maobibo@xxxxxxxxxxx>
>>> ---
>>>  mm/memory.c | 30 ++++++++++++++++++++++--------
>>>  1 file changed, 22 insertions(+), 8 deletions(-)
>>>
>>> diff --git a/mm/memory.c b/mm/memory.c
>>> index f703fe8..3a741ce 100644
>>> --- a/mm/memory.c
>>> +++ b/mm/memory.c
>>> @@ -2436,11 +2436,10 @@ static inline bool cow_user_page(struct page *dst, struct page *src,
>>>  		if (!likely(pte_same(*vmf->pte, vmf->orig_pte))) {
>>>  			/*
>>>  			 * Other thread has already handled the fault
>>> -			 * and we don't need to do anything. If it's
>>> -			 * not the case, the fault will be triggered
>>> -			 * again on the same address.
>>> +			 * and update local tlb only
>>>  			 */
>>>  			ret = false;
>>> +			update_mmu_cache(vma, addr, vmf->pte);
>>>  			goto pte_unlock;
>>>  		}
>>>  
>>> @@ -2463,8 +2462,9 @@ static inline bool cow_user_page(struct page *dst, struct page *src,
>>>  		vmf->pte = pte_offset_map_lock(mm, vmf->pmd, addr, &vmf->ptl);
>>>  		locked = true;
>>>  		if (!likely(pte_same(*vmf->pte, vmf->orig_pte))) {
>>> -			/* The PTE changed under us. Retry page fault. */
>>> +			/* The PTE changed under us. update local tlb */
>>>  			ret = false;
>>> +			update_mmu_cache(vma, addr, vmf->pte);
>>>  			goto pte_unlock;
>>>  		}
>>>  
>>> @@ -2704,6 +2704,7 @@ static vm_fault_t wp_page_copy(struct vm_fault *vmf)
>>>  		}
>>>  		flush_cache_page(vma, vmf->address, pte_pfn(vmf->orig_pte));
>>>  		entry = mk_pte(new_page, vma->vm_page_prot);
>>> +		entry = pte_mkyoung(entry);
>>>  		entry = maybe_mkwrite(pte_mkdirty(entry), vma);
>>>  		/*
>>>  		 * Clear the pte entry and flush it first, before updating the
>>> @@ -2752,6 +2753,7 @@ static vm_fault_t wp_page_copy(struct vm_fault *vmf)
>>>  		new_page = old_page;
>>>  		page_copied = 1;
>>>  	} else {
>>> +		update_mmu_cache(vma, vmf->address, vmf->pte);
>>>  		mem_cgroup_cancel_charge(new_page, memcg, false);
>>>  	}
>>>  
>>> @@ -2812,6 +2814,7 @@ vm_fault_t finish_mkwrite_fault(struct vm_fault *vmf)
>>>  	 * pte_offset_map_lock.
>>>  	 */
>>>  	if (!pte_same(*vmf->pte, vmf->orig_pte)) {
>>> +		update_mmu_cache(vmf->vma, vmf->address, vmf->pte);
>>>  		pte_unmap_unlock(vmf->pte, vmf->ptl);
>>>  		return VM_FAULT_NOPAGE;
>>>  	}
>>> @@ -2936,6 +2939,7 @@ static vm_fault_t do_wp_page(struct vm_fault *vmf)
>>>  			vmf->pte = pte_offset_map_lock(vma->vm_mm, vmf->pmd,
>>>  					vmf->address, &vmf->ptl);
>>>  			if (!pte_same(*vmf->pte, vmf->orig_pte)) {
>>> +				update_mmu_cache(vma, vmf->address, vmf->pte);
>>>  				unlock_page(vmf->page);
>>>  				pte_unmap_unlock(vmf->pte, vmf->ptl);
>>>  				put_page(vmf->page);
>>> @@ -3341,8 +3345,10 @@ static vm_fault_t do_anonymous_page(struct vm_fault *vmf)
>>>  						vma->vm_page_prot));
>>>  		vmf->pte = pte_offset_map_lock(vma->vm_mm, vmf->pmd,
>>>  				vmf->address, &vmf->ptl);
>>> -		if (!pte_none(*vmf->pte))
>>> +		if (!pte_none(*vmf->pte)) {
>>> +			update_mmu_cache(vma, vmf->address, vmf->pte);
>>>  			goto unlock;
>>> +		}
>>>  		ret = check_stable_address_space(vma->vm_mm);
>>>  		if (ret)
>>>  			goto unlock;
>>> @@ -3373,13 +3379,16 @@ static vm_fault_t do_anonymous_page(struct vm_fault *vmf)
>>>  	__SetPageUptodate(page);
>>>  
>>>  	entry = mk_pte(page, vma->vm_page_prot);
>>> +	entry = pte_mkyoung(entry);
>>>  	if (vma->vm_flags & VM_WRITE)
>>>  		entry = pte_mkwrite(pte_mkdirty(entry));
>>>  
>>>  	vmf->pte = pte_offset_map_lock(vma->vm_mm, vmf->pmd, vmf->address,
>>>  			&vmf->ptl);
>>> -	if (!pte_none(*vmf->pte))
>>> +	if (!pte_none(*vmf->pte)) {
>>> +		update_mmu_cache(vma, vmf->address, vmf->pte);
>>>  		goto release;
>>> +	}
>>>  
>>>  	ret = check_stable_address_space(vma->vm_mm);
>>>  	if (ret)
>>> @@ -3646,11 +3655,14 @@ vm_fault_t alloc_set_pte(struct vm_fault *vmf, struct mem_cgroup *memcg,
>>>  	}
>>>  
>>>  	/* Re-check under ptl */
>>> -	if (unlikely(!pte_none(*vmf->pte)))
>>> +	if (unlikely(!pte_none(*vmf->pte))) {
>>> +		update_mmu_cache(vma, vmf->address, vmf->pte);
>>>  		return VM_FAULT_NOPAGE;
>>> +	}
>>>  
>>>  	flush_icache_page(vma, page);
>>>  	entry = mk_pte(page, vma->vm_page_prot);
>>> +	entry = pte_mkyoung(entry);
>>>  	if (write)
>>>  		entry = maybe_mkwrite(pte_mkdirty(entry), vma);
>>>  	/* copy-on-write page */
>>> @@ -4224,8 +4236,10 @@ static vm_fault_t handle_pte_fault(struct vm_fault *vmf)
>>>  	vmf->ptl = pte_lockptr(vmf->vma->vm_mm, vmf->pmd);
>>>  	spin_lock(vmf->ptl);
>>>  	entry = vmf->orig_pte;
>>> -	if (unlikely(!pte_same(*vmf->pte, entry)))
>>> +	if (unlikely(!pte_same(*vmf->pte, entry))) {
>>> +		update_mmu_cache(vmf->vma, vmf->address, vmf->pte);
>>>  		goto unlock;
>>> +	}
>>>  	if (vmf->flags & FAULT_FLAG_WRITE) {
>>>  		if (!pte_write(entry))
>>>  			return do_wp_page(vmf);
>>>
>>
>>





[Index of Archives]     [Linux ARM Kernel]     [Linux ARM]     [Linux Omap]     [Fedora ARM]     [IETF Annouce]     [Bugtraq]     [Linux OMAP]     [Linux MIPS]     [eCos]     [Asterisk Internet PBX]     [Linux API]

  Powered by Linux