Blame view

trunk/research/st/stk.c 4.8 KB
winlin authored
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
/* 
 * The contents of this file are subject to the Mozilla Public
 * License Version 1.1 (the "License"); you may not use this file
 * except in compliance with the License. You may obtain a copy of
 * the License at http://www.mozilla.org/MPL/
 * 
 * Software distributed under the License is distributed on an "AS
 * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
 * implied. See the License for the specific language governing
 * rights and limitations under the License.
 * 
 * The Original Code is the Netscape Portable Runtime library.
 * 
 * The Initial Developer of the Original Code is Netscape
 * Communications Corporation.  Portions created by Netscape are 
 * Copyright (C) 1994-2000 Netscape Communications Corporation.  All
 * Rights Reserved.
 * 
 * Contributor(s):  Silicon Graphics, Inc.
 * 
 * Portions created by SGI are Copyright (C) 2000-2001 Silicon
 * Graphics, Inc.  All Rights Reserved.
 * 
 * Alternatively, the contents of this file may be used under the
 * terms of the GNU General Public License Version 2 or later (the
 * "GPL"), in which case the provisions of the GPL are applicable 
 * instead of those above.  If you wish to allow use of your 
 * version of this file only under the terms of the GPL and not to
 * allow others to use your version of this file under the MPL,
 * indicate your decision by deleting the provisions above and
 * replace them with the notice and other provisions required by
 * the GPL.  If you do not delete the provisions above, a recipient
 * may use your version of this file under either the MPL or the
 * GPL.
 */

/*
 * This file is derived directly from Netscape Communications Corporation,
 * and consists of extensive modifications made during the year(s) 1999-2000.
 */

#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>
#include "common.h"

/* How much space to leave between the stacks, at each end */
50
#define REDZONE    _ST_PAGE_SIZE
winlin authored
51 52 53 54 55 56 57

_st_clist_t _st_free_stacks = ST_INIT_STATIC_CLIST(&_st_free_stacks);
int _st_num_free_stacks = 0;
int _st_randomize_stacks = 0;

static char *_st_new_stk_segment(int size);
58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
/**
The below comments is by winlin:
The stack memory struct:
    | REDZONE |          stack         |  extra  | REDZONE |
    +---------+------------------------+---------+---------+
    |    4k   |                        |   4k/0  |    4k   |
    +---------+------------------------+---------+---------+
    vaddr     bottom                   top
When _st_randomize_stacks is on, by st_randomize_stacks(),
the bottom and top will random movided in the extra:
        long offset = (random() % extra) & ~0xf;
        ts->stk_bottom += offset;
        ts->stk_top += offset;
Both REDZONE are protected by mprotect when DEBUG is on.
*/
winlin authored
73 74
_st_stack_t *_st_stack_new(int stack_size)
{
winlin authored
75 76 77 78
    _st_clist_t *qp;
    _st_stack_t *ts;
    int extra;
    
79
    // TODO: WINLIN: remove the stack reuse.
winlin authored
80 81 82 83 84 85 86 87 88 89
    for (qp = _st_free_stacks.next; qp != &_st_free_stacks; qp = qp->next) {
        ts = _ST_THREAD_STACK_PTR(qp);
        if (ts->stk_size >= stack_size) {
            /* Found a stack that is big enough */
            ST_REMOVE_LINK(&ts->links);
            _st_num_free_stacks--;
            ts->links.next = NULL;
            ts->links.prev = NULL;
            return ts;
        }
winlin authored
90
    }
winlin authored
91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106
    
    /* Make a new thread stack object. */
    if ((ts = (_st_stack_t *)calloc(1, sizeof(_st_stack_t))) == NULL) {
        return NULL;
    }
    extra = _st_randomize_stacks ? _ST_PAGE_SIZE : 0;
    ts->vaddr_size = stack_size + 2*REDZONE + extra;
    ts->vaddr = _st_new_stk_segment(ts->vaddr_size);
    if (!ts->vaddr) {
        free(ts);
        return NULL;
    }
    ts->stk_size = stack_size;
    ts->stk_bottom = ts->vaddr + REDZONE;
    ts->stk_top = ts->stk_bottom + stack_size;
    
winlin authored
107
#ifdef DEBUG
winlin authored
108 109
    mprotect(ts->vaddr, REDZONE, PROT_NONE);
    mprotect(ts->stk_top + extra, REDZONE, PROT_NONE);
winlin authored
110
#endif
winlin authored
111 112 113 114 115 116 117 118 119
    
    if (extra) {
        long offset = (random() % extra) & ~0xf;
        
        ts->stk_bottom += offset;
        ts->stk_top += offset;
    }
    
    return ts;
winlin authored
120 121 122 123 124 125 126
}

/*
 * Free the stack for the current thread
 */
void _st_stack_free(_st_stack_t *ts)
{
winlin authored
127 128 129 130 131 132 133
    if (!ts) {
        return;
    }
    
    /* Put the stack on the free list */
    ST_APPEND_LINK(&ts->links, _st_free_stacks.prev);
    _st_num_free_stacks++;
winlin authored
134 135 136 137 138
}

static char *_st_new_stk_segment(int size)
{
#ifdef MALLOC_STACK
winlin authored
139
    void *vaddr = malloc(size);
winlin authored
140
#else
winlin authored
141
    #error "Only Supports Malloc Stack"
winlin authored
142
#endif
winlin authored
143 144
    
    return (char *)vaddr;
winlin authored
145 146 147 148 149 150 151
}

/* Not used */
#if 0
void _st_delete_stk_segment(char *vaddr, int size)
{
#ifdef MALLOC_STACK
winlin authored
152
    free(vaddr);
winlin authored
153
#else
154
    #error Unknown Stack Malloc
winlin authored
155 156 157 158 159 160
#endif
}
#endif

int st_randomize_stacks(int on)
{
winlin authored
161 162 163 164 165 166 167 168
    int wason = _st_randomize_stacks;
    
    _st_randomize_stacks = on;
    if (on) {
        srandom((unsigned int) st_utime());
    }
    
    return wason;
winlin authored
169
}