On 29.6.2012 5:23, Adam Hraska wrote:
> 1) APIC: waiting for completion
> -------------------------------
> APIC has a bit that indicates if an IPI is in progress.
> Should we not wait for the dispatch of the previous IPI
> to complete before we send another one? Note that I don't
> know if l_apic[ICRlo].delivs is CPU local (so a simple
> while(l_apic[ICRlo].delivs == DELIVS_PENDING){} would
> suffice) or global for the system (then we'd need a lock).
> IPIs are sent via l_apic_broadcast_custom_ipi in
> arch/ia32/src/smp/apic.c:
> 
> int l_apic_broadcast_custom_ipi(uint8_t vector)
> {
>       icr_t icr;
>       
>       // Wait here for icr.delivs != DELIVS_PENDING ?
>       
>       icr.lo = l_apic[ICRlo];
>       icr.delmod = DELMOD_FIXED;
>       icr.destmod = DESTMOD_LOGIC;
>       icr.level = LEVEL_ASSERT;
>       icr.shorthand = SHORTHAND_ALL_EXCL;
>       icr.trigger_mode = TRIGMOD_LEVEL;
>       icr.vector = vector;
>       
>       l_apic[ICRlo] = icr.lo;
>       
>       icr.lo = l_apic[ICRlo];
>       if (icr.delivs == DELIVS_PENDING) {
> #ifdef CONFIG_DEBUG
>               printf("IPI is pending.\n");
> #endif
>       }
>       
>       return apic_poll_errors();
> }

Hm, I remember seeing "IPI is pending" messages when running HelenOS on
my laptop, which suggests this is a real issue :-) Looks like a good
idea to wait for some time. Does waiting indefinitely here look like a
good idea?

> 2) sparc64/sun4U: while-loop cond
> ---------------------------------
> arch/sparc64/src/smp/sun4u/ipi.c sends IPIs via cross_call().
> It has a suspicious while loop end condition. I don't
> know enough to decide if it is a bug or not.
> 
> static void cross_call(int mid, void (* func)(void))
> {
>       uint64_t status;
>       bool done;
> 
>       /* snip */
>       
>       do {
>               // snip
>               if (!done) {
>                       /*
>                        * Prevent deadlock.
>                        */                     
>                       (void) interrupts_enable();
>                       delay(20 + (tick_read() & 0xff));
>                       (void) interrupts_disable();
>               }
> 
>       } while (done); // <-- instead of "while (!done)" ?!
>       
>       preemption_enable();
> }

Indeed, this looks wrong. The idea should be to loop until the other CPU
acknowledges the IPI. I wonder this has gone unnoticed for so long. I
will reverse the condition and test on the Ultra 60.

> 3) sparc64/sun4v: cpu->arch.id vs cpu->id
> -----------------------------------------
> In arch/sparc64/src/smp/sun4v/ipi.c, ipi_broadcast_arch()
> seems to be mixing cpu->arch.id with cpu->id as if they
> were the same (even if they are guaranteed to match, it
> is just not obvious from the code):
> 
> void ipi_broadcast_arch(int ipi)
> {
>       void (* func)(void);
>       /* snip */
>       unsigned int i;
>       unsigned idx = 0;
>       for (i = 0; i < config.cpu_active; i++) {
>               if (&cpus[i] == CPU) {
>                       continue;
>               }
> 
>               // Was this supposed to be CPU->arch.id and
>               // cpus[i].arch.id ??
>               ipi_cpu_list[CPU->id][idx] = (uint16_t) cpus[i].id;
>               idx++;
>       }
> 
>       ipi_brodcast_to(func, ipi_cpu_list[CPU->arch.id], idx);
> }

Yeah, looks like it should be either cpu->id or cpu->arch.id, but not
both at the same time. We may want to consult this with Pavel.
Unfortunately, sun4v support is currently broken.

> Thanks to anyone with the proper knowledge for checking
> these inconsistencies.

Thanks for pointing them out. These things are kind of hard-to-spot if
you are not looking into the code trying to fix some particular problem.
So with every additional code review, the quality of code increases.
Again, I am quite surprised that some of theses bugs did not bite us
already.

Jakub

_______________________________________________
HelenOS-devel mailing list
[email protected]
http://lists.modry.cz/cgi-bin/listinfo/helenos-devel

Reply via email to