Home | History | Annotate | Download | only in os
      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 (the "License").
      6  * You may not use this file except in compliance with the License.
      7  *
      8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9  * or http://www.opensolaris.org/os/licensing.
     10  * See the License for the specific language governing permissions
     11  * and limitations under the License.
     12  *
     13  * When distributing Covered Code, include this CDDL HEADER in each
     14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15  * If applicable, add the following below this CDDL HEADER, with the
     16  * fields enclosed by brackets "[]" replaced with your own identifying
     17  * information: Portions Copyright [yyyy] [name of copyright owner]
     18  *
     19  * CDDL HEADER END
     20  */
     21 /*
     22  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
     23  * Use is subject to license terms.
     24  */
     25 
     26 #include <sys/types.h>
     27 #include <sys/param.h>
     28 #include <sys/sysmacros.h>
     29 #include <sys/bitmap.h>
     30 #include <sys/var.h>
     31 #include <sys/thread.h>
     32 #include <sys/proc.h>
     33 #include <sys/brand.h>
     34 #include <sys/zone.h>
     35 #include <sys/lx_brand.h>
     36 #include <sys/lx_pid.h>
     37 
     38 #define	LINUX_PROC_FACTOR	8	/* factor down the hash table by this */
     39 static int hash_len = 4;		/* desired average hash chain length */
     40 static int hash_size;			/* no of buckets in the hash table */
     41 
     42 static struct lx_pid **stol_pid_hash;
     43 static struct lx_pid **ltos_pid_hash;
     44 
     45 #define	LTOS_HASH(pid)		((pid) & (hash_size - 1))
     46 #define	STOL_HASH(pid, tid)	(((pid) + (tid)) & (hash_size - 1))
     47 
     48 static kmutex_t hash_lock;
     49 
     50 static void
     51 lx_pid_insert_hash(struct lx_pid *lpidp)
     52 {
     53 	int shash = STOL_HASH(lpidp->s_pid, lpidp->s_tid);
     54 	int lhash = LTOS_HASH(lpidp->l_pid);
     55 
     56 	ASSERT(MUTEX_HELD(&hash_lock));
     57 
     58 	lpidp->stol_next = stol_pid_hash[shash];
     59 	stol_pid_hash[shash] = lpidp;
     60 
     61 	lpidp->ltos_next = ltos_pid_hash[lhash];
     62 	ltos_pid_hash[lhash] = lpidp;
     63 }
     64 
     65 static struct lx_pid *
     66 lx_pid_remove_hash(pid_t pid, id_t tid)
     67 {
     68 	struct lx_pid **hpp;
     69 	struct lx_pid *lpidp;
     70 
     71 	ASSERT(MUTEX_HELD(&hash_lock));
     72 
     73 	hpp = &stol_pid_hash[STOL_HASH(pid, tid)];
     74 	while (*hpp) {
     75 		if ((*hpp)->s_pid == pid && (*hpp)->s_tid == tid) {
     76 			lpidp = *hpp;
     77 			*hpp = (*hpp)->stol_next;
     78 			break;
     79 		}
     80 		hpp = &(*hpp)->stol_next;
     81 	}
     82 
     83 	/*
     84 	 * when called during error recovery the pid may already
     85 	 * be released
     86 	 */
     87 	if (lpidp == NULL)
     88 		return (NULL);
     89 
     90 	hpp = &ltos_pid_hash[LTOS_HASH(lpidp->l_pid)];
     91 	while (*hpp) {
     92 		if (*hpp == lpidp) {
     93 			*hpp = lpidp->ltos_next;
     94 			break;
     95 		}
     96 		hpp = &(*hpp)->ltos_next;
     97 	}
     98 
     99 	return (lpidp);
    100 }
    101 
    102 /*
    103  * given a solaris pid/tid pair, create a linux pid
    104  */
    105 int
    106 lx_pid_assign(kthread_t *t)
    107 {
    108 	proc_t *p = ttoproc(t);
    109 	pid_t s_pid = p->p_pid;
    110 	id_t s_tid = t->t_tid;
    111 	struct pid *pidp;
    112 	struct lx_pid *lpidp;
    113 	lx_lwp_data_t *lwpd = ttolxlwp(t);
    114 	pid_t newpid;
    115 
    116 	if (p->p_lwpcnt > 0) {
    117 		/*
    118 		 * Allocate a pid for any thread other than the first
    119 		 */
    120 		if ((newpid = pid_allocate(p, 0, 0)) < 0)
    121 			return (-1);
    122 
    123 		pidp = pid_find(newpid);
    124 	} else {
    125 		pidp = NULL;
    126 		newpid = s_pid;
    127 	}
    128 
    129 	lpidp = kmem_alloc(sizeof (struct lx_pid), KM_SLEEP);
    130 	lpidp->l_pid = newpid;
    131 	lpidp->s_pid = s_pid;
    132 	lpidp->s_tid = s_tid;
    133 	lpidp->l_pidp = pidp;
    134 	lpidp->l_start = t->t_start;
    135 
    136 	/*
    137 	 * now put the pid into the linux-solaris and solaris-linux
    138 	 * conversion hash tables
    139 	 */
    140 	mutex_enter(&hash_lock);
    141 	lx_pid_insert_hash(lpidp);
    142 	mutex_exit(&hash_lock);
    143 
    144 	lwpd->br_pid = newpid;
    145 
    146 	return (0);
    147 }
    148 
    149 /*
    150  * If we are exec()ing the process, this thread's tid is about to be reset
    151  * to 1.  Make sure the Linux PID bookkeeping reflects that change.
    152  */
    153 void
    154 lx_pid_reassign(kthread_t *t)
    155 {
    156 	proc_t *p = ttoproc(t);
    157 	struct pid *old_pidp;
    158 	struct lx_pid *lpidp;
    159 
    160 	ASSERT(p->p_lwpcnt == 1);
    161 
    162 	mutex_enter(&hash_lock);
    163 
    164 	/*
    165 	 * Clean up all the traces of this thread's 'fake' Linux PID.
    166 	 */
    167 	lpidp = lx_pid_remove_hash(p->p_pid, t->t_tid);
    168 	ASSERT(lpidp != NULL);
    169 	old_pidp = lpidp->l_pidp;
    170 	lpidp->l_pidp = NULL;
    171 
    172 	/*
    173 	 * Now register this thread as (pid, 1).
    174 	 */
    175 	lpidp->l_pid = p->p_pid;
    176 	lpidp->s_pid = p->p_pid;
    177 	lpidp->s_tid = 1;
    178 	lx_pid_insert_hash(lpidp);
    179 
    180 	mutex_exit(&hash_lock);
    181 
    182 	if (old_pidp)
    183 		(void) pid_rele(old_pidp);
    184 }
    185 
    186 /*
    187  * release a solaris pid/tid pair
    188  */
    189 void
    190 lx_pid_rele(pid_t pid, id_t tid)
    191 {
    192 	struct lx_pid *lpidp;
    193 
    194 	mutex_enter(&hash_lock);
    195 	lpidp = lx_pid_remove_hash(pid, tid);
    196 	mutex_exit(&hash_lock);
    197 
    198 	if (lpidp) {
    199 		if (lpidp->l_pidp)
    200 			(void) pid_rele(lpidp->l_pidp);
    201 
    202 		kmem_free(lpidp, sizeof (*lpidp));
    203 	}
    204 }
    205 
    206 /*
    207  * given a linux pid, return the solaris pid/tid pair
    208  */
    209 int
    210 lx_lpid_to_spair(pid_t l_pid, pid_t *s_pid, id_t *s_tid)
    211 {
    212 	struct lx_pid *hp;
    213 
    214 	mutex_enter(&hash_lock);
    215 	for (hp = ltos_pid_hash[LTOS_HASH(l_pid)]; hp; hp = hp->ltos_next) {
    216 		if (l_pid == hp->l_pid) {
    217 			if (s_pid)
    218 				*s_pid = hp->s_pid;
    219 			if (s_tid)
    220 				*s_tid = hp->s_tid;
    221 			break;
    222 		}
    223 	}
    224 	mutex_exit(&hash_lock);
    225 	if (hp != NULL)
    226 		return (0);
    227 
    228 	/*
    229 	 * We didn't find this pid in our translation table.
    230 	 * But this still could be the pid of a native process
    231 	 * running in the current zone so check for that here.
    232 	 *
    233 	 * Note that prfind() only searches for processes in the current zone.
    234 	 */
    235 	mutex_enter(&pidlock);
    236 	if (prfind(l_pid) != NULL) {
    237 		mutex_exit(&pidlock);
    238 		if (s_pid)
    239 			*s_pid = l_pid;
    240 		if (s_tid)
    241 			*s_tid = 0;
    242 		return (0);
    243 	}
    244 	mutex_exit(&pidlock);
    245 
    246 	return (-1);
    247 }
    248 
    249 /*
    250  * Given an lwp, return the Linux pid of its parent.  If the caller
    251  * wants them, we return the Solaris (pid, tid) as well.
    252  */
    253 pid_t
    254 lx_lwp_ppid(klwp_t *lwp, pid_t *ppidp, id_t *ptidp)
    255 {
    256 	lx_lwp_data_t *lwpd = lwptolxlwp(lwp);
    257 	proc_t *p = lwptoproc(lwp);
    258 	struct lx_pid *hp;
    259 	pid_t zoneinit = curproc->p_zone->zone_proc_initpid;
    260 	pid_t lppid, ppid;
    261 
    262 	/*
    263 	 * Be sure not to return a parent pid that should be invisible
    264 	 * within this zone.
    265 	 */
    266 	ppid = ((p->p_flag & SZONETOP)
    267 	    ? curproc->p_zone->zone_zsched->p_pid : p->p_ppid);
    268 
    269 	/*
    270 	 * If the parent process's pid is the zone's init process, force it
    271 	 * to the Linux init pid value of 1.
    272 	 */
    273 	if (ppid == zoneinit)
    274 		ppid = 1;
    275 
    276 	/*
    277 	 * There are two cases in which the Linux definition of a 'parent'
    278 	 * matches that of Solaris:
    279 	 *
    280 	 * - if our tgid is the same as our PID, then we are either the
    281 	 *   first thread in the process or a CLONE_THREAD thread.
    282 	 *
    283 	 * - if the brand lwp value for ppid is 0, then we are either the
    284 	 *   child of a differently-branded process or a CLONE_PARENT thread.
    285 	 */
    286 	if (p->p_pid == lwpd->br_tgid || lwpd->br_ppid == 0) {
    287 		if (ppidp != NULL)
    288 			*ppidp = ppid;
    289 		if (ptidp != NULL)
    290 			*ptidp = -1;
    291 		return (ppid);
    292 	}
    293 
    294 	/*
    295 	 * Set the default Linux parent pid to be the pid of the zone's init
    296 	 * process; this will get converted back to the Linux default of 1
    297 	 * later.
    298 	 */
    299 	lppid = zoneinit;
    300 
    301 	/*
    302 	 * If the process's parent isn't init, try and look up the Linux "pid"
    303 	 * corresponding to the process's parent.
    304 	 */
    305 	if (ppid != 1) {
    306 		/*
    307 		 * In all other cases, we are looking for the parent of this
    308 		 * specific thread, which in Linux refers to the thread that
    309 		 * clone()d it.   We stashed that thread's PID away when this
    310 		 * thread was created.
    311 		 */
    312 		mutex_enter(&hash_lock);
    313 		for (hp = ltos_pid_hash[LTOS_HASH(lwpd->br_ppid)]; hp;
    314 		    hp = hp->ltos_next) {
    315 			if (lwpd->br_ppid == hp->l_pid) {
    316 				/*
    317 				 * We found the PID we were looking for, but
    318 				 * since we cached its value in this LWP's brand
    319 				 * structure, it has exited and been reused by
    320 				 * another process.
    321 				 */
    322 				if (hp->l_start > lwptot(lwp)->t_start)
    323 					break;
    324 
    325 				lppid = lwpd->br_ppid;
    326 				if (ppidp != NULL)
    327 					*ppidp = hp->s_pid;
    328 				if (ptidp != NULL)
    329 					*ptidp = hp->s_tid;
    330 
    331 				break;
    332 			}
    333 		}
    334 		mutex_exit(&hash_lock);
    335 	}
    336 
    337 	if (lppid == zoneinit) {
    338 		lppid = 1;
    339 
    340 		if (ppidp != NULL)
    341 			*ppidp = lppid;
    342 		if (ptidp != NULL)
    343 			*ptidp = -1;
    344 	}
    345 
    346 	return (lppid);
    347 }
    348 
    349 void
    350 lx_pid_init(void)
    351 {
    352 	hash_size = 1 << highbit(v.v_proc / (hash_len * LINUX_PROC_FACTOR));
    353 
    354 	stol_pid_hash = kmem_zalloc(sizeof (struct lx_pid *) * hash_size,
    355 	    KM_SLEEP);
    356 	ltos_pid_hash = kmem_zalloc(sizeof (struct lx_pid *) * hash_size,
    357 	    KM_SLEEP);
    358 
    359 	mutex_init(&hash_lock, NULL, MUTEX_DEFAULT, NULL);
    360 }
    361 
    362 void
    363 lx_pid_fini(void)
    364 {
    365 	kmem_free(stol_pid_hash, sizeof (struct lx_pid *) * hash_size);
    366 	kmem_free(ltos_pid_hash, sizeof (struct lx_pid *) * hash_size);
    367 }
    368