Changeset 1281 for trunk/doc/Fork.os2
- Timestamp:
- Mar 6, 2004, 10:48:26 PM (22 years ago)
- File:
-
- 1 edited
-
trunk/doc/Fork.os2 (modified) (11 diffs, 1 prop)
Legend:
- Unmodified
- Added
- Removed
-
trunk/doc/Fork.os2
-
Property cvs2svn:cvs-rev
changed from
1.2to1.3
r1280 r1281 162 162 3. Extended versions of some memory related OS/2 APIs must be implemented. 163 163 164 The implemen etation will further make the following assumption about the164 The implementation will further make the following assumption about the 165 165 operation of OS/2: 166 166 1. DosExecPgm will not return till all DLLs are initated successfully. 167 167 2. DosQueryMemState() is broken if more than one page is specified. 168 (no idea why/how/where it's broken, but testcase shows it is :/ ) 168 169 169 170 … … 171 172 --------------------------------- 172 173 173 The fork() implementation requires a method oftelling the child process174 The fork() implementation requires a method telling the child process 174 175 that it's being forked and must take a very different startup route. For 175 some other LIBC apis there isneed for parent -> child and child -> parent176 some other LIBC apis there need for parent -> child and child -> parent 176 177 information exchange. More specifically, the inheritance of sockets, 177 178 signals, the different scheduler actions of a posix_spawn[p]() call, and 178 179 possibly some process group stuff related to posix_spawn too if we get it 179 180 figured out eventually. All this was parent -> child during spawn/fork. A 180 need exist alsofor child -> parent notification and possibly exchange for181 need for child -> parent notification and possibly exchange for 181 182 process termination. It might be necessary to reimplement the different 182 183 wait apis and implement SIGCHLD, it's likely that those tasks will make … … 184 185 185 186 The choice is now whether or not to make this shared process management 186 specific to each LIBC version or try to make it survive normal LIBC updates. 187 Making is specific have advantages in code size and memory footprint (no 188 reserved field), however it have certain disadvantages when LIBC is updated. 189 The other option is to use a named shared memory object, defining the 190 content with reserved space for later extensions so several versions of 191 LIBC with more or less features implemented can co use the memory space. 187 specific to each LIBC version as a shared segement or try to make it 188 survive normal LIBC updates. Making is specific have advantages in code 189 size and memory footprint (no reserved fields), however it have certain 190 disadvantages when LIBC is updated. The other option is to use a named 191 shared memory object, defining the content with reserved space for later 192 extensions so several versions of LIBC with more or less features 193 implemented can co use the memory space. 192 194 193 195 The latter option is prefered since it allows more applications to … … 196 198 processes using multiple versions of LIBC. 197 199 198 The shared memory mustbe named \SHAREMEM\INNOTEKLIBC.V01, the version200 The shared memory be named \SHAREMEM\INNOTEKLIBC.V01, the version 199 201 number being the one of the shared memory layout and contents, it will 200 202 only be increased when incompatible changes are made. 201 203 202 The shared memory will be protected by an standard OS/2 mutex semaphore.203 It will not use any fast R3 semaphore since the the usage frequency is low204 and the result of a messup may be disastrous. Care must be take for204 The shared memory ll be protected by an standard OS/2 mutex semaphore. 205 It 206 and the result of a messup may be disastrous. Care must be take for 205 207 avoiding creation races and owner died scenarios. 206 208 207 The memory will have a fixed size, since adding segments is very hard.209 The memory ll have a fixed size, since adding segments is very hard. 208 210 Thus the size must be large enough to cope with a great deal of 209 processes, butbearing in mind that OS/2 normally doesn't support more211 processes, bearing in mind that OS/2 normally doesn't support more 210 212 than a 1000 processes, with a theoritical max of some 4000 (being the 211 213 max thread count). A very simplistic allocation scheme will be … … 214 216 lists a linked list based heap would do fine. 215 217 216 The process blocks will be rounded up to in size adding a reasonable218 The process blocks ll be rounded up to in size adding a reasonable 217 219 amount of space resevered for future extensions. Reserved space must be 218 220 all zeroed. 219 221 220 The fork() specific members of the process block will be a pointer to222 The fork() specific members of the process block ll be a pointer to 221 223 the shared memory object for the fork operation (the fork handle) and 222 224 list of forkable modules. The fork handle will it self contain … … 227 229 the forking of each module. (more details in section 4.0) 228 230 229 The parent will before spawn, fork and exec (essentially before DosExecPgm231 The parent ll before spawn, fork and exec (essentially before DosExecPgm 230 232 or DosStartSession) create a process block for the child to be born and 231 link it into an embryo list in the shared memory block. The child will 232 find the process block by looking searching an embryo list using the 233 parent pid as key. All DosExecPgm and DosStartSession calls are 234 serialized within one LIBC version. (If some empty headed programmer 235 manages to link together a program which may end up using two or more 236 LIBC versions and having two or more thread doing DosExecPgm at the 237 very same time, well then he really deserves what ever trouble he gets! 238 At least don't blame me!) 239 240 Process blocks will have to stay around after the process terminated 233 link it into an embryo list in the shared memory block. The child shall 234 find it's process block by searching the embryo list using the parent pid 235 as key. All DosExecPgm and DosStartSession calls shall be serialized within 236 one LIBC version. (If some empty headed programmer manages to link together 237 a program which may end up using two or more LIBC versions and having two 238 or more thread doing DosExecPgm at the very same time, well then he really 239 deserves what ever trouble he gets! At least don't blame me!) 240 241 Process blocks shall have to stay around after the process terminated 241 242 (for child -> parent term exchange), a cleanup mechanism will be invoked 242 243 whenever a free memory threshold is reached. All processes will register … … 250 251 251 252 252 The implementation will bebased on a fork handle and a set of primitives.253 The implementation based on a fork handle and a set of primitives. 253 254 The fork handle is a pointer to an shared memory object allocated for the 254 255 occation and which will be freed before fork() returns. The primitives … … 261 262 262 263 The support for fork() is an optional feature of LIBC. The default 263 executable produced with LIBC and GCC willnot be forkable. The fork264 executable produced with LIBC and GCC not be forkable. The fork 264 265 support will be based on registration of the DLLs and EXEs in their 265 266 LIBC supplied startup code (crt0/dll0). A set of fork versions of these 266 modules will be made.267 modules . 267 268 268 269 The big differnece between the ordinary crt0/dll0 and the forkable … … 270 271 handling of the return code of that call. 271 272 272 The structure will contain these fields: 273 - chain pointer. 274 - data segment base address. 275 - data segment end address. 276 - fork callback function. 277 278 The fork callback function is called _atfork_callback, it takes the fork 273 The fork module structure: 274 typedef struct __libc_ForkModule 275 { 276 /** Structure version. (Initially 'FMO1' as viewed in hex editor.) */ 277 unsigned int iMagic; 278 /** Fork callback function */ 279 int (*pfnAtFork)(__LIBC_FORKMODULE *pModule, 280 __LIBC_FORKHANDLE *pForkHandle, enum __LIBC_CALLBACKOPERATION enmOperation); 281 /** Pointer to the _CRT_FORK_PARENT1 set vector. 282 * It's formatted as {priority,callback}. */ 283 void *pvParentVector1; 284 /** Pointer to the _CRT_FORK_CHILD1 set vector. 285 * It's formatted as {priority,callback}. */ 286 void *pvChildVector1; 287 /** Data segment base address. */ 288 void *pvDataSegBase; 289 /** Data segment end address (exclusive). */ 290 void *pvDataSegEnd; 291 /** Reserved - must be zero. */ 292 int iReserved1; 293 } __LIBC_FORKMODULE, *__LIBC_PFORKMODULE; /* urg! conventions */ 294 295 296 The fork callback function which crt0/dll0 references when initializing 297 the fork modules structure is called _atfork_callback. It takes the fork 279 298 handle, module structure, and an operation enum as arguments. LIBC will 280 299 contain a default implementation of _atfork_callback() which simply 281 duplicates the data segment. 282 283 The register call, __libc_ForkRegisterModule(), will return: 284 - 0 if normal process startup. no forking. 285 - 1 if fork() is in progress. The crt0/dll0 code will then 286 not call any standard initiation code, but let the 287 _atfork_callback() do all necessary stuff. 300 duplicates the data segment, and processes the two set vectors 301 (_CRT_FORK_*1). 302 303 crt0/dll0 will register the fork module structure and detect a forked 304 child by calling __libc_ForkRegisterModule(). 305 306 Prototypes: 307 /** 308 * Register a forkable module. Called by crt0 and dll0. 309 * 310 * The call links pModule into the list of forkable modules 311 * which is maintained in the process block. 312 * 313 * @returns 0 on normal process startup. 314 * @returns 1 on forked child process startup. 315 * The caller should respond by not calling any _DLL_InitTerm 316 * or similar constructs. 317 * @returns negative on failure. 318 * The caller should return from the dll init returning FALSE 319 * or DosExit in case of crt0. _atfork_callback() will take 320 * care of necessary module initiation. 321 * @param pModule Pointer to the fork module structure for the 322 * module which is to registered. 323 */ 324 int __libc_ForkRegisterModule(__LIBC_FORKMODULE *pModule); 325 326 327 288 328 289 329 … … 292 332 293 333 These primitives are provided by the fork implementation in the fork 294 handle structure. We will define a set of these primitives now, if295 laternew ones are added the users of these must check that they are334 handle structure. We 335 new ones are added the users of these must check that they are 296 336 actually present. 297 337 … … 347 387 */ 348 388 int pfnFlush(__LIBC_FORKHANDLE *pForkHandle); 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 349 414 ... 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 -
Property cvs2svn:cvs-rev
changed from
Note:
See TracChangeset
for help on using the changeset viewer.
