Mercurial > trustbridge > nss-cmake-static
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 } |