Subject: perfmon2: restructure pfm_cell_hw_smpl_handler From: Kevin Corry Restructure the pfm_cell_hw_smpl_handler() routine to make it a bit easier to understand, and to prepare for an upcoming patch for "partial" sample handling. Signed-off-by: Kevin Corry Signed-off-by: Carl Love Signed-off-by: Arnd Bergmann Index: linux-2.6/arch/powerpc/perfmon/perfmon_cell_hw_smpl.c =================================================================== --- linux-2.6.orig/arch/powerpc/perfmon/perfmon_cell_hw_smpl.c +++ linux-2.6/arch/powerpc/perfmon/perfmon_cell_hw_smpl.c @@ -124,6 +124,79 @@ static int pfm_cell_hw_smpl_notify_user( } /** + * init_entry_header + **/ +static struct pfm_cell_hw_smpl_entry_hdr * +init_entry_header(struct pfm_cell_hw_smpl_hdr *buf_hdr, + struct pfm_event_set *set) +{ + struct pfm_cell_hw_smpl_entry_hdr *ent_hdr; + + ent_hdr = (void *)buf_hdr + buf_hdr->cur_offset; + ent_hdr->pid = current->pid; + ent_hdr->tgid = current->tgid; + ent_hdr->cpu = smp_processor_id(); + ent_hdr->set = set->id; + ent_hdr->num_samples = 0; + ent_hdr->entry_num = buf_hdr->count; + + return ent_hdr; +} + +/** + * read_trace_buffer + * + * Read at most 1024 samples from the trace-buffer. Note, samples could + * be added to the trace-buffer while it is being read. However, we only + * made sure we had space for up to 1024 samples. + **/ +static void read_trace_buffer(struct pfm_cell_hw_smpl_entry_hdr *ent_hdr, + u64 **trace_buffer_sample) +{ + int cpu = smp_processor_id(); + u32 trace_addr; + + *trace_buffer_sample = (u64 *)(ent_hdr + 1); + trace_addr = cbe_read_pm(cpu, trace_address); + while (!(trace_addr & CBE_PM_TRACE_BUF_EMPTY) && + ent_hdr->num_samples < CBE_PM_TRACE_BUF_MAX_COUNT) { + cbe_read_trace_buffer(cpu, *trace_buffer_sample); + *trace_buffer_sample += 2; + ent_hdr->num_samples++; + trace_addr = cbe_read_pm(cpu, trace_address); + } +} + +/** + * handle_full_buffer + **/ +static int handle_full_buffer(struct pfm_cell_hw_smpl_hdr *buf_hdr, + struct pfm_context *ctx, + struct pfm_event_set *set) +{ + PFM_DBG_ovfl("Sampling-buffer full. free bytes=%lu, count=%lu", + buf_hdr->buf_size - buf_hdr->cur_offset, buf_hdr->count); + + /* Increment the number of sampling-buffer overflows. This + * is important for detecting duplicate sets of samples. + */ + buf_hdr->overflows++; + + /* Add a message to the context's message queue and wake up any + * user-space program's that are polling on the context's file + * descriptor. + */ + pfm_cell_hw_smpl_notify_user(ctx); + + /* Mask monitoring until a pfm_restart() occurs. */ + pfm_mask_monitoring(ctx, set); + ctx->state = PFM_CTX_MASKED; + ctx->flags.can_restart = 1; + + return -ENOBUFS; +} + +/** * pfm_cell_hw_smpl_handler * * Create a new entry-header in the sampling-buffer and copy the current @@ -137,10 +210,10 @@ static int pfm_cell_hw_smpl_handler(void { struct pfm_cell_hw_smpl_hdr *hdr = buf; struct pfm_cell_hw_smpl_entry_hdr *ent; + struct pfm_event_set *set; struct pfm_context *ctx; - void *cur, *end; - u64 *trace_buffer_lines; - u32 trace_addr; + u64 *trace_buffer_sample; + u64 free_bytes; /* If this handler was called due to an actual PMD overflowing, do * nothing. Only store the contents of the trace-buffer if the trace- @@ -149,51 +222,22 @@ static int pfm_cell_hw_smpl_handler(void if (arg->ovfl_pmd != PFM_CELL_HW_SMPL_OVFL_PMD) return 0; - cur = buf + hdr->cur_offset; - end = buf + hdr->buf_size; ctx = __get_cpu_var(pmu_ctx); + set = ctx->active_set; /* Check if the sampling-buffer is full. This should never happen, * since we check if the buffer is full after adding the new entry. */ - if ((end - cur) < PFM_CELL_HW_SMPL_MAX_ENTRY_SIZE) { + free_bytes = buf_hdr->buf_size - buf_hdr->cur_offset; + if (free_bytes < PFM_CELL_HW_SMPL_MAX_ENTRY_SIZE) { PFM_ERR("Cell HW Sampling: Buffer is full " "before adding new entry."); - goto full; + return handle_full_buffer(buf_hdr, ctx, set); } - ent = cur; + ent = init_entry_header(buf_hdr, set); - /* current = task running at the time of the overflow. - * - * per-task mode: - * - This is ususally the task being monitored. - * Under certain conditions, it might be a different task - * - * system-wide: - * - This is not necessarily the task controlling the session - */ - ent->pid = current->pid; - ent->tgid = current->tgid; - ent->cpu = smp_processor_id(); - ent->set = arg->active_set; - ent->num_samples = 0; - ent->entry_num = hdr->count; - - /* Read at most 1024 lines from the trace-buffer. Note, lines could be - * added to the trace-buffer while it is being read. However, we only - * made sure we had space for up to 1024 lines. - */ - - trace_buffer_lines = (u64 *)(ent + 1); - trace_addr = cbe_read_pm(ent->cpu, trace_address); - while (!(trace_addr & CBE_PM_TRACE_BUF_EMPTY) && - ent->num_samples < CBE_PM_TRACE_BUF_MAX_COUNT) { - cbe_read_trace_buffer(ent->cpu, trace_buffer_lines); - trace_buffer_lines += 2; - ent->num_samples++; - trace_addr = cbe_read_pm(ent->cpu, trace_address); - } + read_trace_buffer(ent_hdr, &trace_buffer_sample); /* Update the sampling-buffer header for the next entry. Since the * hw_smpl_hdr and hw_smpl_entry_hdr structures are both padded to @@ -201,40 +245,18 @@ static int pfm_cell_hw_smpl_handler(void * every buffer entry will start on a 128-bit boundary. */ if (ent->num_samples) { - cur = trace_buffer_lines; - hdr->cur_offset = cur - (void *)hdr; + hdr->cur_offset = (void *)trace_buffer_sample - (void *)buf_hdr; hdr->count++; } /* Check the available size in the buffer again so we won't lose the * next sample entry. */ - if ((end - cur) < PFM_CELL_HW_SMPL_MAX_ENTRY_SIZE) - goto full; + free_bytes = buf_hdr->buf_size - buf_hdr->cur_offset; + if (free_bytes < PFM_CELL_HW_SMPL_MAX_ENTRY_SIZE) + return handle_full_buffer(buf_hdr, ctx, set); return 0; - -full: - PFM_DBG_ovfl("Sampling-buffer full. free bytes=%lu, count=%lu", - end-cur, hdr->count); - - /* Increment the number of sampling-buffer overflows. This - * is important for detecting duplicate sets of samples. - */ - hdr->overflows++; - - /* Add a message to the context's message queue and wake up any - * user-space program's that are polling on the context's file - * descriptor. - */ - pfm_cell_hw_smpl_notify_user(ctx); - - /* Mask monitoring until a pfm_restart() occurs. */ - pfm_mask_monitoring(ctx, ctx->active_set); - ctx->state = PFM_CTX_MASKED; - ctx->flags.can_restart = 1; - - return -ENOBUFS; } /**