register-atfork.c 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. /* Copyright (C) 2002, 2003, 2005, 2007 Free Software Foundation, Inc.
  2. This file is part of the GNU C Library.
  3. Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
  4. The GNU C Library is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU Lesser General Public
  6. License as published by the Free Software Foundation; either
  7. version 2.1 of the License, or (at your option) any later version.
  8. The GNU C Library is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. Lesser General Public License for more details.
  12. You should have received a copy of the GNU Lesser General Public
  13. License along with the GNU C Library; if not, see
  14. <http://www.gnu.org/licenses/>. */
  15. #include <errno.h>
  16. #include <stdlib.h>
  17. #include <string.h>
  18. #include <fork.h>
  19. #include <atomic.h>
  20. #include <tls.h>
  21. /* Lock to protect allocation and deallocation of fork handlers. */
  22. int __fork_lock = LLL_LOCK_INITIALIZER;
  23. /* Number of pre-allocated handler entries. */
  24. #define NHANDLER 48
  25. /* Memory pool for fork handler structures. */
  26. static struct fork_handler_pool
  27. {
  28. struct fork_handler_pool *next;
  29. struct fork_handler mem[NHANDLER];
  30. } fork_handler_pool;
  31. static struct fork_handler *
  32. fork_handler_alloc (void)
  33. {
  34. struct fork_handler_pool *runp = &fork_handler_pool;
  35. struct fork_handler *result = NULL;
  36. unsigned int i;
  37. do
  38. {
  39. /* Search for an empty entry. */
  40. for (i = 0; i < NHANDLER; ++i)
  41. if (runp->mem[i].refcntr == 0)
  42. goto found;
  43. }
  44. while ((runp = runp->next) != NULL);
  45. /* We have to allocate a new entry. */
  46. runp = (struct fork_handler_pool *) calloc (1, sizeof (*runp));
  47. if (runp != NULL)
  48. {
  49. /* Enqueue the new memory pool into the list. */
  50. runp->next = fork_handler_pool.next;
  51. fork_handler_pool.next = runp;
  52. /* We use the last entry on the page. This means when we start
  53. searching from the front the next time we will find the first
  54. entry unused. */
  55. i = NHANDLER - 1;
  56. found:
  57. result = &runp->mem[i];
  58. result->refcntr = 1;
  59. result->need_signal = 0;
  60. }
  61. return result;
  62. }
  63. int
  64. __register_atfork (
  65. void (*prepare) (void),
  66. void (*parent) (void),
  67. void (*child) (void),
  68. void *dso_handle)
  69. {
  70. /* Get the lock to not conflict with other allocations. */
  71. lll_lock (__fork_lock, LLL_PRIVATE);
  72. struct fork_handler *newp = fork_handler_alloc ();
  73. if (newp != NULL)
  74. {
  75. /* Initialize the new record. */
  76. newp->prepare_handler = prepare;
  77. newp->parent_handler = parent;
  78. newp->child_handler = child;
  79. newp->dso_handle = dso_handle;
  80. __linkin_atfork (newp);
  81. }
  82. /* Release the lock. */
  83. lll_unlock (__fork_lock, LLL_PRIVATE);
  84. return newp == NULL ? ENOMEM : 0;
  85. }
  86. libc_hidden_def (__register_atfork)
  87. void
  88. attribute_hidden
  89. __linkin_atfork (struct fork_handler *newp)
  90. {
  91. do
  92. newp->next = __fork_handlers;
  93. while (catomic_compare_and_exchange_bool_acq (&__fork_handlers,
  94. newp, newp->next) != 0);
  95. }
  96. #if 0
  97. libc_freeres_fn (free_mem)
  98. {
  99. /* Get the lock to not conflict with running forks. */
  100. lll_lock (__fork_lock, LLL_PRIVATE);
  101. /* No more fork handlers. */
  102. __fork_handlers = NULL;
  103. /* Free eventually alloated memory blocks for the object pool. */
  104. struct fork_handler_pool *runp = fork_handler_pool.next;
  105. memset (&fork_handler_pool, '\0', sizeof (fork_handler_pool));
  106. /* Release the lock. */
  107. lll_unlock (__fork_lock, LLL_PRIVATE);
  108. /* We can free the memory after releasing the lock. */
  109. while (runp != NULL)
  110. {
  111. struct fork_handler_pool *oldp = runp;
  112. runp = runp->next;
  113. free (oldp);
  114. }
  115. }
  116. #endif