1 /* 2 * CDDL HEADER START 3 * 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 7 * with the License. 8 * 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. 13 * 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] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 /* 30 * plock - lock "segments" in physical memory. 31 * 32 * Supports SVID-compatible plock, taking into account dynamically linked 33 * objects (such as shared libraries). 34 */ 35 #pragma weak plock = _plock 36 37 #include "synonyms.h" 38 #include <mtlib.h> 39 #include <sys/types.h> 40 #include <sys/mman.h> 41 #include <sys/lock.h> 42 #include <errno.h> 43 #include <stddef.h> 44 #include <unistd.h> 45 #include <thread.h> 46 #include <synch.h> 47 48 /* 49 * Module-scope variables. 50 */ 51 static int lock_state = 0; /* lock state */ 52 static pid_t state_pid = -1; /* pid to which state belongs */ 53 static mutex_t plock_lock = DEFAULTMUTEX; 54 55 /* 56 * plock 57 */ 58 int 59 plock(int op) /* desired operation */ 60 { 61 int e; /* return value */ 62 pid_t pid; /* current pid */ 63 64 lmutex_lock(&plock_lock); 65 66 /* 67 * Validate state of lock's. If parent has forked, then 68 * the lock state needs to be reset (children do not inherit 69 * memory locks, and thus do not inherit their state). 70 */ 71 if ((pid = getpid()) != state_pid) { 72 lock_state = 0; 73 state_pid = pid; 74 } 75 76 /* 77 * Dispatch on operation. Note: plock and its relatives depend 78 * upon "op" being bit encoded. 79 */ 80 switch (op) { 81 82 /* 83 * UNLOCK: remove all memory locks. Requires that some be set! 84 */ 85 case UNLOCK: 86 if (lock_state == 0) { 87 errno = EINVAL; 88 lmutex_unlock(&plock_lock); 89 return (-1); 90 } 91 e = munlockall(); 92 if (e) { 93 lmutex_unlock(&plock_lock); 94 return (-1); 95 } else { 96 lock_state = 0; 97 lmutex_unlock(&plock_lock); 98 return (0); 99 } 100 /*NOTREACHED*/ 101 102 /* 103 * TXTLOCK: locks text segments. 104 */ 105 case TXTLOCK: 106 107 /* 108 * If a text or process lock is already set, then fail. 109 */ 110 if ((lock_state & TXTLOCK) || (lock_state & PROCLOCK)) { 111 errno = EINVAL; 112 lmutex_unlock(&plock_lock); 113 return (-1); 114 } 115 116 /* 117 * Try to apply the lock(s). If a failure occurs, 118 * memcntl backs them out automatically. 119 */ 120 e = memcntl(NULL, 0, MC_LOCKAS, (caddr_t)MCL_CURRENT, 121 PROC_TEXT|PRIVATE, (int)NULL); 122 if (!e) 123 lock_state |= TXTLOCK; 124 lmutex_unlock(&plock_lock); 125 return (e); 126 /*NOTREACHED*/ 127 128 /* 129 * DATLOCK: locks data segment(s), including the stack and all 130 * future growth in the address space. 131 */ 132 case DATLOCK: 133 134 /* 135 * If a data or process lock is already set, then fail. 136 */ 137 if ((lock_state & DATLOCK) || (lock_state & PROCLOCK)) { 138 errno = EINVAL; 139 lmutex_unlock(&plock_lock); 140 return (-1); 141 } 142 143 /* 144 * Try to lock the data and stack segments. On failure 145 * memcntl undoes the locks internally. 146 */ 147 e = memcntl(NULL, 0, MC_LOCKAS, (caddr_t)MCL_CURRENT, 148 PROC_DATA|PRIVATE, (int)NULL); 149 if (e) { 150 lmutex_unlock(&plock_lock); 151 return (-1); 152 } 153 154 /* try to set a lock for all future mappings. */ 155 e = mlockall(MCL_FUTURE); 156 157 /* 158 * If failures have occurred, back out the locks 159 * and return failure. 160 */ 161 if (e) { 162 e = errno; 163 (void) memcntl(NULL, 0, MC_UNLOCKAS, 164 (caddr_t)MCL_CURRENT, PROC_DATA|PRIVATE, (int)NULL); 165 errno = e; 166 lmutex_unlock(&plock_lock); 167 return (-1); 168 } 169 170 /* 171 * Data, stack, and growth have been locked. Set state 172 * and return success. 173 */ 174 lock_state |= DATLOCK; 175 lmutex_unlock(&plock_lock); 176 return (0); 177 /*NOTREACHED*/ 178 179 /* 180 * PROCLOCK: lock everything, and all future things as well. 181 * There should be nothing locked when this is called. 182 */ 183 case PROCLOCK: 184 if (lock_state) { 185 errno = EINVAL; 186 lmutex_unlock(&plock_lock); 187 return (-1); 188 } 189 if (mlockall(MCL_CURRENT | MCL_FUTURE) == 0) { 190 lock_state |= PROCLOCK; 191 lmutex_unlock(&plock_lock); 192 return (0); 193 } else { 194 lmutex_unlock(&plock_lock); 195 return (-1); 196 } 197 /*NOTREACHED*/ 198 199 /* 200 * Invalid operation. 201 */ 202 default: 203 errno = EINVAL; 204 lmutex_unlock(&plock_lock); 205 return (-1); 206 /*NOTREACHED*/ 207 } 208 } 209