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 |
|
---|
53 | SV_DATA SEGMENT
|
---|
54 |
|
---|
55 | NO_PID = 0FFFFFFFFH
|
---|
56 | MIN_PID = 2
|
---|
57 |
|
---|
58 | NEXT_PID DD MIN_PID ; Next process ID
|
---|
59 | PROCESS_PTR DW ? ; PTE of current process
|
---|
60 | PROCESS_SIG DW ? ; Ditto, not changed for I/O
|
---|
61 | PROCESS_FP DW ? ; The coprocessor contains
|
---|
62 | ; the status of this process
|
---|
63 | PROCESS_FPUEMU DW ? ; FPU emulator PTE
|
---|
64 | PROCESS_FPUCLIENT DW ? ; FPU client PTE
|
---|
65 | VIDEO_LIN DD ? ; Linear address of video mem
|
---|
66 |
|
---|
67 | TIMER_MIN DD 0
|
---|
68 | TIMER_TICKS DD 0
|
---|
69 |
|
---|
70 | CLOCK_LO DWORD 0
|
---|
71 | CLOCK_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 | ;
|
---|
78 | PROCESS_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 | ;
|
---|
83 | PROC0 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
|
---|
97 | TIMER_TABLE TIMER MAX_TIMERS DUP (<TT_NONE, NO_PROCESS>)
|
---|
98 |
|
---|
99 | ;
|
---|
100 | ; Temporary variables
|
---|
101 | ;
|
---|
102 | ARGV_SIZE DD ?
|
---|
103 | ENVP_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 | ;
|
---|
110 | EMX_DIR DB 100 DUP (?)
|
---|
111 |
|
---|
112 | ;
|
---|
113 | ; The result of FIND_EXEC is stored here.
|
---|
114 | ;
|
---|
115 | EXEC_FNAME BYTE 256 DUP (?)
|
---|
116 |
|
---|
117 | ;
|
---|
118 | ; State of the FPU emulator
|
---|
119 | ;
|
---|
120 | FPUEMU_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 | ;
|
---|
142 | NP1 NEW_PROC <>
|
---|
143 |
|
---|
144 | SV_DATA ENDS
|
---|
145 |
|
---|
146 |
|
---|
147 | SV_CODE SEGMENT
|
---|
148 |
|
---|
149 | ASSUME CS:SV_CODE, DS:NOTHING
|
---|
150 |
|
---|
151 | NP_FRAME_SIZE = 4
|
---|
152 | NP_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
|
---|
166 | NEW_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 |
|
---|
193 | LOAD_OK: CALL NP_FILES
|
---|
194 | CALL NP_SIGNALS
|
---|
195 | CALL NP_STACK
|
---|
196 | CALL NP_REGS
|
---|
197 | XOR AX, AX ; Success
|
---|
198 | NP_RET: ADD ESP, NP_FRAME_SIZE
|
---|
199 | POP EBP
|
---|
200 | RET
|
---|
201 | ASSUME SI:NOTHING
|
---|
202 | ASSUME DI:NOTHING
|
---|
203 | NEW_PROCESS ENDP
|
---|
204 |
|
---|
205 | ;
|
---|
206 | ; Check mode
|
---|
207 | ;
|
---|
208 | ASSUME SI:PTR NEW_PROC
|
---|
209 | NP_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
|
---|
221 | NP_CM_RET: RET
|
---|
222 | ASSUME SI:NOTHING
|
---|
223 | NP_CHECK_MODE ENDP
|
---|
224 |
|
---|
225 |
|
---|
226 | ;
|
---|
227 | ; Find empty process table slot
|
---|
228 | ;
|
---|
229 | ; Out: DI Pointer to process table entry
|
---|
230 | ;
|
---|
231 | NP_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
|
---|
237 | NP_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
|
---|
245 | NP_FS_RET: RET ; Done
|
---|
246 | NP_FIND_SLOT ENDP
|
---|
247 |
|
---|
248 |
|
---|
249 | ;
|
---|
250 | ; Create unique process ID
|
---|
251 | ;
|
---|
252 | TALIGN 2
|
---|
253 | CREATE_PID PROC NEAR
|
---|
254 | PUSH BX
|
---|
255 | NP_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 |
|
---|
265 | NP_CP_WRAP: MOV NEXT_PID, MIN_PID
|
---|
266 | JMP SHORT NP_CP_LOOP
|
---|
267 | CREATE_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
|
---|
276 | NP_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
|
---|
301 | NP_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
|
---|
317 | NP_SET_TAB ENDP
|
---|
318 |
|
---|
319 | ;
|
---|
320 | ; Create segments
|
---|
321 | ;
|
---|
322 | ASSUME DI:PTR PROCESS
|
---|
323 | NP_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
|
---|
357 | NP_SEGMENTS ENDP
|
---|
358 |
|
---|
359 |
|
---|
360 | ;
|
---|
361 | ; Create stdin/stdout/stderr handles, inherit open files
|
---|
362 | ;
|
---|
363 | ASSUME DI:PTR PROCESS
|
---|
364 | NP_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
|
---|
373 | NP_FILES ENDP
|
---|
374 |
|
---|
375 |
|
---|
376 | ;
|
---|
377 | ; Setup signal handling
|
---|
378 | ;
|
---|
379 | ASSUME DI:PTR PROCESS
|
---|
380 | NP_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
|
---|
391 | NP_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
|
---|
395 | NP_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
|
---|
404 | NP_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
|
---|
412 | NP_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
|
---|
485 | QUOTE_NO: MOV AL, 00H
|
---|
486 | JMP SHORT QUOTE_1
|
---|
487 | QUOTE_YES: MOV AL, 01H
|
---|
488 | QUOTE_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
|
---|
503 | NP_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
|
---|
512 | NP_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
|
---|
525 | NP_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 | ;
|
---|
538 | PCOPY 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
|
---|
561 | PCOPY1: MOV ES:[EBX], EDI ; Put pointer
|
---|
562 | ADD DWORD PTR ES:[EBX], EBP ; Skip flag byte
|
---|
563 | ADD EBX, 4
|
---|
564 | PCOPY2: LODS BYTE PTR DS:[ESI]
|
---|
565 | STOS BYTE PTR ES:[EDI]
|
---|
566 | OR AL, AL
|
---|
567 | JNZ SHORT PCOPY2
|
---|
568 | LOOP PCOPY1
|
---|
569 | PCOPY3: 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
|
---|
576 | PCOPY 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 | ;
|
---|
585 | PQUOTE PROC NEAR
|
---|
586 | PUSH EDI
|
---|
587 | MOV DI, G_TMP2_SEL
|
---|
588 | MOV ES, DI
|
---|
589 | PQ_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
|
---|
596 | PQ_RET: POP EDI
|
---|
597 | RET
|
---|
598 | PQUOTE 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
|
---|
608 | FIND_PROCESS PROC NEAR
|
---|
609 | PUSH ECX
|
---|
610 | LEA BX, PROCESS_TABLE
|
---|
611 | ASSUME BX:PTR PROCESS
|
---|
612 | MOV CX, MAX_PROCESSES
|
---|
613 | FP1: CMP EAX, [BX].P_PID
|
---|
614 | JE SHORT FP2
|
---|
615 | ADD BX, SIZE PROCESS
|
---|
616 | LOOP FP1
|
---|
617 | MOV BX, NO_PROCESS
|
---|
618 | FP2: POP ECX
|
---|
619 | RET
|
---|
620 | ASSUME BX:NOTHING
|
---|
621 | FIND_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
|
---|
631 | ZOMBIE_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
|
---|
637 | ZOMBIE_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
|
---|
647 | REMOVE_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
|
---|
653 | REMOVE_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
|
---|
665 | KILL_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
|
---|
670 | KILL_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
|
---|
679 | FREE_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
|
---|
689 | FP_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
|
---|
698 | FP_PROFIL_1:
|
---|
699 | ;
|
---|
700 | ; Reclaim timers
|
---|
701 | ;
|
---|
702 | LEA SI, TIMER_TABLE
|
---|
703 | ASSUME SI:PTR TIMER
|
---|
704 | MOV CX, MAX_TIMERS
|
---|
705 | FP_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
|
---|
709 | FP_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
|
---|
733 | RP_1: POP SI
|
---|
734 | POP CX
|
---|
735 | POP AX
|
---|
736 | RET
|
---|
737 | ASSUME BX:NOTHING
|
---|
738 | FREE_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
|
---|
752 | SAVE_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
|
---|
773 | SAVE_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
|
---|
791 | REST_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
|
---|
822 | RP_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
|
---|
832 | REST_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
|
---|
844 | WAIT_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
|
---|
851 | WP_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
|
---|
858 | WP_NEXT: ADD BX, SIZE PROCESS
|
---|
859 | LOOP WP_LOOP
|
---|
860 | ASSUME BX:NOTHING
|
---|
861 | MOV BX, DX
|
---|
862 | WP_RET: POP DX
|
---|
863 | POP ECX
|
---|
864 | RET
|
---|
865 | WAIT_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
|
---|
876 | SLEEP 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
|
---|
883 | SLEEP_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
|
---|
889 | SLEEP_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
|
---|
896 | SLEEP_RET: RET
|
---|
897 | SLEEP 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
|
---|
914 | SET_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
|
---|
923 | ST_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
|
---|
930 | ST_FIND_LOOP: CMP [SI].T_TYPE, DX
|
---|
931 | JNE SHORT ST_FIND_NEXT
|
---|
932 | CMP [SI].T_PROCESS, BX
|
---|
933 | JE SHORT ST_EXISTS
|
---|
934 | ST_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
|
---|
938 | ST_NEW: LEA SI, TIMER_TABLE
|
---|
939 | MOV CX, MAX_TIMERS
|
---|
940 | ST_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 |
|
---|
947 | ST_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
|
---|
954 | ST_NEW_1: MOV TIMER_MIN, EAX
|
---|
955 | ST_OK_ZERO: XOR EAX, EAX
|
---|
956 | JMP SHORT ST_OK
|
---|
957 |
|
---|
958 | ST_CLEAR: MOV [SI].T_TYPE, TT_NONE
|
---|
959 | MOV EAX, [SI].T_TICKS
|
---|
960 | JMP SHORT ST_OK
|
---|
961 |
|
---|
962 | ST_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
|
---|
972 | ST_RESET_1: MOV TIMER_MIN, EAX
|
---|
973 | ST_RESET_2: POP EAX
|
---|
974 | ST_OK: CLC
|
---|
975 | ST_RET: STI
|
---|
976 | POP SI
|
---|
977 | POP CX
|
---|
978 | RET
|
---|
979 | ASSUME SI:NOTHING
|
---|
980 | SET_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
|
---|
993 | SET_COMMIT PROC NEAR
|
---|
994 | TEST [DI].P_FLAGS, PF_COMMIT
|
---|
995 | JZ SHORT SC_RET
|
---|
996 | OR BX, PAGE_ALLOC
|
---|
997 | SC_RET: RET
|
---|
998 | ASSUME DI:NOTHING
|
---|
999 | SET_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
|
---|
1009 | FIND_EXEC PROC NEAR
|
---|
1010 | ;
|
---|
1011 | ; Use program name as is if it contains \, /, or :
|
---|
1012 | ;
|
---|
1013 | MOV BX, SI
|
---|
1014 | FE_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
|
---|
1041 | FE_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 | ;
|
---|
1049 | FE_DEFAULT: MOVZX EDX, SI
|
---|
1050 | JMP SHORT FE_RET
|
---|
1051 | ;
|
---|
1052 | ; Executable file found in path
|
---|
1053 | ;
|
---|
1054 | FE_OK: XOR EDX, EDX
|
---|
1055 | LEA DX, EXEC_FNAME
|
---|
1056 | FE_RET: RET
|
---|
1057 | FIND_EXEC ENDP
|
---|
1058 |
|
---|
1059 |
|
---|
1060 | ;
|
---|
1061 | ; Try to load a floating point unit emulator
|
---|
1062 | ;
|
---|
1063 | ASSUME DS:SV_DATA
|
---|
1064 | FPUEMU_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
|
---|
1080 | USE_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 | ;
|
---|
1087 | LOAD: 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 |
|
---|
1116 | FAIL: MOV FPUEMU_STATE, FES_NONE
|
---|
1117 | RET
|
---|
1118 | FPUEMU_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
|
---|
1126 | FPUEMU_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
|
---|
1178 | FPUEMU_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
|
---|
1189 | FPUEMU_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
|
---|
1209 | FIN: RET
|
---|
1210 | FPUEMU_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
|
---|
1221 | FPUEMU_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
|
---|
1241 | FIN: RET
|
---|
1242 | FPUEMU_NEWPROC ENDP
|
---|
1243 |
|
---|
1244 |
|
---|
1245 | SV_CODE ENDS
|
---|
1246 |
|
---|
1247 | ;
|
---|
1248 | ; Real-mode code
|
---|
1249 | ;
|
---|
1250 | INIT_CODE SEGMENT
|
---|
1251 |
|
---|
1252 | ASSUME CS:INIT_CODE, DS:NOTHING
|
---|
1253 |
|
---|
1254 |
|
---|
1255 | ASSUME DS:SV_DATA
|
---|
1256 |
|
---|
1257 | PROCESS_INIT PROC NEAR
|
---|
1258 | LEA BX, PROCESS_TABLE
|
---|
1259 | ASSUME BX:PTR PROCESS
|
---|
1260 | MOV CX, MAX_PROCESSES
|
---|
1261 | PI_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
|
---|
1265 | PI_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
|
---|
1291 | PI_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
|
---|
1301 | PROCESS_INIT ENDP
|
---|
1302 |
|
---|
1303 | INIT_CODE ENDS
|
---|
1304 |
|
---|
1305 | END
|
---|