home *** CD-ROM | disk | FTP | other *** search
- head 1.6;
- access;
- symbols
- version39-41:1.4;
- locks;
- comment @ * @;
-
-
- 1.6
- date 92.09.14.01.48.11; author mwild; state Exp;
- branches;
- next 1.5;
-
- 1.5
- date 92.08.09.21.01.43; author amiga; state Exp;
- branches;
- next 1.4;
-
- 1.4
- date 92.07.04.19.24.12; author mwild; state Exp;
- branches;
- next 1.3;
-
- 1.3
- date 92.05.18.12.26.25; author mwild; state Exp;
- branches;
- next 1.2;
-
- 1.2
- date 92.05.18.01.02.31; author mwild; state Exp;
- branches;
- next 1.1;
-
- 1.1
- date 92.05.14.19.55.40; author mwild; state Exp;
- branches;
- next ;
-
-
- desc
- @provide vfork(),wait4()
- @
-
-
- 1.6
- log
- @move kmalloc() out of Forbid() (since the allocator is now Semaphore-based).
- move errno assignment after sigsetmask (thanks Niklas!)
- remove dead code
- @
- text
- @/*
- * This file is part of ixemul.library for the Amiga.
- * Copyright (C) 1991, 1992 Markus M. Wild
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * $Id: vfork.c,v 1.5 1992/08/09 21:01:43 amiga Exp $
- *
- * $Log: vfork.c,v $
- * Revision 1.5 1992/08/09 21:01:43 amiga
- * change to 2.x header files
- * duplicate calling stack frame in vfork_resume() instead of just doing rts.
- * temporary abort calling 1.3 vfork, until that's fixed again (when???).
- *
- * Revision 1.4 1992/07/04 19:24:12 mwild
- * get passing of environment right.
- * change ix_sleep() calls to new semantics.
- *
- * Revision 1.3 1992/05/18 12:26:25 mwild
- * fixed bad typo that didn't close files before sending wait message.
- * Set childs Input()/Output() to NIL:, we only keep the files in our
- * own filetable.
- *
- * Revision 1.2 1992/05/18 01:02:31 mwild
- * add temporary Delay(100) before CloseLibrary() in the child after
- * vfork(), there seem to arrive some late packets (don't know why..)
- * pass NIL: filehandles as Input()/Output() to the child, so that the
- * real I/O-handles only depend on ix-filetable for usage-count
- *
- * Revision 1.1 1992/05/14 19:55:40 mwild
- * Initial revision
- *
- */
-
- #define KERNEL
- #include "ixemul.h"
-
- /* #undef DEBUG */
- #ifdef DEBUG
- #define DP(a) kprintf a
- #else
- #define DP(a)
- #endif
-
- #include <sys/syscall.h>
- #include <sys/resource.h>
- #include <sys/wait.h>
- #include <stddef.h>
- #include <setjmp.h>
-
- extern int _dos20;
-
- void volatile vfork_longjmp (jmp_buf, int);
-
- #include <utility/tagitem.h>
- #include <dos/dostags.h>
-
- /* ARP stuff for 1.3 */
- struct ProcessControlBlock {
- u_int pcb_StackSize; /* Stacksize for new process */
- char pcb_Pri; /* Priority of new task */
- u_char pcb_Control; /* Control bits, see defines below */
- void * pcb_TrapCode; /* Optional Trap Code */
- BPTR pcb_Input;
- BPTR pcb_Output; /* Optional stdin, stdout */
- void * pcb_Console; /* really a union */
- void * pcb_LoadedCode; /* If not null, will not load/unload code */
- struct ZombieMsg *pcb_LastGasp; /* ReplyMsg() to be filled in by exit */
- struct MsgPort *pcb_WBProcess; /* Valid only when PRB_NOCLI */
- };
-
- #define PRB_SAVEIO 0L /* Don't free/check file handles on exit */
- #define PRB_CLOSESPLAT 1L /* Close Splat file, must request explicitly */
- #define PRB_NOCLI 2L /* Don't create a CLI process */
- /* PRB_INTERACTIVE 3L This is now obsolete... */
- #define PRB_CODE 4L /* Dangerous yet enticing */
- #define PRB_STDIO 5L /* Do the stdio thing, splat = CON:Filename */
-
- #define PRF_SAVEIO (1L << PRB_SAVEIO)
- #define PRF_CLOSESPLAT (1L << PRB_CLOSESPLAT)
- #define PRF_NOCLI (1L << PRB_NOCLI)
- #define PRF_CODE (1L << PRB_CODE)
- #define PRF_STDIO (1L << PRB_STDIO)
-
- #undef BASE_NAME
- #define BASE_EXT_DECL
- #define BASE_NAME ix.ix_arp_base
- #define BASE_PAR_DECL
- #define BASE_PAR_DECL0
- __inline static LONG ASyncRun(BASE_PAR_DECL const char* name, const char* command, struct ProcessControlBlock* pcb)
- {
- BASE_EXT_DECL
- register LONG res __asm("d0");
- register void *a6 __asm ("a6");
- register const char* a0 __asm("a0");
- register const char* a1 __asm("a1");
- register struct ProcessControlBlock* a2 __asm("a2");
-
- a6 = BASE_NAME;
- a0 = name;
- a1 = command;
- a2 = pcb;
- __asm volatile ("
- jsr a6@@(-0x222)"
- : "=r" (res)
- : "r" (a6), "r" (a0), "r" (a1), "r" (a2)
- : "d0", "d1", "a0", "a1", "a2");
- *(char *)a2=*(char *)a2;
- return res;
- }
-
- __inline static struct Process* FindCLI(BASE_PAR_DECL LONG clinum)
- {
- BASE_EXT_DECL
- register struct Process* res __asm("d0");
- register void *a6 __asm ("a6");
- register LONG d0 __asm("d0");
-
- a6 = BASE_NAME;
- d0 = clinum;
- __asm volatile ("
- jsr a6@@(-0x1a4)"
- : "=r" (res)
- : "r" (a6), "r" (d0)
- : "d0", "d1", "a0", "a1");
- return res;
- }
-
-
- /* having it in a struct makes parameter passing easier */
-
- struct reg_parms {
- jmp_buf jb;
- };
-
- struct vfork_msg {
- struct Message vm_msg;
- struct Process *vm_self; /* for validation purposes (1.3, grrr) */
- struct Process *vm_pptr;
- struct reg_parms *vm_regs; /* parents context to restore */
- int vm_rc; /* 0 if the child started normally, else errno */
- };
-
- struct death_msg {
- struct MinNode dm_node;
- struct Process *dm_child;
- int dm_pgrp;
- int dm_status;
- struct rusage dm_rusage;
- };
-
- /* this is the new process generated by vfork () ! */
- static void
- launcher ()
- {
- void *ixb = OpenLibrary ("ixemul.library", IX_VERSION);
- struct Process *me = (struct Process *) FindTask (0);
- struct vfork_msg *vm;
- int omask;
-
- /* the launcher() generated by Arp's ASyncRun seems to get a weird
- message. Verify that the message at least looks right.. (damn 1.3 support..) */
- vm = 0;
- do
- {
- if (! vm)
- WaitPort (& me->pr_MsgPort);
- vm = (struct vfork_msg *) GetMsg (& me->pr_MsgPort);
- }
- while (vm->vm_self != me);
-
-
- if (ixb)
- {
- /* get parents user area */
- volatile struct user *pu = (struct user *) (vm->vm_pptr->pr_Task.tc_TrapData);
- /* `my' user area. This way we don't have to recalculate it too often */
- volatile struct user *mu = &u;
- /* reaping the dup function of execve() ;-)) */
- extern char **dupvec (char **);
- int fd, rc;
-
- /* link ourselves into the parents process lists. Guarantee single
- * threaded access to those lists by locking out any other users of
- * the library (nicer than to just call Forbid()) */
- ix_lock_base ();
-
- /* our older sybling is the last recently created child of the parent */
- mu->p_osptr = pu->p_cptr;
- /* we have no younger sybling */
- mu->p_ysptr = 0;
- /* if we have an older sybling, point its `younger sybling' field at us */
- if (mu->p_osptr)
- {
- struct user *ou = (struct user *) (mu->p_osptr->pr_Task.tc_TrapData);
- ou->p_ysptr = me;
- }
- /* set the parents `last recently created child' field at us */
- pu->p_cptr = me;
-
- /* inherit the process group of our parent */
- mu->p_pgrp = pu->p_pgrp;
- mu->p_pptr = vm->vm_pptr;
-
- /* inherit these global variables. */
- mu->u_environ = (char ***) malloc (4);
- * mu->u_environ = dupvec (* pu->u_environ);
- mu->u_errno = pu->u_errno;
-
- /* and inherit several other things as well, upto not including u_md */
- bcopy (& pu->u_signal[0], & mu->u_signal[0],
- offsetof (struct user, u_md) - offsetof (struct user, u_signal[0]));
-
- /* some things have been copied that should be reset */
- bzero (& mu->u_ru, sizeof (struct rusage));
- bzero (& mu->u_cru, sizeof (struct rusage));
- bzero (& mu->u_timer[0], sizeof (struct itimerval)); /* just the REAL timer! */
- syscall (SYS_gettimeofday, & mu->u_start, 0);
- omask = vm->vm_rc; /* signal mask to restore at the end */
-
- /* and adjust the open count of each of the copied filedescriptors */
- for (fd = 0; fd < NOFILE; fd++)
- if (mu->u_ofile[fd])
- mu->u_ofile[fd]->f_count++;
-
- /* copying finished, allow other processes to vfork() as well ;-)) */
- ix_unlock_base ();
-
- /* remember the message we have to reply when either _exit() or
- * execve() is called */
- mu->p_vfork_msg = vm;
-
- vm->vm_rc = 0;
-
- mu->u_save_sp = (void *) get_sp ();
-
- /* we get here when the user does an _exit()
- * (so as well after execve() terminates !) */
- if (rc = setjmp (mu->u_jmp_buf))
- {
- struct death_msg *dm = 0;
- int i;
-
- /* reset `mu' in here, setjmp() might have clobbered it */
- mu = &u;
-
- /* although this is done in CloseLibrary(), files should
- really be closed *before* a death-message is sent to
- the parent. */
- for (i = 0; i < NOFILE; i++)
- if (u.u_ofile[i]) syscall (SYS_close, i);
-
- /* DP(("vforked: _exit in progress, rc = %ld.\n", rc)); */
-
- /* this whole thing only happens if our parent is still alive ! */
- if (mu->p_pptr && mu->p_pptr != (struct Process *) 1)
- {
- rc --;
-
- /*DP(("vforked: parent alive, zombie-sig = %ld, vfork_msg = $%lx.\n",
- pu->p_zombie_sig, mu->p_vfork_msg));*/
-
- pu = (struct user *) (mu->p_pptr->pr_Task.tc_TrapData);
-
- /* send the parent a death message with our return code */
- dm = (struct death_msg *) kmalloc (sizeof (struct death_msg));
-
- Forbid ();
- if (dm)
- {
- dm->dm_status = (rc >= 128) ? W_EXITCODE (0, rc & 0x7f)
- : W_EXITCODE (rc, 0);
- dm->dm_rusage = mu->u_ru;
- ruadd (&dm->dm_rusage, &mu->u_cru);
- dm->dm_child = (struct Process *) FindTask (0);
- dm->dm_pgrp = mu->p_pgrp;
- DP(("vfork-exit: Adding child $%lx to $%lx\n", dm->dm_child, mu->p_pptr));
- AddTail ((struct List *) &pu->p_zombies, (struct Node *) dm);
- }
-
- _psignal (mu->p_pptr, SIGCHLD);
- /* have to wakeup the parent `by hand' to make sure it gets
- out of its sleep, since it might have SIGCHLD masked out or
- ignored at the moment */
- if (pu->p_stat == SSLEEP && pu->p_wchan == (caddr_t) pu)
- ix_wakeup (pu);
-
- if (mu->p_vfork_msg)
- ReplyMsg ((struct Message *) mu->p_vfork_msg);
-
- /*DP(("vforked: unlinking from parent process chains\n"));*/
- /* unlink us from the parents process chains */
-
- if (mu->p_ysptr)
- {
- struct user *yu = (struct user *) (mu->p_ysptr->pr_Task.tc_TrapData);
- yu->p_osptr = mu->p_osptr;
- }
-
- if (mu->p_osptr)
- {
- struct user *ou = (struct user *) (mu->p_osptr->pr_Task.tc_TrapData);
- ou->p_ysptr = mu->p_ysptr;
- }
-
- if (pu->p_cptr == me)
- pu->p_cptr = mu->p_osptr;
- }
- else
- {
- Forbid ();
- DP(("vforked: couldn't send death_msg\n"));
- }
-
- /* this seems to be necessary for process synchronisation, or
- else it is possible that the same process address is
- reused before the parent noticed the death of this child,
- and this would rather confuse it (or ksh at least ;-)) */
- if (dm)
- ix_sleep (dm, "vfork-dm");
- DP(("vforked: now closing library\n"));
-
- /* temporary `fix'.. there seem to be some packets arriving
- too late.. */
- Delay (100);
-
- CloseLibrary (ixb);
-
- DP(("vforked: falling off the edge of the world.\n"));
- /* just fall off the edge of the world, this is a process */
- return;
- }
-
- syscall (SYS_sigsetmask, omask);
-
- DP(("vforked: jumping back\n"));
-
- /* jump into nevereverland ;-) */
- vfork_longjmp (vm->vm_regs->jb, 0);
- /* NOTREACHED */
- }
-
- vm->vm_rc = ENOMEM; /* can't imagine any other reason why the OpenLib should fail */
- ReplyMsg ((struct Message *) vm);
- /* fall off the edge of the world ;-) */
- }
-
-
- /*
- * this is an implementation extension to the `real' vfork(). Normally you
- * can only cause the parent to resume by calling _exit() or execve() from
- * the child. Since I can't provide a real fork() on the Amiga, this function
- * is a third possibility to make the parent resume. You have then two
- * concurrent processes sharing the same frame and global data... Please be
- * EXTREMLY careful what you may do and what not. vfork() itself is a hack,
- * this is an even greater one...
- */
- static void
- _vfork_resume (u_int *copy_from_sp)
- {
- struct vfork_msg **vm = &u.p_vfork_msg;
-
- if (*vm)
- {
- u_int *sp = (u_int *)u.u_save_sp;
- u_int *copy_till_sp = (u_int *)get_sp ();
-
- /* copy the stack frame */
- copy_from_sp++;
- do
- *--sp = *--copy_from_sp;
- while (copy_from_sp > copy_till_sp);
-
- set_sp (sp);
-
- ReplyMsg ((struct Message *) *vm);
- *vm = 0;
-
- /* optimizers *want* to be fooled, right ? ;-)) */
- /* asm volatile ("rts" : "=g" (u.p_vfork_msg) : "0" (u.p_vfork_msg)); */
- }
- }
-
-
- asm ("
- .globl _vfork
- .globl _vfork_resume
- _vfork:
- | store a setjmp () compatible frame on the stack to pass to _vfork ()
- lea sp@@(-18*4),sp | _JBLEN (17) longs on the stack
- pea sp@@
- jbsr _setjmp
- lea sp@@(4),sp
- | now patch sp and pc, since they differ
- addl #20*4,sp@@(8) | account for buffer space
- movel sp@@(18*4),sp@@(20) | insert real PC (return addr on stack)
- bsr __vfork
- lea sp@@(18*4),sp
- rts
-
-
- | the following is longjmp(), with the subtle difference that this
- | thing doesn't insist in returning something non-zero...
- _vfork_longjmp:
- movel sp@@(4),a0 /* save area pointer */
- tstl a0@@(8) /* ensure non-zero SP */
- jeq Lbotch /* oops! */
- movel sp@@(8),d0 /* grab return value */
- moveml a0@@(28),d2-d7/a2-a4/a6 /* restore non-scratch regs */
- movel a0,sp@@- /* let sigreturn */
- jbsr _sigreturn /* finish for us */
-
- Lbotch:
- jsr _longjmperror
- stop #0
-
- _vfork_resume:
- pea sp@@ | pass the sp containing the return address
- bsr __vfork_resume
- lea sp@@(4),sp
- rts
- ");
-
- static int
- _vfork (struct reg_parms rp)
- {
- struct Process *me = (struct Process *) FindTask(0);
- struct CommandLineInterface *CLI = BTOCPTR (me->pr_CLI);
- u_int stack_size = CLI ? CLI->cli_DefaultStack * 4 : me->pr_StackSize;
- BPTR input, output;
- /* those *have* to be in registers to survive the stack deallocation */
- register struct vfork_msg *vm asm ("a2");
- register int omask asm ("d2");
- register struct Process *child asm ("a3");
-
- if (! _dos20)
- {
- ix_panic ("vfork currently broken in 1.3. Want to fix?");
- return -1;
- }
-
- vm = (struct vfork_msg *) kmalloc (sizeof (struct vfork_msg));
- if (! vm)
- {
- errno = ENOMEM;
- return -1;
- }
-
- vm->vm_msg.mn_ReplyPort = u.u_sync_mp;
- vm->vm_msg.mn_Node.ln_Type = NT_MESSAGE;
- vm->vm_msg.mn_Length = sizeof (struct vfork_msg);
- vm->vm_pptr = me;
- vm->vm_regs = & rp;
-
- /* we have to block all signals as long as the child uses our resources.
- * but since the child needs to start with the signal mask BEFORE this
- * general blocking, we have to pass it the old signal mask. This is a
- * way to do it */
- vm->vm_rc =
- omask = syscall (SYS_sigsetmask, ~0);
-
- /* save the passed frame in our user structure, since the child will
- deallocate it from the stack when it `returns' to user code */
- bcopy (&rp, &u.u_vfork_frame, sizeof (rp));
-
- #if 0
- /* NOTE: would like to pass our real filehandles like this to the
- child. But then the files stay open even if the child
- process closes them. That way, the parent is not able to
- get rid of them as long as the child runs, this is not
- acceptable */
- if (u.u_ofile[0] && u.u_ofile[0]->f_type == DTYPE_FILE)
- input = CTOBPTR (u.u_ofile[0]->f_fh);
- else
- input = Input();
-
- if (u.u_ofile[1] && u.u_ofile[1]->f_type == DTYPE_FILE)
- output = CTOBPTR (u.u_ofile[1]->f_fh);
- else
- output = Output();
- #else
- if (! _dos20)
- {
- /* use Open(), so that we can safely ask the child to close the
- files on termination */
- input = Open ("nil:", MODE_OLDFILE);
- output = Open ("nil:", MODE_OLDFILE);
-
- if (!input || !output)
- ix_panic ("Couldn't open NIL: for I/O ?!?!");
- }
- #endif
-
- if (_dos20)
- {
- struct TagItem tags [] = {
- { NP_Entry, (ULONG) launcher, },
- #if 0
- /* NIL: filehandles are the default according to the man page */
- { NP_Input, (ULONG) input, },
- { NP_Output, (ULONG) output, },
- { NP_CloseInput, (ULONG) -1, }, /* do close (nil:) */
- { NP_CloseOutput, (ULONG) -1, }, /* do close (nil:) */
- #endif
- { NP_Cli, (ULONG) (CLI ? -1 : 0), }, /* same thing we are */
- { NP_Name, (ULONG) "vfork()'d process", }, /* to be overridden by execve() */
- { NP_StackSize, stack_size, }, /* same size we use */
- { TAG_END, 0, }
- };
-
- child = CreateNewProc (tags);
- }
- else
- {
- struct ProcessControlBlock pcb = {
- stack_size, /* pcb_StackSize */
- 0, /* pcb_Pri */
- CLI ? PRF_CODE : PRF_NOCLI|PRF_CODE,
- 0, /* pcb_TrapCode */
- input, output, /* pcb_Input, pcb_Output */
- 0, /* pcb_Console */
- launcher, /* pcb_LoadedCode */
- 0, /* pcb_LastGasp */
- 0, /* pcb_WBProcess */
- };
- int cli_num;
-
- cli_num = ASyncRun ("vfork()'d process", 0, &pcb);
- if (cli_num > 0)
- child = FindCLI (cli_num);
- else if (cli_num == 0)
- child = (struct Process *)((int)pcb.pcb_WBProcess -
- offsetof(struct Process, pr_MsgPort));
- else
- child = 0;
- }
-
- if (! child)
- {
- /* do I have to close input/output here? Or does the startup close
- them no matter whether it succeeds or not ? */
- kfree (vm);
- syscall (SYS_sigsetmask, omask);
- errno = EPROCLIM;
- return -1;
- }
-
- /* As soon as this message is dispatched, the child will `return' and
- deallocate the stack we're running on. So afterwards, *only* use
- register variables and then longjmp () back.
- Since we don't have a stack until after the longjmp(), temporarily
- switch to our mini-stack */
- set_sp ((u_int) &u.u_mini_stack[sizeof (u.u_mini_stack) / sizeof (long)]);
-
- vm->vm_self = child;
- PutMsg (& child->pr_MsgPort, (struct Message *) vm);
- /* wait until the child does execve() or _exit() */
- WaitPort (u.u_sync_mp);
- GetMsg (u.u_sync_mp);
- syscall (SYS_sigsetmask, omask);
-
- if (vm->vm_rc)
- {
- errno = (int) vm->vm_rc;
- child = (struct Process *) -1;
- }
-
- /* this is the parent return, so we pass the id of the new child */
- kfree (vm);
- /* could use longjmp() here, but since we already *have* the local one.. */
- vfork_longjmp (u.u_vfork_frame, (int) child);
- }
-
-
- ruadd(ru, ru2)
- register struct rusage *ru, *ru2;
- {
- register long *ip, *ip2;
- register int i;
-
- timevaladd(&ru->ru_utime, &ru2->ru_utime);
- timevaladd(&ru->ru_stime, &ru2->ru_stime);
- if (ru->ru_maxrss < ru2->ru_maxrss)
- ru->ru_maxrss = ru2->ru_maxrss;
- ip = &ru->ru_first; ip2 = &ru2->ru_first;
- for (i = &ru->ru_last - &ru->ru_first; i > 0; i--)
- *ip++ += *ip2++;
- }
-
-
- /* This function is in desperate need of redesign !!!! */
-
- int
- wait4 (int pid, int *status, int options, struct rusage *rusage)
- {
- struct Process * me = (struct Process *) FindTask (0);
- struct user * mu = (struct user *) me->pr_Task.tc_TrapData;
- int omask;
-
- for (;;)
- {
- int err = 0, omask;
- struct death_msg *dm, *ndm;
- int got_node;
-
- got_node = 0;
- Forbid ();
-
- for (dm = (struct death_msg *) mu->p_zombies.mlh_Head;
- ndm = (struct death_msg *) dm->dm_node.mln_Succ;
- dm = ndm)
- if (pid == -1 ||
- (pid == 0 && dm->dm_pgrp == mu->p_pgrp) ||
- (pid < -1 && dm->dm_pgrp == - pid) ||
- (pid == (int) dm->dm_child))
- {
- got_node = 1;
- Remove ((struct Node *) dm);
- break;
- }
-
- if (!got_node && !mu->p_cptr)
- err = ECHILD;
-
- if (got_node)
- {
- struct Process *child;
-
- DP(("wait4: unlinking child $%lx\n", dm->dm_child));
- ix_wakeup (dm);
- Permit ();
-
- if (status)
- *status = dm->dm_status;
- if (rusage)
- *rusage = dm->dm_rusage;
-
- child = dm->dm_child;
-
- kfree (dm);
-
- return (int) child;
- }
-
- if (!got_node && err)
- {
- Permit ();
- errno = err;
- return -1;
- }
-
- if (options & WNOHANG)
- {
- Permit ();
- return 0;
- }
-
- DP(("wait4: waiting for SIGCHLD\n"));
- ix_sleep (mu, "wait4");
- if (mu->p_sig)
- err = EINTR;
-
- Permit ();
- if (CURSIG (mu))
- setrun (me);
- }
- }
- @
-
-
- 1.5
- log
- @change to 2.x header files
- duplicate calling stack frame in vfork_resume() instead of just doing rts.
- temporary abort calling 1.3 vfork, until that's fixed again (when???).
- @
- text
- @d19 1
- a19 1
- * $Id: vfork.c,v 1.4 1992/07/04 19:24:12 mwild Exp $
- d22 5
- a264 2
- ix_lock_base ();
-
- a276 2
- Forbid ();
-
- d279 2
- a282 1
- /* don't need to fill out dm_message, it won't be ReplyMsg'd */
- a292 5
- #if 0
- /* once for Exec */
- Signal ((struct Task *) mu->p_pptr, 1 << pu->p_zombie_sig);
- /* and once for my signals ;-) */
- #endif
- a326 3
- /*DP(("vforked: unlocking base and closing library\n"));*/
- ix_unlock_base ();
-
- a553 1
- errno = EPROCLIM;
- d556 1
- a617 1
- ix_lock_base ();
- a635 5
- #if 0
- else if (!ndm && !(options & WNOHANG))
- /* it's important to do this while ixbase is locked ! */
- SetSignal (0, 1 << mu->p_zombie_sig);
- #endif
- a636 2
- ix_unlock_base ();
-
- a669 3
- #if 0
- Wait ((1 << mu->p_zombie_sig) | (1 << mu->u_sleep_sig) | SIGBREAKF_CTRL_C);
- #else
- d674 1
- a674 1
- #endif
- @
-
-
- 1.4
- log
- @get passing of environment right.
- change ix_sleep() calls to new semantics.
- @
- text
- @d19 1
- a19 1
- * $Id: vfork.c,v 1.3 1992/05/18 12:26:25 mwild Exp $
- d22 4
- d62 2
- a63 22
- #include "gcc:include20/utility/tagitem.h"
- #include "gcc:include20/dos/dostags.h"
- #define BASE_EXT_DECL
- #define BASE_PAR_DECL
- #define BASE_PAR_DECL0
- #define BASE_NAME ix.ix_dos_base
- __inline static struct Process* CreateNewProc(BASE_PAR_DECL struct TagItem* tags)
- {
- BASE_EXT_DECL
- register struct Process* res __asm("d0");
- register void *a6 __asm ("a6");
- register struct TagItem* d1 __asm("d1");
-
- a6 = BASE_NAME;
- d1 = tags;
- __asm volatile ("
- jsr a6@@(-0x1f2)"
- : "=r" (res)
- : "r" (a6), "r" (d1)
- : "d0", "d1", "a0", "a1");
- return res;
- }
- d93 1
- d95 2
- d145 1
- d168 11
- a178 2
- WaitPort (& me->pr_MsgPort);
- vm = (struct vfork_msg *) GetMsg (& me->pr_MsgPort);
- d213 1
- a213 1
- mu->u_environ = malloc (4);
- d242 1
- a242 1
- mu->u_save_sp = get_sp ();
- d377 1
- a377 1
- _vfork_resume (u_int jmp_to)
- d379 3
- a381 1
- if (u.p_vfork_msg)
- d383 8
- a390 3
- /* make room on the new stack for the return address */
- ((u_int *)u.u_save_sp) --;
- *((u_int *)u.u_save_sp) = jmp_to;
- d392 1
- a392 1
- set_sp ((u_int) u.u_save_sp);
- d394 2
- a395 2
- ReplyMsg ((struct Message *) u.p_vfork_msg);
- u.p_vfork_msg = 0;
- d398 1
- a398 1
- asm volatile ("rts" : "=g" (u.p_vfork_msg) : "0" (u.p_vfork_msg));
- d436 1
- a436 1
- movel sp@@,sp@@- | pass the return address on the stack
- d454 6
- d534 1
- a534 1
- stack_size, /* pcb_StackSize XXXX FIX ME !!! */
- d573 1
- @
-
-
- 1.3
- log
- @fixed bad typo that didn't close files before sending wait message.
- Set childs Input()/Output() to NIL:, we only keep the files in our
- own filetable.
- @
- text
- @d19 1
- a19 1
- * $Id: vfork.c,v 1.2 1992/05/18 01:02:31 mwild Exp $
- d22 5
- d189 2
- d216 2
- a217 1
- mu->u_environ = pu->u_environ;
- d341 1
- a341 1
- ix_sleep (dm);
- d677 1
- a677 1
- ix_sleep (mu);
- @
-
-
- 1.2
- log
- @add temporary Delay(100) before CloseLibrary() in the child after
- vfork(), there seem to arrive some late packets (don't know why..)
- pass NIL: filehandles as Input()/Output() to the child, so that the
- real I/O-handles only depend on ix-filetable for usage-count
- @
- text
- @d19 1
- a19 1
- * $Id: vfork.c,v 1.1 1992/05/14 19:55:40 mwild Exp $
- d22 6
- d253 1
- a253 1
- if (u.u_ofile[fd]) syscall (SYS_close, fd);
- d482 10
- a491 4
- /* use Open(), so that we can safely ask the child to close the
- files on termination */
- input = Open ("nil:", MODE_OLDFILE);
- output = Open ("nil:", MODE_NEWFILE);
- d498 2
- d504 1
- @
-
-
- 1.1
- log
- @Initial revision
- @
- text
- @d19 1
- a19 1
- * $Id$
- d21 4
- a24 1
- * $Log$
- d330 4
- d460 6
- d475 6
- d488 2
- a489 2
- { NP_CloseInput, 0, }, /* don't close */
- { NP_CloseOutput, 0, }, /* don't close */
- d503 1
- a503 1
- CLI ? PRF_SAVEIO|PRF_CODE : PRF_SAVEIO|PRF_NOCLI|PRF_CODE,
- d525 2
- @
-