| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862 |
- #include <linux/types.h>
- #include <linux/module.h>
- #include <linux/mm.h>
- #include <linux/oom.h>
- #include <linux/sched.h>
- #include <linux/vmstat.h>
- #include <linux/sysinfo.h>
- #include <linux/swap.h>
- #include <linux/cpu.h>
- #include <linux/slab.h>
- #include <linux/fs.h>
- #include <linux/cpumask.h>
- #include <linux/cred.h>
- #include <linux/rcupdate.h>
- #include <linux/seq_file.h>
- #include <asm/uaccess.h>
- #include <linux/version.h>
- #ifdef CONFIG_MTK_GPU_SUPPORT
- #define COLLECT_GPU_MEMINFO
- #endif
- #ifdef COLLECT_GPU_MEMINFO
- #include <mt-plat/mtk_gpu_utility.h>
- #endif
- #ifdef CONFIG_ZRAM
- #include <zram_drv.h>
- #endif
- /* for collecting ion total memory usage*/
- #ifdef CONFIG_MTK_ION
- #include <mtk/ion_drv.h>
- #endif
- #include "mlog_internal.h"
- #include "mlog_logger.h"
- #define CONFIG_MLOG_BUF_SHIFT 16 /* 64KB */
- #define P2K(x) (((unsigned long)x) << (PAGE_SHIFT - 10))
- #define B2K(x) (((unsigned long)x) >> (10))
- #define MLOG_STR_LEN 16
- #define MLOG_BUF_LEN ((1 << CONFIG_MLOG_BUF_SHIFT) >> 2)
- #define MLOG_BUF_MASK (mlog_buf_len-1)
- #define MLOG_BUF(idx) (mlog_buffer[(idx) & MLOG_BUF_MASK])
- #define MLOG_ID ULONG_MAX
- #define AID_ROOT 0 /* traditional unix root user */
- #define AID_SYSTEM 1000 /* system server */
- #define M_MEMFREE (1 << 0)
- #define M_SWAPFREE (1 << 1)
- #define M_CACHED (1 << 2)
- #define M_GPUUSE (1 << 3)
- #define M_MLOCK (1 << 4)
- #define M_ZRAM (1 << 5)
- #define M_ACTIVE (1 << 6)
- #define M_INACTIVE (1 << 7)
- #define M_SHMEM (1 << 8)
- #define M_GPU_PAGE_CACHE (1 << 9)
- #define M_ION (1 << 10)
- #define V_PSWPIN (1 << 0)
- #define V_PSWPOUT (1 << 1)
- #define V_PGFMFAULT (1 << 2)
- #define V_PGANFAULT (1 << 3)
- #define P_ADJ (1 << 0)
- #define P_RSS (1 << 1)
- #define P_RSWAP (1 << 2)
- #define P_SWPIN (1 << 3)
- #define P_SWPOUT (1 << 4)
- #define P_FMFAULT (1 << 5)
- #define P_MINFAULT (1 << 6)
- #define P_MAJFAULT (1 << 7)
- #define B_NORMAL (1 << 0)
- #define B_HIGH (1 << 1)
- #define P_FMT_SIZE (P_RSS | P_RSWAP)
- #define P_FMT_COUNT (P_SWPIN | P_SWPOUT | P_FMFAULT | P_MINFAULT | P_MAJFAULT)
- #define M_FILTER_ALL (M_MEMFREE | M_SWAPFREE | M_CACHED | M_GPUUSE \
- | M_GPU_PAGE_CACHE | M_MLOCK | M_ZRAM \
- | M_ACTIVE | M_INACTIVE | M_SHMEM | M_ION)
- #define V_FILTER_ALL (V_PSWPIN | V_PSWPOUT | V_PGFMFAULT | V_PGANFAULT)
- #define P_FILTER_ALL (P_ADJ | P_RSS | P_RSWAP | P_SWPIN | P_SWPOUT | P_FMFAULT)
- #define B_FILTER_ALL (B_NORMAL | B_HIGH)
- #define MLOG_TRIGGER_TIMER 0
- #define MLOG_TRIGGER_LMK 1
- #define MLOG_TRIGGER_LTK 2
- static uint meminfo_filter = M_FILTER_ALL;
- static uint vmstat_filter = V_FILTER_ALL;
- static uint proc_filter = P_FILTER_ALL;
- static uint buddyinfo_filter = B_FILTER_ALL;
- static DEFINE_SPINLOCK(mlogbuf_lock);
- DECLARE_WAIT_QUEUE_HEAD(mlog_wait);
- static long mlog_buffer[MLOG_BUF_LEN];
- static int mlog_buf_len = MLOG_BUF_LEN;
- static unsigned mlog_start;
- static unsigned mlog_end;
- static int min_adj = -16;
- static int max_adj = 16;
- static int limit_pid = -1;
- static struct timer_list mlog_timer;
- static unsigned long timer_intval = HZ;
- static const char **strfmt_list;
- static int strfmt_idx;
- static int strfmt_len;
- static int strfmt_proc;
- static const char cr_str[] = "%c";
- static const char type_str[] = "<%ld>";
- static const char time_sec_str[] = "[%5lu";
- static const char time_nanosec_str[] = ".%06lu]";
- static const char mem_size_str[] = " %6lu";
- static const char acc_count_str[] = " %7lu";
- static const char pid_str[] = " [%lu]";
- static const char adj_str[] = " %3ld";
- /*
- buddyinfo
- Node 0, zone Normal 486 297 143 59 30 16 7 0 2 1 54
- Node 0, zone HighMem 74 18 7 65 161 67 23 10 0 1 21
- */
- /* 0 1 2 3 4 5 6 7 8 9 10 */
- static const char order_start_str[] = " [%6lu";
- static const char order_middle_str[] = " %6lu";
- static const char order_end_str[] = " %6lu]";
- /*
- active & inactive
- Active: 211748 kB
- Inactive: 257988 kB
- */
- static void mlog_emit_32(long v)
- {
- MLOG_BUF(mlog_end) = v;
- mlog_end++;
- if (mlog_end - mlog_start > mlog_buf_len)
- mlog_start = mlog_end - mlog_buf_len;
- }
- /*
- static void mlog_emit_32_ex(long v)
- {
- spin_lock_bh(&mlogbuf_lock);
- mlog_emit_32(v);
- spin_unlock_bh(&mlogbuf_lock);
- }
- static void mlog_emit_64(long long v)
- {
- mlog_emit_32(v >> BITS_PER_LONG);
- mlog_emit_32(v & ULONG_MAX);
- }
- */
- static void mlog_reset_format(void)
- {
- int len;
- spin_lock_bh(&mlogbuf_lock);
- if (meminfo_filter)
- meminfo_filter = M_FILTER_ALL;
- if (vmstat_filter)
- vmstat_filter = V_FILTER_ALL;
- if (buddyinfo_filter)
- buddyinfo_filter = B_FILTER_ALL;
- if (proc_filter)
- proc_filter = P_FILTER_ALL;
- /* calc len */
- len = 4; /* id, type, sec, nanosec */
- len += hweight32(meminfo_filter);
- len += hweight32(vmstat_filter);
- /* buddyinfo */
- len += (2 * MAX_ORDER);
- if (proc_filter) {
- len++; /* PID */
- len += hweight32(proc_filter);
- }
- if (!strfmt_list || strfmt_len != len) {
- kfree(strfmt_list);
- strfmt_list = kmalloc_array(len, sizeof(char *), GFP_ATOMIC);
- strfmt_len = len;
- BUG_ON(!strfmt_list);
- }
- /* setup str format */
- len = 0;
- strfmt_proc = 0;
- strfmt_list[len++] = cr_str;
- strfmt_list[len++] = type_str;
- strfmt_list[len++] = time_sec_str;
- strfmt_list[len++] = time_nanosec_str;
- if (meminfo_filter) {
- int i;
- for (i = 0; i < hweight32(meminfo_filter); ++i)
- strfmt_list[len++] = mem_size_str;
- }
- if (vmstat_filter) {
- int i;
- for (i = 0; i < hweight32(vmstat_filter); ++i)
- strfmt_list[len++] = acc_count_str;
- }
- if (buddyinfo_filter) {
- int i, j;
- /* normal and high zone */
- for (i = 0; i < 2; ++i) {
- strfmt_list[len++] = order_start_str;
- for (j = 0; j < MAX_ORDER - 2; ++j)
- strfmt_list[len++] = order_middle_str;
- strfmt_list[len++] = order_end_str;
- }
- }
- if (proc_filter) {
- int i;
- strfmt_proc = len;
- strfmt_list[len++] = pid_str; /* PID */
- strfmt_list[len++] = adj_str; /* ADJ */
- for (i = 0; i < hweight32(proc_filter & (P_FMT_SIZE)); ++i)
- strfmt_list[len++] = mem_size_str;
- for (i = 0; i < hweight32(proc_filter & (P_FMT_COUNT)); ++i)
- strfmt_list[len++] = acc_count_str;
- }
- strfmt_idx = 0;
- BUG_ON(len != strfmt_len);
- spin_unlock_bh(&mlogbuf_lock);
- MLOG_PRINTK("[mlog] reset format %d", strfmt_len);
- for (len = 0; len < strfmt_len; ++len)
- MLOG_PRINTK(" %s", strfmt_list[len]);
- MLOG_PRINTK("\n");
- }
- int mlog_print_fmt(struct seq_file *m)
- {
- seq_puts(m, "<type> [time]");
- if (meminfo_filter & M_MEMFREE)
- seq_puts(m, " memfr");
- if (meminfo_filter & M_SWAPFREE)
- seq_puts(m, " swpfr");
- if (meminfo_filter & M_CACHED)
- seq_puts(m, " cache");
- if (meminfo_filter & M_GPUUSE)
- seq_puts(m, " gpu");
- if (meminfo_filter & M_GPU_PAGE_CACHE)
- seq_puts(m, " gpu_page_cache");
- if (meminfo_filter & M_MLOCK)
- seq_puts(m, " mlock");
- if (meminfo_filter & M_ZRAM)
- seq_puts(m, " zram");
- if (meminfo_filter & M_ACTIVE)
- seq_puts(m, " active");
- if (meminfo_filter & M_INACTIVE)
- seq_puts(m, " inactive");
- if (meminfo_filter & M_SHMEM)
- seq_puts(m, " shmem");
- if (meminfo_filter & M_ION)
- seq_puts(m, " ion");
- if (vmstat_filter & V_PSWPIN)
- seq_puts(m, " swpin");
- if (vmstat_filter & V_PSWPOUT)
- seq_puts(m, " swpout");
- if (vmstat_filter & V_PGFMFAULT)
- seq_puts(m, " fmflt");
- if (vmstat_filter & V_PGANFAULT)
- seq_puts(m, " anflt");
- if (buddyinfo_filter) {
- seq_puts(m, " [normal]");
- seq_puts(m, " [high]");
- }
- if (proc_filter) {
- seq_puts(m, " [pid]");
- if (proc_filter & P_ADJ)
- seq_puts(m, " adj");
- if (proc_filter & P_RSS)
- seq_puts(m, " rss");
- if (proc_filter & P_RSWAP)
- seq_puts(m, " rswp");
- if (proc_filter & P_SWPIN)
- seq_puts(m, " pswpin");
- if (proc_filter & P_SWPOUT)
- seq_puts(m, " pswpout");
- if (proc_filter & P_FMFAULT)
- seq_puts(m, " pfmflt");
- }
- seq_puts(m, "\n");
- return 0;
- }
- static void mlog_reset_buffer(void)
- {
- spin_lock_bh(&mlogbuf_lock);
- mlog_end = mlog_start = 0;
- spin_unlock_bh(&mlogbuf_lock);
- MLOG_PRINTK("[mlog] reset buffer\n");
- }
- #ifndef CONFIG_MTKPASR
- #define mtkpasr_show_page_reserved(void) (0)
- #endif
- static void mlog_meminfo(void)
- {
- unsigned long memfree;
- unsigned long swapfree;
- unsigned long cached;
- unsigned int gpuuse = 0;
- unsigned int gpu_page_cache = 0;
- unsigned long mlock;
- unsigned long zram;
- unsigned long active, inactive;
- unsigned long shmem;
- unsigned long ion = 0;
- memfree = P2K(global_page_state(NR_FREE_PAGES) + mtkpasr_show_page_reserved());
- swapfree = P2K(atomic_long_read(&nr_swap_pages));
- cached = P2K(global_page_state(NR_FILE_PAGES) - total_swapcache_pages());
- /*
- use following code if kernel version is under 3.10.
- swapfree = P2K(nr_swap_pages);
- cached = P2K(global_page_state(NR_FILE_PAGES) - total_swapcache_pages);
- */
- #ifdef COLLECT_GPU_MEMINFO
- if (mtk_get_gpu_memory_usage(&gpuuse))
- gpuuse = B2K(gpuuse);
- if (mtk_get_gpu_page_cache(&gpu_page_cache))
- gpu_page_cache = B2K(gpu_page_cache);
- #endif
- mlock = P2K(global_page_state(NR_MLOCK));
- #if defined(CONFIG_ZRAM) && defined(CONFIG_ZSMALLOC)
- zram = zram_mlog();
- #else
- zram = 0;
- #endif
- active = P2K(global_page_state(NR_ACTIVE_ANON) + global_page_state(NR_ACTIVE_FILE));
- inactive = P2K(global_page_state(NR_INACTIVE_ANON) + global_page_state(NR_INACTIVE_FILE));
- /* MLOG_PRINTK("active: %lu, inactive: %lu\n", active, inactive); */
- shmem = P2K(global_page_state(NR_SHMEM));
- #ifdef CONFIG_MTK_ION
- ion = B2K((unsigned long)ion_mm_heap_total_memory());
- #endif
- spin_lock_bh(&mlogbuf_lock);
- mlog_emit_32(memfree);
- mlog_emit_32(swapfree);
- mlog_emit_32(cached);
- mlog_emit_32(gpuuse);
- mlog_emit_32(gpu_page_cache);
- mlog_emit_32(mlock);
- mlog_emit_32(zram);
- mlog_emit_32(active);
- mlog_emit_32(inactive);
- mlog_emit_32(shmem);
- mlog_emit_32(ion);
- spin_unlock_bh(&mlogbuf_lock);
- }
- static void mlog_vmstat(void)
- {
- int cpu;
- unsigned long v[NR_VM_EVENT_ITEMS];
- memset(v, 0, NR_VM_EVENT_ITEMS * sizeof(unsigned long));
- for_each_online_cpu(cpu) {
- struct vm_event_state *this = &per_cpu(vm_event_states, cpu);
- v[PSWPIN] += this->event[PSWPIN];
- v[PSWPOUT] += this->event[PSWPOUT];
- v[PGFMFAULT] += this->event[PGFMFAULT];
- }
- spin_lock_bh(&mlogbuf_lock);
- mlog_emit_32(v[PSWPIN]);
- mlog_emit_32(v[PSWPOUT]);
- mlog_emit_32(v[PGFMFAULT]);
- mlog_emit_32(0);
- spin_unlock_bh(&mlogbuf_lock);
- }
- /* static void mlog_buddyinfo(void) */
- void mlog_buddyinfo(void)
- {
- int i;
- struct zone *zone;
- struct zone *node_zones;
- unsigned int order;
- int zone_nr = 0;
- unsigned long normal_nr_free[MAX_ORDER] = {0};
- unsigned long high_nr_free[MAX_ORDER] = {0};
- for_each_online_node(i) {
- pg_data_t *pgdat = NODE_DATA(i);
- unsigned long flags;
- node_zones = pgdat->node_zones;
- /* MAX_NR_ZONES 3 */
- for (zone = node_zones; zone - node_zones < MAX_NR_ZONES; ++zone) {
- if (!populated_zone(zone))
- continue;
- spin_lock_irqsave(&zone->lock, flags);
- zone_nr++;
- for (order = 0; order < MAX_ORDER; ++order) {
- if (zone_nr == 1)
- normal_nr_free[order] = zone->free_area[order].nr_free;
- if (zone_nr == 2)
- high_nr_free[order] = zone->free_area[order].nr_free;
- }
- spin_unlock_irqrestore(&zone->lock, flags);
- }
- }
- if (zone_nr == 1) {
- for (order = 0; order < MAX_ORDER; ++order)
- high_nr_free[order] = 0;
- }
- #ifdef CONFIG_MTKPASR
- if (zone_nr == 2)
- high_nr_free[MAX_ORDER - 1] += (mtkpasr_show_page_reserved() >> (MAX_ORDER - 1));
- #endif
- spin_lock_bh(&mlogbuf_lock);
- for (order = 0; order < MAX_ORDER; ++order)
- mlog_emit_32(normal_nr_free[order]);
- for (order = 0; order < MAX_ORDER; ++order)
- mlog_emit_32(high_nr_free[order]);
- spin_unlock_bh(&mlogbuf_lock);
- }
- struct task_struct *find_trylock_task_mm(struct task_struct *t)
- {
- if (spin_trylock(&t->alloc_lock)) {
- if (likely(t->mm))
- return t;
- task_unlock(t);
- }
- return NULL;
- }
- /*
- * it's copied from lowmemorykiller.c
- */
- static short lowmem_oom_score_adj_to_oom_adj(short oom_score_adj)
- {
- if (oom_score_adj == OOM_SCORE_ADJ_MAX)
- return OOM_ADJUST_MAX;
- else
- return ((oom_score_adj * -OOM_DISABLE * 10) / OOM_SCORE_ADJ_MAX + 5) / 10; /* round */
- }
- static void mlog_procinfo(void)
- {
- struct task_struct *tsk;
- rcu_read_lock();
- for_each_process(tsk) {
- int oom_score_adj;
- const struct cred *cred = NULL;
- struct task_struct *real_parent;
- struct task_struct *p;
- pid_t ppid;
- struct task_struct *t;
- unsigned long swap_in, swap_out, fm_flt, min_flt, maj_flt;
- unsigned long rss;
- unsigned long rswap;
- if (tsk->flags & PF_KTHREAD)
- continue;
- p = find_trylock_task_mm(tsk);
- if (!p)
- continue;
- if (!p->signal)
- goto unlock_continue;
- #ifdef CONFIG_ANDROID_LOW_MEMORY_KILLER_AUTODETECT_OOM_ADJ_VALUES
- oom_score_adj = lowmem_oom_score_adj_to_oom_adj(p->signal->oom_score_adj);
- #else
- oom_score_adj = p->signal->oom_adj;
- #endif
- if (max_adj < oom_score_adj || oom_score_adj < min_adj)
- goto unlock_continue;
- if (limit_pid != -1 && p->pid != limit_pid)
- goto unlock_continue;
- cred = get_task_cred(p);
- if (!cred)
- goto unlock_continue;
- /*
- * 1. mediaserver is a suspect in many ANR/FLM cases.
- * 2. procesname is "mediaserver" not "/system/bin/mediaserver"
- */
- if (strncmp("mediaserver", p->comm, TASK_COMM_LEN) == 0)
- goto collect_proc_mem_info;
- /* skip root user */
- if (__kuid_val(cred->uid) == AID_ROOT)
- goto unlock_continue;
- real_parent = rcu_dereference(p->real_parent);
- if (!real_parent)
- goto unlock_continue;
- ppid = real_parent->pid;
- /* skip non java proc (parent is init) */
- if (ppid == 1)
- goto unlock_continue;
- if (oom_score_adj == -16) {
- /* only keep system server */
- if (__kuid_val(cred->uid) != AID_SYSTEM)
- goto unlock_continue;
- }
- collect_proc_mem_info:
- /* reset data */
- swap_in = swap_out = fm_flt = min_flt = maj_flt = 0;
- /* all threads */
- t = p;
- do {
- /* min_flt += t->min_flt; */
- /* maj_flt += t->maj_flt; */
- fm_flt += t->fm_flt;
- #ifdef CONFIG_SWAP
- swap_in += t->swap_in;
- swap_out += t->swap_out;
- #endif
- t = next_thread(t);
- #ifdef MLOG_DEBUG
- #if defined(__LP64__) || defined(_LP64)
- if ((long long)t < 0xffffffc000000000)
- break;
- #endif
- #endif
- } while (t != p);
- /* emit log */
- rss = P2K(get_mm_rss(p->mm));
- rswap = P2K(get_mm_counter(p->mm, MM_SWAPENTS));
- spin_lock_bh(&mlogbuf_lock);
- mlog_emit_32(p->pid);
- mlog_emit_32(oom_score_adj);
- mlog_emit_32(rss);
- mlog_emit_32(rswap);
- mlog_emit_32(swap_in);
- mlog_emit_32(swap_out);
- mlog_emit_32(fm_flt);
- /* mlog_emit_32(min_flt); */
- /* mlog_emit_32(maj_flt); */
- spin_unlock_bh(&mlogbuf_lock);
- unlock_continue:
- if (cred)
- put_cred(cred);
- task_unlock(p);
- }
- rcu_read_unlock();
- }
- void mlog(int type)
- {
- /* unsigned long flag; */
- unsigned long microsec_rem;
- unsigned long long t = local_clock();
- #ifdef PROFILE_MLOG_OVERHEAD
- unsigned long long t1 = t;
- #endif
- /* MLOG_PRINTK("[mlog] log %d %d %d\n", meminfo_filter, vmstat_filter, proc_filter); */
- /* time stamp */
- microsec_rem = do_div(t, 1000000000);
- /* spin_lock_irqsave(&mlogbuf_lock, flag); */
- spin_lock_bh(&mlogbuf_lock);
- mlog_emit_32(MLOG_ID); /* tag for correct start point */
- mlog_emit_32(type);
- mlog_emit_32((unsigned long)t);
- mlog_emit_32(microsec_rem / 1000);
- spin_unlock_bh(&mlogbuf_lock);
- /* memory log */
- if (meminfo_filter)
- mlog_meminfo();
- if (vmstat_filter)
- mlog_vmstat();
- if (buddyinfo_filter)
- mlog_buddyinfo();
- if (proc_filter)
- mlog_procinfo();
- /* spin_unlock_irqrestore(&mlogbuf_lock, flag); */
- if (waitqueue_active(&mlog_wait))
- wake_up_interruptible(&mlog_wait);
- #ifdef PROFILE_MLOG_OVERHEAD
- MLOG_PRINTK("[mlog] %llu ns\n", local_clock() - t1);
- #endif
- }
- EXPORT_SYMBOL(mlog);
- void mlog_doopen(void)
- {
- spin_lock_bh(&mlogbuf_lock);
- strfmt_idx = 0;
- spin_unlock_bh(&mlogbuf_lock);
- }
- int mlog_unread(void)
- {
- return mlog_end - mlog_start;
- }
- int mlog_doread(char __user *buf, size_t len)
- {
- unsigned i;
- int error = -EINVAL;
- char mlog_str[MLOG_STR_LEN];
- if (!buf || len < 0)
- goto out;
- error = 0;
- if (!len)
- goto out;
- if (!access_ok(VERIFY_WRITE, buf, len)) {
- error = -EFAULT;
- goto out;
- }
- /* MLOG_PRINTK("[mlog] wait %d %d\n", mlog_start, mlog_end); */
- error = wait_event_interruptible(mlog_wait, (mlog_start - mlog_end));
- if (error)
- goto out;
- i = 0;
- spin_lock_bh(&mlogbuf_lock);
- /* MLOG_PRINTK("[mlog] doread %d %d\n", mlog_start, mlog_end); */
- while (!error && (mlog_start != mlog_end) && i < len - MLOG_STR_LEN) {
- int size;
- int v;
- /* retrieve value */
- v = MLOG_BUF(mlog_start);
- mlog_start++;
- if (unlikely((v == MLOG_ID) ^ (strfmt_idx == 0))) {
- /* find first valid log */
- if (strfmt_idx == 0)
- continue;
- strfmt_idx = 0;
- }
- if (strfmt_idx == 0)
- v = '\n';
- /* MLOG_PRINTK("[mlog] %d: %s\n", strfmt_idx, strfmt_list[strfmt_idx]); */
- size = snprintf(mlog_str, MLOG_STR_LEN, strfmt_list[strfmt_idx++], v);
- if (strfmt_idx >= strfmt_len)
- strfmt_idx = strfmt_proc;
- spin_unlock_bh(&mlogbuf_lock);
- if (__copy_to_user(buf, mlog_str, size))
- error = -EFAULT;
- else {
- buf += size;
- i += size;
- }
- cond_resched();
- spin_lock_bh(&mlogbuf_lock);
- }
- spin_unlock_bh(&mlogbuf_lock);
- if (!error)
- error = i;
- out:
- /* MLOG_PRINTK("[mlog] doread end %d\n", error); */
- return error;
- }
- static void mlog_timer_handler(unsigned long data)
- {
- mlog(MLOG_TRIGGER_TIMER);
- mod_timer(&mlog_timer, round_jiffies(jiffies + timer_intval));
- }
- static void mlog_init_logger(void)
- {
- spin_lock_init(&mlogbuf_lock);
- mlog_reset_format();
- mlog_reset_buffer();
- setup_timer(&mlog_timer, mlog_timer_handler, 0);
- mlog_timer.expires = jiffies + timer_intval;
- add_timer(&mlog_timer);
- }
- static void mlog_exit_logger(void)
- {
- kfree(strfmt_list);
- strfmt_list = NULL;
- }
- static int __init mlog_init(void)
- {
- mlog_init_logger();
- mlog_init_procfs();
- return 0;
- }
- static void __exit mlog_exit(void)
- {
- mlog_exit_logger();
- }
- module_param(min_adj, int, S_IRUGO | S_IWUSR);
- module_param(max_adj, int, S_IRUGO | S_IWUSR);
- module_param(limit_pid, int, S_IRUGO | S_IWUSR);
- static int do_filter_handler(const char *val, const struct kernel_param *kp)
- {
- const int ret = param_set_uint(val, kp);
- mlog_reset_format();
- mlog_reset_buffer();
- return ret;
- }
- static const struct kernel_param_ops param_ops_change_filter = {
- .set = &do_filter_handler,
- .get = ¶m_get_uint,
- .free = NULL,
- };
- static int do_time_intval_handler(const char *val, const struct kernel_param *kp)
- {
- const int ret = param_set_uint(val, kp);
- mod_timer(&mlog_timer, jiffies + ret);
- return ret;
- }
- static const struct kernel_param_ops param_ops_change_time_intval = {
- .set = &do_time_intval_handler,
- .get = ¶m_get_uint,
- .free = NULL,
- };
- param_check_uint(meminfo_filter, &meminfo_filter);
- module_param_cb(meminfo_filter, ¶m_ops_change_filter, &meminfo_filter, S_IRUGO | S_IWUSR);
- __MODULE_PARM_TYPE(meminfo_filter, uint);
- param_check_uint(vmstat_filter, &vmstat_filter);
- module_param_cb(vmstat_filter, ¶m_ops_change_filter, &vmstat_filter, S_IRUGO | S_IWUSR);
- __MODULE_PARM_TYPE(vmstat_filter, uint);
- param_check_uint(proc_filter, &proc_filter);
- module_param_cb(proc_filter, ¶m_ops_change_filter, &proc_filter, S_IRUGO | S_IWUSR);
- __MODULE_PARM_TYPE(proc_filter, uint);
- param_check_ulong(timer_intval, &timer_intval);
- module_param_cb(timer_intval, ¶m_ops_change_time_intval, &timer_intval, S_IRUGO | S_IWUSR);
- __MODULE_PARM_TYPE(timer_intval, ulong);
- static uint do_mlog;
- static int do_mlog_handler(const char *val, const struct kernel_param *kp)
- {
- const int ret = param_set_uint(val, kp);
- mlog(do_mlog);
- /* MLOG_PRINTK("[mlog] do_mlog %d\n", do_mlog); */
- return ret;
- }
- static const struct kernel_param_ops param_ops_do_mlog = {
- .set = &do_mlog_handler,
- .get = ¶m_get_uint,
- .free = NULL,
- };
- param_check_uint(do_mlog, &do_mlog);
- module_param_cb(do_mlog, ¶m_ops_do_mlog, &do_mlog, S_IRUGO | S_IWUSR);
- __MODULE_PARM_TYPE(do_mlog, uint);
- module_init(mlog_init);
- module_exit(mlog_exit);
- /* TODO module license & information */
- MODULE_DESCRIPTION("MEDIATEK Memory Log Driver");
- MODULE_AUTHOR("Jimmy Su<jimmy.su@mediatek.com>");
- MODULE_LICENSE("GPL");
|