home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / std_unix / volume.27 / text0084.txt < prev    next >
Encoding:
Text File  |  1992-05-20  |  58.3 KB  |  1,566 lines

  1. Submitted-by: knighten@intel.com (Robert L. Knighten)
  2.  
  3. Draft 6 of the P1003.4a (Threads Extension) draft standard is in its second
  4. ballot (first reballot.)  This ballot is due at the IEEE Standards Office on
  5. May 1.
  6.  
  7. The following group met and drafted a Common Reference Ballot which
  8. we hope will be considered by other members of the ballot group before they
  9. submit their own ballots.  Our CRB is included at the end of this message.
  10.  
  11. The CRB will be submitted as the first 70 items in the ballot of
  12. Robert L. Knighten of Intel Supercomputer Systems Division.
  13.  
  14. Nawaf Bitar             Kubota-Pacific
  15. David Black             Open Software Foundation
  16. Bob Conti               Digital Equipment Corporation
  17. Bill Cox                Unix Systems Laboratories
  18. Michael Jones           Carneige-Mellon University
  19. Steve Kleiman           SunSoft
  20. Bob Knighten            Intel Supercomputer Systems Division
  21. Jim Pitcairn-Hill       Open Software Foundation
  22. Dave Plauger            Hewlett-Packard
  23. Paul Rabin              Open Software Foundation
  24.  
  25. This CRB is also available in various forms (ASCII, postscript, troff) by
  26. anonymous ftp from export.ssd.intel.com in the directory /pub/tmp/CRB.
  27.  
  28. ==============================================================================
  29. Robert L. Knighten  P1003.4a/D6 Ballot 4/3/92
  30. knighten@ssd.intel.com                (503) 629-4315 FAX 629-9147
  31.  
  32. --------------------------------------------------------------------------
  33. @ all o 1
  34. 1: Section all  page all  line(s) all
  35.  
  36. OBJECTION:
  37.  
  38.      The use of errno is a mistake with new functions.  Existing POSIX.1
  39.      functions and their close relatives should maintain their overall
  40.      structure, as should those tied to existing practice.  The use of
  41.      errno as a global error indicator in multithreaded environments intro-
  42.      duces new difficulties and inefficiencies.
  43.  
  44. ACTION:
  45.  
  46.      New functions should not set a global errno, but instead return an er-
  47.      ror indication as the function return value.  The only exception are
  48.      functions such as pthread_exit() which do not return, and
  49.      pthread_self() which cannot fail.  We do not provide synopses for all
  50.      such functions, but will on request from the technical reviewers.
  51.  
  52.      Change all new functions such as all pthread_ functions to return an
  53.      error indication on failure, as described above.
  54.  
  55. --------------------------------------------------------------------------
  56. @ all o 2
  57. 2: Section all  page all  line(s) all
  58.  
  59. OBJECTION:
  60.  
  61.      The deletion of the POSIX.4 memory model leaves a void in terms of the
  62.      specification of memory access characteristics.  While the CRB group
  63.      is not particularly enamored with the POSIX.4 memory model, we feel
  64.      something is required in this space.
  65.  
  66. ACTION:
  67.  
  68.      Specify a memory model for POSIX.4a.  You may contact Nawaf Bitar to
  69.      coordinate assistance in the development of a memory model.
  70.  
  71. --------------------------------------------------------------------------
  72. @ 2 o 3
  73. 3: Section 2  page 2.2  line(s) 4
  74.  
  75. OBJECTION:
  76.  
  77.      The term "allocation domain" does not clearly refer to a scheduling
  78.      allocation.
  79.  
  80. ACTION:
  81.  
  82.      Change the defined term to "Scheduling Allocation Domain [Allocation
  83.      Domain]".
  84.  
  85. --------------------------------------------------------------------------
  86. @ 2 o 4
  87. 4: Section 2  page 2.2  line(s) 5
  88.  
  89. OBJECTION:
  90.  
  91.      The term "contention scope domain" does not clearly refer to a
  92.      scheduling contention scope.
  93.  
  94. ACTION:
  95.  
  96.      Change the defined term to "Scheduling Contention Scope [Contention
  97.      Scope]".
  98.  
  99. --------------------------------------------------------------------------
  100. @ 2.2 o 5
  101. 5: Section 2.2  page 5  line(s) 80-81
  102.  
  103. OBJECTION:
  104.  
  105.      With the inclusion of the process shared attribute mutexes and other
  106.      synchronization primitives can be used in shared memory by more than
  107.      one processes.
  108.  
  109. ACTION:
  110.  
  111.      Delete lines 80-81.
  112.  
  113. --------------------------------------------------------------------------
  114. @ 2.2 o 6
  115. 6: Section 2.2  page 5  line(s) 98-99
  116.  
  117. OBJECTION:
  118.  
  119.      The set of synchronous signal that can be generated is not limited to
  120.      the list in the text. For example SIGBUS.
  121.  
  122. ACTION:
  123.  
  124.      Either correct the list or change it to the following:
  125.              The signals which may be generaed synchronously include SI-
  126.      GILL,
  127.              SIGFPE, ...
  128.  
  129. --------------------------------------------------------------------------
  130. @ 2.2 o 7
  131. 7: Section 2.2  page 6  line(s) 104
  132.  
  133. OBJECTION:
  134.  
  135.      "with a thread" doesn't make sense.
  136.  
  137. ACTION:
  138.  
  139.      Change "with a thread" to "by a thread."
  140.  
  141. --------------------------------------------------------------------------
  142. @ 2.2 o 8
  143. 8: Section 2.2  page 6  line(s) 115-116
  144.  
  145. OBJECTION:
  146.  
  147.      It should be permissible to use the thread ID of a detached thread if
  148.      the application knows via programmed synchronization that the target
  149.      thread has not exited. Note that a thread cannot spontaneously exit
  150.      without calling pthread_exit(), being cancelled (and running the can-
  151.      cellation handlers), or the process exits.
  152.  
  153. ACTION:
  154.  
  155.      Delete the sentence beginning "Detaching a thread also prohibits..."
  156.      or change it to indicate that if the application know via programmed
  157.      synchronization mechanisms that the thread has not exited then using
  158.      the thread ID is permissible.
  159.  
  160. --------------------------------------------------------------------------
  161. @ 2.2.1.138,6 o 9
  162. 9: Section 2.2.1.138,6  page 4,79-101  line(s) 64-65,1-762
  163.  
  164. OBJECTION:
  165.  
  166.      The terms global and local contention scope are misleading.  [See ob-
  167.      jection ???.]  The terms system and process contention scope are more
  168.      intuitive.
  169.  
  170. ACTION:
  171.  
  172.      Change PTHREAD_SCOPE_GLOBAL to PTHREAD_SCOPE_SYSTEM.  Change
  173.      PTHREAD_SCOPE_LOCAL to PTHREAD_SCOPE_PROCESS.  Change all references
  174.      to `global contention scope' to `system contention scope'.  Change all
  175.      references to `local contention scope' to `process contention scope'.
  176.  
  177. --------------------------------------------------------------------------
  178. @ 2.2.1.139 o 10
  179. 10: Section 2.2.1.139  page 5  line(s) 66-69
  180.  
  181. OBJECTION:
  182.  
  183.      The definition of "initial thread" is misleading, and a holdover from
  184.      older drafts with very different semantics.  In particular, calling
  185.      the thread which results from fork() an initial thread is wrong with
  186.      respect to the current usage of the term in the draft.
  187.  
  188. ACTION:
  189.  
  190.      Replace the definition of "initial thread" with "The first thread
  191.      which calls main() after an exec, or any thread resulting from a
  192.      fork() by an initial thread".
  193.  
  194. --------------------------------------------------------------------------
  195. @ 2.6.2 o 11
  196. 11: Section 2.6.2  page 14  line(s) 388
  197.  
  198. OBJECTION:
  199.  
  200.      The constant name "DATAKEYS_MAX" does not follow the pthreads naming
  201.      conventions.
  202.  
  203. ACTION:
  204.  
  205.      Change the name to "PTHREAD_DATAKEYS_MAX".  Similarly, change
  206.      "_POSIX_DATAKEYS_MAX" to "_POSIX_PTHREAD_DATAKEYS_MAX".
  207.  
  208. --------------------------------------------------------------------------
  209. @ 3 o 12
  210. 12: Section 3  page all  line(s) all
  211.  
  212. OBJECTION:
  213.  
  214.      The use of ENOSYS as an error return requires that all implementations
  215.      maintain stubs simply to return an error.  This is silly: the linkage
  216.      editor can easily report that a particular function is not available.
  217.  
  218. ACTION:
  219.  
  220.      Eliminate all [ENOSYS] errors in this Chapter.  If the only error is
  221.      ENOSYS under a descriptive lead-in paragraph, delete the lead-in para-
  222.      graph as well.
  223.  
  224. --------------------------------------------------------------------------
  225. @ 3 o 13
  226. 13: Section 3  page all  line(s) all
  227.  
  228. OBJECTION:
  229.  
  230.      The use of errno is a mistake with new functions.  Existing POSIX.1
  231.      functions and their close relatives should maintain their overall
  232.      structure, as should those tied to existing practice.  The use of
  233.      errno as a global error indicator in multithreaded environments intro-
  234.      duces new difficulties and inefficiencies.
  235.  
  236. ACTION:
  237.  
  238.      New functions should not set a global errno, but instead return an er-
  239.      ror indication as the function return value.  The only exception are
  240.      functions such as pthread_exit() which do not return, and
  241.      pthread_self() which cannot fail.  We do not provide synopses for all
  242.      such functions, but will on request from the technical reviewers.
  243.  
  244.      Change all new functions such as all pthread_ functions to return an
  245.      error indication on failure, as described above.
  246.  
  247. --------------------------------------------------------------------------
  248. @ 3.3 o 14
  249. 14: Section 3.3  page 29-30  line(s) 408-444
  250.  
  251. OBJECTION:
  252.  
  253.      The function pthread_exit() terminates a thread; if you have pthreads
  254.      at all, the fundamental management routines pthread_create(),
  255.      pthread_join, pthread_exit, and pthread_self are essential.  Permit-
  256.      ting any of those functions to be optional in any way means that you
  257.      don't have threads that you can use.  How can an application use the
  258.      fact that pthread_exit() fail?  How can a function that cannot return
  259.      (line 438) "return 01 and set errno to the corresponding value"?
  260.  
  261. ACTION:
  262.  
  263.      Delete all error return specification from the pthread_exit() specifi-
  264.      cation.
  265.  
  266. --------------------------------------------------------------------------
  267. @ 3.3 o 15
  268. 15: Section 3.3  page 29-30  line(s) 412-471
  269.  
  270. OBJECTION:
  271.  
  272.      The parameter name "status" is misleading.  The actual use of the
  273.      pthread_exit parameter is the return value from the start_function ex-
  274.      ecuted by the thread.
  275.  
  276. ACTION:
  277.  
  278.      Change the synopsis to
  279.  
  280.      void pthread_exit( void *value_ptr);
  281.  
  282. --------------------------------------------------------------------------
  283. @ 3.3 o 16
  284. 16: Section 3.3  page 30  line(s) 431-433,463-471
  285.  
  286. OBJECTION:
  287.  
  288.      This return status makes no sense.  The success or failure of a pro-
  289.      cess is not determined by whether the last thread to exit was de-
  290.      tached.  The exit status for the process should be determined by the
  291.      parameter to an explicit _exit() call or the return value to main() as
  292.      specified in POSIX.1.
  293.  
  294. ACTION:
  295.  
  296.      Delete lines 431-433 and 463-471.
  297.  
  298. --------------------------------------------------------------------------
  299. @ 3.3 o 17
  300. 17: Section 3.3  page 30  line(s) 459-462
  301.  
  302. OBJECTION:
  303.  
  304.      ANSI C does not generally require implementations to preserve integer
  305.      values across multiple typecasts.  The example is non-portable and
  306.      should be deleted.
  307.  
  308. ACTION:
  309.  
  310.      Delete text starting at "it is perfectly" and terminate the sentence.
  311.  
  312. --------------------------------------------------------------------------
  313. @ 3.3.5.2, 7.3.3.2 o 18
  314. 18: Section 3.3.5.2, 7.3.3.2  page 29, 105  line(s) 425-427
  315.  
  316. OBJECTION:
  317.  
  318.      Talking about main() and exit() under the pthread_exit() is extrane-
  319.      ous.
  320.  
  321. ACTION:
  322.  
  323.      Change lines 425-427 to being a note, instead of normative text in the
  324.      pthread_exit() description.  Also, move this text to the description
  325.      of _exit(), in section 7.3.3.2, where it belongs.
  326.  
  327. --------------------------------------------------------------------------
  328. @ 3.4 o 19
  329. 19: Section 3.4  page 37  line(s) 643-652
  330.  
  331. OBJECTION:
  332.  
  333.      Measuring overhead in units of the "null loop" is not portable as op-
  334.      timizing compilers can delete null loops entirely.
  335.  
  336. ACTION:
  337.  
  338.      Delete this performance metric or restate it in terms of a computation
  339.      that takes a certain amount of time instead of iterations of the null
  340.      loop.
  341.  
  342. --------------------------------------------------------------------------
  343. @ 3.4 o 20
  344. 20: Section 3.4  page 37  line(s) 654-660
  345.  
  346. OBJECTION:
  347.  
  348.      Measuring overhead in units of the "null loop" is not portable as op-
  349.      timizing compilers can delete null loops entirely.
  350.  
  351. ACTION:
  352.  
  353.      Delete this performance metric or restate it in terms of a computation
  354.      that takes a certain amount of time instead of iterations of the null
  355.  
  356.      loop.
  357.  
  358. --------------------------------------------------------------------------
  359. @ 4 o 21
  360. 21: Section 4  page all  line(s) all
  361.  
  362. OBJECTION:
  363.  
  364.      The use of ENOSYS as an error return requires that all implementations
  365.      maintain stubs simply to return an error.  This is silly: the linkage
  366.      editor can easily report that a particular function is not available.
  367.  
  368. ACTION:
  369.  
  370.      Eliminate all [ENOSYS] errors in this Chapter.  If the only error is
  371.      ENOSYS under a descriptive lead-in paragraph, delete the lead-in para-
  372.      graph as well.
  373.  
  374. --------------------------------------------------------------------------
  375. @ 4 o 22
  376. 22: Section 4  page all  line(s) all
  377.  
  378. OBJECTION:
  379.  
  380.      The use of errno is a mistake with new functions.  Existing POSIX.1
  381.      functions and their close relatives should maintain their overall
  382.      structure, as should those tied to existing practice.  The use of
  383.      errno as a global error indicator in multithreaded environments intro-
  384.      duces new difficulties and inefficiencies.
  385.  
  386. ACTION:
  387.  
  388.      New functions should not set a global errno, but instead return an er-
  389.      ror indication as the function return value.  The only exception are
  390.      functions such as pthread_exit() which do not return, and
  391.      pthread_self() which cannot fail.  We do not provide synopses for all
  392.      such functions, but will on request from the technical reviewers.
  393.  
  394.      Change all new functions such as all pthread_ functions to return an
  395.      error indication on failure, as described above.
  396.  
  397. --------------------------------------------------------------------------
  398. @ 4.4 o 23
  399. 23: Section 4.4  page 44-61  line(s) 85-676
  400.  
  401. OBJECTION:
  402.  
  403.      There is currently no interface provided by which statically allocated
  404.      mutex and condition variable objects can be statically initialized.
  405.      Providing this ability would make self-initializing modules easier to
  406.      write, and would often make such self-initialization more efficient as
  407.      well.
  408.  
  409.      Furthermore, there is substantial existing practice which provides
  410.      such interfaces, including Mach cthreads, Encore threads, Sun threads,
  411.      and others.
  412.  
  413. ACTION:
  414.  
  415.      Provide new macros PTHREAD_MUTEX_INITIALIZER and
  416.      PTHREAD_COND_INITIALIZER which may be used in static declarations to
  417.      initialize mutexes and condition variables.  The effect of:
  418.          static pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER;
  419.      at compile time should be identical to the effect of:
  420.          static pthread_mutex_t m;
  421.          pthread_mutex_init(&m, NULL);
  422.      at run time.  Similarly, the effect of:
  423.          static pthread_cond_t c = PTHREAD_COND_INITIALIZER;
  424.      at compile time should be identical to the effect of:
  425.          static pthread_cond_t c;
  426.          pthread_cond_init(&c, NULL);
  427.      at run time.
  428.  
  429.      Also, add rationale similar to the following discussion supporting
  430.      this addition.
  431.  
  432.      STATIC INITIALIZATION OF SYNCHRONIZATION OBJECTS:
  433.  
  434.      Providing for static initialization of statically allocated synchroni-
  435.      zation objects  allows modules with private static synchronization
  436.      variables to avoid run time initialization tests and overhead.  Furth-
  437.      ermore, it simplifies the coding of self-initializing modules.  Such
  438.      modules are common in C libraries, where for various reasons the
  439.      design called for self-initialization, instead of requiring an expli-
  440.      cit module initialization function to be called.  An example use of
  441.      static initialization follows.
  442.  
  443.      Without static initialization, a self-initializing routine foo() might
  444.      look like:
  445.          static pthread_once_t foo_once = PTHREAD_ONCE_INIT;
  446.          static pthread_mutex_t &foo_mutex;
  447.          void foo_init()
  448.          {
  449.              pthread_mutex_init(&foo_mutex, NULL);
  450.          }
  451.          void foo()
  452.          {
  453.              pthread_once(&foo_once, foo_init);
  454.              pthread_mutex_lock(&foo_mutex);
  455.              /* Do work */
  456.              pthread_mutex_unlock(&foo_mutex);
  457.          }
  458.      With static initialization, the same routine could be coded as:
  459.          static pthread_mutex_t foo_mutex = PTHREAD_MUTEX_INITIALIZER;
  460.          void foo()
  461.          {
  462.              pthread_mutex_lock(&foo_mutex);
  463.              /* Do work */
  464.              pthread_mutex_unlock(&foo_mutex);
  465.          }
  466.      Note that the static initialization both eliminates the need for the
  467.      initialization test inside pthread_once and the fetch of &foo_mutex to
  468.      learn the address to be passed to pthread_mutex_{lock, unlock}.  Thus,
  469.      the code written is simpler on all machines, and will also be faster
  470.      on a large class of machines.
  471.  
  472.      Yet people will rightly raise the performance question for machines
  473.  
  474.      (such as the Sequent Balance) which require mutexes to be allocated
  475.      out of special memory.  Such machines will actually have to have
  476.      mutexes and possibly condition variables contain pointers to the actu-
  477.      al hardware locks.  For static initialization to work on such
  478.      machines, pthread_mutex_lock() will also have to test whether or not
  479.      the pointer to the actual lock has been allocated.  If it hasn't it
  480.      will have to initialize it before use.  This run time test in
  481.      pthread_mutex_lock would at first seem to be extra work.  Yet notice
  482.      that in the above old example, pthread_once() was explicitly called in
  483.      application code for all implementations to test for mutex initializa-
  484.      tion -- in the new example the test is hidden inside
  485.      pthread_mutex_lock() only for those machines which need it.  The over-
  486.      head for machines doing out-of-line mutex allocation is thus similar
  487.      for modules being implicitly initialized, where it's improved for
  488.      those doing mutex allocation entirely inline.   The inline case is
  489.      thus made much faster and the out-of-line case is no worse.
  490.  
  491.      Two further objections have been raised to static initialization of
  492.      synchronization objects for out-of-line implementations.  First, an
  493.      extra test is required to see if the pointer has been initialized.
  494.      This might seem to add significant expense.  On most machines this
  495.      would actually be implemented as a fetch of the pointer, testing the
  496.      pointer against zero, and then using the pointer if it has already
  497.      been initialized.  While the test might seem to add extra work, the
  498.      extra cost of testing a register is usually negligible since no extra
  499.      memory references are actually done.  As more and more machines pro-
  500.      vide caches, the real expenses are memory references, not instructions
  501.      executed.
  502.  
  503.      Secondly, it is possible that threads would serialize contending for
  504.      initialization locks when attempting to finish initializing statically
  505.      allocated mutexes.  (Such finishing would typically involve taking an
  506.      internal lock, allocating a structure, storing a pointer to the struc-
  507.      ture in the mutex, and releasing the internal lock.)  First, many im-
  508.      plementations would reduce such serialization by hashing on the mutex
  509.      address.  And second, such serialization can only occur a bounded
  510.      number of times.  In particular, it can happen at most as many times
  511.      as there are statically allocated synchronization objects.  Dynamical-
  512.      ly allocated objects would still be initialized via
  513.      pthread_mutex_init() or pthread_cond_init().  Finally, if this is a
  514.      true issue, static initialization can be avoided altogether by expli-
  515.      citly initializing all synchronization objects with the corresponding
  516.      pthread_*_init() functions.
  517.  
  518.      In summary:  (1) Static initialization provides a significant simplif-
  519.      ication for programmers of self-initializing modules.  (2) Static ini-
  520.      tialization significantly improves performance for many implementa-
  521.      tions.  (3)  Static initialization will not significantly degrade per-
  522.      formance for any known implementations.  Thus, facilities allowing for
  523.      static initialization of synchronization objects are included as part
  524.      of the threads interface.
  525.  
  526. --------------------------------------------------------------------------
  527. @ 4.4 o 24
  528. 24: Section 4.4  page 48  line(s) 241-251
  529.  
  530. OBJECTION:
  531.  
  532.      When a process maps a file that contains a process shared synchroniza-
  533.      tion variable it must not reinitialize it. Similarly, if a process has
  534.      an initialized synchronization variable in MAP_SHARED memory and
  535.      forks, it does not have to be reinitialized.
  536.  
  537. ACTION:
  538.  
  539.      After line 251 add something like the following:
  540.  
  541.      If a process shared mutex has previously been initialized by another
  542.      process, the application shall not reinitialize it.
  543.  
  544. --------------------------------------------------------------------------
  545. @ 4.4 o 25
  546. 25: Section 4.4  page 55  line(s) 477-487
  547.  
  548. OBJECTION:
  549.  
  550.      When a process maps a file that contains a process shared synchroniza-
  551.      tion variable it must not reinitialize it. Similarly, if a process has
  552.      an initialized synchronization variable in MAP_SHARED memory and
  553.      forks, it does not have to be reinitialized.
  554.  
  555. ACTION:
  556.  
  557.      Add something like the following after line 487:
  558.  
  559.      If a process shared condition variable has previously been initialized
  560.      by another process, the application shall not reinitialize it.
  561.  
  562. --------------------------------------------------------------------------
  563. @ 4.4.7.6.1 o 26
  564. 26: Section 4.4.7.6.1  page 61  line(s) 681
  565.  
  566. OBJECTION:
  567.  
  568.  
  569. ACTION:
  570.  
  571.      Change "return successfully" to "return without an error".
  572.  
  573. --------------------------------------------------------------------------
  574. @ 5 o 27
  575. 27: Section 5  page all  line(s) all
  576.  
  577. OBJECTION:
  578.  
  579.      The use of ENOSYS as an error return requires that all implementations
  580.      maintain stubs simply to return an error.  This is silly: the linkage
  581.      editor can easily report that a particular function is not available.
  582.  
  583. ACTION:
  584.  
  585.      Eliminate all [ENOSYS] errors in this Chapter.  If the only error is
  586.      ENOSYS under a descriptive lead-in paragraph, delete the lead-in para-
  587.      graph as well.
  588.  
  589. --------------------------------------------------------------------------
  590. @ 5 o 28
  591. 28: Section 5  page all  line(s) all
  592.  
  593. OBJECTION:
  594.  
  595.      The use of errno is a mistake with new functions.  Existing POSIX.1
  596.      functions and their close relatives should maintain their overall
  597.      structure, as should those tied to existing practice.  The use of
  598.      errno as a global error indicator in multithreaded environments intro-
  599.      duces new difficulties and inefficiencies.
  600.  
  601. ACTION:
  602.  
  603.      New functions should not set a global errno, but instead return an er-
  604.      ror indication as the function return value.  The only exception are
  605.      functions such as pthread_exit() which do not return, and
  606.      pthread_self() which cannot fail.  We do not provide synopses for all
  607.      such functions, but will on request from the technical reviewers.
  608.  
  609.      Change all new functions such as all pthread_ functions to return an
  610.      error indication on failure, as described above.
  611.  
  612. --------------------------------------------------------------------------
  613. @ 5.2 o 29
  614. 29: Section 5.2  page 73  line(s) 75-80
  615.  
  616. OBJECTION:
  617.  
  618.      A standard pthread_key_delete() is needed for dynamically linked li-
  619.      braries to recover storage when they are unlinked. Many modern OS im-
  620.      plementations allow programatic runtime linking in of libraries.
  621.  
  622. ACTION:
  623.  
  624.      Add pthread_key_delete(). The destructors should be called in each
  625.      thread.  It is OK if the application id required to ensure that the
  626.      other thread-specific data function are not called simultaneously with
  627.      pthread_key_delete().
  628.  
  629. --------------------------------------------------------------------------
  630. @ 5.2 o 30
  631. 30: Section 5.2  page 74  line(s) 103-107
  632.  
  633. OBJECTION:
  634.  
  635.      Destructor functions must be allowed to call functions that can poten-
  636.      tially allocate thread-specific data, otherwise functions must be
  637.      specifically documented as  callable from a destructor or not.
  638.  
  639. ACTION:
  640.  
  641.      In order to accomplish this, destructor functions must be called re-
  642.      peatedly until all thread-specific data is destroyed. Lines 158-160
  643.      must also be deleted or modified.
  644.  
  645. --------------------------------------------------------------------------
  646. @ 5.2 o 31
  647. 31: Section 5.2  page 75  line(s) 148
  648.  
  649. OBJECTION:
  650.  
  651.      pthread_getspecific() should simply return the value instead of stor-
  652.      ing it through a pointer. This could substantially speed up a critical
  653.      function.
  654.  
  655. ACTION:
  656.  
  657.      Change pthread_getspecific to:
  658.              void * pthread_getspecific(pthread_key_t key); If any error is
  659.      detected, NULL is returned.
  660.  
  661. --------------------------------------------------------------------------
  662. @ 5.2 o 32
  663. 32: Section 5.2  page 75-76  line(s) 151-161
  664.  
  665. OBJECTION:
  666.  
  667.      Since pthread_{s, g}etspecific may not work if the key is undefined
  668.      the standard should explicitly state that called either of these with
  669.      an uncreated or destroyed key is undefined. This explicitly prevents
  670.      the (erroneous) example in lines 246-255.
  671.  
  672. ACTION:
  673.  
  674.      Add something like the following before line 161:
  675.              The effect of calling pthread_getspecific or
  676.      pthread_setspecific
  677.              with a key value that has not been created (or has been des-
  678.      troyed)
  679.              is unspecified.
  680.  
  681. --------------------------------------------------------------------------
  682. @ 5.2 o 33
  683. 33: Section 5.2  page 76  line(s) 174-175
  684.  
  685. OBJECTION:
  686.  
  687.      In implementations that support infinite amounts of thread-specific
  688.      data pthread_setspecific can allocate memory and must be able to re-
  689.      turn an error is memory is unavailable.
  690.  
  691. ACTION:
  692.  
  693.      Add ENOMEM to the list of errors for pthread_setspecific.
  694.  
  695. --------------------------------------------------------------------------
  696. @ 5.3 o 34
  697. 34: Section 5.3  page 77  line(s) 213-215
  698.  
  699. OBJECTION:
  700.  
  701.      The text reads:
  702.              If second and subsequent calls to pthread_setspecific perform
  703.              differently than the first call, then these measurements shall
  704.              also be reported.  In implementation that support an unbounded
  705.      amount of thread-specific data, this can cause an unbounded number of
  706.      measurements.
  707.  
  708. ACTION:
  709.  
  710.      Delete this sentence or replace it with measurements of setting
  711.      storage for specified numbers of keys. It is probably best that these
  712.      be less than 32 keys since this is all a strictly conforming applica-
  713.      tion can depend on.
  714.  
  715. --------------------------------------------------------------------------
  716. @ 5.3 o 35
  717. 35: Section 5.3  page 28-29  line(s) 363-407
  718.  
  719. OBJECTION:
  720.  
  721.      Since there is a "detached" attribute to thread creation, there is no
  722.      longer very much motivation to include pthread_detach() as a separate
  723.      function. There is very little need to detach a thread on the fly,
  724.      since this is mostly known at thread create time when the thread ID is
  725.      stored.  Making the initial thread be created "undetached" by default
  726.      means that it can be joined with, while the potential storage leak is
  727.      limited.
  728.  
  729. ACTION:
  730.  
  731.      Delete pthread_detached(). Add the requirement that the initial thread
  732.      be created "undetached".
  733.  
  734. --------------------------------------------------------------------------
  735. @ 6 o 36
  736. 36: Section 6  page all  line(s) all
  737.  
  738. OBJECTION:
  739.  
  740.      The use of ENOSYS as an error return requires that all implementations
  741.      maintain stubs simply to return an error.  This is silly: the linkage
  742.      editor can easily report that a particular function is not available.
  743.  
  744. ACTION:
  745.  
  746.      Eliminate all [ENOSYS] errors in this Chapter.  If the only error is
  747.      ENOSYS under a descriptive lead-in paragraph, delete the lead-in para-
  748.      graph as well.
  749.  
  750. --------------------------------------------------------------------------
  751. @ 6 o 37
  752. 37: Section 6  page all  line(s) all
  753.  
  754. OBJECTION:
  755.  
  756.      The use of errno is a mistake with new functions.  Existing POSIX.1
  757.      functions and their close relatives should maintain their overall
  758.      structure, as should those tied to existing practice.  The use of
  759.      errno as a global error indicator in multithreaded environments intro-
  760.      duces new difficulties and inefficiencies.
  761.  
  762. ACTION:
  763.  
  764.      New functions should not set a global errno, but instead return an er-
  765.      ror indication as the function return value.  The only exception are
  766.      functions such as pthread_exit() which do not return, and
  767.      pthread_self() which cannot fail.  We do not provide synopses for all
  768.      such functions, but will on request from the technical reviewers.
  769.  
  770.      Change all new functions such as all pthread_ functions to return an
  771.      error indication on failure, as described above.
  772.  
  773. --------------------------------------------------------------------------
  774. @ 6 o 38
  775. 38: Section 6  page all  line(s) all
  776.  
  777. OBJECTION:
  778.  
  779.      The use of realtime-centric nomenclature, and in particular
  780.      SCHED_OTHER, is confusing.  SCHED_OTHER is simply a placeholder for
  781.      "some scheduling algorithm that may be different or not different from
  782.      SCHED_FIFO and SCHED_RR".  This suggests both that SCHED_OTHER is a
  783.      name for some specific scheduling algorithm AND that SCHED_OTHER is a
  784.      name for some selectable scheduling algorithm that may be different
  785.      from SCHED_FIFO and SCHED_RR.
  786.  
  787.      Unfortunately, SCHED_OTHER can't be both.  The apparent meaning is of
  788.      some system-defined policy that is neither FIFO nor RR.  A more ap-
  789.      propriate name is "SCHED_DEFAULT."
  790.  
  791. ACTION:
  792.  
  793.      Rename SCHED_OTHER to SCHED_DEFAULT in the entire chapter.
  794.  
  795. --------------------------------------------------------------------------
  796. @ 6 o 39
  797. 39: Section 6  page all  line(s) all
  798.  
  799. OBJECTION:
  800.  
  801.      The rationale in this chapter talks about many things, most of which
  802.      are not relevant to the scope of POSIX.4a.  Sections 6.1.1.3 and 6.2.3
  803.      are particularly irrelevant, as they talk about scheduling on a
  804.      machine with allocation domain of size greater than one, which was
  805.      specifically excluded from the scope of scheduling by the working
  806.      group.
  807.  
  808.      The text of section 6.2.3 is an attempt to extend the semantics of
  809.      uniprocessor scheduling to the multiprocessor domain in a way that ex-
  810.      cludes existing practice or renders the somewhat intuitive SCHED_FIFO
  811.      and SCHED_RR meaningless (line 214-216).  One point made by previous
  812.      POSIX.14 coordination ballots and comments was that priority is less
  813.      meaningful in a multiprocessor.  Line 217 overspecifies behavior.
  814.  
  815. ACTION:
  816.  
  817.      Delete this chapter.  Define the interactions of draft POSIX.4
  818.      scheduling behavior and pthreads in a separate document, or move the
  819.      contents of this chapter to a non-normative appendix clearly marked as
  820.      "Uniprocessor Thread Scheduling."
  821.  
  822. --------------------------------------------------------------------------
  823. @ 6 o 40
  824. 40: Section 6  page all  line(s) all
  825.  
  826. OBJECTION:
  827.  
  828.      The rationale is excessively broad for the normative text in this
  829.      chapter.  Rationale should explain the derivation and meaning of the
  830.      normative text; the Chapter 6 rationale goes far beyond that.
  831.  
  832.      The most egregious examples are lines 110-118 (Rate Monotonic Schedul-
  833.      ing) and lines 704-739.  The working group did not accept this text
  834.      even for a non-normative appendix, and including it in this draft or
  835.      any final standard based on this draft is excessive.  The rationale is
  836.      not intended as a place to announce interfaces for "future updates"
  837.      when the working group did not find the interfaces acceptable for in-
  838.      clusion anywhere in the draft.
  839.  
  840.      The presentation here amounts to an endorsement by POSIX of a research
  841.      effort and related projects by the current technical reviewer and his
  842.      colleagues, and inappropriate to normative or rationale text.
  843.  
  844. ACTION:
  845.  
  846.      Delete lines 110-118 and 704-739 and any other references in the draft
  847.      that refer to rate monotonic scheduling or sporadic servers.
  848.  
  849. --------------------------------------------------------------------------
  850. @ 6 o 41
  851. 41: Section 6  page all  line(s) all
  852.  
  853. OBJECTION:
  854.  
  855.      This chapter is beyond scope in references to multiprocessors and mul-
  856.      tiprocessor scheduling because the interfaces and uniprocessor tech-
  857.      niques are neither well-understood nor appropriate to multiprocessors.
  858.  
  859.      The extensions to "scheduling domains of size greater than one" is fa-
  860.      tally flawed because they work either poorly or not at all on current
  861.      and near-future multiprocessor architectures such as the Stanford DASH
  862.      machine.  These interfaces and techniques apply only to uniprocessors,
  863.      therefore they conflict with page 1 lines 25-27, and should be delet-
  864.      ed.
  865.  
  866. ACTION:
  867.  
  868.      Delete Chapter 6.
  869.  
  870. --------------------------------------------------------------------------
  871. @ 6.1 o 42
  872. 42: Section 6.1  page 80  line(s) 34
  873.  
  874. OBJECTION:
  875.  
  876.      In POSIX, the concept of a "kernel entity" is misplaced.  The proper
  877.      language would refer instead to a "process."
  878.  
  879. ACTION:
  880.  
  881.      Change "kernel entity (process)" to "process".
  882.  
  883. --------------------------------------------------------------------------
  884. @ 6.2.2 o 43
  885. 43: Section 6.2.2  page 83  line(s) 186-189
  886.  
  887. OBJECTION:
  888.  
  889.      The definition of global contention scope ignores the concept of allo-
  890.      cation domain.  Resource contention only makes sense within an alloca-
  891.      tion domain, as indicated by lines 202-204:         Allocation domain
  892.      is independent of contention scope, as contention         scope merely
  893.      defines the set of threads with which a thread must         contend
  894.      for processor resources, while allocation domain defines         the
  895.      set of processors for which it contends.  The definition of global
  896.      contention scope is inconsistent with this, and makes it impossible
  897.      for systems with multiple allocation domains to support global conten-
  898.      tion scope.
  899.  
  900. ACTION:
  901.  
  902.      Rewrite lines 186-189 to read: A thread created with global contention
  903.      scope contends for resources with all other threads in the same allo-
  904.      cation domain relative to their global scheduling attributes.  The
  905.      global scheduling attributes of a thread created with global conten-
  906.      tion scope are the scheduling attributes with which the thread was
  907.      created.  The global scheduling attributes of a thread created with
  908.      local contention scope are the implementation-defined mapping into
  909.      global attribute space of the scheduling attributes with which the
  910.      thread was created.
  911.  
  912. --------------------------------------------------------------------------
  913. @ 6.2.2 c 44
  914. 44: Section 6.2.2  page 84  line(s) 191
  915.  
  916. EDITORIAL COMMENT:
  917.  
  918.      Change `which' to `that'.
  919.  
  920. --------------------------------------------------------------------------
  921. @ 6.2.3 o 45
  922. 45: Section 6.2.3  page 84  line(s) 196-219
  923.  
  924. OBJECTION:
  925.  
  926.      This section implies that both the allocation domain size and the as-
  927.      signment of threads to allocation domains is static.  Both implica-
  928.      tions can be overly restrictive for some systems.
  929.  
  930.      The `process control' approach to scheduling (cf. Tucker and Gupta,
  931.      "Process Control and Scheduling Issues for Multiprogrammed Shared
  932.      Memory Multiprocessors", Proceedings of 12th SOSP, December 1989, pp.
  933.      159-166) obtains significant performance advantages from dynamic allo-
  934.      cation domain sizes when it is applicable.
  935.  
  936.      Non Uniform Memory Access (NUMA) multiprocessors (e.g., BBN Butterfly,
  937.      Stanford DASH) may use a system scheduling structure that involves
  938.      reassignment of threads among allocation domains.  In NUMA machines, a
  939.      natural model of scheduling is to match allocation domains to clusters
  940.      of processors.  Load Balancing in such an environment requires chang-
  941.      ing the allocation domain to which a thread is assigned.  The system
  942.      should have the freedom to do this.
  943.  
  944. ACTION:
  945.  
  946.      After line 208, add:         Conforming implementations may change the
  947.      size of allocation         domains and the binding of threads to allo-
  948.      cation domains at         any time. Add the second and third para-
  949.      graphs of the objection text to the Rationale after line 109.
  950.  
  951. --------------------------------------------------------------------------
  952. @ 6.3 o 46
  953. 46: Section 6.3  page 93  line(s) 481-499
  954.  
  955. OBJECTION:
  956.  
  957.      The parameter proposed for pthread_yield() is not used and is required
  958.      to be NULL.  The claim in the rationale that this allows extensions is
  959.      bogus.  The use of a void * does not permit passing of any integer or
  960.      long value, hence does not permit the extensibility that is claimed.
  961.      The reference to thread_switch is misplaced in a discussion of a yield
  962.      interface; thread_switch is an implementation tool, not a user-level
  963.      scheduling tool to skirt around the priority scheduling that the rest
  964.      of this chapter says is so important.
  965.  
  966. ACTION:
  967.  
  968.      Delete the parameter to pthread_yield and lines 490 and 505-510.
  969.  
  970. --------------------------------------------------------------------------
  971. @ 6.3 o 47
  972. 47: Section 6.3  page 95-96  line(s) 551-590
  973.  
  974. OBJECTION:
  975.  
  976.      The priority ceiling "emulation" protocol is slower that priority in-
  977.      heritance in that work must be done in the no-contention case instead
  978.      of the contention case. It is also more difficult to use in that the
  979.      priority of all calling threads must be computed a priori. It is also
  980.      redundant functionality with respect to priority inheritance.
  981.  
  982. ACTION:
  983.  
  984.      Delete the priority ceiling "emulation" protocol. Delete
  985.      pthread_mutexattr_setceiling(), pthread_mutexattr_getceiling(), and
  986.      lines 561-587.
  987.  
  988. --------------------------------------------------------------------------
  989. @ 6.3.4 o 48
  990. 48: Section 6.3.4  page 94  line(s) 511-537
  991.  
  992. OBJECTION:
  993.  
  994.      The specified behavior for threads with global contention scope
  995.      directly contradicts the requirements of POSIX.4 for processes with
  996.      exactly one thread (namely the initial thread).  This is a fundamental
  997.      conflict between the scheduling primitives in POSIX.4 and POSIX.4a.
  998.      There are two choices here; either resolve the conflict or define it
  999.      out of existence.
  1000.  
  1001.      Resolving the conflict is unlikely to yield a clean solution for
  1002.      processes that use POSIX.4 scheduling primitives and link against a
  1003.      library that creates hidden threads.  The various choices appear to
  1004.      be:
  1005.  
  1006.      a) Treat the initial thread specially and apply POSIX.4 primitives to
  1007.      it alone.
  1008.  
  1009.      b) Ensure that a process consisting only of the initial thread is
  1010.      treated as POSIX.4 scheduling requires
  1011.  
  1012.      c) Extend POSIX.4 scheduling primitives to all threads.
  1013.  
  1014.      Option a) is unacceptable because all threads should be as equivalent
  1015.      as possible, and compatibility support for POSIX.4 primitives is in-
  1016.      sufficient justification for introducing this degree of asymmetry.
  1017.      Option c) is also unacceptable because it creates two methods for af-
  1018.      fecting the scheduling of threads; this both complicates the implemen-
  1019.      tations and makes the resulting program behavior more difficult to
  1020.      understand with no benefits.  Option b) is the least objectionable of
  1021.      the three, but leaves a POSIX.4 program at the mercy of
  1022.      implementation-defined behavior if it should happen to link with a li-
  1023.      brary that creates internal threads.  We offer it as one possible
  1024.      resolution to this objection with the rationale that an application
  1025.      performing its own realtime scheduling must understand the scheduling
  1026.      implications of any library that it links to.
  1027.  
  1028.      The alternative is to define the problem out of existence by prevent-
  1029.      ing the simultaneous use of POSIX.4a primitives and POSIX.4 primi-
  1030.      tives.  Doing this at the source level is not straightforward because
  1031.      of the ability to link separately compiled modules.  The linker must
  1032.      reject any application that attempts to use primitives from both
  1033.      classes; dynamically linked libraries complicate this problem.
  1034.  
  1035.      Also, the specified behavior for threads with local contention scope
  1036.      is an excessively long version of "implementation defined".
  1037.  
  1038. ACTION:
  1039.  
  1040.      Any of the following actions are acceptable to resolve this objection:
  1041.  
  1042.      (1) Replace lines 522-528 with the following:
  1043.  
  1044.      The semantics of these functions (except yield()) are exactly as de-
  1045.      fined in Priority Scheduling s21, POSIX.4 for processes that consist
  1046.      of an initial thread with global contention scope and have created no
  1047.      other threads.  In all other cases, the semantics are implementation
  1048.      defined.
  1049.  
  1050.      (2) Replace lines 522-532 with the following:
  1051.  
  1052.      The semantics of these functions are implementation defined.
  1053.  
  1054.      (3) Replace lines 522-532 with the following:
  1055.  
  1056.      These functions shall fail.
  1057.  
  1058.      (4) Delete section 6.3.4 (lines 511-537) and replace it with a res-
  1059.      triction that prevents a conforming implementation from defining both
  1060.      _POSIX_THREADS and _POSIX_PROCESS_SCHEDULING.  Insert a rationale sec-
  1061.      tion explaining how to do this in practice on a system that can sup-
  1062.      port each option independently.
  1063.  
  1064. --------------------------------------------------------------------------
  1065. @ 6.3.4 c 49
  1066. 49: Section 6.3.4  page 94  line(s) 511-537
  1067.  
  1068. EDITORIAL COMMENT:
  1069.  
  1070.      POSIX.4 has changed the names of the scheduling functions and symbolic
  1071.      constant used in this section.  The new names are prefixed with sched_
  1072.      and the new symbolic constant is _POSIX_PRIORITY_SCHEDULING.
  1073.  
  1074. ACTION:
  1075.  
  1076.      Update to match POSIX.4.
  1077.  
  1078. --------------------------------------------------------------------------
  1079. @ 6.3 o 50
  1080. 50: Section 6.3  page 95-96  line(s) 551-590
  1081.  
  1082. OBJECTION:
  1083.  
  1084.      The priority ceiling "emulation" protocol is slower that priority in-
  1085.      heritance in that work must be done in the no-contention case instead
  1086.  
  1087.      of the contention case. It is also more difficult to use in that the
  1088.      priority of all calling threads must be computed a priori. It is also
  1089.      redundant functionality with respect to priority inheritance.
  1090.  
  1091. ACTION:
  1092.  
  1093.      Delete the priority ceiling "emulation" protocol. Delete:
  1094.              pthread_mutexattr_setceiling(),
  1095.              pthread_mutexattr_getceiling(),
  1096.      and lines 561-587.
  1097.  
  1098. --------------------------------------------------------------------------
  1099. @ 7 o 51
  1100. 51: Section 7  page all  line(s) all
  1101.  
  1102. OBJECTION:
  1103.  
  1104.      The use of ENOSYS as an error return requires that all implementations
  1105.      maintain stubs simply to return an error.  This is silly: the linkage
  1106.      editor can easily report that a particular function is not available.
  1107.  
  1108. ACTION:
  1109.  
  1110.      Eliminate all [ENOSYS] errors in this Chapter.  If the only error is
  1111.      ENOSYS under a descriptive lead-in paragraph, delete the lead-in para-
  1112.      graph as well.
  1113.  
  1114. --------------------------------------------------------------------------
  1115. @ 7 o 52
  1116. 52: Section 7  page all  line(s) all
  1117.  
  1118. OBJECTION:
  1119.  
  1120.      The use of errno is a mistake with new functions.  Existing POSIX.1
  1121.      functions and their close relatives should maintain their overall
  1122.      structure, as should those tied to existing practice.  The use of
  1123.      errno as a global error indicator in multithreaded environments intro-
  1124.      duces new difficulties and inefficiencies.
  1125.  
  1126. ACTION:
  1127.  
  1128.      New functions should not set a global errno, but instead return an er-
  1129.      ror indication as the function return value.  The only exception are
  1130.      functions such as pthread_exit() which do not return, and
  1131.      pthread_self() which cannot fail.  We do not provide synopses for all
  1132.      such functions, but will on request from the technical reviewers.
  1133.  
  1134.      Change all new functions such as all pthread_ functions to return an
  1135.      error indication on failure, as described above.
  1136.  
  1137. --------------------------------------------------------------------------
  1138. @ 7.3 o 53
  1139. 53: Section 7.3  page 104  line(s) 33-56
  1140.  
  1141. OBJECTION:
  1142.  
  1143.      fork() as defined has only the calling thread continue in the child
  1144.      process.  This introduces problems with locks and other state main-
  1145.  
  1146.      tained by user code.  For example, if the surviving thread in the
  1147.      child blocks attempting to lock a mutex between fork() and exec(), no
  1148.      other thread exists to free the lock.  This is exacerbated by limited
  1149.      cancelability (cf. Section 9.3.2, page 126) where a blocking
  1150.      pthread_mutex_lock operation is not an interruption point, so signals
  1151.      and other events that might create another thread cannot do so.
  1152.  
  1153.      There are two useful definitions for fork(), one in which only the
  1154.      calling thread survives, and a second where all threads in the process
  1155.      survive in the child.  With both alternatives useful under some cir-
  1156.      cumstances, both should be defined.
  1157.  
  1158. ACTION:
  1159.  
  1160.      Change the name of fork() on this page to "fork1()".  Define, under an
  1161.      option, a new interface, forkall(), defined below, to duplicate all
  1162.      extant threads in the child process.  Specify that it is
  1163.      implementation-defined whether fork() is fork1() or forkall().
  1164.  
  1165. NAME
  1166.    forkall()
  1167.  
  1168. DESCRIPTION
  1169.    forkall() causes creation of a new process, cloning the parent process
  1170.    in its entirety including all existing pthreads.
  1171.  
  1172. SYNOPSIS
  1173.       #include <sys/types.h>
  1174.       #include <unistd.h>
  1175.  
  1176.       pid_t forkall(void);
  1177.  
  1178. PROCESSING
  1179.    The new process created by forkall duplicates the calling process, in-
  1180.    cluding the set of threads that exist as of the time of the call (up to
  1181.    simultaneity constraints), the data area, and stack(s).
  1182.  
  1183. OUTPUT
  1184.    Upon successful completion, forkall() returns a value of 0 to the new
  1185.    process and returns the process ID of the new process to the caller.
  1186.  
  1187. ERROR/DIAGNOSTICS
  1188.    On failure, a value of (pid_t) -1 is returned to the caller, no new pro-
  1189.    cess is created, and errno is set to indicate the error.
  1190.  
  1191.       EAGAIN
  1192.                 The system limit on number of threads per real user-id would be
  1193.                 exceeded if the call succeeds.
  1194.  
  1195.       EINTR
  1196.                A forkall() has been interrupted by a forkall() executed by
  1197.                another stream of execution in the process.
  1198.  
  1199. --------------------------------------------------------------------------
  1200. @ 7.3 o 54
  1201. 54: Section 7.3  page 104  line(s) 33-56
  1202.  
  1203. OBJECTION:
  1204.  
  1205.      In the event that this ballot's objection with action to define for-
  1206.      kall() is accepted, additional rationale is required to address the
  1207.      issue of how a portable application would use forkall() and fork1().
  1208.  
  1209. --------------------------------------------------------------------------
  1210. @ 7.3.1 o 55
  1211. 55: Section 7.3.1  page 105  line(s)
  1212.  
  1213. OBJECTION:
  1214.  
  1215.      There are at least two serious problems with the semantics of fork()
  1216.      in a multi-threaded program.  One problem has to do with state (e.g.,
  1217.      memory) covered by mutexes.  Consider the case where one thread has a
  1218.      mutex locked and the state covered by that mutex is inconsistent while
  1219.      another thread calls fork(). In the child, the mutex will be in the
  1220.      locked state (locked by a non-existent thread and thus can never be
  1221.      unlocked).  Having the child simply reinitialize the mutex is unsatis-
  1222.      factory since this approach doesn't resolve the question about how to
  1223.      correct or otherwise deal with the inconsistent state in the child.
  1224.  
  1225.      The Pthreads draft suggests that programs that use fork() will call
  1226.      exec() very soon afterwards in the child process, thus resetting all
  1227.      state.  In the meantime, only a short list of "safe" library routines
  1228.      are promised to be available.
  1229.  
  1230.      Unfortunately, this solution does not address the needs of multi-
  1231.      threaded libraries.  Application programs may not be aware that a
  1232.      multi-threaded library is in use, and will feel free to call any
  1233.      number of library routines between fork() and exec(), just as they al-
  1234.      ways have.  Indeed, they may be extant single-threaded programs and
  1235.      cannot, therefore, be expected to obey new restrictions imposed by the
  1236.      thread library.
  1237.  
  1238.      On the other hand, the multi-threaded library needs a way to protect
  1239.      its internal state during fork() in case it is reentered later in the
  1240.      child process.  The problem arises especially in multi-threaded I/O
  1241.      libraries, which are almost sure to be invoked between fork() and
  1242.      exec() to effect I/O redirection.  The solution may require locking
  1243.      mutex variables during fork(), or it may entail simply resetting the
  1244.      state in the child after the fork() processing completes.
  1245.  
  1246.      pthread_atfork1(), as defined below, provides multi-threaded libraries
  1247.      with a mechanism to protect themselves from innocent application pro-
  1248.      grams which call fork(), and it provides multi-threaded application
  1249.      programs with a standard mechanism for protecting themselves from
  1250.      fork() calls in a library routine or the application itself.
  1251.  
  1252.      For example, an application can supply a "prepare" routine that ac-
  1253.      quires the necessary mutexes the library maintains and "child" and
  1254.      "parent" routines that release those mutexes, thus ensuring that the
  1255.      child gets a consistent snapshot of the library's state (and that no
  1256.  
  1257.      mutexes are left stranded).  Alternatively, some libraries might be
  1258.      able to supply just a "child" routine that reinitializes the library's
  1259.      mutexes and all associated state to some known value (e.g., what it
  1260.      was when the image was originally exec'd).
  1261.  
  1262.      Another problem with the semantics of fork() in a multi-threaded pro-
  1263.      gram is the question of which threads that exist in the parent are du-
  1264.      plicated into the child.  The Pthreads draft states that the child
  1265.      process starts with exactly one thread--a copy of the thread that
  1266.      called fork(). Unfortunately, in some cases, the right thing would
  1267.      have been to recreate at least some of the other threads in the child
  1268.      process as well.  pthread_atfork1() allows applications and libraries
  1269.      to deal with this problem as well.  A library or application that
  1270.      creates threads and wants those threads to exist in the child can sup-
  1271.      ply an pthread_atfork1() "child" routine that recreates the threads.
  1272.      This is not exactly equivalent to preserving the thread, but it comes
  1273.      close and should meet most needs.
  1274.  
  1275. ACTION:
  1276.  
  1277.      Add the function pthread_atfork1() as specified below.
  1278.  
  1279.  
  1280. NAME
  1281.    pthread_atfork1() - arrange for fork1 cleanup handling
  1282.  
  1283. SYNOPSIS
  1284.  
  1285.         pthread_atfork1(void (*prepare)(), void (*parent)(), void
  1286.         (*child)());
  1287.         void (*prepare)();
  1288.         void (*parent)();
  1289.         void (*child)();
  1290.  
  1291. DESCRIPTION
  1292.    pthread_atfork1() declares handlers to be called before and after
  1293.    fork1(). The prepare handler is called before fork1() processing com-
  1294.    mences.  The parent handler is called after fork1() processing com-
  1295.    pletes, but in the parent process. The child handler is called after
  1296.    fork1(0 processing completes, but in the child process.
  1297.  
  1298.    If no handling is desired at any one of these three places, its
  1299.    corresponding handler address may be set to NULL.
  1300.  
  1301.    The expected usage is that the prepare handler acquires all mutex locks,
  1302.    and the other two handlers release them.
  1303.  
  1304.    Alternatively, one may also declare only a child handler to just clear
  1305.    any locks.
  1306.  
  1307.    The table of fork handlers maintained by pthread_atfork1() should be
  1308.    semi-static. That is, it is established by calls to pthread_atfork1()
  1309.    during initialization. Handlers are called in last-in, first-out order,
  1310.    to enforce any desired locking hierarchy.  Therefore, the order of calls
  1311.    to pthread_atfork1() is significant.
  1312.  
  1313. RETURN
  1314.    pthread_atfork1() returns 0 if successful.  Otherwise, it returns -1 if
  1315.  
  1316.    there is insufficient table space to record the handler addresses.
  1317.  
  1318. --------------------------------------------------------------------------
  1319. @ 8 o 56
  1320. 56: Section 8  page all  line(s) all
  1321.  
  1322. OBJECTION:
  1323.  
  1324.      The use of errno is a mistake with new functions.  Existing POSIX.1
  1325.      functions and their close relatives should maintain their overall
  1326.      structure, as should those tied to existing practice.  The use of
  1327.      errno as a global error indicator in multithreaded environments intro-
  1328.      duces new difficulties and inefficiencies.
  1329.  
  1330. ACTION:
  1331.  
  1332.      New functions should not set a global errno, but instead return an er-
  1333.      ror indication as the function return value.  The only exception are
  1334.      functions such as pthread_exit() which do not return, and
  1335.      pthread_self() which cannot fail.  We do not provide synopses for all
  1336.      such functions, but will on request from the technical reviewers.
  1337.  
  1338.      Change all new functions such as all pthread_ functions to return an
  1339.      error indication on failure, as described above.
  1340.  
  1341. --------------------------------------------------------------------------
  1342. @ 8.3.2 o 57
  1343. 57: Section 8.3.2  page 111  line(s) 142-143
  1344.  
  1345. OBJECTION:
  1346.  
  1347.  
  1348. ACTION:
  1349.  
  1350.      Change these lines to, "POSIX.4a introduces no new async safe func-
  1351.      tions."
  1352.  
  1353. --------------------------------------------------------------------------
  1354. @ 8.3.3.4.1.1 o 58
  1355. 58: Section 8.3.3.4.1.1  page 113  line(s) 207-215
  1356.  
  1357. OBJECTION:
  1358.  
  1359.      The interest model no longer applies with the introduction of the new
  1360.      signals model.
  1361.  
  1362. ACTION:
  1363.  
  1364.      Delete these lines.
  1365.  
  1366. --------------------------------------------------------------------------
  1367. @ 8.4.1.1 o 59
  1368. 59: Section 8.4.1.1  page 115  line(s) 270
  1369.  
  1370. OBJECTION:
  1371.  
  1372.  
  1373. ACTION:
  1374.  
  1375.      Change to read "int sigwait(const sigset_t *set);"
  1376.  
  1377. --------------------------------------------------------------------------
  1378. @ 8.4.1.2 o 60
  1379. 60: Section 8.4.1.2  page 115  line(s) 276
  1380.  
  1381. OBJECTION:
  1382.  
  1383.      Clarify that it is the caller's responsibility to block signals prior
  1384.      to a call to sigwait.
  1385.  
  1386. ACTION:
  1387.  
  1388.      Change "defined by set shall be blocked" to "defined by set shall have
  1389.      been blocked".
  1390.  
  1391. --------------------------------------------------------------------------
  1392. @ 8.4.1.2 o 61
  1393. 61: Section 8.4.1.2  page 115  line(s) 274
  1394.  
  1395. OBJECTION:
  1396.  
  1397.      In the presence of an implementation that supports queued signals it
  1398.      should be guaranteed that sigwait doesn't flush all instances of a
  1399.      pending signal number.
  1400.  
  1401. ACTION:
  1402.  
  1403.      After the sentence ending "returns that signal number.", add the sen-
  1404.      tence, "If prior to the call to sigwait there are multiple pending in-
  1405.      stances of a single signal number, it is implementation-defined wheth-
  1406.      er upon successful return there are any remaining pending signals for
  1407.      that signal number."
  1408.  
  1409. --------------------------------------------------------------------------
  1410. @ 8.4.7.4 o 62
  1411. 62: Section 8.4.7.4  page 121  line(s) 455
  1412.  
  1413. OBJECTION:
  1414.  
  1415.      ESRCH is a legitimate error return for pthread_kill().
  1416.  
  1417. ACTION:
  1418.  
  1419.      Add it.
  1420.  
  1421. --------------------------------------------------------------------------
  1422. @ 9 o 63
  1423. 63: Section 9  page all  line(s) all
  1424.  
  1425. OBJECTION:
  1426.  
  1427.      The use of ENOSYS as an error return requires that all implementations
  1428.      maintain stubs simply to return an error.  This is silly: the linkage
  1429.      editor can easily report that a particular function is not available.
  1430.  
  1431. ACTION:
  1432.  
  1433.      Eliminate all [ENOSYS] errors in this Chapter.  If the only error is
  1434.      ENOSYS under a descriptive lead-in paragraph, delete the lead-in para-
  1435.      graph as well.
  1436.  
  1437. --------------------------------------------------------------------------
  1438. @ 9 o 64
  1439. 64: Section 9  page all  line(s) all
  1440.  
  1441. OBJECTION:
  1442.  
  1443.      The use of errno is a mistake with new functions.  Existing POSIX.1
  1444.      functions and their close relatives should maintain their overall
  1445.      structure, as should those tied to existing practice.  The use of
  1446.      errno as a global error indicator in multithreaded environments intro-
  1447.      duces new difficulties and inefficiencies.
  1448.  
  1449. ACTION:
  1450.  
  1451.      New functions should not set a global errno, but instead return an er-
  1452.      ror indication as the function return value.  The only exception are
  1453.      functions such as pthread_exit() which do not return, and
  1454.      pthread_self() which cannot fail.  We do not provide synopses for all
  1455.      such functions, but will on request from the technical reviewers.
  1456.  
  1457.      Change all new functions such as all pthread_ functions to return an
  1458.      error indication on failure, as described above.
  1459.  
  1460. --------------------------------------------------------------------------
  1461. @ 9.3.5 o 65
  1462. 65: Section 9.3.5  page 129  line(s) 225-226
  1463.  
  1464. OBJECTION:
  1465.  
  1466.  
  1467. ACTION:
  1468.  
  1469.      Change these lines to, "POSIX.4a introduces no new interrupt safe
  1470.      functions."
  1471.  
  1472. --------------------------------------------------------------------------
  1473. @ 9.3.4 o 66
  1474. 66: Section 9.3.4  page 128-129  line(s) 187-217
  1475.  
  1476. OBJECTION:
  1477.  
  1478.      This is rationale.
  1479.  
  1480. ACTION:
  1481.  
  1482.      So indicate.
  1483.  
  1484. --------------------------------------------------------------------------
  1485. @ 10 o 67
  1486. 67: Section 10  page all  line(s) all
  1487.  
  1488. OBJECTION:
  1489.  
  1490.      The use of ENOSYS as an error return requires that all implementations
  1491.      maintain stubs simply to return an error.  This is silly: the linkage
  1492.      editor can easily report that a particular function is not available.
  1493.  
  1494. ACTION:
  1495.  
  1496.      Eliminate all [ENOSYS] errors in this Chapter.  If the only error is
  1497.      ENOSYS under a descriptive lead-in paragraph, delete the lead-in para-
  1498.      graph as well.
  1499.  
  1500. --------------------------------------------------------------------------
  1501. @ 10 o 68
  1502. 68: Section 10  page all  line(s) all
  1503.  
  1504. OBJECTION:
  1505.  
  1506.      The use of errno is a mistake with new functions.  Existing POSIX.1
  1507.      functions and their close relatives should maintain their overall
  1508.      structure, as should those tied to existing practice.  The use of
  1509.      errno as a global error indicator in multithreaded environments intro-
  1510.      duces new difficulties and inefficiencies.
  1511.  
  1512. ACTION:
  1513.  
  1514.      New functions should not set a global errno, but instead return an er-
  1515.      ror indication as the function return value.  The only exception are
  1516.      functions such as pthread_exit() which do not return, and
  1517.      pthread_self() which cannot fail.  We do not provide synopses for all
  1518.      such functions, but will on request from the technical reviewers.
  1519.  
  1520.      Change all new functions such as all pthread_ functions to return an
  1521.      error indication on failure, as described above.
  1522.  
  1523. --------------------------------------------------------------------------
  1524. @ 10 c 69
  1525. 69: Section 10  page all  line(s) all
  1526.  
  1527. EDITORIAL COMMENT:
  1528.  
  1529.      This chapter needs reorganization.  The ordering of functions and or-
  1530.      ganization into major subsections is confusing.
  1531.  
  1532. ACTION:
  1533.  
  1534.      Reorder and reorganize the chapter, perhaps as a flat list of func-
  1535.      tions.
  1536.  
  1537. --------------------------------------------------------------------------
  1538. @ 10.3.4.2 o 70
  1539. 70: Section 10.3.4.2  page 155  line(s) 503-504
  1540.  
  1541. OBJECTION:
  1542.  
  1543.      Given that some input functions can implicitly cause output this re-
  1544.      quirement treated strictly can cause deadlocks.  In particular, line
  1545.      buffered streams will cause the associated output stream to be flushed
  1546.      upon input.
  1547.  
  1548. ACTION:
  1549.  
  1550.      Add the sentence:  "Implicit operations to streams other than the ex-
  1551.      plicitly referenced stream need not behave as if protected by flock-
  1552.      file() on such implicitly referenced streams".  Also, add rationale
  1553.      saying that this apparent weakening of the semantics is present to
  1554.      avoid lock ordering deadlocks.  Mention that line buffered streams can
  1555.      cause this problem.
  1556. ==============================================================================
  1557. --
  1558. Robert L. Knighten                 | knighten@ssd.intel.com
  1559. Intel Supercomputer Systems Division | 
  1560. 15201 N.W. Greenbrier Pkwy.         | (503) 629-4315
  1561. Beaverton, Oregon  97006         | (503) 629-9147 [FAX]
  1562.  
  1563.  
  1564. Volume-Number: Volume 27, Number 83
  1565.  
  1566.