source: vendor/emx/current/src/dos/process.asm

Last change on this file was 18, checked in by bird, 22 years ago

Initial revision

  • Property cvs2svn:cvs-rev set to 1.1
  • Property svn:eol-style set to native
  • Property svn:executable set to *
File size: 43.0 KB
Line 
1;
2; PROCESS.ASM -- Manage processes
3;
4; Copyright (c) 1991-1996 by Eberhard Mattes
5;
6; This file is part of emx.
7;
8; emx is free software; you can redistribute it and/or modify it
9; under the terms of the GNU General Public License as published by
10; the Free Software Foundation; either version 2, or (at your option)
11; any later version.
12;
13; emx is distributed in the hope that it will be useful,
14; but WITHOUT ANY WARRANTY; without even the implied warranty of
15; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16; GNU General Public License for more details.
17;
18; You should have received a copy of the GNU General Public License
19; along with emx; see the file COPYING. If not, write to
20; the Free Software Foundation, 59 Temple Place - Suite 330,
21; Boston, MA 02111-1307, USA.
22;
23; See emx.asm for a special exception.
24;
25
26__PROCESS = 1
27 INCLUDE EMX.INC
28 INCLUDE LOADER.INC
29 INCLUDE SIGNAL.INC
30 INCLUDE PROCESS.INC
31 INCLUDE PROFIL.INC
32 INCLUDE TABLES.INC
33 INCLUDE SEGMENTS.INC
34 INCLUDE PAGING.INC
35 INCLUDE PMINT.INC
36 INCLUDE PMIO.INC
37 INCLUDE FILEIO.INC
38 INCLUDE MISC.INC
39 INCLUDE UTILS.INC
40 INCLUDE ERRORS.INC
41
42 PUBLIC PROCESS_TABLE, PROC0, PROCESS_PTR, PROCESS_SIG
43 PUBLIC PROCESS_FP, PROCESS_FPUEMU, PROCESS_FPUCLIENT
44 PUBLIC FPUEMU_STATE, EMX_DIR, NP1
45 PUBLIC VIDEO_LIN, TIMER_TABLE, TIMER_MIN, TIMER_TICKS
46 PUBLIC NEW_PROCESS, CREATE_PID, FIND_EXEC
47 PUBLIC REMOVE_PROCESS, ZOMBIE_PROCESS, KILL_PROCESS
48 PUBLIC FIND_PROCESS, WAIT_PROCESS
49 PUBLIC SAVE_PROCESS, REST_PROCESS, SET_TIMER, SLEEP
50 PUBLIC PROCESS_INIT
51
52
53SV_DATA SEGMENT
54
55NO_PID = 0FFFFFFFFH
56MIN_PID = 2
57
58NEXT_PID DD MIN_PID ; Next process ID
59PROCESS_PTR DW ? ; PTE of current process
60PROCESS_SIG DW ? ; Ditto, not changed for I/O
61PROCESS_FP DW ? ; The coprocessor contains
62 ; the status of this process
63PROCESS_FPUEMU DW ? ; FPU emulator PTE
64PROCESS_FPUCLIENT DW ? ; FPU client PTE
65VIDEO_LIN DD ? ; Linear address of video mem
66
67TIMER_MIN DD 0
68TIMER_TICKS DD 0
69
70CLOCK_LO DWORD 0
71CLOCK_HI DWORD 0
72
73;
74; The offset of this table must be > 1 !
75; (PROCESS_PTR = NO_PROCESS = 0 means handle translation turned off,
76; PROCESS_PTR = NO_WPROCESS = 1 is a special return value of WAIT_PROCESS)
77;
78PROCESS_TABLE DB MAX_PROCESSES DUP (SIZE PROCESS DUP (0))
79;
80; Dummy process (used for starting first process). This must follow
81; directly after PROCESS_TABLE, see MAP_TRANSLATE.
82;
83PROC0 LABEL PROCESS
84 DB SIZE PROCESS DUP (0)
85
86;
87; This doesn't work (linker bug?):
88;
89; PROCESS_TABLE PROCESS MAX_PROCESSES DUP (<NO_PID>)
90; PROC0 PROCESS <>
91;
92
93;
94; The table of timers
95;
96 DALIGN 4
97TIMER_TABLE TIMER MAX_TIMERS DUP (<TT_NONE, NO_PROCESS>)
98
99;
100; Temporary variables
101;
102ARGV_SIZE DD ?
103ENVP_SIZE DD ?
104
105;
106; This is the name of the directory from which emx.exe was loaded.
107; It is empty if emx.exe is bound to the executable. The directory
108; name ends with a backslash.
109;
110EMX_DIR DB 100 DUP (?)
111
112;
113; The result of FIND_EXEC is stored here.
114;
115EXEC_FNAME BYTE 256 DUP (?)
116
117;
118; State of the FPU emulator
119;
120FPUEMU_STATE DB FES_OFF
121
122;
123; File name of the FPU emulator
124;
125$FPUEMU_NAME DB "emxfpemu", 0
126
127;
128; Arguments to pass to the FPU emulator (argc=0).
129;
130$FPUEMU_ARG DB 0, 0
131
132$PROC_FULL DB "Too many processes", CR, LF, 0
133$INV_MODE DB "Invalid spawn mode", CR, LF, 0
134
135;
136; This structure is used for starting the initial process and
137; the FPU emulator. Some members initialized by emx.asm for
138; the initial process are later used again without modification
139; for starting the FPU emulator: NP_ENV_OFF, NP_ENV_SEL, NP_ENV_COUNT,
140; NP_ENV_SIZE, NP_PARENT, and NP_FPROC.
141;
142NP1 NEW_PROC <>
143
144SV_DATA ENDS
145
146
147SV_CODE SEGMENT
148
149 ASSUME CS:SV_CODE, DS:NOTHING
150
151NP_FRAME_SIZE = 4
152NP_ARGS EQU (WORD PTR [BP-2])
153
154;
155; In: SI Pointer to arguments (STRUC NEW_PROC)
156;
157; Out: DI Pointer to process entry
158; AX Return code (0=ok)
159; EDX Error message (for AX > 0)
160;
161; Note: This function is not reentrant (uses global variables; GDT, for
162; instance).
163;
164 ASSUME DS:SV_DATA
165 ASSUME SI:PTR NEW_PROC
166NEW_PROCESS PROC NEAR
167 PUSH EBP ; Build stack frame
168 MOV BP, SP ; (we use some local
169 SUB ESP, NP_FRAME_SIZE ; variables)
170 MOV NP_ARGS, SI ; Save pointer to param. table
171;
172 CALL NP_CHECK_MODE
173 OR AX, AX
174 JNZ SHORT NP_RET
175 CALL NP_FIND_SLOT
176 OR AX, AX
177 JNZ SHORT NP_RET
178 ASSUME DI:PTR PROCESS
179 CALL CREATE_PID
180 CALL NP_SET_TAB
181 CALL NP_SEGMENTS
182
183 MOV SI, NP_ARGS
184 MOV AX, [SI].NP_FNAME_SEL ; File name, selector
185 MOV EDX, [SI].NP_FNAME_OFF ; File name, offset
186 CALL LOADER
187 OR AX, AX ; Error?
188 JZ SHORT LOAD_OK
189 MOV [DI].P_PID, NO_PID ; Remove process
190 MOV [DI].P_STATUS, PS_NONE
191 JMP SHORT NP_RET
192
193LOAD_OK: CALL NP_FILES
194 CALL NP_SIGNALS
195 CALL NP_STACK
196 CALL NP_REGS
197 XOR AX, AX ; Success
198NP_RET: ADD ESP, NP_FRAME_SIZE
199 POP EBP
200 RET
201 ASSUME SI:NOTHING
202 ASSUME DI:NOTHING
203NEW_PROCESS ENDP
204
205;
206; Check mode
207;
208 ASSUME SI:PTR NEW_PROC
209NP_CHECK_MODE PROC NEAR
210 XOR AX, AX
211 CMP BYTE PTR [SI].NP_MODE1, NP_SPAWN_SYNC
212 JE SHORT NP_CM_RET
213 CMP BYTE PTR [SI].NP_MODE1, NP_SPAWN_ASYNC
214 JE SHORT NP_CM_RET
215 CMP BYTE PTR [SI].NP_MODE1, NP_EXEC
216 JE SHORT NP_CM_RET
217 CMP BYTE PTR [SI].NP_MODE1, NP_DEBUG
218 JE SHORT NP_CM_RET
219 MOV AX, EINVAL
220 LEA EDX, $INV_MODE
221NP_CM_RET: RET
222 ASSUME SI:NOTHING
223NP_CHECK_MODE ENDP
224
225
226;
227; Find empty process table slot
228;
229; Out: DI Pointer to process table entry
230;
231NP_FIND_SLOT PROC NEAR
232 XOR AX, AX ; No error
233 LEA DI, PROCESS_TABLE ; The table of processes
234 ASSUME DI:PTR PROCESS
235 MOV DL, 1 ; First process index
236 MOV CX, MAX_PROCESSES ; There are this many slots
237NP_FS_LOOP: CMP [DI].P_STATUS, PS_NONE ; Empty slot?
238 JE SHORT NP_FS_RET ; Yes -> use it!
239 ADD DI, SIZE PROCESS ; Next slot
240 INC DL ; Next process index
241 LOOP NP_FS_LOOP ; Repeat
242 ASSUME DI:NOTHING
243 MOV AX, EAGAIN ; Error:
244 LEA EDX, $PROC_FULL ; Too many processes
245NP_FS_RET: RET ; Done
246NP_FIND_SLOT ENDP
247
248
249;
250; Create unique process ID
251;
252 TALIGN 2
253CREATE_PID PROC NEAR
254 PUSH BX
255NP_CP_LOOP: MOV EAX, NEXT_PID ; Get next process ID
256 INC NEXT_PID
257 CMP EAX, NO_PID ; Wrap around?
258 JE SHORT NP_CP_WRAP ; Yes -> restart
259 CALL FIND_PROCESS ; PID already used?
260 CMP BX, NO_PROCESS
261 JNE SHORT NP_CP_LOOP ; Yes -> next PID
262 POP BX
263 RET
264
265NP_CP_WRAP: MOV NEXT_PID, MIN_PID
266 JMP SHORT NP_CP_LOOP
267CREATE_PID ENDP
268
269
270;
271; Initialize process table entry
272;
273 TALIGN 2
274 ASSUME SI:PTR NEW_PROC
275 ASSUME DI:PTR PROCESS
276NP_SET_TAB PROC NEAR
277 MOV [DI].P_PID, EAX ; Set PID
278 MOV [DI].P_PIDX, DL ; Set process index
279 DEC DL ; Process number (0..)
280 AND EDX, 0FFH
281 MOV [DI].P_NUMBER, EDX
282 SHL DX, 3 ; 8 bytes per GDT entry
283 ADD DX, G_LDT_SEL ; LDT selector
284 MOV [DI].P_LDT, DX ; Save LDT selector
285 MOV [DI].P_EXEC_HANDLE, NO_FILE_HANDLE
286 MOV [DI].P_PAGE_FAULTS, 0 ; No page faults yet
287 MOV [DI].P_FLAGS, 0 ; No flags set (see L_OPTIONS)
288 MOV [DI].P_TRUNC, 0 ; Set -t- (see L_OPTIONS)
289 MOV [DI].P_UFLAGS, 0 ; No user flags set
290 MOV [DI].P_STATUS, PS_INIT ; Process not running yet
291 MOV [DI].P_HW_ACCESS, 0 ; See L_OPTIONS
292 MOV [DI].P_DRIVE, 0 ; No default drive (-r option)
293 MOV [DI].P_COMMIT_SIZE, 0 ; No add. pages (-C option)
294 MOV [DI].P_STACK_SIZE, 00800000H ; (default; see -s option)
295 CMP BYTE PTR [SI].NP_MODE1, NP_DEBUG ; Debugging?
296 JNE SHORT NP_ST_1 ; No -> skip
297 MOV [DI].P_STATUS, PS_STOP ; Process `stopped'
298 MOV [DI].P_SIG_NO, SIGTRAP ; by SIGTRAP
299 OR [DI].P_FLAGS, PF_DEBUG OR PF_WAIT_WAIT
300 OR [DI].P_HW_ACCESS, HW_ACCESS_CODE ; Set -ac option
301NP_ST_1: MOV BX, [SI].NP_FPROC ; Process which owns the files
302 ASSUME BX:PTR PROCESS
303 MOV AX, [BX].P_UMASK ; Copy umask of that process
304 MOV [DI].P_UMASK, AX ; to new process
305 MOV AX, [BX].P_UMASK1 ; Copy umask of that process
306 MOV [DI].P_UMASK1, AX ; to new process
307 MOV BX, [SI].NP_PARENT ; Parent process
308 MOV EAX, [BX].P_PID ; Copy ID of parent to
309 MOV [DI].P_PPID, EAX ; parent ID of new process
310 MOV [DI].P_SYMBOLS, 0 ; No symbols (yet)
311 MOV [DI].P_VESAINFO_PTR, 0 ; No VESA info data area
312 MOV [DI].P_PRF_SCALE, 0 ; Profiling not active
313 RET
314 ASSUME BX:NOTHING
315 ASSUME SI:NOTHING
316 ASSUME DI:NOTHING
317NP_SET_TAB ENDP
318
319;
320; Create segments
321;
322 ASSUME DI:PTR PROCESS
323NP_SEGMENTS PROC NEAR
324 LEA SI, GDT + (G_SV_DATA_SEL AND NOT 07H)
325 CALL GET_BASE ; SV_DATA base address -> EBX
326
327 MOV DX, [DI].P_LDT ; Get LDT selector
328 MOV SI, DX
329 LEA SI, GDT[SI] ; SI -> GDT
330
331 SUB DX, G_LDT_SEL
332 IMUL DX, LDT_ENTRIES
333 ADD DX, OFFSET SV_DATA:LDTS
334 MOV [DI].P_LDT_PTR, DX
335 MOVZX EDX, DX
336 ADD EBX, EDX ; EBX -> LDT (linear)
337 MOV AX, A_LDT OR DPL_0
338 MOV ECX, 8*LDT_ENTRIES
339 CALL CREATE_SEG ; LDT entry in GDT
340 MOV SI, DX ; SI -> LDT (SV_CODE)
341 CALL NULL_SEG ; null
342 ADD SI, 8
343 CALL NULL_SEG ; code
344 ADD SI, 8
345 CALL NULL_SEG ; data
346 ADD SI, 8
347 MOV EBX, VIDEO_LIN
348 MOV ECX, 4000-1
349 MOV AX, A_DATA32 OR DPL_3
350 CALL CREATE_SEG ; Video segment
351 ADD SI, 8
352 CALL NULL_SEG ; Symbols and strings
353 ADD SI, 8
354 CALL NULL_SEG ; Client process
355 RET
356 ASSUME DI:NOTHING
357NP_SEGMENTS ENDP
358
359
360;
361; Create stdin/stdout/stderr handles, inherit open files
362;
363 ASSUME DI:PTR PROCESS
364NP_FILES PROC NEAR
365 MOV SI, NP_ARGS
366 ASSUME SI:PTR NEW_PROC
367 MOV SI, [SI].NP_FPROC ; Process which owns the files
368 ASSUME SI:PTR PROCESS
369 CALL INHERIT_HANDLES
370 RET
371 ASSUME SI:NOTHING
372 ASSUME DI:NOTHING
373NP_FILES ENDP
374
375
376;
377; Setup signal handling
378;
379 ASSUME DI:PTR PROCESS
380NP_SIGNALS PROC NEAR
381 MOV SI, NP_ARGS
382 ASSUME SI:PTR NEW_PROC
383 MOV SI, [SI].NP_FPROC ; Parent process
384 ASSUME SI:PTR PROCESS
385;
386; Inherit signal handlers from parent process. SIG_IGN is inherited
387; as SIG_IGN, everything else as SIG_DFL.
388;
389 MOV CX, SIGNALS
390 MOV BX, 0
391NP_SIG1: MOV EAX, [SI].P_SIG_HANDLERS[BX]
392 CMP EAX, SIG_IGN
393 JE SHORT NP_SIG2
394 MOV EAX, SIG_DFL ; Default signal handler
395NP_SIG2: MOV [DI].P_SIG_HANDLERS[BX], EAX
396 MOV [DI].P_SA_MASK[BX], 0
397 MOV [DI].P_SA_FLAGS[BX], SA_ACK
398 ADD BX, 4
399 LOOP NP_SIG1
400 MOV [DI].P_SIG_PENDING, 0 ; No signals pending
401 MOV [DI].P_SIG_BLOCKED, 0 ; No signals blocked
402 RET
403 ASSUME DI:NOTHING
404NP_SIGNALS ENDP
405
406
407;
408; Construct initial stack for C runtime startup code
409; containing environment and arguments
410;
411 ASSUME DI:PTR PROCESS
412NP_STACK PROC NEAR
413;
414; Make the stack segment of the process accessible
415;
416 PUSH SI
417 MOV SI, [DI].P_LDT
418 MOV AX, L_DATA_SEL
419 CALL GET_DESC
420 MOV_ES_DS
421 PUSH DI
422 LEA DI, G_TMP2_DESC
423 CLD
424 MOVS DWORD PTR ES:[DI], DWORD PTR DS:[SI]
425 MOVS DWORD PTR ES:[DI], DWORD PTR DS:[SI]
426 POP DI
427 POP SI
428;
429; End ->
430; Argument strings
431; Environment
432; argv[]
433; ESP -> envp[]
434;
435 MOV SI, NP_ARGS
436 ASSUME SI:PTR NEW_PROC
437 MOVZX EAX, [SI].NP_ENV_COUNT ; Get number of env strings
438 LEA EAX, [4*EAX+4] ; sizeof (envp[])
439 MOV ENVP_SIZE, EAX
440 MOVZX EAX, [SI].NP_ARG_COUNT ; Get argc
441 LEA EAX, [4*EAX+4] ; sizeof (argv[])
442 MOV ARGV_SIZE, EAX
443
444 MOV EBX, [DI].P_STACK_ADDR
445 MOVZX EAX, [SI].NP_ARG_SIZE ; Size of arguments
446 SUB EBX, EAX ; Argument strings
447 MOVZX EAX, [SI].NP_ENV_SIZE ; Size of environment
448 SUB EBX, EAX ; Environment strings
449 SUB EBX, ARGV_SIZE ; argv[]
450 SUB EBX, ENVP_SIZE ; envp[]
451 AND EBX, NOT 3 ; Alignment
452 MOV [DI].P_ESP, EBX ; Initial stack pointer
453 ASSUME DI:NOTHING
454 PUSH DI ; Save DI
455 MOV EDI, EBX ; Destination address
456 ADD EDI, ENVP_SIZE
457 ADD EDI, ARGV_SIZE
458 CLD
459 MOV CX, [SI].NP_ENV_COUNT
460 MOV EAX, [SI].NP_ENV_OFF
461 MOV DX, [SI].NP_ENV_SEL
462 MOV EBP, 0 ; No extra bytes
463 CALL PCOPY
464 XOR AL, AL
465 STOS BYTE PTR ES:[EDI]
466 MOV CX, [SI].NP_ARG_COUNT
467 MOV EAX, [SI].NP_ARG_OFF
468 MOV DX, [SI].NP_ARG_SEL
469 MOV EBP, 1 ; One extra byte
470 PUSH EBX ; Save EBX for PQUOTE
471 CALL PCOPY
472 POP EBX
473;
474; If the -q option is set for the parent process, quote all arguments
475;
476 TEST [SI].NP_MODE2, NP2_QUOTE
477 JNZ SHORT QUOTE_YES
478 CMP PROCESS_PTR, NO_PROCESS
479 JE SHORT QUOTE_NO
480 PUSH BX
481 MOV BX, PROCESS_PTR
482 TEST (PROCESS PTR [BX]).P_FLAGS, PF_QUOTE
483 POP BX
484 JNZ SHORT QUOTE_YES
485QUOTE_NO: MOV AL, 00H
486 JMP SHORT QUOTE_1
487QUOTE_YES: MOV AL, 01H
488QUOTE_1: CALL PQUOTE ; In: EBX
489;
490; Remove temporary GDT entries for security
491;
492 MOV AX, G_NULL_SEL
493 MOV ES, AX
494 PUSH SI
495 LEA SI, G_TMP1_DESC
496 CALL NULL_SEG
497 LEA SI, G_TMP2_DESC
498 CALL NULL_SEG
499 POP SI
500 POP DI ; Restore DI
501 RET
502 ASSUME SI:NOTHING
503NP_STACK ENDP
504
505
506;
507; Set initial values of registers
508;
509; ESP is set in NP_STACK.
510;
511 ASSUME DI:PTR PROCESS
512NP_REGS PROC NEAR
513 MOV [DI].P_CS, L_CODE_SEL
514 MOV AX, L_DATA_SEL
515 MOV [DI].P_DS, AX
516 MOV [DI].P_ES, AX
517 MOV [DI].P_FS, AX
518 MOV [DI].P_GS, AX
519 MOV [DI].P_SS, AX
520 MOV EAX, [DI].P_ENTRY_POINT
521 MOV [DI].P_EIP, EAX
522 MOV [DI].P_EFLAGS, 0202H ; IOPL=0, IF=1
523 RET
524 ASSUME DI:NOTHING
525NP_REGS ENDP
526
527
528;
529; Copy arguments / environment
530;
531; In: CX Number of strings
532; EAX Offset of strings
533; DX Segment of strings
534; EBP Add this to the table entry (skipping leading bytes)
535; EDI Destination address for strings
536; EBX Destination address for table
537;
538PCOPY PROC NEAR
539 PUSH ESI
540 PUSH DS ; Save DS & ESI
541 PUSH EAX
542 .386P
543 SLDT SI
544 .386
545 MOV AX, DX
546 CALL GET_DESC
547 MOV_ES_DS
548 PUSH DI
549 LEA DI, G_TMP1_DESC
550 CLD
551 MOVS DWORD PTR ES:[DI], DWORD PTR DS:[SI]
552 MOVS DWORD PTR ES:[DI], DWORD PTR DS:[SI]
553 POP DI
554 POP ESI
555 MOV AX, G_TMP1_SEL
556 MOV DS, AX
557 ASSUME DS:NOTHING
558 MOV AX, G_TMP2_SEL
559 MOV ES, AX
560 JCXZ PCOPY3
561PCOPY1: MOV ES:[EBX], EDI ; Put pointer
562 ADD DWORD PTR ES:[EBX], EBP ; Skip flag byte
563 ADD EBX, 4
564PCOPY2: LODS BYTE PTR DS:[ESI]
565 STOS BYTE PTR ES:[EDI]
566 OR AL, AL
567 JNZ SHORT PCOPY2
568 LOOP PCOPY1
569PCOPY3: XOR EAX, EAX
570 MOV ES:[EBX], EAX
571 ADD EBX, 4
572 POP DS
573 ASSUME DS:SV_DATA
574 POP ESI
575 RET
576PCOPY ENDP
577
578
579;
580; Quote or unquote all arguments in the child process' stack.
581;
582; In: EBX Pointer to argv[] (in segment G_TMP2_SEL)
583; AL 00H (unquote) or 01H (quote)
584;
585PQUOTE PROC NEAR
586 PUSH EDI
587 MOV DI, G_TMP2_SEL
588 MOV ES, DI
589PQ_LOOP: MOV EDI, ES:[EBX]
590 TEST EDI, EDI
591 JZ SHORT PQ_RET
592 AND BYTE PTR ES:[EDI-1], NOT 01H
593 OR BYTE PTR ES:[EDI-1], AL
594 ADD EBX, 4
595 JMP SHORT PQ_LOOP
596PQ_RET: POP EDI
597 RET
598PQUOTE ENDP
599
600;
601; Find process table entry for given process ID
602;
603; In: EAX Process ID
604;
605; Out: BX Pointer to process table entry (NO_PROCESS: not found)
606;
607 ASSUME DS:SV_DATA
608FIND_PROCESS PROC NEAR
609 PUSH ECX
610 LEA BX, PROCESS_TABLE
611 ASSUME BX:PTR PROCESS
612 MOV CX, MAX_PROCESSES
613FP1: CMP EAX, [BX].P_PID
614 JE SHORT FP2
615 ADD BX, SIZE PROCESS
616 LOOP FP1
617 MOV BX, NO_PROCESS
618FP2: POP ECX
619 RET
620 ASSUME BX:NOTHING
621FIND_PROCESS ENDP
622
623
624;
625; Turn process into defunct process (zombie)
626;
627; In: BX Pointer to process table entry
628;
629 ASSUME DS:SV_DATA
630 ASSUME BX:PTR PROCESS
631ZOMBIE_PROCESS PROC NEAR
632 CALL FREE_PROCESS
633 MOV [BX].P_STATUS, PS_DEFUNCT
634 OR [BX].P_FLAGS, PF_WAIT_WAIT
635 RET
636 ASSUME BX:NOTHING
637ZOMBIE_PROCESS ENDP
638
639
640;
641; Remove (kill) process
642;
643; In: BX Pointer to process table entry
644;
645 ASSUME DS:SV_DATA
646 ASSUME BX:PTR PROCESS
647REMOVE_PROCESS PROC NEAR
648 CALL FREE_PROCESS
649 MOV [BX].P_PID, NO_PID
650 MOV [BX].P_STATUS, PS_NONE
651 RET
652 ASSUME BX:NOTHING
653REMOVE_PROCESS ENDP
654
655
656;
657; Remove last vestiges of a defunct process (zombie)
658;
659; In: BX Pointer to process table entry
660;
661; Note: Never call this without calling ZOMBIE_PROCESS first!
662;
663 ASSUME DS:SV_DATA
664 ASSUME BX:PTR PROCESS
665KILL_PROCESS PROC NEAR
666 MOV [BX].P_PID, NO_PID ; Remove last vestiges
667 MOV [BX].P_STATUS, PS_NONE ; of process
668 RET
669 ASSUME BX:NOTHING
670KILL_PROCESS ENDP
671
672;
673; Free all resources used by a process (but keep the process table entry)
674;
675; In: BX Pointer to process table entry
676;
677 ASSUME DS:SV_DATA
678 ASSUME BX:PTR PROCESS
679FREE_PROCESS PROC NEAR
680 PUSH AX
681 PUSH CX
682 PUSH SI
683;
684; Unassign the FPU
685;
686 CMP PROCESS_FP, BX ; FPU assigned to this process?
687 JNE SHORT FP_FPU_1 ; No -> skip
688 MOV PROCESS_FP, NO_PROCESS ; Don't store FPU context
689FP_FPU_1:
690;
691; Turn off profiling
692;
693 XOR EAX, EAX
694 XCHG EAX, [BX].P_PRF_SCALE
695 TEST EAX, EAX
696 JZ SHORT FP_PROFIL_1
697 CALL PROFIL_STOP
698FP_PROFIL_1:
699;
700; Reclaim timers
701;
702 LEA SI, TIMER_TABLE
703 ASSUME SI:PTR TIMER
704 MOV CX, MAX_TIMERS
705FP_TIMER_LOOP: CMP [SI].T_PROCESS, BX
706 JNE SHORT FP_TIMER_NEXT
707 MOV [SI].T_TYPE, TT_NONE
708 MOV [SI].T_PROCESS, NO_PROCESS
709FP_TIMER_NEXT: ADD SI, SIZE TIMER
710 LOOP FP_TIMER_LOOP
711 ASSUME SI:NOTHING
712;
713; Reclaim memory
714;
715 MOV AL, [BX].P_PIDX ; Get process index
716 CALL FREE_LIN ; Free linear address space
717 CALL FREE_PAGES ; Adjust page table entries
718;
719; Close all files
720;
721 CALL CLOSE_HANDLES
722;
723; Close exec file
724;
725 MOV AX, NO_FILE_HANDLE
726 XCHG AX, [BX].P_EXEC_HANDLE
727 CMP AX, NO_FILE_HANDLE
728 JE SHORT RP_1
729 PUSH BX
730 MOV BX, AX
731 CALL CLOSE
732 POP BX
733RP_1: POP SI
734 POP CX
735 POP AX
736 RET
737 ASSUME BX:NOTHING
738FREE_PROCESS ENDP
739
740
741;
742; Store the registers saved on the stack by an interrupt
743; in the process table entry
744;
745; In: SS:BP Pointer to interrupt stack frame
746; DS:BX Pointer to process table entry
747;
748; Note: Only for user (ring 3) processes (ESP, SS!)
749;
750 ASSUME DS:SV_DATA
751 ASSUME BX:PTR PROCESS
752SAVE_PROCESS PROC NEAR
753 PUSH DS
754 PUSH ES
755 PUSH SI
756 PUSH DI
757 PUSH CX
758 LEA DI, [BX].P_GS
759 MOV_ES_DS
760 MOV SI, BP
761 PUSH SS
762 POP DS
763 CLD
764 MOV CX, I_REG_DWORDS
765 REP MOVS DWORD PTR ES:[DI], DWORD PTR DS:[SI]
766 POP CX
767 POP DI
768 POP SI
769 POP ES
770 POP DS
771 RET
772 ASSUME BX:NOTHING
773SAVE_PROCESS ENDP
774
775
776;
777; Copy the registers from a process table entry to the interrupt
778; stack frame, set TS bit of CR0, set spawnve() return value if required
779;
780; In: SS:BP Pointer to interrupt stack frame
781; DS:BX Pointer to process table entry
782;
783; Out: LDTR
784; CR0 TS set
785;
786; Note: Only for user (ring 3) processes (ESP, SS!)
787;
788 ASSUME DS:SV_DATA
789 ASSUME BX:PTR PROCESS
790 ASSUME BP:PTR ISTACKFRAME
791REST_PROCESS PROC NEAR
792 PUSH DS
793 PUSH ES
794 PUSH SI
795 PUSH DI
796 PUSH EAX
797 PUSH ECX
798 LEA SI, [BX].P_GS
799 MOV DI, BP
800 PUSH SS
801 POP ES
802 CLD
803 MOV CX, I_REG_DWORDS
804 REP MOVS DWORD PTR ES:[DI], DWORD PTR DS:[SI]
805 .386P
806 LLDT [BX].P_LDT
807 MOV ECX, CR0
808 OR ECX, CR0_TS ; For coprocessor task switches
809 MOV CR0, ECX
810 .386
811 CMP [BX].P_STATUS, PS_WAIT_SPAWN ; In spawnve()?
812 JNE SHORT RP_RET
813 MOV EAX, [BX].P_SPAWN_RC ; Return code or PID of child
814 MOV I_EAX, EAX ; returned in EAX
815 TEST [BX].P_FLAGS, PF_PSEUDO_ASYNC ; Pseudo async child?
816 JZ SHORT RP_RET ; No -> continue
817 CMP [BX].P_SIG_HANDLERS[4*SIGCLD], SIG_IGN
818 JE SHORT RP_RET
819 CMP [BX].P_SIG_HANDLERS[4*SIGCLD], SIG_DFL
820 JE SHORT RP_RET
821 BTS [BX].P_SIG_PENDING, SIGCLD ; Generate SIGCLD
822RP_RET: MOV [BX].P_STATUS, PS_RUN ; Running again
823 POP ECX
824 POP EAX
825 POP DI
826 POP SI
827 POP ES
828 POP DS
829 RET
830 ASSUME BX:NOTHING
831 ASSUME BP:NOTHING
832REST_PROCESS ENDP
833
834;
835; Wait for a child process
836;
837; In: EAX Parent process ID
838;
839; Out: BX Pointer to process table entry or:
840; NO_PROCESS: no child process found
841; NO_WPROCESS: no child process stopped/terminated
842;
843 ASSUME DS:SV_DATA
844WAIT_PROCESS PROC NEAR
845 PUSH ECX
846 PUSH DX
847 MOV DX, NO_PROCESS ; Default return value
848 LEA BX, PROCESS_TABLE
849 ASSUME BX:PTR PROCESS
850 MOV CX, MAX_PROCESSES
851WP_LOOP: CMP [BX].P_STATUS, PS_NONE ; Empty slot?
852 JE SHORT WP_NEXT ; Yes -> skip
853 CMP EAX, [BX].P_PPID ; Child process?
854 JNE SHORT WP_NEXT ; No -> skip
855 MOV DX, NO_WPROCESS ; Change default return value
856 TEST [BX].P_FLAGS, PF_WAIT_WAIT ; stopped/terminated?
857 JNZ SHORT WP_RET ; Yes -> found
858WP_NEXT: ADD BX, SIZE PROCESS
859 LOOP WP_LOOP
860 ASSUME BX:NOTHING
861 MOV BX, DX
862WP_RET: POP DX
863 POP ECX
864 RET
865WAIT_PROCESS ENDP
866
867;
868; Suspend process
869;
870; In: BX Pointer to process table entry
871; EAX Number of timer ticks
872;
873; Out: EAX Number of timer ticks remaining
874;
875 ASSUME BX:PTR PROCESS
876SLEEP PROC NEAR
877 PUSH CLOCK_LO
878 PUSH EAX
879 AND [BX].P_FLAGS, NOT PF_SLEEP_FLAG
880 MOV DX, TT_SLEEP
881 CALL SET_TIMER
882 JC SHORT SLEEP_DONE
883SLEEP_WAIT: MOV EAX, [BX].P_SIG_BLOCKED ; Compute set of pending,
884 NOT EAX ; unblocked signals
885 AND EAX, [BX].P_SIG_PENDING
886 JNZ SHORT SLEEP_DONE
887 TEST [BX].P_FLAGS, PF_SLEEP_FLAG
888 JZ SHORT SLEEP_WAIT
889SLEEP_DONE: POP EAX
890 POP ECX
891 SUB ECX, CLOCK_LO
892 NEG ECX ; Elapsed time
893 SUB EAX, ECX
894 JNC SHORT SLEEP_RET
895 XOR EAX, EAX
896SLEEP_RET: RET
897SLEEP ENDP
898 ASSUME BX:NOTHING
899
900
901;
902; Set a timer. If there is already a timer of the given type, the timer
903; value is set to the new value.
904;
905; In: BX Pointer to process table entry
906; DX Timer type
907; EAX Timer value (ticks), stop the timer if this is zero
908;
909; Out: CY Table overflow
910; EAX Time remaining previously
911;
912 ASSUME DS:SV_DATA
913 TALIGN 2
914SET_TIMER PROC NEAR
915 PUSH CX
916 PUSH SI
917 LEA SI, TIMER_TABLE
918 ASSUME SI:PTR TIMER
919 MOV CX, MAX_TIMERS
920 PUSH EAX
921 CLI
922 MOV EAX, TIMER_TICKS
923ST_ADJUST: SUB [SI].T_TICKS, EAX
924 ADD SI, SIZE TIMER
925 LOOP ST_ADJUST
926 MOV TIMER_TICKS, 0
927 POP EAX
928 LEA SI, TIMER_TABLE
929 MOV CX, MAX_TIMERS
930ST_FIND_LOOP: CMP [SI].T_TYPE, DX
931 JNE SHORT ST_FIND_NEXT
932 CMP [SI].T_PROCESS, BX
933 JE SHORT ST_EXISTS
934ST_FIND_NEXT: ADD SI, SIZE TIMER
935 LOOP ST_FIND_LOOP
936 OR EAX, EAX ; Stop the timer?
937 JZ SHORT ST_OK_ZERO ; Yes -> don't start it
938ST_NEW: LEA SI, TIMER_TABLE
939 MOV CX, MAX_TIMERS
940ST_NEW_LOOP: CMP [SI].T_TYPE, TT_RUNNING
941 JB SHORT ST_NEW_FOUND
942 ADD SI, SIZE TIMER
943 LOOP ST_NEW_LOOP
944 STC
945 JMP SHORT ST_RET
946
947ST_NEW_FOUND: MOV [SI].T_TICKS, EAX
948 MOV [SI].T_PROCESS, BX
949 MOV [SI].T_TYPE, DX
950 CMP TIMER_MIN, 0
951 JE SHORT ST_NEW_1
952 CMP EAX, TIMER_MIN
953 JAE SHORT ST_OK_ZERO
954ST_NEW_1: MOV TIMER_MIN, EAX
955ST_OK_ZERO: XOR EAX, EAX
956 JMP SHORT ST_OK
957
958ST_CLEAR: MOV [SI].T_TYPE, TT_NONE
959 MOV EAX, [SI].T_TICKS
960 JMP SHORT ST_OK
961
962ST_EXISTS: OR EAX, EAX
963 JZ SHORT ST_CLEAR
964 PUSH [SI].T_TICKS
965 MOV [SI].T_TICKS, EAX
966 MOV [SI].T_PROCESS, BX
967 MOV [SI].T_TYPE, DX
968 CMP TIMER_MIN, 0
969 JE SHORT ST_RESET_1
970 CMP EAX, TIMER_MIN
971 JAE SHORT ST_RESET_2
972ST_RESET_1: MOV TIMER_MIN, EAX
973ST_RESET_2: POP EAX
974ST_OK: CLC
975ST_RET: STI
976 POP SI
977 POP CX
978 RET
979 ASSUME SI:NOTHING
980SET_TIMER ENDP
981
982;
983; Set the PAGE_ALLOC bit of EBX (for SET_PAGES) if PF_COMMIT is set.
984;
985; In: EBX Process table entry
986; DI Pointer to process table entry
987;
988; Out: EBX Process table entry
989;
990 ASSUME DS:SV_DATA
991 ASSUME DI:PTR PROCESS
992 TALIGN 2
993SET_COMMIT PROC NEAR
994 TEST [DI].P_FLAGS, PF_COMMIT
995 JZ SHORT SC_RET
996 OR BX, PAGE_ALLOC
997SC_RET: RET
998 ASSUME DI:NOTHING
999SET_COMMIT ENDP
1000
1001;
1002; Find an executable file
1003;
1004; In: SI Pointer to program name
1005;
1006; Out: DX Pointer to path name
1007;
1008 ASSUME DS:SV_DATA
1009FIND_EXEC PROC NEAR
1010;
1011; Use program name as is if it contains \, /, or :
1012;
1013 MOV BX, SI
1014FE_1: MOV AL, [BX]
1015 INC BX
1016 CMP AL, "/"
1017 JE SHORT FE_DEFAULT
1018 CMP AL, "\"
1019 JE SHORT FE_DEFAULT
1020 CMP AL, ":"
1021 JE SHORT FE_DEFAULT
1022 OR AL, AL
1023 JNZ SHORT FE_1
1024;
1025; Executable file in current directory?
1026;
1027 MOVZX EDX, SI
1028 CALL ACCESS
1029 JNC SHORT FE_RET
1030;
1031; Search EMXPATH and PATH for executable file
1032;
1033 MOV AX, G_ENV_SEL
1034 MOV ES, AX
1035 LEA BX, EXEC_FNAME ; Buffer
1036 MOVZX EDI, ENV_EMXPATH
1037 OR EDI, EDI
1038 JZ SHORT FE_2
1039 CALL FIND_FILE
1040 JNC SHORT FE_OK
1041FE_2: MOVZX EDI, ENV_PATH
1042 OR EDI, EDI
1043 JZ SHORT FE_DEFAULT
1044 CALL FIND_FILE
1045 JNC SHORT FE_OK
1046;
1047; Executable file not found (or name contains "\/:"); be naive
1048;
1049FE_DEFAULT: MOVZX EDX, SI
1050 JMP SHORT FE_RET
1051;
1052; Executable file found in path
1053;
1054FE_OK: XOR EDX, EDX
1055 LEA DX, EXEC_FNAME
1056FE_RET: RET
1057FIND_EXEC ENDP
1058
1059
1060;
1061; Try to load a floating point unit emulator
1062;
1063 ASSUME DS:SV_DATA
1064FPUEMU_LOAD PROC NEAR
1065 MOV FPUEMU_STATE, FES_LOADING
1066;
1067; Find the FPU emulator
1068;
1069 CMP EMX_DIR[0], 0
1070 JE SHORT USE_PATH
1071 LEA DI, EXEC_FNAME
1072 LEA SI, EMX_DIR
1073 CALL NSTRCPY
1074 MOV DI, AX
1075 LEA SI, $FPUEMU_NAME
1076 CALL NSTRCPY
1077 LEA EDX, EXEC_FNAME
1078 CALL ACCESS
1079 JNC SHORT LOAD
1080USE_PATH: LEA SI, $FPUEMU_NAME
1081 CALL FIND_EXEC
1082;
1083; Set up NP1 for loading the FPU emulator. Don't touch the members
1084; related to the environment and to the parent process, they have been
1085; already initialized for the initial process and can be reused.
1086;
1087LOAD: MOV NP1.NP_FNAME_OFF, EDX
1088 MOV NP1.NP_FNAME_SEL, DS
1089 MOV NP1.NP_ARG_OFF, OFFSET $FPUEMU_ARG
1090 MOV NP1.NP_ARG_SEL, DS
1091 MOV NP1.NP_ARG_COUNT, 0
1092 MOV NP1.NP_ARG_SIZE, 0
1093 MOV NP1.NP_MODE1, NP_SPAWN_SYNC
1094 MOV NP1.NP_MODE2, 0
1095 LEA SI, NP1 ; Arguments
1096 CALL NEW_PROCESS ; Load the program
1097 OR AX, AX ; Ok?
1098 JNZ SHORT FAIL
1099;
1100; Put the interrupted process to sleep
1101;
1102 MOV BX, PROCESS_PTR
1103 MOV PROCESS_FPUCLIENT, BX
1104 MOV (PROCESS PTR [BX]).P_STATUS, PS_FPUEMU_CLIENT
1105 CALL SAVE_PROCESS
1106;
1107; Run the FPU emulator. Don't set PROCESS_SIG as SIGINT should be sent
1108; to the client process instead of the FPU emulator.
1109;
1110 MOV PROCESS_PTR, DI
1111 MOV BX, DI
1112 CALL REST_PROCESS
1113 CALL BREAK_AFTER_IRET ; TODO
1114 RET
1115
1116FAIL: MOV FPUEMU_STATE, FES_NONE
1117 RET
1118FPUEMU_LOAD ENDP
1119
1120;
1121; Switch to the floating point unit emulator for emulating one or more
1122; floating point instructions
1123;
1124 ASSUME DS:SV_DATA
1125 ASSUME BP:PTR ISTACKFRAME
1126FPUEMU_CALL PROC NEAR
1127;
1128; Put the interrupted process to sleep
1129;
1130 MOV DI, PROCESS_PTR
1131 ASSUME DI:PTR PROCESS
1132 MOV PROCESS_FPUCLIENT, DI
1133 MOV [DI].P_STATUS, PS_FPUEMU_CLIENT
1134 MOV BX, DI
1135 CALL SAVE_PROCESS
1136;
1137; Set up segment and FS register for the emulator
1138;
1139 MOV BX, PROCESS_FPUEMU
1140 ASSUME BX:PTR PROCESS
1141 MOV SI, [DI].P_LDT_PTR
1142 ADD SI, L_DATA_SEL AND NOT 07H
1143 MOV EAX, [SI+0]
1144 MOV EDX, [SI+4]
1145 MOV SI, [BX].P_LDT_PTR
1146 ADD SI, L_CLIENT_SEL AND NOT 07H
1147 MOV [SI+0], EAX
1148 MOV [SI+4], EDX
1149 MOV [BX].P_FS, L_CLIENT_SEL
1150;
1151; Wake up the emulator
1152;
1153 MOV PROCESS_PTR, BX
1154 CALL REST_PROCESS
1155;;;; CALL BREAK_AFTER_IRET
1156;
1157; Fill-in the communication area
1158;
1159 MOV EAX, [DI].P_NUMBER
1160 ASSUME DI:NOTHING
1161 MOV ES, I_DS
1162 MOV EDI, I_EDX
1163 ASSUME EDI:NEAR32 PTR FPUEMU_COM
1164 MOV ES:[EDI].FEC_PNUM, EAX
1165 MOV ES:[EDI].FEC_NOTIFY, FPUN_EMU
1166 MOV ES:[EDI].FEC_SIGNAL, 0
1167 LEA EDI, [EDI].FEC_FRAME
1168 MOVZX ESI, PROCESS_FPUCLIENT
1169 LEA SI, (PROCESS PTR [SI]).P_GS
1170 MOV ECX, I_REG_DWORDS
1171 REP MOVS DWORD PTR ES:[EDI], DWORD PTR DS:[ESI]
1172 MOV I_EAX, 0 ; Return 0 from __fpuemu()
1173 MOV I_ECX, 0
1174 RET
1175 ASSUME BP:NOTHING
1176 ASSUME BX:NOTHING
1177 ASSUME EDI:NOTHING
1178FPUEMU_CALL ENDP
1179
1180
1181;
1182; A process has terminated, a different process is about to be run
1183;
1184; In: EAX P_NUMBER of the terminated process
1185; BP Pointer to stack frame
1186;
1187 ASSUME DS:SV_DATA
1188 ASSUME BP:PTR ISTACKFRAME
1189FPUEMU_ENDPROC PROC NEAR
1190 CMP FPUEMU_STATE, FES_ON
1191 JNE SHORT FIN
1192 MOV FPUEMU_STATE, FES_ENDPROC
1193 PUSH EAX
1194 MOV BX, PROCESS_PTR ; Save the incoming process
1195 MOV PROCESS_FPUCLIENT, BX
1196 MOV (PROCESS PTR [BX]).P_STATUS, PS_FPUEMU_CLIENT
1197 CALL SAVE_PROCESS
1198 MOV BX, PROCESS_FPUEMU ; Restore the FPU emulator
1199 MOV PROCESS_PTR, BX
1200 CALL REST_PROCESS
1201 MOV ES, I_DS
1202 MOV EDI, I_EDX
1203 ASSUME EDI:NEAR32 PTR FPUEMU_COM
1204 POP ES:[EDI].FEC_PNUM
1205 MOV ES:[EDI].FEC_NOTIFY, FPUN_ENDPROC
1206 MOV ES:[EDI].FEC_SIGNAL, 0
1207 MOV I_EAX, 0
1208 MOV I_ECX, 0
1209FIN: RET
1210FPUEMU_ENDPROC ENDP
1211
1212
1213;
1214; A new process is about to start
1215;
1216; In: EAX P_NUMBER of the terminated process
1217; BP Pointer to stack frame
1218;
1219 ASSUME DS:SV_DATA
1220 ASSUME BP:PTR ISTACKFRAME
1221FPUEMU_NEWPROC PROC NEAR
1222 CMP FPUEMU_STATE, FES_ON
1223 JNE SHORT FIN
1224 MOV FPUEMU_STATE, FES_NEWPROC
1225 PUSH EAX
1226 MOV BX, PROCESS_PTR ; Save the incoming process
1227 MOV PROCESS_FPUCLIENT, BX
1228 MOV (PROCESS PTR [BX]).P_STATUS, PS_FPUEMU_CLIENT
1229 CALL SAVE_PROCESS
1230 MOV BX, PROCESS_FPUEMU ; Restore the FPU emulator
1231 MOV PROCESS_PTR, BX
1232 CALL REST_PROCESS
1233 MOV ES, I_DS
1234 MOV EDI, I_EDX
1235 ASSUME EDI:NEAR32 PTR FPUEMU_COM
1236 POP ES:[EDI].FEC_PNUM
1237 MOV ES:[EDI].FEC_NOTIFY, FPUN_NEWPROC
1238 MOV ES:[EDI].FEC_SIGNAL, 0
1239 MOV I_EAX, 0
1240 MOV I_ECX, 0
1241FIN: RET
1242FPUEMU_NEWPROC ENDP
1243
1244
1245SV_CODE ENDS
1246
1247;
1248; Real-mode code
1249;
1250INIT_CODE SEGMENT
1251
1252 ASSUME CS:INIT_CODE, DS:NOTHING
1253
1254
1255 ASSUME DS:SV_DATA
1256
1257PROCESS_INIT PROC NEAR
1258 LEA BX, PROCESS_TABLE
1259 ASSUME BX:PTR PROCESS
1260 MOV CX, MAX_PROCESSES
1261PI_LOOP_PROC: MOV [BX].P_PID, NO_PID
1262 MOV [BX].P_STATUS, PS_NONE
1263 MOV [BX].P_EXEC_HANDLE, NO_FILE_HANDLE
1264 MOV SI, 0
1265PI_LOOP_HANDLE: MOV [BX].P_HANDLES[SI], NO_FILE_HANDLE
1266 MOV [BX].P_HFLAGS[SI], 0
1267 ADD SI, 2
1268 CMP SI, 2 * MAX_FILES
1269 JB SHORT PI_LOOP_HANDLE
1270 ADD BX, SIZE PROCESS
1271 LOOP PI_LOOP_PROC
1272 ASSUME BX:NOTHING
1273 MOV PROCESS_PTR, NO_PROCESS
1274 MOV PROCESS_SIG, NO_PROCESS
1275 MOV PROCESS_FP, NO_PROCESS ; Noone is using the FPU
1276 MOV PROCESS_FPUEMU, NO_PROCESS ; No emulator loaded
1277;
1278; Initialize dummy parent process. INIT_FILEIO has already initialized
1279; the P_HANDLES and P_HFLAGS arrays of PROC0.
1280;
1281 MOV PROC0.P_PID, 0
1282 MOV PROC0.P_STATUS, PS_INIT
1283 MOV PROC0.P_FLAGS, 0
1284 MOV PROC0.P_TRUNC, 0
1285 MOV PROC0.P_UMASK, 022Q
1286 MOV PROC0.P_UMASK1, 644Q
1287 MOV PROC0.P_PRF_SCALE, 0
1288
1289 MOV CX, SIGNALS
1290 MOV BX, 0
1291PI_LOOP_SIG: MOV PROC0.P_SIG_HANDLERS[BX], SIG_DFL
1292 MOV PROC0.P_SA_MASK[BX], 0
1293 MOV PROC0.P_SA_FLAGS[BX], SA_ACK
1294 ADD BX, 4
1295 LOOP PI_LOOP_SIG
1296
1297 MOV PROC0.P_SIG_PENDING, 0
1298 MOV PROC0.P_SIG_BLOCKED, NOT 0 ; No signals allowed
1299 MOV PROC0.P_EXEC_HANDLE, NO_FILE_HANDLE
1300 RET
1301PROCESS_INIT ENDP
1302
1303INIT_CODE ENDS
1304
1305 END
Note: See TracBrowser for help on using the repository browser.