aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndre Detsch <adetsch@br.ibm.com>2007-07-20 15:39:33 -0400
committerArnd Bergmann <arnd@klappe.arndb.de>2007-07-20 15:41:50 -0400
commit27ec41d3a1d4df2b7cd190e93aad22ab86a72aa1 (patch)
tree6c9d5af3fc3c3cfbef390eb34caf4dc7e7a3913e
parente840cfe6814d6f13ecb86cff7097ad7259df502e (diff)
[CELL] spufs: add spu stats in sysfs and ctx stat file in spufs
This patch exports per-context statistics in spufs as long as spu statistics in sysfs. It was formed by merging: "spufs: add spu stats in sysfs" From: Christoph Hellwig "spufs: add stat file to spufs" From: Christoph Hellwig "spufs: fix libassist accounting" From: Jeremy Kerr "spusched: fix spu utilization statistics" From: Luke Browning And some adjustments by myself, after suggestions on cbe-oss-dev. Having separate patches was making the review process harder than it should, as we end up integrating spus and ctx statistics accounting much more than it was on the first implementation. Signed-off-by: Andre Detsch <adetsch@br.ibm.com> Signed-off-by: Jeremy Kerr <jk@ozlabs.org> Signed-off-by: Arnd Bergmann <arnd.bergmann@de.ibm.com>
-rw-r--r--arch/powerpc/platforms/cell/spu_base.c24
-rw-r--r--arch/powerpc/platforms/cell/spufs/context.c3
-rw-r--r--arch/powerpc/platforms/cell/spufs/fault.c8
-rw-r--r--arch/powerpc/platforms/cell/spufs/file.c32
-rw-r--r--arch/powerpc/platforms/cell/spufs/run.c10
-rw-r--r--arch/powerpc/platforms/cell/spufs/sched.c22
-rw-r--r--arch/powerpc/platforms/cell/spufs/spufs.h63
-rw-r--r--include/asm-powerpc/spu.h10
8 files changed, 94 insertions, 78 deletions
diff --git a/arch/powerpc/platforms/cell/spu_base.c b/arch/powerpc/platforms/cell/spu_base.c
index c563066e640d..caaf2bf78cad 100644
--- a/arch/powerpc/platforms/cell/spu_base.c
+++ b/arch/powerpc/platforms/cell/spu_base.c
@@ -553,6 +553,7 @@ static int __init create_spu(void *data)
553 int ret; 553 int ret;
554 static int number; 554 static int number;
555 unsigned long flags; 555 unsigned long flags;
556 struct timespec ts;
556 557
557 ret = -ENOMEM; 558 ret = -ENOMEM;
558 spu = kzalloc(sizeof (*spu), GFP_KERNEL); 559 spu = kzalloc(sizeof (*spu), GFP_KERNEL);
@@ -586,8 +587,9 @@ static int __init create_spu(void *data)
586 spin_unlock_irqrestore(&spu_list_lock, flags); 587 spin_unlock_irqrestore(&spu_list_lock, flags);
587 mutex_unlock(&spu_mutex); 588 mutex_unlock(&spu_mutex);
588 589
589 spu->stats.utilization_state = SPU_UTIL_IDLE; 590 spu->stats.util_state = SPU_UTIL_IDLE_LOADED;
590 spu->stats.tstamp = jiffies; 591 ktime_get_ts(&ts);
592 spu->stats.tstamp = timespec_to_ns(&ts);
591 593
592 goto out; 594 goto out;
593 595
@@ -608,12 +610,20 @@ static const char *spu_state_names[] = {
608static unsigned long long spu_acct_time(struct spu *spu, 610static unsigned long long spu_acct_time(struct spu *spu,
609 enum spu_utilization_state state) 611 enum spu_utilization_state state)
610{ 612{
613 struct timespec ts;
611 unsigned long long time = spu->stats.times[state]; 614 unsigned long long time = spu->stats.times[state];
612 615
613 if (spu->stats.utilization_state == state) 616 /*
614 time += jiffies - spu->stats.tstamp; 617 * If the spu is idle or the context is stopped, utilization
618 * statistics are not updated. Apply the time delta from the
619 * last recorded state of the spu.
620 */
621 if (spu->stats.util_state == state) {
622 ktime_get_ts(&ts);
623 time += timespec_to_ns(&ts) - spu->stats.tstamp;
624 }
615 625
616 return jiffies_to_msecs(time); 626 return time / NSEC_PER_MSEC;
617} 627}
618 628
619 629
@@ -623,11 +633,11 @@ static ssize_t spu_stat_show(struct sys_device *sysdev, char *buf)
623 633
624 return sprintf(buf, "%s %llu %llu %llu %llu " 634 return sprintf(buf, "%s %llu %llu %llu %llu "
625 "%llu %llu %llu %llu %llu %llu %llu %llu\n", 635 "%llu %llu %llu %llu %llu %llu %llu %llu\n",
626 spu_state_names[spu->stats.utilization_state], 636 spu_state_names[spu->stats.util_state],
627 spu_acct_time(spu, SPU_UTIL_USER), 637 spu_acct_time(spu, SPU_UTIL_USER),
628 spu_acct_time(spu, SPU_UTIL_SYSTEM), 638 spu_acct_time(spu, SPU_UTIL_SYSTEM),
629 spu_acct_time(spu, SPU_UTIL_IOWAIT), 639 spu_acct_time(spu, SPU_UTIL_IOWAIT),
630 spu_acct_time(spu, SPU_UTIL_IDLE), 640 spu_acct_time(spu, SPU_UTIL_IDLE_LOADED),
631 spu->stats.vol_ctx_switch, 641 spu->stats.vol_ctx_switch,
632 spu->stats.invol_ctx_switch, 642 spu->stats.invol_ctx_switch,
633 spu->stats.slb_flt, 643 spu->stats.slb_flt,
diff --git a/arch/powerpc/platforms/cell/spufs/context.c b/arch/powerpc/platforms/cell/spufs/context.c
index 6d7bd60f5380..0e5e55f53c8b 100644
--- a/arch/powerpc/platforms/cell/spufs/context.c
+++ b/arch/powerpc/platforms/cell/spufs/context.c
@@ -59,8 +59,7 @@ struct spu_context *alloc_spu_context(struct spu_gang *gang)
59 spu_gang_add_ctx(gang, ctx); 59 spu_gang_add_ctx(gang, ctx);
60 ctx->cpus_allowed = current->cpus_allowed; 60 ctx->cpus_allowed = current->cpus_allowed;
61 spu_set_timeslice(ctx); 61 spu_set_timeslice(ctx);
62 ctx->stats.execution_state = SPUCTX_UTIL_USER; 62 ctx->stats.util_state = SPU_UTIL_IDLE_LOADED;
63 ctx->stats.tstamp = jiffies;
64 63
65 atomic_inc(&nr_spu_contexts); 64 atomic_inc(&nr_spu_contexts);
66 goto out; 65 goto out;
diff --git a/arch/powerpc/platforms/cell/spufs/fault.c b/arch/powerpc/platforms/cell/spufs/fault.c
index f53a07437472..917eab4be486 100644
--- a/arch/powerpc/platforms/cell/spufs/fault.c
+++ b/arch/powerpc/platforms/cell/spufs/fault.c
@@ -179,16 +179,14 @@ int spufs_handle_class1(struct spu_context *ctx)
179 if (!(dsisr & (MFC_DSISR_PTE_NOT_FOUND | MFC_DSISR_ACCESS_DENIED))) 179 if (!(dsisr & (MFC_DSISR_PTE_NOT_FOUND | MFC_DSISR_ACCESS_DENIED)))
180 return 0; 180 return 0;
181 181
182 spuctx_switch_state(ctx, SPUCTX_UTIL_IOWAIT); 182 spuctx_switch_state(ctx, SPU_UTIL_IOWAIT);
183 183
184 pr_debug("ctx %p: ea %016lx, dsisr %016lx state %d\n", ctx, ea, 184 pr_debug("ctx %p: ea %016lx, dsisr %016lx state %d\n", ctx, ea,
185 dsisr, ctx->state); 185 dsisr, ctx->state);
186 186
187 ctx->stats.hash_flt++; 187 ctx->stats.hash_flt++;
188 if (ctx->state == SPU_STATE_RUNNABLE) { 188 if (ctx->state == SPU_STATE_RUNNABLE)
189 ctx->spu->stats.hash_flt++; 189 ctx->spu->stats.hash_flt++;
190 spu_switch_state(ctx->spu, SPU_UTIL_IOWAIT);
191 }
192 190
193 /* we must not hold the lock when entering spu_handle_mm_fault */ 191 /* we must not hold the lock when entering spu_handle_mm_fault */
194 spu_release(ctx); 192 spu_release(ctx);
@@ -226,7 +224,7 @@ int spufs_handle_class1(struct spu_context *ctx)
226 } else 224 } else
227 spufs_handle_dma_error(ctx, ea, SPE_EVENT_SPE_DATA_STORAGE); 225 spufs_handle_dma_error(ctx, ea, SPE_EVENT_SPE_DATA_STORAGE);
228 226
229 spuctx_switch_state(ctx, SPUCTX_UTIL_SYSTEM); 227 spuctx_switch_state(ctx, SPU_UTIL_SYSTEM);
230 return ret; 228 return ret;
231} 229}
232EXPORT_SYMBOL_GPL(spufs_handle_class1); 230EXPORT_SYMBOL_GPL(spufs_handle_class1);
diff --git a/arch/powerpc/platforms/cell/spufs/file.c b/arch/powerpc/platforms/cell/spufs/file.c
index fe164112b3d0..9351db9472d9 100644
--- a/arch/powerpc/platforms/cell/spufs/file.c
+++ b/arch/powerpc/platforms/cell/spufs/file.c
@@ -2079,14 +2079,26 @@ static const char *ctx_state_names[] = {
2079}; 2079};
2080 2080
2081static unsigned long long spufs_acct_time(struct spu_context *ctx, 2081static unsigned long long spufs_acct_time(struct spu_context *ctx,
2082 enum spuctx_execution_state state) 2082 enum spu_utilization_state state)
2083{ 2083{
2084 unsigned long time = ctx->stats.times[state]; 2084 struct timespec ts;
2085 unsigned long long time = ctx->stats.times[state];
2085 2086
2086 if (ctx->stats.execution_state == state) 2087 /*
2087 time += jiffies - ctx->stats.tstamp; 2088 * In general, utilization statistics are updated by the controlling
2089 * thread as the spu context moves through various well defined
2090 * state transitions, but if the context is lazily loaded its
2091 * utilization statistics are not updated as the controlling thread
2092 * is not tightly coupled with the execution of the spu context. We
2093 * calculate and apply the time delta from the last recorded state
2094 * of the spu context.
2095 */
2096 if (ctx->spu && ctx->stats.util_state == state) {
2097 ktime_get_ts(&ts);
2098 time += timespec_to_ns(&ts) - ctx->stats.tstamp;
2099 }
2088 2100
2089 return jiffies_to_msecs(time); 2101 return time / NSEC_PER_MSEC;
2090} 2102}
2091 2103
2092static unsigned long long spufs_slb_flts(struct spu_context *ctx) 2104static unsigned long long spufs_slb_flts(struct spu_context *ctx)
@@ -2121,11 +2133,11 @@ static int spufs_show_stat(struct seq_file *s, void *private)
2121 spu_acquire(ctx); 2133 spu_acquire(ctx);
2122 seq_printf(s, "%s %llu %llu %llu %llu " 2134 seq_printf(s, "%s %llu %llu %llu %llu "
2123 "%llu %llu %llu %llu %llu %llu %llu %llu\n", 2135 "%llu %llu %llu %llu %llu %llu %llu %llu\n",
2124 ctx_state_names[ctx->stats.execution_state], 2136 ctx_state_names[ctx->stats.util_state],
2125 spufs_acct_time(ctx, SPUCTX_UTIL_USER), 2137