From 87c576584d73f8ba208602735e43913409204ab8 Mon Sep 17 00:00:00 2001 From: Tomas Hruby Date: Thu, 23 Sep 2010 10:49:48 +0000 Subject: [PATCH] Internal 64M buffer for profiling - when profiling is compiled in kernel includes a 64M buffer for sample - 64M is the default used by profile tool as its buffer - when using nmi profiling it is not possible to always copy sample stright to userland as the nmi may (and does) happen in bad moments - reduces sampling overhead as samples are copied out only when profiling stops --- kernel/profile.c | 30 +++++++++++++----------------- kernel/profile.h | 3 +++ kernel/system/do_sprofile.c | 5 ++++- 3 files changed, 20 insertions(+), 18 deletions(-) diff --git a/kernel/profile.c b/kernel/profile.c index 626202338..4319eccd5 100644 --- a/kernel/profile.c +++ b/kernel/profile.c @@ -63,32 +63,26 @@ PUBLIC void stop_profile_clock() PRIVATE sprof_save_sample(struct proc * p) { - struct sprof_sample s; + struct sprof_sample *s; - s.proc = p->p_endpoint; - s.pc = (void *) p->p_reg.pc; + s = (struct sprof_sample *) (sprof_sample_buffer + sprof_info.mem_used); - /* Store sample (process name and program counter). */ - data_copy(KERNEL, (vir_bytes) &s, - sprof_ep, sprof_data_addr_vir + sprof_info.mem_used, - sizeof(s)); + s->proc = p->p_endpoint; + s->pc = (void *) p->p_reg.pc; - sprof_info.mem_used += sizeof(s); + sprof_info.mem_used += sizeof(struct sprof_sample); } PRIVATE sprof_save_proc(struct proc * p) { - struct sprof_proc s; + struct sprof_proc * s; - s.proc = p->p_endpoint; - memcpy(s.name, p->p_name, P_NAME_LEN); + s = (struct sprof_proc *) (sprof_sample_buffer + sprof_info.mem_used); - /* Store sample (process name and program counter). */ - data_copy(KERNEL, (vir_bytes) &s, - sprof_ep, sprof_data_addr_vir + sprof_info.mem_used, - sizeof(s)); + s->proc = p->p_endpoint; + memcpy(&s->name, p->p_name, P_NAME_LEN); - sprof_info.mem_used += sizeof(s); + sprof_info.mem_used += sizeof(struct sprof_proc); } PRIVATE void profile_sample(struct proc * p) @@ -100,7 +94,9 @@ PRIVATE void profile_sample(struct proc * p) return; /* Check if enough memory available before writing sample. */ - if (sprof_info.mem_used + sizeof(sprof_info) > sprof_mem_size) { + if (sprof_info.mem_used + sizeof(sprof_info) + + 2*sizeof(struct sprof_sample) + + 2*sizeof(struct sprof_sample) > sprof_mem_size) { sprof_info.mem_used = -1; return; } diff --git a/kernel/profile.h b/kernel/profile.h index 275ec8711..5580bf544 100644 --- a/kernel/profile.h +++ b/kernel/profile.h @@ -7,6 +7,9 @@ #include "arch_watchdog.h" +#define SAMPLE_BUFFER_SIZE (64 << 20) +EXTERN char sprof_sample_buffer[SAMPLE_BUFFER_SIZE]; + EXTERN int sprofiling; /* whether profiling is running */ EXTERN int sprofiling_type; /* whether profiling is running */ EXTERN int sprof_mem_size; /* available user memory for data */ diff --git a/kernel/system/do_sprofile.c b/kernel/system/do_sprofile.c index d4f4b404d..e5aebc821 100644 --- a/kernel/system/do_sprofile.c +++ b/kernel/system/do_sprofile.c @@ -65,7 +65,8 @@ PUBLIC int do_sprofile(struct proc * caller, message * m_ptr) sprof_info.system_samples = 0; sprof_info.user_samples = 0; - sprof_mem_size = m_ptr->PROF_MEM_SIZE; + sprof_mem_size = m_ptr->PROF_MEM_SIZE < SAMPLE_BUFFER_SIZE ? + m_ptr->PROF_MEM_SIZE : SAMPLE_BUFFER_SIZE; switch (sprofiling_type = m_ptr->PROF_INTR_TYPE) { case PROF_RTC: @@ -111,6 +112,8 @@ PUBLIC int do_sprofile(struct proc * caller, message * m_ptr) data_copy(KERNEL, (vir_bytes) &sprof_info, sprof_ep, sprof_info_addr_vir, sizeof(sprof_info)); + data_copy(KERNEL, (vir_bytes) sprof_sample_buffer, + sprof_ep, sprof_data_addr_vir, sprof_info.mem_used); clean_seen_flag(); -- 2.44.0