Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 62242
b: refs/heads/master
c: 27ec41d
h: refs/heads/master
v: v3
  • Loading branch information
Andre Detsch authored and Arnd Bergmann committed Jul 20, 2007
1 parent 59a0770 commit 5e60de9
Show file tree
Hide file tree
Showing 9 changed files with 95 additions and 79 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: e840cfe6814d6f13ecb86cff7097ad7259df502e
refs/heads/master: 27ec41d3a1d4df2b7cd190e93aad22ab86a72aa1
24 changes: 17 additions & 7 deletions trunk/arch/powerpc/platforms/cell/spu_base.c
Original file line number Diff line number Diff line change
Expand Up @@ -553,6 +553,7 @@ static int __init create_spu(void *data)
int ret;
static int number;
unsigned long flags;
struct timespec ts;

ret = -ENOMEM;
spu = kzalloc(sizeof (*spu), GFP_KERNEL);
Expand Down Expand Up @@ -586,8 +587,9 @@ static int __init create_spu(void *data)
spin_unlock_irqrestore(&spu_list_lock, flags);
mutex_unlock(&spu_mutex);

spu->stats.utilization_state = SPU_UTIL_IDLE;
spu->stats.tstamp = jiffies;
spu->stats.util_state = SPU_UTIL_IDLE_LOADED;
ktime_get_ts(&ts);
spu->stats.tstamp = timespec_to_ns(&ts);

goto out;

Expand All @@ -608,12 +610,20 @@ static const char *spu_state_names[] = {
static unsigned long long spu_acct_time(struct spu *spu,
enum spu_utilization_state state)
{
struct timespec ts;
unsigned long long time = spu->stats.times[state];

if (spu->stats.utilization_state == state)
time += jiffies - spu->stats.tstamp;
/*
* If the spu is idle or the context is stopped, utilization
* statistics are not updated. Apply the time delta from the
* last recorded state of the spu.
*/
if (spu->stats.util_state == state) {
ktime_get_ts(&ts);
time += timespec_to_ns(&ts) - spu->stats.tstamp;
}

return jiffies_to_msecs(time);
return time / NSEC_PER_MSEC;
}


Expand All @@ -623,11 +633,11 @@ static ssize_t spu_stat_show(struct sys_device *sysdev, char *buf)

return sprintf(buf, "%s %llu %llu %llu %llu "
"%llu %llu %llu %llu %llu %llu %llu %llu\n",
spu_state_names[spu->stats.utilization_state],
spu_state_names[spu->stats.util_state],
spu_acct_time(spu, SPU_UTIL_USER),
spu_acct_time(spu, SPU_UTIL_SYSTEM),
spu_acct_time(spu, SPU_UTIL_IOWAIT),
spu_acct_time(spu, SPU_UTIL_IDLE),
spu_acct_time(spu, SPU_UTIL_IDLE_LOADED),
spu->stats.vol_ctx_switch,
spu->stats.invol_ctx_switch,
spu->stats.slb_flt,
Expand Down
3 changes: 1 addition & 2 deletions trunk/arch/powerpc/platforms/cell/spufs/context.c
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,7 @@ struct spu_context *alloc_spu_context(struct spu_gang *gang)
spu_gang_add_ctx(gang, ctx);
ctx->cpus_allowed = current->cpus_allowed;
spu_set_timeslice(ctx);
ctx->stats.execution_state = SPUCTX_UTIL_USER;
ctx->stats.tstamp = jiffies;
ctx->stats.util_state = SPU_UTIL_IDLE_LOADED;

atomic_inc(&nr_spu_contexts);
goto out;
Expand Down
8 changes: 3 additions & 5 deletions trunk/arch/powerpc/platforms/cell/spufs/fault.c
Original file line number Diff line number Diff line change
Expand Up @@ -179,16 +179,14 @@ int spufs_handle_class1(struct spu_context *ctx)
if (!(dsisr & (MFC_DSISR_PTE_NOT_FOUND | MFC_DSISR_ACCESS_DENIED)))
return 0;

spuctx_switch_state(ctx, SPUCTX_UTIL_IOWAIT);
spuctx_switch_state(ctx, SPU_UTIL_IOWAIT);

pr_debug("ctx %p: ea %016lx, dsisr %016lx state %d\n", ctx, ea,
dsisr, ctx->state);

ctx->stats.hash_flt++;
if (ctx->state == SPU_STATE_RUNNABLE) {
if (ctx->state == SPU_STATE_RUNNABLE)
ctx->spu->stats.hash_flt++;
spu_switch_state(ctx->spu, SPU_UTIL_IOWAIT);
}

/* we must not hold the lock when entering spu_handle_mm_fault */
spu_release(ctx);
Expand Down Expand Up @@ -226,7 +224,7 @@ int spufs_handle_class1(struct spu_context *ctx)
} else
spufs_handle_dma_error(ctx, ea, SPE_EVENT_SPE_DATA_STORAGE);

spuctx_switch_state(ctx, SPUCTX_UTIL_SYSTEM);
spuctx_switch_state(ctx, SPU_UTIL_SYSTEM);
return ret;
}
EXPORT_SYMBOL_GPL(spufs_handle_class1);
32 changes: 22 additions & 10 deletions trunk/arch/powerpc/platforms/cell/spufs/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -2079,14 +2079,26 @@ static const char *ctx_state_names[] = {
};

