stk.c 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. /*
  2. * The contents of this file are subject to the Mozilla Public
  3. * License Version 1.1 (the "License"); you may not use this file
  4. * except in compliance with the License. You may obtain a copy of
  5. * the License at http://www.mozilla.org/MPL/
  6. *
  7. * Software distributed under the License is distributed on an "AS
  8. * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
  9. * implied. See the License for the specific language governing
  10. * rights and limitations under the License.
  11. *
  12. * The Original Code is the Netscape Portable Runtime library.
  13. *
  14. * The Initial Developer of the Original Code is Netscape
  15. * Communications Corporation. Portions created by Netscape are
  16. * Copyright (C) 1994-2000 Netscape Communications Corporation. All
  17. * Rights Reserved.
  18. *
  19. * Contributor(s): Silicon Graphics, Inc.
  20. *
  21. * Portions created by SGI are Copyright (C) 2000-2001 Silicon
  22. * Graphics, Inc. All Rights Reserved.
  23. *
  24. * Alternatively, the contents of this file may be used under the
  25. * terms of the GNU General Public License Version 2 or later (the
  26. * "GPL"), in which case the provisions of the GPL are applicable
  27. * instead of those above. If you wish to allow use of your
  28. * version of this file only under the terms of the GPL and not to
  29. * allow others to use your version of this file under the MPL,
  30. * indicate your decision by deleting the provisions above and
  31. * replace them with the notice and other provisions required by
  32. * the GPL. If you do not delete the provisions above, a recipient
  33. * may use your version of this file under either the MPL or the
  34. * GPL.
  35. */
  36. /*
  37. * This file is derived directly from Netscape Communications Corporation,
  38. * and consists of extensive modifications made during the year(s) 1999-2000.
  39. */
  40. #include <stdlib.h>
  41. #include <sys/types.h>
  42. #include <sys/stat.h>
  43. #include <fcntl.h>
  44. #include <sys/mman.h>
  45. #include "common.h"
  46. /* How much space to leave between the stacks, at each end */
  47. #define REDZONE _ST_PAGE_SIZE
  48. _st_clist_t _st_free_stacks = ST_INIT_STATIC_CLIST(&_st_free_stacks);
  49. int _st_num_free_stacks = 0;
  50. int _st_randomize_stacks = 0;
  51. static char *_st_new_stk_segment(int size);
  52. _st_stack_t *_st_stack_new(int stack_size)
  53. {
  54. _st_clist_t *qp;
  55. _st_stack_t *ts;
  56. int extra;
  57. for (qp = _st_free_stacks.next; qp != &_st_free_stacks; qp = qp->next) {
  58. ts = _ST_THREAD_STACK_PTR(qp);
  59. if (ts->stk_size >= stack_size) {
  60. /* Found a stack that is big enough */
  61. ST_REMOVE_LINK(&ts->links);
  62. _st_num_free_stacks--;
  63. ts->links.next = NULL;
  64. ts->links.prev = NULL;
  65. return ts;
  66. }
  67. }
  68. /* Make a new thread stack object. */
  69. if ((ts = (_st_stack_t *)calloc(1, sizeof(_st_stack_t))) == NULL)
  70. return NULL;
  71. extra = _st_randomize_stacks ? _ST_PAGE_SIZE : 0;
  72. ts->vaddr_size = stack_size + 2*REDZONE + extra;
  73. ts->vaddr = _st_new_stk_segment(ts->vaddr_size);
  74. if (!ts->vaddr) {
  75. free(ts);
  76. return NULL;
  77. }
  78. ts->stk_size = stack_size;
  79. ts->stk_bottom = ts->vaddr + REDZONE;
  80. ts->stk_top = ts->stk_bottom + stack_size;
  81. #ifdef DEBUG
  82. mprotect(ts->vaddr, REDZONE, PROT_NONE);
  83. mprotect(ts->stk_top + extra, REDZONE, PROT_NONE);
  84. #endif
  85. if (extra) {
  86. long offset = (random() % extra) & ~0xf;
  87. ts->stk_bottom += offset;
  88. ts->stk_top += offset;
  89. }
  90. return ts;
  91. }
  92. /*
  93. * Free the stack for the current thread
  94. */
  95. void _st_stack_free(_st_stack_t *ts)
  96. {
  97. if (!ts)
  98. return;
  99. /* Put the stack on the free list */
  100. ST_APPEND_LINK(&ts->links, _st_free_stacks.prev);
  101. _st_num_free_stacks++;
  102. }
  103. static char *_st_new_stk_segment(int size)
  104. {
  105. #ifdef MALLOC_STACK
  106. void *vaddr = malloc(size);
  107. #else
  108. static int zero_fd = -1;
  109. int mmap_flags = MAP_PRIVATE;
  110. void *vaddr;
  111. #if defined (MD_USE_SYSV_ANON_MMAP)
  112. if (zero_fd < 0) {
  113. if ((zero_fd = open("/dev/zero", O_RDWR, 0)) < 0)
  114. return NULL;
  115. fcntl(zero_fd, F_SETFD, FD_CLOEXEC);
  116. }
  117. #elif defined (MD_USE_BSD_ANON_MMAP)
  118. mmap_flags |= MAP_ANON;
  119. #else
  120. #error Unknown OS
  121. #endif
  122. vaddr = mmap(NULL, size, PROT_READ | PROT_WRITE, mmap_flags, zero_fd, 0);
  123. if (vaddr == (void *)MAP_FAILED)
  124. return NULL;
  125. #endif /* MALLOC_STACK */
  126. return (char *)vaddr;
  127. }
  128. /* Not used */
  129. #if 0
  130. void _st_delete_stk_segment(char *vaddr, int size)
  131. {
  132. #ifdef MALLOC_STACK
  133. free(vaddr);
  134. #else
  135. (void) munmap(vaddr, size);
  136. #endif
  137. }
  138. #endif
  139. int st_randomize_stacks(int on)
  140. {
  141. int wason = _st_randomize_stacks;
  142. _st_randomize_stacks = on;
  143. if (on)
  144. srandom((unsigned int) st_utime());
  145. return wason;
  146. }