stk.c 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  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. /**
  53. The below comments is by winlin:
  54. The stack memory struct:
  55. | REDZONE | stack | extra | REDZONE |
  56. +---------+------------------------+---------+---------+
  57. | 4k | | 4k/0 | 4k |
  58. +---------+------------------------+---------+---------+
  59. vaddr bottom top
  60. When _st_randomize_stacks is on, by st_randomize_stacks(),
  61. the bottom and top will random movided in the extra:
  62. long offset = (random() % extra) & ~0xf;
  63. ts->stk_bottom += offset;
  64. ts->stk_top += offset;
  65. Both REDZONE are protected by mprotect when DEBUG is on.
  66. */
  67. _st_stack_t *_st_stack_new(int stack_size)
  68. {
  69. _st_clist_t *qp;
  70. _st_stack_t *ts;
  71. int extra;
  72. // TODO: WINLIN: remove the stack reuse.
  73. for (qp = _st_free_stacks.next; qp != &_st_free_stacks; qp = qp->next) {
  74. ts = _ST_THREAD_STACK_PTR(qp);
  75. if (ts->stk_size >= stack_size) {
  76. /* Found a stack that is big enough */
  77. ST_REMOVE_LINK(&ts->links);
  78. _st_num_free_stacks--;
  79. ts->links.next = NULL;
  80. ts->links.prev = NULL;
  81. return ts;
  82. }
  83. }
  84. /* Make a new thread stack object. */
  85. if ((ts = (_st_stack_t *)calloc(1, sizeof(_st_stack_t))) == NULL) {
  86. return NULL;
  87. }
  88. extra = _st_randomize_stacks ? _ST_PAGE_SIZE : 0;
  89. ts->vaddr_size = stack_size + 2*REDZONE + extra;
  90. ts->vaddr = _st_new_stk_segment(ts->vaddr_size);
  91. if (!ts->vaddr) {
  92. free(ts);
  93. return NULL;
  94. }
  95. ts->stk_size = stack_size;
  96. ts->stk_bottom = ts->vaddr + REDZONE;
  97. ts->stk_top = ts->stk_bottom + stack_size;
  98. #ifdef DEBUG
  99. mprotect(ts->vaddr, REDZONE, PROT_NONE);
  100. mprotect(ts->stk_top + extra, REDZONE, PROT_NONE);
  101. #endif
  102. if (extra) {
  103. long offset = (random() % extra) & ~0xf;
  104. ts->stk_bottom += offset;
  105. ts->stk_top += offset;
  106. }
  107. return ts;
  108. }
  109. /*
  110. * Free the stack for the current thread
  111. */
  112. void _st_stack_free(_st_stack_t *ts)
  113. {
  114. if (!ts) {
  115. return;
  116. }
  117. /* Put the stack on the free list */
  118. ST_APPEND_LINK(&ts->links, _st_free_stacks.prev);
  119. _st_num_free_stacks++;
  120. }
  121. static char *_st_new_stk_segment(int size)
  122. {
  123. #ifdef MALLOC_STACK
  124. void *vaddr = malloc(size);
  125. #else
  126. #error "Only Supports Malloc Stack"
  127. #endif
  128. return (char *)vaddr;
  129. }
  130. /* Not used */
  131. #if 0
  132. void _st_delete_stk_segment(char *vaddr, int size)
  133. {
  134. #ifdef MALLOC_STACK
  135. free(vaddr);
  136. #else
  137. #error Unknown Stack Malloc
  138. #endif
  139. }
  140. #endif
  141. int st_randomize_stacks(int on)
  142. {
  143. int wason = _st_randomize_stacks;
  144. _st_randomize_stacks = on;
  145. if (on) {
  146. srandom((unsigned int) st_utime());
  147. }
  148. return wason;
  149. }