static unsigned long long spufs_acct_time(struct spu_context *ctx,
enum spuctx_execution_state state)
enum spu_utilization_state state)
{
unsigned long time = ctx->stats.times[state];
struct timespec ts;
unsigned long long time = ctx->stats.times[state];

if (ctx->stats.execution_state == state)
time += jiffies - ctx->stats.tstamp;
/*
* In general, utilization statistics are updated by the controlling
* thread as the spu context moves through various well defined
* state transitions, but if the context is lazily loaded its
* utilization statistics are not updated as the controlling thread
* is not tightly coupled with the execution of the spu context. We
* calculate and apply the time delta from the last recorded state
* of the spu context.
*/
if (ctx->spu && ctx->stats.util_state == state) {
ktime_get_ts(&ts);
time += timespec_to_ns(&ts) - ctx->stats.tstamp;
}

return jiffies_to_msecs(time);
return time / NSEC_PER_MSEC;
}

static unsigned long long spufs_slb_flts(struct spu_context *ctx)
Expand Down Expand Up @@ -2121,11 +2133,11 @@ static int spufs_show_stat(struct seq_file *s, void *private)
spu_acquire(ctx);
seq_printf(s, "%s %llu %llu %llu %llu "
"%llu %llu %llu %llu %llu %llu %llu %llu\n",
ctx_state_names[ctx->stats.execution_state],
spufs_acct_time(ctx, SPUCTX_UTIL_USER),
spufs_acct_time(ctx, SPUCTX_UTIL_SYSTEM),
spufs_acct_time(ctx, SPUCTX_UTIL_IOWAIT),
spufs_acct_time(ctx, SPUCTX_UTIL_LOADED),
ctx_state_names[ctx->stats.util_state],
spufs_acct_time(ctx, SPU_UTIL_USER),
spufs_acct_time(ctx, SPU_UTIL_SYSTEM),
spufs_acct_time(ctx, SPU_UTIL_IOWAIT),
spufs_acct_time(ctx, SPU_UTIL_IDLE_LOADED),
ctx->stats.vol_ctx_switch,
ctx->stats.invol_ctx_switch,
spufs_slb_flts(ctx),
Expand Down
10 changes: 10 additions & 0 deletions trunk/arch/powerpc/platforms/cell/spufs/run.c
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,8 @@ static int spu_setup_isolated(struct spu_context *ctx)

static int spu_run_init(struct spu_context *ctx, u32 * npc)
{
spuctx_switch_state(ctx, SPU_UTIL_SYSTEM);

if (ctx->flags & SPU_CREATE_ISOLATE) {
unsigned long runcntl;

Expand All @@ -151,6 +153,8 @@ static int spu_run_init(struct spu_context *ctx, u32 * npc)
ctx->ops->runcntl_write(ctx, SPU_RUNCNTL_RUNNABLE);
}

spuctx_switch_state(ctx, SPU_UTIL_USER);

return 0;
}

Expand All @@ -161,6 +165,8 @@ static int spu_run_fini(struct spu_context *ctx, u32 * npc,

*status = ctx->ops->status_read(ctx);
*npc = ctx->ops->npc_read(ctx);

spuctx_switch_state(ctx, SPU_UTIL_IDLE_LOADED);
spu_release(ctx);

if (signal_pending(current))
Expand Down Expand Up @@ -328,6 +334,9 @@ long spufs_run_spu(struct file *file, struct spu_context *ctx,
ret = spufs_wait(ctx->stop_wq, spu_stopped(ctx, &status));
if (unlikely(ret))
break;

spuctx_switch_state(ctx, SPU_UTIL_SYSTEM);

if ((status & SPU_STATUS_STOPPED_BY_STOP) &&
(status >> SPU_STOP_STATUS_SHIFT == 0x2104)) {
ret = spu_process_callback(ctx);
Expand Down Expand Up @@ -356,6 +365,7 @@ long spufs_run_spu(struct file *file, struct spu_context *ctx,
(ctx->state == SPU_STATE_RUNNABLE))
ctx->stats.libassist++;


ctx->ops->master_stop(ctx);
ret = spu_run_fini(ctx, npc, &status);
spu_yield(ctx);
Expand Down
22 changes: 9 additions & 13 deletions trunk/arch/powerpc/platforms/cell/spufs/sched.c
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,7 @@ static void spu_bind_context(struct spu *spu, struct spu_context *ctx)
{
pr_debug("%s: pid=%d SPU=%d NODE=%d\n", __FUNCTION__, current->pid,
spu->number, spu->node);
spuctx_switch_state(ctx, SPU_UTIL_SYSTEM);

ctx->stats.slb_flt_base = spu->stats.slb_flt;
ctx->stats.class2_intr_base = spu->stats.class2_intr;
Expand All @@ -251,7 +252,8 @@ static void spu_bind_context(struct spu *spu, struct spu_context *ctx)
spu_cpu_affinity_set(spu, raw_smp_processor_id());
spu_switch_notify(spu, ctx);
ctx->state = SPU_STATE_RUNNABLE;
spu_switch_state(spu, SPU_UTIL_SYSTEM);

spuctx_switch_state(ctx, SPU_UTIL_IDLE_LOADED);
}

/**
Expand All @@ -263,8 +265,7 @@ static void spu_unbind_context(struct spu *spu, struct spu_context *ctx)
{
pr_debug("%s: unbind pid=%d SPU=%d NODE=%d\n", __FUNCTION__,
spu->pid, spu->number, spu->node);

spu_switch_state(spu, SPU_UTIL_IDLE);
spuctx_switch_state(ctx, SPU_UTIL_SYSTEM);

spu_switch_notify(spu, NULL);
spu_unmap_mappings(ctx);
Expand All @@ -279,14 +280,17 @@ static void spu_unbind_context(struct spu *spu, struct spu_context *ctx)
spu_associate_mm(spu, NULL);
spu->pid = 0;
ctx->ops = &spu_backing_ops;
ctx->spu = NULL;
spu->flags = 0;
spu->ctx = NULL;

ctx->stats.slb_flt +=
(spu->stats.slb_flt - ctx->stats.slb_flt_base);
ctx->stats.class2_intr +=
(spu->stats.class2_intr - ctx->stats.class2_intr_base);

/* This maps the underlying spu state to idle */
spuctx_switch_state(ctx, SPU_UTIL_IDLE_LOADED);
ctx->spu = NULL;
}

/**
Expand Down Expand Up @@ -455,8 +459,6 @@ static struct spu *find_victim(struct spu_context *ctx)
*/
int spu_activate(struct spu_context *ctx, unsigned long flags)
{
spuctx_switch_state(ctx, SPUCTX_UTIL_SYSTEM);

do {
struct spu *spu;

Expand Down Expand Up @@ -551,7 +553,6 @@ static int __spu_deactivate(struct spu_context *ctx, int force, int max_prio)
void spu_deactivate(struct spu_context *ctx)
{
__spu_deactivate(ctx, 1, MAX_PRIO);
spuctx_switch_state(ctx, SPUCTX_UTIL_USER);
}

/**
Expand All @@ -566,12 +567,7 @@ void spu_yield(struct spu_context *ctx)
{
if (!(ctx->flags & SPU_CREATE_NOSCHED)) {
mutex_lock(&ctx->state_mutex);
if (__spu_deactivate(ctx, 0, MAX_PRIO))
spuctx_switch_state(ctx, SPUCTX_UTIL_USER);
else {
spuctx_switch_state(ctx, SPUCTX_UTIL_LOADED);
spu_switch_state(ctx->spu, SPU_UTIL_USER);
}
__spu_deactivate(ctx, 0, MAX_PRIO);
mutex_unlock(&ctx->state_mutex);
}
}
Expand Down
63 changes: 27 additions & 36 deletions trunk/arch/powerpc/platforms/cell/spufs/spufs.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,19 +40,6 @@ enum {
struct spu_context_ops;
struct spu_gang;

/*
* This is the state for spu utilization reporting to userspace.
* Because this state is visible to userspace it must never change and needs
* to be kept strictly separate from any internal state kept by the kernel.
*/
enum spuctx_execution_state {
SPUCTX_UTIL_USER = 0,
SPUCTX_UTIL_SYSTEM,
SPUCTX_UTIL_IOWAIT,
SPUCTX_UTIL_LOADED,
SPUCTX_UTIL_MAX
};

struct spu_context {
struct spu *spu; /* pointer to a physical SPU */
struct spu_state csa; /* SPU context save area. */
Expand Down Expand Up @@ -104,9 +91,9 @@ struct spu_context {
/* statistics */
struct {
/* updates protected by ctx->state_mutex */
enum spuctx_execution_state execution_state;
unsigned long tstamp; /* time of last ctx switch */
unsigned long times[SPUCTX_UTIL_MAX];
enum spu_utilization_state util_state;
unsigned long long tstamp; /* time of last state switch */
unsigned long long times[SPU_UTIL_MAX];
unsigned long long vol_ctx_switch;
unsigned long long invol_ctx_switch;
unsigned long long min_flt;
Expand Down Expand Up @@ -293,30 +280,34 @@ extern int spufs_coredump_num_notes;
* line.
*/
static inline void spuctx_switch_state(struct spu_context *ctx,
enum spuctx_execution_state new_state)
enum spu_utilization_state new_state)
{
WARN_ON(!mutex_is_locked(&ctx->state_mutex));
unsigned long long curtime;
signed long long delta;
struct timespec ts;
struct spu *spu;
enum spu_utilization_state old_state;

if (ctx->stats.execution_state != new_state) {
unsigned long curtime = jiffies;
ktime_get_ts(&ts);
curtime = timespec_to_ns(&ts);
delta = curtime - ctx->stats.tstamp;

ctx->stats.times[ctx->stats.execution_state] +=
curtime - ctx->stats.tstamp;
ctx->stats.tstamp = curtime;
ctx->stats.execution_state = new_state;
}
}

static inline void spu_switch_state(struct spu *spu,
enum spuctx_execution_state new_state)
{
if (spu->stats.utilization_state != new_state) {
unsigned long curtime = jiffies;

spu->stats.times[spu->stats.utilization_state] +=
curtime - spu->stats.tstamp;
WARN_ON(!mutex_is_locked(&ctx->state_mutex));
WARN_ON(delta < 0);

spu = ctx->spu;
old_state = ctx->stats.util_state;
ctx->stats.util_state = new_state;
ctx->stats.tstamp = curtime;

/*
* Update the physical SPU utilization statistics.
*/
if (spu) {
ctx->stats.times[old_state] += delta;
spu->stats.times[old_state] += delta;
spu->stats.util_state = new_state;
spu->stats.tstamp = curtime;
spu->stats.utilization_state = new_state;
}
}

Expand Down
10 changes: 5 additions & 5 deletions trunk/include/asm-powerpc/spu.h
Original file line number Diff line number Diff line change
Expand Up @@ -107,10 +107,10 @@ struct spu_runqueue;
struct device_node;

enum spu_utilization_state {
SPU_UTIL_SYSTEM,
SPU_UTIL_USER,
SPU_UTIL_SYSTEM,
SPU_UTIL_IOWAIT,
SPU_UTIL_IDLE,
SPU_UTIL_IDLE_LOADED,
SPU_UTIL_MAX
};

Expand Down Expand Up @@ -167,9 +167,9 @@ struct spu {

struct {
/* protected by interrupt reentrancy */
enum spu_utilization_state utilization_state;
unsigned long tstamp; /* time of last ctx switch */
unsigned long times[SPU_UTIL_MAX];
enum spu_utilization_state util_state;
unsigned long long tstamp;
unsigned long long times[SPU_UTIL_MAX];
unsigned long long vol_ctx_switch;
unsigned long long invol_ctx_switch;
unsigned long long min_flt;
Expand Down

0 comments on commit 5e60de9

Please sign in to comment.