Skip to content
Snippets Groups Projects
Select Git revision
  • f80b08fc44536a311a9f3182e50f318b79076425
  • vme-testing default
  • ci-test
  • master
  • remoteproc
  • am625-sk-ov5640
  • pcal6534-upstreaming
  • lps22df-upstreaming
  • msc-upstreaming
  • imx8mp
  • iio/noa1305
  • vme-next
  • vme-next-4.14-rc4
  • v4.14-rc4
  • v4.14-rc3
  • v4.14-rc2
  • v4.14-rc1
  • v4.13
  • vme-next-4.13-rc7
  • v4.13-rc7
  • v4.13-rc6
  • v4.13-rc5
  • v4.13-rc4
  • v4.13-rc3
  • v4.13-rc2
  • v4.13-rc1
  • v4.12
  • v4.12-rc7
  • v4.12-rc6
  • v4.12-rc5
  • v4.12-rc4
  • v4.12-rc3
32 results

page_alloc.c

Blame
    • Charan Teja Reddy's avatar
      f80b08fc
      mm, page_alloc: skip ->waternark_boost for atomic order-0 allocations · f80b08fc
      Charan Teja Reddy authored
      When boosting is enabled, it is observed that rate of atomic order-0
      allocation failures are high due to the fact that free levels in the
      system are checked with ->watermark_boost offset.  This is not a problem
      for sleepable allocations but for atomic allocations which looks like
      regression.
      
      This problem is seen frequently on system setup of Android kernel running
      on Snapdragon hardware with 4GB RAM size.  When no extfrag event occurred
      in the system, ->watermark_boost factor is zero, thus the watermark
      configurations in the system are:
      
         _watermark = (
                [WMARK_MIN] = 1272, --> ~5MB
                [WMARK_LOW] = 9067, --> ~36MB
                [WMARK_HIGH] = 9385), --> ~38MB
         watermark_boost = 0
      
      After launching some memory hungry applications in Android which can cause
      extfrag events in the system to an extent that ->watermark_boost can be
      set to max i.e.  default boost factor makes it to 150% of high watermark.
      
         _watermark = (
                [WMARK_MIN] = 1272, --> ~5MB
                [WMARK_LOW] = 9067, --> ~36MB
                [WMARK_HIGH] = 9385), --> ~38MB
         watermark_boost = 14077, -->~57MB
      
      With default system configuration, for an atomic order-0 allocation to
      succeed, having free memory of ~2MB will suffice.  But boosting makes the
      min_wmark to ~61MB thus for an atomic order-0 allocation to be successful
      system should have minimum of ~23MB of free memory(from calculations of
      zone_watermark_ok(), min = 3/4(min/2)).  But failures are observed despite
      system is having ~20MB of free memory.  In the testing, this is
      reproducible as early as first 300secs since boot and with furtherlowram
      configurations(<2GB) it is observed as early as first 150secs since boot.
      
      These failures can be avoided by excluding the ->watermark_boost in
      watermark caluculations for atomic order-0 allocations.
      
      [akpm@linux-foundation.org: fix comment grammar, reflow comment]
      [charante@codeaurora.org: fix suggested by Mel Gorman]
        Link: http://lkml.kernel.org/r/31556793-57b1-1c21-1a9d-22674d9bd938@codeaurora.org
      
      
      
      Signed-off-by: default avatarCharan Teja Reddy <charante@codeaurora.org>
      Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
      Acked-by: default avatarVlastimil Babka <vbabka@suse.cz>
      Cc: Vinayak Menon <vinmenon@codeaurora.org>
      Cc: Mel Gorman <mgorman@techsingularity.net>
      Link: http://lkml.kernel.org/r/1589882284-21010-1-git-send-email-charante@codeaurora.org
      
      
      Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
      f80b08fc
      History
      mm, page_alloc: skip ->waternark_boost for atomic order-0 allocations
      Charan Teja Reddy authored
      When boosting is enabled, it is observed that rate of atomic order-0
      allocation failures are high due to the fact that free levels in the
      system are checked with ->watermark_boost offset.  This is not a problem
      for sleepable allocations but for atomic allocations which looks like
      regression.
      
      This problem is seen frequently on system setup of Android kernel running
      on Snapdragon hardware with 4GB RAM size.  When no extfrag event occurred
      in the system, ->watermark_boost factor is zero, thus the watermark
      configurations in the system are:
      
         _watermark = (
                [WMARK_MIN] = 1272, --> ~5MB
                [WMARK_LOW] = 9067, --> ~36MB
                [WMARK_HIGH] = 9385), --> ~38MB
         watermark_boost = 0
      
      After launching some memory hungry applications in Android which can cause
      extfrag events in the system to an extent that ->watermark_boost can be
      set to max i.e.  default boost factor makes it to 150% of high watermark.
      
         _watermark = (
                [WMARK_MIN] = 1272, --> ~5MB
                [WMARK_LOW] = 9067, --> ~36MB
                [WMARK_HIGH] = 9385), --> ~38MB
         watermark_boost = 14077, -->~57MB
      
      With default system configuration, for an atomic order-0 allocation to
      succeed, having free memory of ~2MB will suffice.  But boosting makes the
      min_wmark to ~61MB thus for an atomic order-0 allocation to be successful
      system should have minimum of ~23MB of free memory(from calculations of
      zone_watermark_ok(), min = 3/4(min/2)).  But failures are observed despite
      system is having ~20MB of free memory.  In the testing, this is
      reproducible as early as first 300secs since boot and with furtherlowram
      configurations(<2GB) it is observed as early as first 150secs since boot.
      
      These failures can be avoided by excluding the ->watermark_boost in
      watermark caluculations for atomic order-0 allocations.
      
      [akpm@linux-foundation.org: fix comment grammar, reflow comment]
      [charante@codeaurora.org: fix suggested by Mel Gorman]
        Link: http://lkml.kernel.org/r/31556793-57b1-1c21-1a9d-22674d9bd938@codeaurora.org
      
      
      
      Signed-off-by: default avatarCharan Teja Reddy <charante@codeaurora.org>
      Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
      Acked-by: default avatarVlastimil Babka <vbabka@suse.cz>
      Cc: Vinayak Menon <vinmenon@codeaurora.org>
      Cc: Mel Gorman <mgorman@techsingularity.net>
      Link: http://lkml.kernel.org/r/1589882284-21010-1-git-send-email-charante@codeaurora.org
      
      
      Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
    rdpmc.c 3.03 KiB
    #include <unistd.h>
    #include <stdlib.h>
    #include <signal.h>
    #include <sys/mman.h>
    #include "types.h"
    #include "perf.h"
    #include "debug.h"
    #include "tests.h"
    
    #if defined(__x86_64__) || defined(__i386__)
    
    static u64 rdpmc(unsigned int counter)
    {
    	unsigned int low, high;
    
    	asm volatile("rdpmc" : "=a" (low), "=d" (high) : "c" (counter));
    
    	return low | ((u64)high) << 32;
    }
    
    static u64 rdtsc(void)
    {
    	unsigned int low, high;
    
    	asm volatile("rdtsc" : "=a" (low), "=d" (high));
    
    	return low | ((u64)high) << 32;
    }
    
    static u64 mmap_read_self(void *addr)
    {
    	struct perf_event_mmap_page *pc = addr;
    	u32 seq, idx, time_mult = 0, time_shift = 0;
    	u64 count, cyc = 0, time_offset = 0, enabled, running, delta;
    
    	do {
    		seq = pc->lock;
    		barrier();
    
    		enabled = pc->time_enabled;
    		running = pc->time_running;
    
    		if (enabled != running) {
    			cyc = rdtsc();
    			time_mult = pc->time_mult;
    			time_shift = pc->time_shift;
    			time_offset = pc->time_offset;
    		}
    
    		idx = pc->index;
    		count = pc->offset;
    		if (idx)
    			count += rdpmc(idx - 1);
    
    		barrier();
    	} while (pc->lock != seq);
    
    	if (enabled != running) {
    		u64 quot, rem;
    
    		quot = (cyc >> time_shift);
    		rem = cyc & ((1 << time_shift) - 1);
    		delta = time_offset + quot * time_mult +
    			((rem * time_mult) >> time_shift);
    
    		enabled += delta;
    		if (idx)
    			running += delta;
    
    		quot = count / running;
    		rem = count % running;
    		count = quot * enabled + (rem * enabled) / running;
    	}
    
    	return count;
    }
    
    /*
     * If the RDPMC instruction faults then signal this back to the test parent task:
     */
    static void segfault_handler(int sig __maybe_unused,
    			     siginfo_t *info __maybe_unused,
    			     void *uc __maybe_unused)
    {
    	exit(-1);
    }
    
    static int __test__rdpmc(void)
    {
    	volatile int tmp = 0;
    	u64 i, loops = 1000;
    	int n;
    	int fd;
    	void *addr;
    	struct perf_event_attr attr = {
    		.type = PERF_TYPE_HARDWARE,
    		.config = PERF_COUNT_HW_INSTRUCTIONS,
    		.exclude_kernel = 1,
    	};
    	u64 delta_sum = 0;
            struct sigaction sa;
    
    	sigfillset(&sa.sa_mask);
    	sa.sa_sigaction = segfault_handler;
    	sigaction(SIGSEGV, &sa, NULL);
    
    	fd = sys_perf_event_open(&attr, 0, -1, -1, 0);
    	if (fd < 0) {
    		pr_err("Error: sys_perf_event_open() syscall returned "
    		       "with %d (%s)\n", fd, strerror(errno));
    		return -1;
    	}
    
    	addr = mmap(NULL, page_size, PROT_READ, MAP_SHARED, fd, 0);
    	if (addr == (void *)(-1)) {
    		pr_err("Error: mmap() syscall returned with (%s)\n",
    		       strerror(errno));
    		goto out_close;
    	}
    
    	for (n = 0; n < 6; n++) {
    		u64 stamp, now, delta;
    
    		stamp = mmap_read_self(addr);
    
    		for (i = 0; i < loops; i++)
    			tmp++;
    
    		now = mmap_read_self(addr);
    		loops *= 10;
    
    		delta = now - stamp;
    		pr_debug("%14d: %14Lu\n", n, (long long)delta);
    
    		delta_sum += delta;
    	}
    
    	munmap(addr, page_size);
    	pr_debug("   ");
    out_close:
    	close(fd);
    
    	if (!delta_sum)
    		return -1;
    
    	return 0;
    }
    
    int test__rdpmc(void)
    {
    	int status = 0;
    	int wret = 0;
    	int ret;
    	int pid;
    
    	pid = fork();
    	if (pid < 0)
    		return -1;
    
    	if (!pid) {
    		ret = __test__rdpmc();
    
    		exit(ret);
    	}
    
    	wret = waitpid(pid, &status, 0);
    	if (wret < 0 || status)
    		return -1;
    
    	return 0;
    }
    
    #endif