www.delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp/1995/06/03/21:18:20

Xref: news-dnh.mv.net comp.os.msdos.djgpp:110
Path: news-dnh.mv.net!mv!news.sprintlink.net!gatech!howland.reston.ans.net!pipex!sunic!sunic.sunet.se!news.uni-c.dk!diku.dk!terra
From: terra AT diku DOT dk (Morten Welinder)
Newsgroups: comp.os.msdos.djgpp
Subject: Re: fork()/join()
Date: 3 Jun 1995 21:57:56 GMT
Organization: Department of Computer Science, U of Copenhagen
Lines: 288
Sender: terra AT tyr DOT diku DOT dk
References: <3qhk5s$tvn AT news DOT telebyte DOT com> <D9H1Mq DOT 7HG AT cunews DOT carleton DOT ca> <3qlh05$kcn AT odin DOT diku DOT dk> <3qm587$68t AT news DOT telebyte DOT com>
Nntp-Posting-Host: odin.diku.dk
To: djgpp AT sun DOT soe DOT clarkson DOT edu
Dj-Gateway: from newsgroup comp.os.msdos.djgpp

jhunter AT kendaco DOT telebyte DOT com (Joel Hunter) writes:

>  Wow.  The first actual down-right rude reply I have ever seen on the
>DJGPP mailing-list/newsgroup.  Since when is ignorance and/or
>incompetence met with this level of hostility?

Hmm.  I do that occasionally when somebody gets the idea that they
are in a position to start demanding that things get done, and get
done now.

When it coincides with people whom I have never seen contribute I
get mad.  I assume that (e.g.) DJ also gets mad, but he's much
more polite.  Since he's low on sleep try pressing the issue.

Relatedly, I get weekly requests for this or that with Emacs (and
that includes M-x shell which really comes down to fork).  I rarely
get any help.

Enough whinging from me.

Morten




From: Morten Welinder <terra AT diku DOT dk>
Date: Tue, 14 Mar 1995 02:08:47 +0100
To: djgpp-v2 AT delorie DOT mv DOT com
Subject: Multitasking again



/* -*- C -*- */

Ok, this is a not-so-sketchy version of a multitasking library for V2.
Please comment.

Morten



March 13, 1995:		Initial version



The architecture is that when a program calls something that needs
multitasking a special process, "init", will be loaded.  The C library
will only contain code for loading this and for transmitting parameters
to it.

The "init" procedure hooks enough interrupts to make it able to do
context switching.  It unloads itself when all clients have exited.

Communications between processes has not been spelled out yet, but
it cannot be that hard.






============================================================================
                              COMMON DEFINES
============================================================================

/* Since compiled binaries will depend on "init" sharing these, we may not
   change the numbers used here.  Therefore we have large friendly holes
   at the section breaks.  */

#define SYSCALL_IDENTIFY_INITLOADER		0
#define SYSCALL_UNLOAD				1

#define SYSCALL_FORK				1000
#define SYSCALL_KILL				1001



============================================================================
                   LIB C STUFF -- ONE COPY PER PROCESS
============================================================================



/* ---------------------------------------------------------------------- */
/* Init process loader section.  */

#define SYSCALL(PARMS) \
  <push PARMS>; call far syscall_function_sel:syscall_function_addr


static int process_manager_loaded;  /* = 0 by default */

static int
load_process_manager (void)
{
  if (process_manager_loaded)
    return 0;
  
  /* Try to load and execute "init" returning here _without_
     termination of that process.  */

  if (loading suceeded)
    {
      syscall_function_sel = magic_sel;
      syscall_function_addr = magic_addr;
      process_manager_loaded = 1;

      /* Is this needed?  */
      SYSCALL (SYSCALL_IDENTIFY_INITLOADER);
      return 0;
    }
  else
    {
      errno = foo;
      return -1;
    }
}


/* Except for memory use this is a no-op.  */
int
__manually_unload_init_process (void)
{
  if (process_manager_loaded)
    {
      process_manager_loaded = SYSCALL (SYSCALL_UNLOAD);
      return process_manager_loaded ? -1 : 0;
    }
  else
    return 0;
}
/* ---------------------------------------------------------------------- */
/* Selected libc functions follow.  */

int
kill (pid_t process, int signal)
{
  if (process_manager_loaded)
    return SYSCALL (SYSCALL_KILL, process, signal);
  else
    /* Do stub thing. */
}



pid_t
fork (void)
{
  return load_process_manager () ? : SYSCALL (SYSCALL_FORK);
}
/* ---------------------------------------------------------------------- */






============================================================================
                    "INIT" PROCESS -- JUST ONE COPY
============================================================================

int
main (int argc, char **argv)
{
  if (!called_from_libc)
    {
      /* Complain fiercly.  */
      exit (1);
    }
  
  initialize ();

  /* Arrange to return our CS and &syscall somehow.  */
  /* Magically jump back to caller.  */

  /* NOT REACHED.  */
  abort ();
}

void
initialize (void)
{
  /* Set up process table.  */
  /* Hook vectors.  */
}

int
syscall (int bogus_stack_frame_fixer, int action, ...)
{
  switch (action)
    {
    case SYSCALL_KILL:
      if (switch_context ("process"))
	{
	  /* Killed process: */
	  /* Send process the signal.  */
	  restart_process ();
	  /* NOT REACHED.  */
	}
      /* Killing process: */
      return 0;
    case SYSCALL_FORK:
      newproc = createproc ();
      /* Given the fact that the LDT is shared under DPMI 0.9 this is not
	 completely possible, but perhaps we can fake it well enough.  */
      copyproc (newproc, currentproc);
      return newproc;
    default:
      /* Complain fiercely.  */
      kill (currentproc);
      /* NOT REACHED.  */
    }
}

interrupt_handler
p21 (whatever)
{
  if (terminating process)
    {
      /* Clients must terminate in reverse creation order.  */

      /* Mark current process as exiting.  */
      while (currentproc != lastproc)
	start_next_process ();
      if (currentproc == very_first_process)
	{
	  /* Terminate "init" and initial client.  */
	}
      else
	/* Go ahead and make DPMI host terminate us.  */
    }
  if (suitable condition)
    start_next_process ();
  /* Do the intended 21h function call.  */
}


pid_t
create_proc (void)
{
  /* Make entry in process tables.  */

  /* Move a stub to real mode that creates a new DPMI client then jumps
     back here somehow with 0 as result .  When client finally exits (far
     in the future), jump back to here with 1 as result.  Jump to that
     stub.  */
  if (result)
    start_next_process ();
  else
    return newproc;
}


int
switch_context (pid_t newproc)
{
  /* Save current process' status in such a way that it will return from
     this function immediately with result 0.  */

  currentproc = newproc;
  /* Load relevant stuff from process table.  */
  return 1;
}


void
start_next_process ()
{
  pid_t newproc;

  newproc = choose_next_process ();
  if (switch_context (newproc))
    restart_process ();
}


pid_t
choose_next_process (void)
{
  if (lastproc is exiting)
    return lastproc;

  if (livecount == 1 && currentproc live)
    return currentproc;

  return next_live_process;
}

- Raw text -


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