comparison nspr/pr/src/threads/combined/prustack.c @ 0:1e5118fa0cb1

This is NSS with a Cmake Buildsyste To compile a static NSS library for Windows we've used the Chromium-NSS fork and added a Cmake buildsystem to compile it statically for Windows. See README.chromium for chromium changes and README.trustbridge for our modifications.
author Andre Heinecke <andre.heinecke@intevation.de>
date Mon, 28 Jul 2014 10:47:06 +0200
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:1e5118fa0cb1
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5
6 #include "primpl.h"
7
8 /* List of free stack virtual memory chunks */
9 PRLock *_pr_stackLock;
10 PRCList _pr_freeStacks = PR_INIT_STATIC_CLIST(&_pr_freeStacks);
11 PRIntn _pr_numFreeStacks;
12 PRIntn _pr_maxFreeStacks = 4;
13
14 #ifdef DEBUG
15 /*
16 ** A variable that can be set via the debugger...
17 */
18 PRBool _pr_debugStacks = PR_FALSE;
19 #endif
20
21 /* How much space to leave between the stacks, at each end */
22 #define REDZONE (2 << _pr_pageShift)
23
24 #define _PR_THREAD_STACK_PTR(_qp) \
25 ((PRThreadStack*) ((char*) (_qp) - offsetof(PRThreadStack,links)))
26
27 void _PR_InitStacks(void)
28 {
29 _pr_stackLock = PR_NewLock();
30 }
31
32 void _PR_CleanupStacks(void)
33 {
34 if (_pr_stackLock) {
35 PR_DestroyLock(_pr_stackLock);
36 _pr_stackLock = NULL;
37 }
38 }
39
40 /*
41 ** Allocate a stack for a thread.
42 */
43 PRThreadStack *_PR_NewStack(PRUint32 stackSize)
44 {
45 PRCList *qp;
46 PRThreadStack *ts;
47 PRThread *thr;
48
49 /*
50 ** Trim the list of free stacks. Trim it backwards, tossing out the
51 ** oldest stack found first (this way more recent stacks have a
52 ** chance of being present in the data cache).
53 */
54 PR_Lock(_pr_stackLock);
55 qp = _pr_freeStacks.prev;
56 while ((_pr_numFreeStacks > _pr_maxFreeStacks) && (qp != &_pr_freeStacks)) {
57 ts = _PR_THREAD_STACK_PTR(qp);
58 thr = _PR_THREAD_STACK_TO_PTR(ts);
59 qp = qp->prev;
60 /*
61 * skip stacks which are still being used
62 */
63 if (thr->no_sched)
64 continue;
65 PR_REMOVE_LINK(&ts->links);
66
67 /* Give platform OS to clear out the stack for debugging */
68 _PR_MD_CLEAR_STACK(ts);
69
70 _pr_numFreeStacks--;
71 _PR_DestroySegment(ts->seg);
72 PR_DELETE(ts);
73 }
74
75 /*
76 ** Find a free thread stack. This searches the list of free'd up
77 ** virtually mapped thread stacks.
78 */
79 qp = _pr_freeStacks.next;
80 ts = 0;
81 while (qp != &_pr_freeStacks) {
82 ts = _PR_THREAD_STACK_PTR(qp);
83 thr = _PR_THREAD_STACK_TO_PTR(ts);
84 qp = qp->next;
85 /*
86 * skip stacks which are still being used
87 */
88 if ((!(thr->no_sched)) && ((ts->allocSize - 2*REDZONE) >= stackSize)) {
89 /*
90 ** Found a stack that is not in use and is big enough. Change
91 ** stackSize to fit it.
92 */
93 stackSize = ts->allocSize - 2*REDZONE;
94 PR_REMOVE_LINK(&ts->links);
95 _pr_numFreeStacks--;
96 ts->links.next = 0;
97 ts->links.prev = 0;
98 PR_Unlock(_pr_stackLock);
99 goto done;
100 }
101 ts = 0;
102 }
103 PR_Unlock(_pr_stackLock);
104
105 if (!ts) {
106 /* Make a new thread stack object. */
107 ts = PR_NEWZAP(PRThreadStack);
108 if (!ts) {
109 return NULL;
110 }
111
112 /*
113 ** Assign some of the virtual space to the new stack object. We
114 ** may not get that piece of VM, but if nothing else we will
115 ** advance the pointer so we don't collide (unless the OS screws
116 ** up).
117 */
118 ts->allocSize = stackSize + 2*REDZONE;
119 ts->seg = _PR_NewSegment(ts->allocSize, 0);
120 if (!ts->seg) {
121 PR_DELETE(ts);
122 return NULL;
123 }
124 }
125
126 done:
127 ts->allocBase = (char*)ts->seg->vaddr;
128 ts->flags = _PR_STACK_MAPPED;
129 ts->stackSize = stackSize;
130
131 #ifdef HAVE_STACK_GROWING_UP
132 ts->stackTop = ts->allocBase + REDZONE;
133 ts->stackBottom = ts->stackTop + stackSize;
134 #else
135 ts->stackBottom = ts->allocBase + REDZONE;
136 ts->stackTop = ts->stackBottom + stackSize;
137 #endif
138
139 PR_LOG(_pr_thread_lm, PR_LOG_NOTICE,
140 ("thread stack: base=0x%x limit=0x%x bottom=0x%x top=0x%x\n",
141 ts->allocBase, ts->allocBase + ts->allocSize - 1,
142 ts->allocBase + REDZONE,
143 ts->allocBase + REDZONE + stackSize - 1));
144
145 _PR_MD_INIT_STACK(ts,REDZONE);
146
147 return ts;
148 }
149
150 /*
151 ** Free the stack for the current thread
152 */
153 void _PR_FreeStack(PRThreadStack *ts)
154 {
155 if (!ts) {
156 return;
157 }
158 if (ts->flags & _PR_STACK_PRIMORDIAL) {
159 PR_DELETE(ts);
160 return;
161 }
162
163 /*
164 ** Put the stack on the free list. This is done because we are still
165 ** using the stack. Next time a thread is created we will trim the
166 ** list down; it's safe to do it then because we will have had to
167 ** context switch to a live stack before another thread can be
168 ** created.
169 */
170 PR_Lock(_pr_stackLock);
171 PR_APPEND_LINK(&ts->links, _pr_freeStacks.prev);
172 _pr_numFreeStacks++;
173 PR_Unlock(_pr_stackLock);
174 }
This site is hosted by Intevation GmbH (Datenschutzerklärung und Impressum | Privacy Policy and Imprint)