Thursday, September 07, 2006

FW: system call - cont 2


/* __ipipe_dispatch_event() -- Low-level event dispatcher. */

int fastcall __ipipe_dispatch_event (unsigned event, void *data)
{
struct ipipe_domain *start_domain, *this_domain, *next_domain;
struct list_head *pos, *npos;
unsigned long flags;
ipipe_declare_cpuid;
int propagate = 1;

ipipe_lock_cpu(flags);

start_domain = this_domain = ipipe_percpu_domain[cpuid];

list_for_each_safe(pos,npos,&__ipipe_pipeline) {

next_domain = list_entry(pos,struct
ipipe_domain,p_link);

/*
* Note: Domain migration may occur while running
* event or interrupt handlers, in which case the
* current register set is going to be recycled for a
* different domain than the initiating one. We do
* care for that, always tracking the current domain
* descriptor upon return from those handlers.
*/
if (next_domain->evhand[event] != NULL) {
ipipe_percpu_domain[cpuid] = next_domain;
ipipe_unlock_cpu(flags);
propagate =
!next_domain->evhand[event](event,start_domain,data);
ipipe_lock_cpu(flags);
if (ipipe_percpu_domain[cpuid] != next_domain)
this_domain =
ipipe_percpu_domain[cpuid];
}

if (next_domain != ipipe_root_domain && /* NEVER sync
the root stage here. */
next_domain->cpudata[cpuid].irq_pending_hi != 0 &&

!test_bit(IPIPE_STALL_FLAG,&next_domain->cpudata[cpuid].status)) {
ipipe_percpu_domain[cpuid] = next_domain;
__ipipe_sync_pipeline(IPIPE_IRQMASK_ANY);
ipipe_load_cpuid();
if (ipipe_percpu_domain[cpuid] != next_domain)
this_domain =
ipipe_percpu_domain[cpuid];
}

ipipe_percpu_domain[cpuid] = this_domain;

if (next_domain == this_domain || !propagate)
break;
}

ipipe_unlock_cpu(flags);

return !propagate;
}

Ksrc/nucleus/shadow.c

static inline int do_losyscall_event (unsigned event, unsigned domid,
void *data) ---------- For ipipe_root_domain()

static inline int do_hisyscall_event (unsigned event, unsigned domid,
void *data) ---------- For Xenomai domain()

ipipe_walk_pipeline


/* __ipipe_walk_pipeline(): Plays interrupts pending in the log. Must
be called with local hw interrupts disabled. */

void fastcall __ipipe_walk_pipeline(struct list_head *pos, int cpuid)
{
struct ipipe_domain *this_domain = ipipe_percpu_domain[cpuid];

while (pos != &__ipipe_pipeline) {
struct ipipe_domain *next_domain =
list_entry(pos, struct ipipe_domain, p_link);

if (test_bit
(IPIPE_STALL_FLAG,
&next_domain->cpudata[cpuid].status))
break; /* Stalled stage -- do not go further.
*/

if (next_domain->cpudata[cpuid].irq_pending_hi != 0) {

if (next_domain == this_domain)

__ipipe_sync_pipeline(IPIPE_IRQMASK_ANY);
else {
__ipipe_switch_to(this_domain,
next_domain,
cpuid);

ipipe_load_cpuid(); /* Processor
might have changed. */

if (this_domain->cpudata[cpuid].
irq_pending_hi != 0
&& !test_bit(IPIPE_STALL_FLAG,

&this_domain->cpudata[cpuid].status))

__ipipe_sync_pipeline(IPIPE_IRQMASK_ANY);
}

break;
} else if (next_domain == this_domain)
break;

pos = next_domain->p_link.next;
}
}

/* Called with hw interrupts off. */
static inline void __ipipe_switch_to(struct ipipe_domain *out,
struct ipipe_domain *in, int cpuid)
{
void ipipe_suspend_domain(void);

/-----------------------------------------------------------------------
-

Strange statement here - but "ipipe_suspend_domain()" will not be called
------------------------------------------------------------------------
/

/*
* "in" is guaranteed to be closer than "out" from the head of
the
* pipeline (and obviously different).
*/

ipipe_percpu_domain[cpuid] = in;

ipipe_suspend_domain(); /* Sync stage and propagate interrupts.
*/
ipipe_load_cpuid(); /* Processor might have changed. */

if (ipipe_percpu_domain[cpuid] == in)
/*
* Otherwise, something has changed the current domain
under
* our feet recycling the register set; do not override.
*/
ipipe_percpu_domain[cpuid] = out;
}

Blog Archive