Print this page
re #13613 rb4516 Tunables needs volatile keyword
| Split |
Close |
| Expand all |
| Collapse all |
--- old/usr/src/uts/common/io/ptms_conf.c
+++ new/usr/src/uts/common/io/ptms_conf.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
↓ open down ↓ |
14 lines elided |
↑ open up ↑ |
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21 /*
22 22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23 23 * Use is subject to license terms.
24 24 */
25 +/*
26 + * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
27 + */
25 28
26 -#pragma ident "%Z%%M% %I% %E% SMI"
27 -
28 29 /*
29 30 * This file contains global data and code shared between master and slave parts
30 31 * of the pseudo-terminal driver.
31 32 *
32 33 * Pseudo terminals (or pt's for short) are allocated dynamically.
33 34 * pt's are put in the global ptms_slots array indexed by minor numbers.
34 35 *
35 36 * The slots array is initially small (of the size NPTY_MIN). When more pt's are
36 37 * needed than the slot array size, the larger slot array is allocated and all
37 38 * opened pt's move to the new one.
38 39 *
39 40 * Resource allocation:
40 41 *
41 42 * pt_ttys structures are allocated via pt_ttys_alloc, which uses
42 43 * kmem_cache_alloc().
43 44 * Minor number space is allocated via vmem_alloc() interface.
44 45 * ptms_slots arrays are allocated via kmem_alloc().
45 46 *
46 47 * Minors are started from 1 instead of 0 because vmem_alloc returns 0 in case
47 48 * of failure. Also, in anticipation of removing clone device interface to
48 49 * pseudo-terminal subsystem, minor 0 should not be used. (Potential future
49 50 * development).
50 51 *
51 52 * After the table slot size reaches pt_maxdelta, we stop 2^N extension
52 53 * algorithm and start extending the slot table size by pt_maxdelta.
53 54 *
54 55 * Device entries /dev/pts directory are created dynamically by the
55 56 * /dev filesystem. We no longer call ddi_create_minor_node() on
56 57 * behalf of the slave driver. The /dev filesystem creates /dev/pts
57 58 * nodes based on the pt_ttys array.
58 59 *
59 60 * Synchronization:
60 61 *
61 62 * All global data synchronization between ptm/pts is done via global
62 63 * ptms_lock mutex which is implicitly initialized by declaring it global.
63 64 *
64 65 * Individual fields of pt_ttys structure (except ptm_rdq, pts_rdq and
65 66 * pt_nullmsg) are protected by pt_ttys.pt_lock mutex.
66 67 *
67 68 * PT_ENTER_READ/PT_ENTER_WRITE are reference counter based read-write locks
68 69 * which allow reader locks to be reacquired by the same thread (usual
69 70 * reader/writer locks can't be used for that purpose since it is illegal for
70 71 * a thread to acquire a lock it already holds, even as a reader). The sole
71 72 * purpose of these macros is to guarantee that the peer queue will not
72 73 * disappear (due to closing peer) while it is used. It is safe to use
73 74 * PT_ENTER_READ/PT_EXIT_READ brackets across calls like putq/putnext (since
74 75 * they are not real locks but reference counts).
75 76 *
76 77 * PT_ENTER_WRITE/PT_EXIT_WRITE brackets are used ONLY in master/slave
77 78 * open/close paths to modify ptm_rdq and pts_rdq fields. These fields should
78 79 * be set to appropriate queues *after* qprocson() is called during open (to
79 80 * prevent peer from accessing the queue with incomplete plumbing) and set to
80 81 * NULL before qprocsoff() is called during close. Put and service procedures
81 82 * use PT_ENTER_READ/PT_EXIT_READ to prevent peer closes.
82 83 *
83 84 * The pt_nullmsg field is only used in open/close routines and is also
84 85 * protected by PT_ENTER_WRITE/PT_EXIT_WRITE brackets to avoid extra mutex
85 86 * holds.
86 87 *
87 88 * Lock Ordering:
88 89 *
89 90 * If both ptms_lock and per-pty lock should be held, ptms_lock should always
90 91 * be entered first, followed by per-pty lock.
91 92 *
92 93 * Global functions:
93 94 *
94 95 * void ptms_init(void);
95 96 *
96 97 * Called by pts/ptm _init entry points. It performes one-time
97 98 * initialization needed for both pts and ptm. This initialization is done
98 99 * here and not in ptms_initspace because all these data structures are not
99 100 * needed if pseudo-terminals are not used in the system.
100 101 *
101 102 * struct pt_ttys *pt_ttys_alloc(void);
102 103 *
103 104 * Allocate new minor number and pseudo-terminal entry. May sleep.
104 105 * New minor number is recorded in pt_minor field of the entry returned.
105 106 * This routine also initializes pt_minor and pt_state fields of the new
106 107 * pseudo-terminal and puts a pointer to it into ptms_slots array.
107 108 *
108 109 * struct pt_ttys *ptms_minor2ptty(minor_t minor)
109 110 *
110 111 * Find pt_ttys structure by minor number.
111 112 * Returns NULL when minor is out of range.
112 113 *
113 114 * int ptms_minor_valid(minor_t minor, uid_t *ruid, gid_t *rgid)
114 115 *
115 116 * Check if minor refers to an allocated pty in the current zone.
116 117 * Returns
117 118 * 0 if not allocated or not for this zone.
118 119 * 1 if an allocated pty in the current zone.
119 120 * Also returns owner of pty.
120 121 *
121 122 * int ptms_minor_exists(minor_t minor)
122 123 * Check if minor refers to an allocated pty (in any zone)
123 124 * Returns
124 125 * 0 if not an allocated pty
125 126 * 1 if an allocated pty
126 127 *
127 128 * void ptms_set_owner(minor_t minor, uid_t ruid, gid_t rgid)
128 129 *
129 130 * Sets the owner associated with a pty.
130 131 *
131 132 * void ptms_close(struct pt_ttys *pt, uint_t flags_to_clear);
132 133 *
133 134 * Clear flags_to_clear in pt and if no one owns it (PTMOPEN/PTSOPEN not
134 135 * set) free pt entry and corresponding slot.
135 136 *
136 137 * Tuneables and configuration:
137 138 *
138 139 * pt_cnt: minimum number of pseudo-terminals in the system. The system
139 140 * should provide at least this number of ptys (provided sufficient
140 141 * memory is available). It is different from the older semantics
141 142 * of pt_cnt meaning maximum number of ptys.
142 143 * Set to 0 by default.
143 144 *
144 145 * pt_max_pty: Maximum number of pseudo-terminals in the system. The system
145 146 * should not allocate more ptys than pt_max_pty (although, it may
146 147 * impose stricter maximum). Zero value means no user-defined
147 148 * maximum. This is intended to be used as "denial-of-service"
148 149 * protection.
149 150 * Set to 0 by default.
150 151 *
151 152 * Both pt_cnt and pt_max_pty may be modified during system lifetime
152 153 * with their semantics preserved.
153 154 *
154 155 * pt_init_cnt: Initial size of ptms_slots array. Set to NPTY_INITIAL.
155 156 *
156 157 * pt_ptyofmem: Approximate percentage of system memory that may be
157 158 * occupied by pty data structures. Initially set to NPTY_PERCENT.
158 159 * This variable is used once during initialization to estimate
159 160 * maximum number of ptys in the system. The actual maximum is
160 161 * determined as minimum of pt_max_pty and calculated value.
161 162 *
162 163 * pt_maxdelta: Maximum extension chunk of the slot table.
163 164 */
164 165
165 166
166 167
167 168 #include <sys/types.h>
168 169 #include <sys/param.h>
169 170 #include <sys/termios.h>
170 171 #include <sys/stream.h>
171 172 #include <sys/stropts.h>
172 173 #include <sys/kmem.h>
173 174 #include <sys/ptms.h>
174 175 #include <sys/stat.h>
175 176 #include <sys/sunddi.h>
176 177 #include <sys/ddi.h>
177 178 #include <sys/bitmap.h>
178 179 #include <sys/sysmacros.h>
179 180 #include <sys/ddi_impldefs.h>
180 181 #include <sys/zone.h>
181 182 #ifdef DEBUG
182 183 #include <sys/strlog.h>
183 184 #endif
184 185
185 186
186 187 /* Initial number of ptms slots */
|
↓ open down ↓ |
149 lines elided |
↑ open up ↑ |
187 188 #define NPTY_INITIAL 16
188 189
189 190 #define NPTY_PERCENT 5
190 191
191 192 /* Maximum increment of the slot table size */
192 193 #define PTY_MAXDELTA 128
193 194
194 195 /*
195 196 * Tuneable variables.
196 197 */
197 -uint_t pt_cnt = 0; /* Minimum number of ptys */
198 -size_t pt_max_pty = 0; /* Maximum number of ptys */
198 +volatile uint_t pt_cnt = 0; /* Minimum number of ptys */
199 +volatile size_t pt_max_pty = 0; /* Maximum number of ptys */
199 200 uint_t pt_init_cnt = NPTY_INITIAL; /* Initial number of ptms slots */
200 -uint_t pt_pctofmem = NPTY_PERCENT; /* Percent of memory to use for ptys */
201 +volatile uint_t pt_pctofmem = NPTY_PERCENT; /* Percent of memory to use */
202 + /* for ptys */
201 203 uint_t pt_maxdelta = PTY_MAXDELTA; /* Max increment for slot table size */
202 204
203 205 /* Other global variables */
204 206
205 207 kmutex_t ptms_lock; /* Global data access lock */
206 208
207 209 /*
208 210 * Slot array and its management variables
209 211 */
210 212 static struct pt_ttys **ptms_slots = NULL; /* Slots for actual pt structures */
211 213 static size_t ptms_nslots = 0; /* Size of slot array */
212 214 static size_t ptms_ptymax = 0; /* Maximum number of ptys */
213 215 static size_t ptms_inuse = 0; /* # of ptys currently allocated */
214 216
215 217 dev_info_t *pts_dip = NULL; /* set if slave is attached */
216 218
217 219 static struct kmem_cache *ptms_cache = NULL; /* pty cache */
218 220
219 221 static vmem_t *ptms_minor_arena = NULL; /* Arena for device minors */
220 222
221 223 static uint_t ptms_roundup(uint_t);
222 224 static int ptms_constructor(void *, void *, int);
223 225 static void ptms_destructor(void *, void *);
224 226 static minor_t ptms_grow(void);
225 227
226 228 /*
227 229 * Total size occupied by one pty. Each pty master/slave pair consumes one
228 230 * pointer for ptms_slots array, one pt_ttys structure and one empty message
229 231 * preallocated for pts close.
230 232 */
231 233
232 234 #define PTY_SIZE (sizeof (struct pt_ttys) + \
233 235 sizeof (struct pt_ttys *) + \
234 236 sizeof (dblk_t))
235 237
236 238 #ifdef DEBUG
237 239 int ptms_debug = 0;
238 240 #define PTMOD_ID 5
239 241 #endif
240 242
241 243 /*
242 244 * Clear all bits of x except the highest bit
243 245 */
244 246 #define truncate(x) ((x) <= 2 ? (x) : (1 << (highbit(x) - 1)))
245 247
246 248 /*
247 249 * Roundup the number to the nearest power of 2
248 250 */
249 251 static uint_t
250 252 ptms_roundup(uint_t x)
251 253 {
252 254 uint_t p = truncate(x); /* x with non-high bits stripped */
253 255
254 256 /*
255 257 * If x is a power of 2, return x, otherwise roundup.
256 258 */
257 259 return (p == x ? p : (p * 2));
258 260 }
259 261
260 262 /*
261 263 * Allocate ptms_slots array and kmem cache for pt_ttys. This initialization is
262 264 * only called once during system lifetime. Called from ptm or pts _init
263 265 * routine.
264 266 */
265 267 void
266 268 ptms_init(void)
267 269 {
268 270 mutex_enter(&ptms_lock);
269 271
270 272 if (ptms_slots == NULL) {
271 273 ptms_slots = kmem_zalloc(pt_init_cnt *
272 274 sizeof (struct pt_ttys *), KM_SLEEP);
273 275
274 276 ptms_cache = kmem_cache_create("pty_map",
275 277 sizeof (struct pt_ttys), 0, ptms_constructor,
276 278 ptms_destructor, NULL, NULL, NULL, 0);
277 279
278 280 ptms_nslots = pt_init_cnt;
279 281
280 282 /* Allocate integer space for minor numbers */
281 283 ptms_minor_arena = vmem_create("ptms_minor", (void *)1,
282 284 ptms_nslots, 1, NULL, NULL, NULL, 0,
283 285 VM_SLEEP | VMC_IDENTIFIER);
284 286
285 287 /*
286 288 * Calculate available number of ptys - how many ptys can we
287 289 * allocate in pt_pctofmem % of available memory. The value is
288 290 * rounded up to the nearest power of 2.
289 291 */
290 292 ptms_ptymax = ptms_roundup((pt_pctofmem * kmem_maxavail()) /
291 293 (100 * PTY_SIZE));
292 294 }
293 295 mutex_exit(&ptms_lock);
294 296 }
295 297
296 298 /*
297 299 * This routine attaches the pts dip.
298 300 */
299 301 int
300 302 ptms_attach_slave(void)
301 303 {
302 304 if (pts_dip == NULL && i_ddi_attach_pseudo_node("pts") == NULL)
303 305 return (-1);
304 306
305 307 ASSERT(pts_dip);
306 308 return (0);
307 309 }
308 310
309 311 /*
310 312 * Called from /dev fs. Checks if dip is attached,
311 313 * and if it is, returns its major number.
312 314 */
313 315 major_t
314 316 ptms_slave_attached(void)
315 317 {
316 318 major_t maj = DDI_MAJOR_T_NONE;
317 319
318 320 mutex_enter(&ptms_lock);
319 321 if (pts_dip)
320 322 maj = ddi_driver_major(pts_dip);
321 323 mutex_exit(&ptms_lock);
322 324
323 325 return (maj);
324 326 }
325 327
326 328 /*
327 329 * Allocate new minor number and pseudo-terminal entry. Returns the new entry or
328 330 * NULL if no memory or maximum number of entries reached.
329 331 */
330 332 struct pt_ttys *
331 333 pt_ttys_alloc(void)
332 334 {
333 335 minor_t dminor;
334 336 struct pt_ttys *pt = NULL;
335 337
336 338 mutex_enter(&ptms_lock);
337 339
338 340 /*
339 341 * Always try to allocate new pty when pt_cnt minimum limit is not
340 342 * achieved. If it is achieved, the maximum is determined by either
341 343 * user-specified value (if it is non-zero) or our memory estimations -
342 344 * whatever is less.
343 345 */
344 346 if (ptms_inuse >= pt_cnt) {
345 347 /*
346 348 * When system achieved required minimum of ptys, check for the
347 349 * denial of service limits.
348 350 *
349 351 * Since pt_max_pty may be zero, the formula below is used to
350 352 * avoid conditional expression. It will equal to pt_max_pty if
351 353 * it is not zero and ptms_ptymax otherwise.
352 354 */
353 355 size_t user_max = (pt_max_pty == 0 ? ptms_ptymax : pt_max_pty);
354 356
355 357 /* Do not try to allocate more than allowed */
356 358 if (ptms_inuse >= min(ptms_ptymax, user_max)) {
357 359 mutex_exit(&ptms_lock);
358 360 return (NULL);
359 361 }
360 362 }
361 363 ptms_inuse++;
362 364
363 365 /*
364 366 * Allocate new minor number. If this fails, all slots are busy and
365 367 * we need to grow the hash.
366 368 */
367 369 dminor = (minor_t)(uintptr_t)
368 370 vmem_alloc(ptms_minor_arena, 1, VM_NOSLEEP);
369 371
370 372 if (dminor == 0) {
371 373 /* Grow the cache and retry allocation */
372 374 dminor = ptms_grow();
373 375 }
374 376
375 377 if (dminor == 0) {
376 378 /* Not enough memory now */
377 379 ptms_inuse--;
378 380 mutex_exit(&ptms_lock);
379 381 return (NULL);
380 382 }
381 383
382 384 pt = kmem_cache_alloc(ptms_cache, KM_NOSLEEP);
383 385 if (pt == NULL) {
384 386 /* Not enough memory - this entry can't be used now. */
385 387 vmem_free(ptms_minor_arena, (void *)(uintptr_t)dminor, 1);
386 388 ptms_inuse--;
387 389 } else {
388 390 pt->pt_minor = dminor;
389 391 pt->pt_pid = curproc->p_pid; /* For debugging */
390 392 pt->pt_state = (PTMOPEN | PTLOCK);
391 393 pt->pt_zoneid = getzoneid();
392 394 pt->pt_ruid = 0; /* we don't know uid/gid yet. Report as root */
393 395 pt->pt_rgid = 0;
394 396 ASSERT(ptms_slots[dminor - 1] == NULL);
395 397 ptms_slots[dminor - 1] = pt;
396 398 }
397 399
398 400 mutex_exit(&ptms_lock);
399 401 return (pt);
400 402 }
401 403
402 404 /*
403 405 * Get pt_ttys structure by minor number.
404 406 * Returns NULL when minor is out of range.
405 407 */
406 408 struct pt_ttys *
407 409 ptms_minor2ptty(minor_t dminor)
408 410 {
409 411 struct pt_ttys *pt = NULL;
410 412
411 413 ASSERT(mutex_owned(&ptms_lock));
412 414 if ((dminor >= 1) && (dminor <= ptms_nslots) && ptms_slots != NULL)
413 415 pt = ptms_slots[dminor - 1];
414 416
415 417 return (pt);
416 418 }
417 419
418 420 /*
419 421 * Invoked in response to chown on /dev/pts nodes to change the
420 422 * permission on a pty
421 423 */
422 424 void
423 425 ptms_set_owner(minor_t dminor, uid_t ruid, gid_t rgid)
424 426 {
425 427 struct pt_ttys *pt;
426 428
427 429 ASSERT(ruid >= 0);
428 430 ASSERT(rgid >= 0);
429 431
430 432 if (ruid < 0 || rgid < 0)
431 433 return;
432 434
433 435 /*
434 436 * /dev/pts/0 is not used, but some applications may check it. There
435 437 * is no pty backing it - so we have nothing to do.
436 438 */
437 439 if (dminor == 0)
438 440 return;
439 441
440 442 mutex_enter(&ptms_lock);
441 443 pt = ptms_minor2ptty(dminor);
442 444 if (pt != NULL && pt->pt_zoneid == getzoneid()) {
443 445 pt->pt_ruid = ruid;
444 446 pt->pt_rgid = rgid;
445 447 }
446 448 mutex_exit(&ptms_lock);
447 449 }
448 450
449 451 /*
450 452 * Given a ptm/pts minor number
451 453 * returns:
452 454 * 1 if the pty is allocated to the current zone.
453 455 * 0 otherwise
454 456 *
455 457 * If the pty is allocated to the current zone, it also returns the owner.
456 458 */
457 459 int
458 460 ptms_minor_valid(minor_t dminor, uid_t *ruid, gid_t *rgid)
459 461 {
460 462 struct pt_ttys *pt;
461 463 int ret;
462 464
463 465 ASSERT(ruid);
464 466 ASSERT(rgid);
465 467
466 468 *ruid = (uid_t)-1;
467 469 *rgid = (gid_t)-1;
468 470
469 471 /*
470 472 * /dev/pts/0 is not used, but some applications may check it, so create
471 473 * it also. Report the owner as root. It belongs to all zones.
472 474 */
473 475 if (dminor == 0) {
474 476 *ruid = 0;
475 477 *rgid = 0;
476 478 return (1);
477 479 }
478 480
479 481 ret = 0;
480 482 mutex_enter(&ptms_lock);
481 483 pt = ptms_minor2ptty(dminor);
482 484 if (pt != NULL) {
483 485 ASSERT(pt->pt_ruid >= 0);
484 486 ASSERT(pt->pt_rgid >= 0);
485 487 if (pt->pt_zoneid == getzoneid()) {
486 488 ret = 1;
487 489 *ruid = pt->pt_ruid;
488 490 *rgid = pt->pt_rgid;
489 491 }
490 492 }
491 493 mutex_exit(&ptms_lock);
492 494
493 495 return (ret);
494 496 }
495 497
496 498 /*
497 499 * Given a ptm/pts minor number
498 500 * returns:
499 501 * 0 if the pty is not allocated
500 502 * 1 if the pty is allocated
501 503 */
502 504 int
503 505 ptms_minor_exists(minor_t dminor)
504 506 {
505 507 int ret;
506 508
507 509 mutex_enter(&ptms_lock);
508 510 ret = ptms_minor2ptty(dminor) ? 1 : 0;
509 511 mutex_exit(&ptms_lock);
510 512
511 513 return (ret);
512 514 }
513 515
514 516 /*
515 517 * Close the pt and clear flags_to_clear.
516 518 * If pt device is not opened by someone else, free it and clear its slot.
517 519 */
518 520 void
519 521 ptms_close(struct pt_ttys *pt, uint_t flags_to_clear)
520 522 {
521 523 uint_t flags;
522 524
523 525 ASSERT(MUTEX_NOT_HELD(&ptms_lock));
524 526 ASSERT(pt != NULL);
525 527
526 528 mutex_enter(&ptms_lock);
527 529
528 530 mutex_enter(&pt->pt_lock);
529 531 pt->pt_state &= ~flags_to_clear;
530 532 flags = pt->pt_state;
531 533 mutex_exit(&pt->pt_lock);
532 534
533 535 if (! (flags & (PTMOPEN | PTSOPEN))) {
534 536 /* No one owns the entry - free it */
535 537
536 538 ASSERT(pt->ptm_rdq == NULL);
537 539 ASSERT(pt->pts_rdq == NULL);
538 540 ASSERT(pt->pt_nullmsg == NULL);
539 541 ASSERT(pt->pt_refcnt == 0);
540 542 ASSERT(pt->pt_minor <= ptms_nslots);
541 543 ASSERT(ptms_slots[pt->pt_minor - 1] == pt);
542 544 ASSERT(ptms_inuse > 0);
543 545
544 546 ptms_inuse--;
545 547
546 548 pt->pt_pid = 0;
547 549
548 550 ptms_slots[pt->pt_minor - 1] = NULL;
549 551 /* Return minor number to the pool of minors */
550 552 vmem_free(ptms_minor_arena, (void *)(uintptr_t)pt->pt_minor, 1);
551 553 /* Return pt to the cache */
552 554 kmem_cache_free(ptms_cache, pt);
553 555 }
554 556 mutex_exit(&ptms_lock);
555 557 }
556 558
557 559 /*
558 560 * Allocate another slot table twice as large as the original one (limited to
559 561 * global maximum). Migrate all pt to the new slot table and free the original
560 562 * one. Create more /devices entries for new devices.
561 563 */
562 564 static minor_t
563 565 ptms_grow()
564 566 {
565 567 minor_t old_size = ptms_nslots;
566 568 minor_t delta = MIN(pt_maxdelta, old_size);
567 569 minor_t new_size = old_size + delta;
568 570 struct pt_ttys **ptms_old = ptms_slots;
569 571 struct pt_ttys **ptms_new;
570 572 void *vaddr; /* vmem_add return value */
571 573
572 574 ASSERT(MUTEX_HELD(&ptms_lock));
573 575
574 576 DDBG("ptmopen(%d): need to grow\n", (int)ptms_inuse);
575 577
576 578 /* Allocate new ptms array */
577 579 ptms_new = kmem_zalloc(new_size * sizeof (struct pt_ttys *),
578 580 KM_NOSLEEP);
579 581 if (ptms_new == NULL)
580 582 return ((minor_t)0);
581 583
582 584 /* Increase clone index space */
583 585 vaddr = vmem_add(ptms_minor_arena, (void *)(uintptr_t)(old_size + 1),
584 586 new_size - old_size, VM_NOSLEEP);
585 587
586 588 if (vaddr == NULL) {
587 589 kmem_free(ptms_new, new_size * sizeof (struct pt_ttys *));
588 590 return ((minor_t)0);
589 591 }
590 592
591 593 /* Migrate pt entries to a new location */
592 594 ptms_nslots = new_size;
593 595 bcopy(ptms_old, ptms_new, old_size * sizeof (struct pt_ttys *));
594 596 ptms_slots = ptms_new;
595 597 kmem_free(ptms_old, old_size * sizeof (struct pt_ttys *));
596 598
597 599 /* Allocate minor number and return it */
598 600 return ((minor_t)(uintptr_t)
599 601 vmem_alloc(ptms_minor_arena, 1, VM_NOSLEEP));
600 602 }
601 603
602 604 /*ARGSUSED*/
603 605 static int
604 606 ptms_constructor(void *maddr, void *arg, int kmflags)
605 607 {
606 608 struct pt_ttys *pt = maddr;
607 609
608 610 pt->pts_rdq = NULL;
609 611 pt->ptm_rdq = NULL;
610 612 pt->pt_nullmsg = NULL;
611 613 pt->pt_pid = NULL;
612 614 pt->pt_minor = NULL;
613 615 pt->pt_refcnt = 0;
614 616 pt->pt_state = 0;
615 617 pt->pt_zoneid = GLOBAL_ZONEID;
616 618
617 619 cv_init(&pt->pt_cv, NULL, CV_DEFAULT, NULL);
618 620 mutex_init(&pt->pt_lock, NULL, MUTEX_DEFAULT, NULL);
619 621 return (0);
620 622 }
621 623
622 624 /*ARGSUSED*/
623 625 static void
624 626 ptms_destructor(void *maddr, void *arg)
625 627 {
626 628 struct pt_ttys *pt = maddr;
627 629
628 630 ASSERT(pt->pt_refcnt == 0);
629 631 ASSERT(pt->pt_state == 0);
630 632 ASSERT(pt->ptm_rdq == NULL);
631 633 ASSERT(pt->pts_rdq == NULL);
632 634
633 635 mutex_destroy(&pt->pt_lock);
634 636 cv_destroy(&pt->pt_cv);
635 637 }
636 638
637 639 #ifdef DEBUG
638 640 void
639 641 ptms_log(char *str, uint_t arg)
640 642 {
641 643 if (ptms_debug) {
642 644 if (ptms_debug & 2)
643 645 cmn_err(CE_CONT, str, arg);
644 646 if (ptms_debug & 4)
645 647 (void) strlog(PTMOD_ID, -1, 0, SL_TRACE | SL_ERROR,
646 648 str, arg);
647 649 else
648 650 (void) strlog(PTMOD_ID, -1, 0, SL_TRACE, str, arg);
649 651 }
650 652 }
651 653
652 654 void
653 655 ptms_logp(char *str, uintptr_t arg)
654 656 {
655 657 if (ptms_debug) {
656 658 if (ptms_debug & 2)
657 659 cmn_err(CE_CONT, str, arg);
658 660 if (ptms_debug & 4)
659 661 (void) strlog(PTMOD_ID, -1, 0, SL_TRACE | SL_ERROR,
660 662 str, arg);
661 663 else
662 664 (void) strlog(PTMOD_ID, -1, 0, SL_TRACE, str, arg);
663 665 }
664 666 }
665 667 #endif
|
↓ open down ↓ |
455 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX