GCC and SMP problems
Posted: Fri Nov 20, 2009 2:12 pm
I just finished my interrupt for service things in a smp system (like invaliding pages and so on). So I got a few problems with it and with gcc (4.4.2 on cygwin).
You may have a look at my spinlock functions, because I think that maybe from there could come some of my problems:
A problem is what gcc makes out of this code:
The 2 lines where I wait for "freeList" becoming non null, gcc makes an endless loop out of it But why?
The next problem seems to be a little funny:
If the code is like above it is working, but if I comment out the "printf("ok");", it isn´t working anymore??? I tested this on my real pc, bochs and qemu. I have no idea why should it working with the printf and why shouldn´t it working without it. I mean the same behavior on emulator and real system suggests a coding failure, but I can´t see one.
So if anyone has an idea what I could/should test to find this annoying bug, I would appreciate it !!!
You may have a look at my spinlock functions, because I think that maybe from there could come some of my problems:
Code: Select all
struct spinlock_t {
uint32t volatile lock;
uint32t flags;
};
static inline void spinAcquire(struct spinlock_t *spinlock) {
asm volatile("movl $0x1,%%edx\n\t"
"1:\t testl $0x1,(%%eax)\n\t"
"jne 1b\n\t"
"xchg (%%eax),%%edx\n\t"
"testl $0x1,%%edx\n\t"
"jne 1b\n\t"
"pushfl\n\t"
"popl %[output]\n\t"
"cli"
:[output] "=q"(spinlock->flags)
:"a"(spinlock)
:"%edx");
}
static inline void spinRelease(struct spinlock_t *spinlock) {
//look if ints were enabled or disabled
if(likely((spinlock->flags & 0x200) != 0)) {
spinlock->lock= 0;
asm volatile("sti");
} else {
spinlock->lock= 0;
}
}
Code: Select all
static struct smpMsg_t *freeList;
static struct spinlock_t freeLock;
struct smpMsg_t *smpAllocMsg() {
struct smpMsg_t *msg;
do {
spinAcquire(&freeLock);
if(likely(freeList)) {
msg= freeList;
freeList= msg->next;
spinRelease(&freeLock);
return msg;
}
spinRelease(&freeLock);
while(likely(freeList == 0))
asm volatile("pause");
} while(1);
}
The next problem seems to be a little funny:
Code: Select all
void smpSendMsgBroadcast(uint32t code, uint32t data1, uint32t data2, uint32t data3) {
if(likely(msgsAllowed)) {
struct smpMsg_t *msg= smpAllocMsg();
struct APIC_Regs_t *apic= (struct APIC_Regs_t *)APIC_ADDR_VIRT;
msg->refCount= numCpus - 1;
msg->code= code;
msg->data1= data1;
msg->data2= data2;
msg->data3= data3;
spinAcquire(&msgLock);
serviceMsg= msg;
while(unlikely(apic->icr1[0] & APIC_DELIVERY_STS))
asm volatile("pause");
apic->icr2[0]= 0;
apic->icr1[0]= APIC_SERVICE_INT | APIC_DEL_MODE_FIXED | APIC_DEST_SHORT_ALL_EXC_SELF;
// printf("msg send...");
while(unlikely(apic->icr1[0] & APIC_DELIVERY_STS))
asm volatile("pause");
// printf("waiting...");
while(likely(msg->refCount > 0))
asm volatile("pause");
printf("ok\n");
serviceMsg= 0;
spinRelease(&msgLock);
smpFreeMsg(msg);
}
}
So if anyone has an idea what I could/should test to find this annoying bug, I would appreciate it !!!