delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp/2000/12/19/07:54:53

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: <Pine DOT SUN DOT 3 DOT 91 DOT 1001219131910 DOT 365E-100000 AT is>
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
<eliz AT is DOT elta DOT co DOT il> 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

- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019