4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 1989 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #pragma ident "%Z%%M% %I% %E% SMI"
30 * plock - lock "segments" in physical memory.
32 * Supports SVID-compatible plock, taking into account dynamically linked
33 * objects (such as shared libraries).
36 #include <sys/types.h>
40 #include <sys/resource.h>
41 #include <machine/param.h>
42 #include <machine/vmparam.h>
48 * Globals we reference.
50 extern struct link_dynamic _DYNAMIC
;
53 extern caddr_t
sbrk(); /* find end of data segment */
54 extern caddr_t etext
; /* end of text segment */
57 * Module-scope variables.
59 static int page_size
= 0; /* cached result of getpagesize() */
60 static int lock_state
= 0; /* lock state */
61 static int state_pid
= -1; /* pid to which state belongs */
64 * Local worker routine to lock text and data segments. Handles
65 * dynamically loaded objects. This routine is highly dependent
66 * on executable format and layout.
69 * op: desired operation
70 * f: function to perform
73 apply_lock(int op
, int (*f
)(caddr_t
, u_int
))
75 int e
= 0; /* return value */
76 caddr_t a
; /* address of operation */
77 u_int l
; /* length of operation */
78 struct link_map
*lmp
; /* link map walker */
79 struct exec
*eh
; /* exec header */
82 * Operate on application segment first.
86 a
= (caddr_t
)USRTEXT
; /* note: old Sun-2 not handled */
87 l
= (u_int
)&etext
- USRTEXT
;
90 a
= (caddr_t
)(((int)&etext
+ (SEGSIZ
- 1)) & ~(SEGSIZ
- 1));
91 l
= (u_int
)(sbrk(0) - a
);
94 l
= (l
+ (page_size
- 1)) & (u_int
)~(page_size
- 1);
97 * Perform the operation -- if failure, return immediately.
103 * If we're not a dynamically linked program, we are finished.
109 * Find the list of dynamically linked objects. If we get
110 * dynamic linking formats we don't recognize, then punt.
112 switch (_DYNAMIC
.ld_version
) {
117 lmp
= _DYNAMIC
.ld_un
.ld_2
->ld_loaded
;
124 * Loop over all objects. Extract the addresses and lengths as
125 * required, and perform the appropriate operation.
129 eh
= (struct exec
*)lmp
->lm_addr
;
133 l
= (u_int
)eh
->a_text
;
136 a
= (caddr_t
)((u_int
)eh
+ N_DATADDR(*eh
) -
138 l
= (u_int
)eh
->a_data
+ (u_int
)eh
->a_bss
;
141 l
= (l
+ (page_size
- 1)) & ~(page_size
- 1);
153 * op: desired operation
158 int e
= 0; /* return value */
159 int pid
; /* current pid */
160 caddr_t a1
, a2
; /* loop variables */
161 struct rlimit rl
; /* resource limit */
164 * Initialize static caches.
167 page_size
= getpagesize();
170 * Validate state of lock's. If parent has forked, then
171 * the lock state needs to be reset (children do not inherit
172 * memory locks, and thus do not inherit their state).
174 if ((pid
= getpid()) != state_pid
) {
180 * Dispatch on operation. Note: plock and its relatives depend
181 * upon "op" being bit encoded.
186 * UNLOCK: remove all memory locks. Requires that some be set!
189 if (lock_state
== 0) {
193 if (e
= munlockall())
202 * TXTLOCK: locks text segments.
207 * If a text or process lock is already set, then fail.
209 if ((lock_state
& TXTLOCK
) || (lock_state
& PROCLOCK
)) {
215 * Try to apply the lock(s). If a failure occurs,
216 * back them out. On success, remember that a text
219 if (e
= apply_lock(op
, mlock
))
220 (void) apply_lock(op
, munlock
);
222 lock_state
|= TXTLOCK
;
227 * DATLOCK: locks data segment(s), including the stack and all
228 * future growth in the address space.
233 * If a data or process lock is already set, then fail.
235 if ((lock_state
& DATLOCK
) || (lock_state
& PROCLOCK
)) {
241 * Try to lock the data segments. On failure, back out
242 * the locks and return.
244 if (e
= apply_lock(op
, mlock
)) {
245 (void) apply_lock(op
, munlock
);
250 * Try to lock the stack segment. Find out the extent
251 * and start of the stack (there should be a function for
252 * this!) and then iterate over the pages of the stack
253 * locking them. The stack *could* be sparely populated.
254 * Ignore lock failures resulting from the absence of a
257 (void) getrlimit(RLIMIT_STACK
, &rl
);
258 for (a1
= (caddr_t
)USRSTACK
- page_size
;
259 a1
!= (caddr_t
)USRSTACK
- rl
.rlim_cur
; a1
-= page_size
)
260 if (e
= mlock(a1
, page_size
)) {
267 * If we were successful in locking the stack, then
268 * try to set a lock for all future mappings.
271 e
= mlockall(MCL_FUTURE
);
274 * If failures have occurred, back out the locks
275 * and return failure.
279 (void) apply_lock(op
, munlock
);
280 for (a2
= (caddr_t
)USRSTACK
- page_size
; a2
!= a1
;
282 (void) munlock(a2
, page_size
);
288 * Data, stack, and growth have been locked. Set state
289 * and return success.
291 lock_state
|= DATLOCK
;
296 * PROCLOCK: lock everything, and all future things as well.
297 * There should be nothing locked when this is called.
304 if (mlockall(MCL_CURRENT
| MCL_FUTURE
) == 0) {
305 lock_state
|= PROCLOCK
;