From: tuukka DOT kalliokoski AT nokia DOT com (Tuukka Kalliokoski) Newsgroups: comp.os.msdos.djgpp Subject: Re: Problems with LWP 2.0 / djgpp 2.03 Organization: Nokia PMR Message-ID: <3a3f45ea.1909129843@news.europe.nokia.com> References: X-Newsreader: Forte Free Agent 1.21/32.243 Lines: 217 Date: Tue, 19 Dec 2000 11:56:41 GMT NNTP-Posting-Host: 172.22.117.117 X-Complaints-To: newsmaster AT nokia DOT com X-Trace: news2.nokia.com 977227001 172.22.117.117 (Tue, 19 Dec 2000 13:56:41 EET) NNTP-Posting-Date: Tue, 19 Dec 2000 13:56:41 EET To: djgpp AT delorie DOT com DJ-Gateway: from newsgroup comp.os.msdos.djgpp Reply-To: djgpp AT delorie DOT com On Tue, 19 Dec 2000 13:19:41 +0200 (IST), Eli Zaretskii wrote: >First, please post a SYMIFY'ed traceback, both from Windows and from >plain DOS. If the traceback points into code that isn't included in >what you posted, please show that code as well. OK, I will do that when I get to my own PC... but I think I should first try to figure out exactly how this code is supposed to work myself, before bothering newsgroup readers with possibly small problem. I was hoping to find 'plug and play' threading package to get quickly started in porting my 16-bit application that uses CTASK multitasking library and MSC 6.0 to 32 bit world. Clearly LWP is more 'plug and pray'... >This doesn't show where the control is returned to user code (I assume >that the SIGILL handler acts as a scheduler, so it must jump to >application's code at some point). It is important to see where it >does so. >I also don't see any code which saves the registers of the interrupted >thread and restores the registers of the thread about to be run. >Where is it? Sorry, it is here: (SIGILL handler makes a 'jmpl _lwpYield') .align 4 _lwpYield: pushl %ds .byte 0x2e movw ___djgpp_ds_alias, %ds movl $1, lwpInterruptPending popl %ds pushal pushl %ds pushl %es pushl %fs pushl %gs pushfl subl $108, %esp fwait fnsave (%esp) /* FPU pushal ;) */ fwait .byte 0x2e movw ___djgpp_ds_alias, %ds movl __lwpCur, %esi movl %esp, 12(%esi) yl1: movl 4(%esi), %esi /* Find next ACTIVE thread */ cmpl $0, 24(%esi) je yl1 movl 12(%esi), %esp movl %esi, __lwpCur fwait frstor (%esp) /* FPU popal ;) */ fwait addl $108, %esp popfl popl %gs popl %fs popl %es popl %ds popal pushl %ds .byte 0x2e movw ___djgpp_ds_alias, %ds movl $0, lwpInterruptPending popl %ds ret >This doesn't show the code which locks the interrupt handler's code >and data. Is it there, anywhere? If so, let's see it. Here: (_lwpasmStart and _lwpasmEnd are labels at start and at the end of interrupt handler code) static int _lwpLockMemory() { if(!_lwpLockCode(&_lwpasmStart, (long) &_lwpasmEnd - (long) _lwpasmStart)) { return(FALSE); } if(!_lwpLockData((void *) &_lwpEnable, 4)) { return(FALSE); } return(TRUE); } static int _lwpLockData( void *lockaddr, unsigned long locksize ) { unsigned long baseaddr; __dpmi_meminfo memregion; if( __dpmi_get_segment_base_address( _my_ds(), &baseaddr) == -1 ) { return(FALSE); } memset( &memregion, 0, sizeof(memregion) ); memregion.address = baseaddr + (unsigned long) lockaddr; memregion.size = locksize; if( __dpmi_lock_linear_region( &memregion ) == -1 ) { return(FALSE); } return(TRUE); } static int _lwpLockCode( void *lockaddr, unsigned long locksize ) { unsigned long baseaddr; __dpmi_meminfo memregion; if( __dpmi_get_segment_base_address( _my_cs(), &baseaddr) == -1 ) { return(FALSE); } memset( &memregion, 0, sizeof(memregion) ); memregion.address = baseaddr + (unsigned long) lockaddr; memregion.size = locksize; if( __dpmi_lock_linear_region( &memregion ) == -1 ) { return(FALSE); } return(TRUE); } >I see that LWP also has something to say about the FPU exceptions. >Does the example which crashes actually use FP code? If so, it's >possible that the SIGFPE handler is also involved in this; you didn't >show it. There is no FP involved, yet. >> I suspect that the registers are pushed to stack on incorrect order, > >What registers? I don't see any registers being pushed in the code >you posted. They are pushed and popped in lwpYield routine I accidentally left out in my previous post. >If you become desperate and want to make sure old DJGPP versions >indeed work with LWP, you can always install an old djdevNNN.zip and >try compiling and linking with it. Personally, I don't think this has >anything to do with DJGPP versions, unless some code you omitted will >demonstrate otherwise. That is one possibility, thanks. But I also begin to think the problem is within my copy of LWP. Either the initial task stack created is incorrect or then the task switching code is bad. Here is the task creation fragment where initial stack frame then yielded is created - sorry for long post. Probably some important stuff is again left out but I dont want to post all of LWP in this newsgroup since jtlwp20s.zip can be found in ftp.simtel.net/pub/simtelnet/gnu/djgpp/v2tk tmpLwpPtr->stack[(stackLength/4) - 1] = (long) param; tmpLwpPtr->stack[(stackLength/4) - 2] = (long) _lwpDeadYield; tmpLwpPtr->stack[(stackLength/4) - 3] = (long) proc; tmpLwpPtr->stack[(stackLength/4) - 4] = 0; /* eax */ tmpLwpPtr->stack[(stackLength/4) - 5] = 0; /* ebx */ tmpLwpPtr->stack[(stackLength/4) - 6] = 0; /* ecx */ tmpLwpPtr->stack[(stackLength/4) - 7] = 0; /* edx */ tmpLwpPtr->stack[(stackLength/4) - 8] = 0; /* ebp */ tmpLwpPtr->stack[(stackLength/4) - 9] = 0; /* esp, discarded by popal */ tmpLwpPtr->stack[(stackLength/4) -10 ] = 0; /* esi */ tmpLwpPtr->stack[(stackLength/4) -11] = 0; /* edi */ tmpLwpPtr->stack[(stackLength/4) -12] = (long) _my_ds(); /* ds */ tmpLwpPtr->stack[(stackLength/4) -13] = (long) _my_ds(); /* es */ tmpLwpPtr->stack[(stackLength/4) -14] = (long) _my_ds(); /* fs */ tmpLwpPtr->stack[(stackLength/4) -15] = (long) _my_ds(); /* gs */ tmpLwpPtr->stack[(stackLength/4) -16] = (long) _lwpFlags; /* flags */ /* copy initial FPU state to stack */ memcpy(tmpLwpPtr->stack + (stackLength/4) - 43, _lwpFpuState, 108); tmpLwpPtr->stack = tmpLwpPtr->stack + (stackLength/4) - 43; tmpLwpPtr->priority = priority; tmpLwpPtr->pcount = priority; tmpLwpPtr->active = active; tmpLwpPtr->lwpid = ++_lwpPidCount; tmpLwpPtr->next = _lwpCur->next; _lwpCur->next = tmpLwpPtr; _lwpCount++; _lwpEnable = tmpCriticalSection; return(tmpLwpPtr->lwpid); >Does the LWP docs say exactly on what platform(s) the DJGPP version was >tested to work? Unfortunately no, the only clue is in file dates 12/1997. thanks for help Tuukka