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> <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 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) \ ; 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; }