Print this page
7127 remove -Wno-missing-braces from Makefile.uts
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/uts/common/io/pts.c
+++ new/usr/src/uts/common/io/pts.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.
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 25 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
26 26 /* All Rights Reserved */
27 27
28 28
29 29
30 30 /*
31 31 * Pseudo Terminal Slave Driver.
32 32 *
33 33 * The pseudo-tty subsystem simulates a terminal connection, where the master
34 34 * side represents the terminal and the slave represents the user process's
35 35 * special device end point. The master device is set up as a cloned device
36 36 * where its major device number is the major for the clone device and its minor
37 37 * device number is the major for the ptm driver. There are no nodes in the file
38 38 * system for master devices. The master pseudo driver is opened using the
39 39 * open(2) system call with /dev/ptmx as the device parameter. The clone open
40 40 * finds the next available minor device for the ptm major device.
41 41 *
42 42 * A master device is available only if it and its corresponding slave device
43 43 * are not already open. When the master device is opened, the corresponding
44 44 * slave device is automatically locked out. Only one open is allowed on a
45 45 * master device. Multiple opens are allowed on the slave device. After both
46 46 * the master and slave have been opened, the user has two file descriptors
47 47 * which are the end points of a full duplex connection composed of two streams
48 48 * which are automatically connected at the master and slave drivers. The user
49 49 * may then push modules onto either side of the stream pair.
50 50 *
51 51 * The master and slave drivers pass all messages to their adjacent queues.
52 52 * Only the M_FLUSH needs some processing. Because the read queue of one side
53 53 * is connected to the write queue of the other, the FLUSHR flag is changed to
54 54 * the FLUSHW flag and vice versa. When the master device is closed an M_HANGUP
55 55 * message is sent to the slave device which will render the device
56 56 * unusable. The process on the slave side gets the EIO when attempting to write
57 57 * on that stream but it will be able to read any data remaining on the stream
58 58 * head read queue. When all the data has been read, read() returns 0
59 59 * indicating that the stream can no longer be used. On the last close of the
60 60 * slave device, a 0-length message is sent to the master device. When the
61 61 * application on the master side issues a read() or getmsg() and 0 is returned,
62 62 * the user of the master device decides whether to issue a close() that
63 63 * dismantles the pseudo-terminal subsystem. If the master device is not closed,
64 64 * the pseudo-tty subsystem will be available to another user to open the slave
65 65 * device.
66 66 *
67 67 * Synchronization:
68 68 *
69 69 * All global data synchronization between ptm/pts is done via global
70 70 * ptms_lock mutex which is initialized at system boot time from
71 71 * ptms_initspace (called from space.c).
72 72 *
73 73 * Individual fields of pt_ttys structure (except ptm_rdq, pts_rdq and
74 74 * pt_nullmsg) are protected by pt_ttys.pt_lock mutex.
75 75 *
76 76 * PT_ENTER_READ/PT_ENTER_WRITE are reference counter based read-write locks
77 77 * which allow reader locks to be reacquired by the same thread (usual
78 78 * reader/writer locks can't be used for that purpose since it is illegal for
79 79 * a thread to acquire a lock it already holds, even as a reader). The sole
80 80 * purpose of these macros is to guarantee that the peer queue will not
81 81 * disappear (due to closing peer) while it is used. It is safe to use
82 82 * PT_ENTER_READ/PT_EXIT_READ brackets across calls like putq/putnext (since
83 83 * they are not real locks but reference counts).
84 84 *
85 85 * PT_ENTER_WRITE/PT_EXIT_WRITE brackets are used ONLY in master/slave
86 86 * open/close paths to modify ptm_rdq and pts_rdq fields. These fields should
87 87 * be set to appropriate queues *after* qprocson() is called during open (to
88 88 * prevent peer from accessing the queue with incomplete plumbing) and set to
89 89 * NULL before qprocsoff() is called during close.
90 90 *
91 91 * The pt_nullmsg field is only used in open/close routines and it is also
92 92 * protected by PT_ENTER_WRITE/PT_EXIT_WRITE brackets to avoid extra mutex
93 93 * holds.
94 94 *
95 95 * Lock Ordering:
96 96 *
97 97 * If both ptms_lock and per-pty lock should be held, ptms_lock should always
98 98 * be entered first, followed by per-pty lock.
99 99 *
100 100 * See ptms.h, ptm.c and ptms_conf.c fore more information.
101 101 *
102 102 */
103 103
104 104 #include <sys/types.h>
105 105 #include <sys/param.h>
106 106 #include <sys/sysmacros.h>
107 107 #include <sys/stream.h>
108 108 #include <sys/stropts.h>
109 109 #include <sys/stat.h>
110 110 #include <sys/errno.h>
111 111 #include <sys/debug.h>
112 112 #include <sys/cmn_err.h>
113 113 #include <sys/ptms.h>
114 114 #include <sys/systm.h>
115 115 #include <sys/modctl.h>
116 116 #include <sys/conf.h>
117 117 #include <sys/ddi.h>
118 118 #include <sys/sunddi.h>
119 119 #include <sys/cred.h>
120 120 #include <sys/zone.h>
121 121
122 122 #ifdef DEBUG
123 123 int pts_debug = 0;
124 124 #define DBG(a) if (pts_debug) cmn_err(CE_NOTE, a)
125 125 #else
126 126 #define DBG(a)
127 127 #endif
128 128
129 129 static int ptsopen(queue_t *, dev_t *, int, int, cred_t *);
130 130 static int ptsclose(queue_t *, int, cred_t *);
131 131 static void ptswput(queue_t *, mblk_t *);
132 132 static void ptsrsrv(queue_t *);
133 133 static void ptswsrv(queue_t *);
134 134
135 135 /*
136 136 * Slave Stream Pseudo Terminal Module: stream data structure definitions
137 137 */
138 138 static struct module_info pts_info = {
139 139 0xface,
140 140 "pts",
141 141 0,
142 142 512,
143 143 512,
144 144 128
145 145 };
146 146
147 147 static struct qinit ptsrint = {
148 148 NULL,
149 149 (int (*)()) ptsrsrv,
150 150 ptsopen,
151 151 ptsclose,
152 152 NULL,
153 153 &pts_info,
154 154 NULL
155 155 };
156 156
157 157 static struct qinit ptswint = {
158 158 (int (*)()) ptswput,
159 159 (int (*)()) ptswsrv,
160 160 NULL,
161 161 NULL,
162 162 NULL,
163 163 &pts_info,
164 164 NULL
165 165 };
166 166
167 167 static struct streamtab ptsinfo = {
168 168 &ptsrint,
169 169 &ptswint,
170 170 NULL,
171 171 NULL
172 172 };
173 173
174 174 static int pts_devinfo(dev_info_t *, ddi_info_cmd_t, void *, void **);
175 175 static int pts_attach(dev_info_t *, ddi_attach_cmd_t);
176 176 static int pts_detach(dev_info_t *, ddi_detach_cmd_t);
177 177
178 178 #define PTS_CONF_FLAG (D_NEW | D_MP)
179 179
180 180 /*
181 181 * this will define (struct cb_ops cb_pts_ops) and (struct dev_ops pts_ops)
182 182 */
183 183 DDI_DEFINE_STREAM_OPS(pts_ops, nulldev, nulldev, \
184 184 pts_attach, pts_detach, nodev, \
185 185 pts_devinfo, PTS_CONF_FLAG, &ptsinfo, ddi_quiesce_not_supported);
186 186
187 187 /*
188 188 * Module linkage information for the kernel.
↓ open down ↓ |
188 lines elided |
↑ open up ↑ |
189 189 */
190 190
191 191 static struct modldrv modldrv = {
192 192 &mod_driverops, /* Type of module. This one is a pseudo driver */
193 193 "Slave Stream Pseudo Terminal driver 'pts'",
194 194 &pts_ops, /* driver ops */
195 195 };
196 196
197 197 static struct modlinkage modlinkage = {
198 198 MODREV_1,
199 - &modldrv,
200 - NULL
199 + { &modldrv, NULL }
201 200 };
202 201
203 202 int
204 203 _init(void)
205 204 {
206 205 int rc;
207 206
208 207 if ((rc = mod_install(&modlinkage)) == 0)
209 208 ptms_init();
210 209 return (rc);
211 210 }
212 211
213 212
214 213 int
215 214 _fini(void)
216 215 {
217 216 return (mod_remove(&modlinkage));
218 217 }
219 218
220 219 int
221 220 _info(struct modinfo *modinfop)
222 221 {
223 222 return (mod_info(&modlinkage, modinfop));
224 223 }
225 224
226 225 static int
227 226 pts_attach(dev_info_t *devi, ddi_attach_cmd_t cmd)
228 227 {
229 228 if (cmd != DDI_ATTACH)
230 229 return (DDI_FAILURE);
231 230
232 231 mutex_enter(&ptms_lock);
233 232 pts_dip = devi;
234 233 mutex_exit(&ptms_lock);
235 234
236 235 return (DDI_SUCCESS);
237 236 }
238 237
239 238 /*ARGSUSED*/
240 239 static int
241 240 pts_detach(dev_info_t *devi, ddi_detach_cmd_t cmd)
242 241 {
243 242 if (cmd != DDI_DETACH)
244 243 return (DDI_FAILURE);
245 244
246 245 /*
247 246 * For now, pts cannot be detached.
248 247 */
249 248 return (DDI_FAILURE);
250 249 }
251 250
252 251 /*ARGSUSED*/
253 252 static int
254 253 pts_devinfo(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg,
255 254 void **result)
256 255 {
257 256 int error;
258 257
259 258 switch (infocmd) {
260 259 case DDI_INFO_DEVT2DEVINFO:
261 260 if (pts_dip == NULL) {
262 261 error = DDI_FAILURE;
263 262 } else {
264 263 *result = (void *)pts_dip;
265 264 error = DDI_SUCCESS;
266 265 }
267 266 break;
268 267 case DDI_INFO_DEVT2INSTANCE:
269 268 *result = (void *)0;
270 269 error = DDI_SUCCESS;
271 270 break;
272 271 default:
273 272 error = DDI_FAILURE;
274 273 }
275 274 return (error);
276 275 }
277 276
278 277 /* ARGSUSED */
279 278 /*
280 279 * Open the slave device. Reject a clone open and do not allow the
281 280 * driver to be pushed. If the slave/master pair is locked or if
282 281 * the master is not open, return EACCESS.
283 282 * Upon success, store the write queue pointer in private data and
284 283 * set the PTSOPEN bit in the pt_state field.
285 284 */
286 285 static int
287 286 ptsopen(
288 287 queue_t *rqp, /* pointer to the read side queue */
289 288 dev_t *devp, /* pointer to stream tail's dev */
290 289 int oflag, /* the user open(2) supplied flags */
291 290 int sflag, /* open state flag */
292 291 cred_t *credp) /* credentials */
293 292 {
294 293 struct pt_ttys *ptsp;
295 294 mblk_t *mp;
296 295 mblk_t *mop; /* ptr to a setopts message block */
297 296 minor_t dminor = getminor(*devp);
298 297 struct stroptions *sop;
299 298
300 299 DDBG("entering ptsopen(%d)", dminor);
301 300
302 301 if (sflag != 0) {
303 302 return (EINVAL);
304 303 }
305 304
306 305 mutex_enter(&ptms_lock);
307 306 ptsp = ptms_minor2ptty(dminor);
308 307
309 308 if (ptsp == NULL) {
310 309 mutex_exit(&ptms_lock);
311 310 return (ENXIO);
312 311 }
313 312 mutex_enter(&ptsp->pt_lock);
314 313
315 314 /*
316 315 * Prevent opens from zones other than the one blessed by ptm. We
317 316 * can't even allow the global zone to open all pts's, as it would
318 317 * otherwise inproperly be able to claim pts's already opened by zones.
319 318 */
320 319 if (ptsp->pt_zoneid != getzoneid()) {
321 320 mutex_exit(&ptsp->pt_lock);
322 321 mutex_exit(&ptms_lock);
323 322 return (EPERM);
324 323 }
325 324
326 325 /*
327 326 * Allow reopen of this device.
328 327 */
329 328 if (rqp->q_ptr != NULL) {
330 329 ASSERT(rqp->q_ptr == ptsp);
331 330 ASSERT(ptsp->pts_rdq == rqp);
332 331 mutex_exit(&ptsp->pt_lock);
333 332 mutex_exit(&ptms_lock);
334 333 return (0);
335 334 }
336 335
337 336 DDBGP("ptsopen: p = %p\n", (uintptr_t)ptsp);
338 337 DDBG("ptsopen: state = %x\n", ptsp->pt_state);
339 338
340 339
341 340 ASSERT(ptsp->pt_minor == dminor);
342 341
343 342 if ((ptsp->pt_state & PTLOCK) || !(ptsp->pt_state & PTMOPEN)) {
344 343 mutex_exit(&ptsp->pt_lock);
345 344 mutex_exit(&ptms_lock);
346 345 return (EAGAIN);
347 346 }
348 347
349 348 /*
350 349 * if already, open simply return...
351 350 */
352 351 if (ptsp->pt_state & PTSOPEN) {
353 352 ASSERT(rqp->q_ptr == ptsp);
354 353 ASSERT(ptsp->pts_rdq == rqp);
355 354 mutex_exit(&ptsp->pt_lock);
356 355 mutex_exit(&ptms_lock);
357 356 return (0);
358 357 }
359 358
360 359 /*
361 360 * Allocate message block for setting stream head options.
362 361 */
363 362 if ((mop = allocb(sizeof (struct stroptions), BPRI_MED)) == NULL) {
364 363 mutex_exit(&ptsp->pt_lock);
365 364 mutex_exit(&ptms_lock);
366 365 return (ENOMEM);
367 366 }
368 367
369 368 /*
370 369 * Slave should send zero-length message to a master when it is
371 370 * closing. If memory is low at that time, master will not detect slave
372 371 * closes, this pty will not be deallocated. So, preallocate this
373 372 * zero-length message block early.
374 373 */
375 374 if ((mp = allocb(0, BPRI_MED)) == NULL) {
376 375 mutex_exit(&ptsp->pt_lock);
377 376 mutex_exit(&ptms_lock);
378 377 freemsg(mop);
379 378 return (ENOMEM);
380 379 }
381 380
382 381 ptsp->pt_state |= PTSOPEN;
383 382
384 383 WR(rqp)->q_ptr = rqp->q_ptr = ptsp;
385 384
386 385 mutex_exit(&ptsp->pt_lock);
387 386 mutex_exit(&ptms_lock);
388 387
389 388 qprocson(rqp);
390 389
391 390 /*
392 391 * After qprocson pts driver is fully plumbed into the stream and can
393 392 * send/receive messages. Setting pts_rdq will allow master side to send
394 393 * messages to the slave. This setting can't occur before qprocson() is
395 394 * finished because slave is not ready to process them.
396 395 */
397 396 PT_ENTER_WRITE(ptsp);
398 397 ptsp->pts_rdq = rqp;
399 398 ASSERT(ptsp->pt_nullmsg == NULL);
400 399 ptsp->pt_nullmsg = mp;
401 400 PT_EXIT_WRITE(ptsp);
402 401
403 402 /*
404 403 * set up hi/lo water marks on stream head read queue
405 404 * and add controlling tty if not set
406 405 */
407 406
408 407 mop->b_datap->db_type = M_SETOPTS;
409 408 mop->b_wptr += sizeof (struct stroptions);
410 409 sop = (struct stroptions *)mop->b_rptr;
411 410 sop->so_flags = SO_HIWAT | SO_LOWAT | SO_ISTTY;
412 411 sop->so_hiwat = 512;
413 412 sop->so_lowat = 256;
414 413 putnext(rqp, mop);
415 414
416 415 return (0);
417 416 }
418 417
419 418
420 419
421 420 /*
422 421 * Find the address to private data identifying the slave's write
423 422 * queue. Send a 0-length msg up the slave's read queue to designate
424 423 * the master is closing. Uattach the master from the slave by nulling
425 424 * out master's write queue field in private data.
426 425 */
427 426 /*ARGSUSED1*/
428 427 static int
429 428 ptsclose(queue_t *rqp, int flag, cred_t *credp)
430 429 {
431 430 struct pt_ttys *ptsp;
432 431 queue_t *wqp;
433 432 mblk_t *mp;
434 433 mblk_t *bp;
435 434
436 435 /*
437 436 * q_ptr should never be NULL in the close routine and it is checked in
438 437 * DEBUG kernel by ASSERT. For non-DEBUG kernel the attempt is made to
439 438 * behave gracefully.
440 439 */
441 440 ASSERT(rqp->q_ptr != NULL);
442 441 if (rqp->q_ptr == NULL) {
443 442 qprocsoff(rqp);
444 443 return (0);
445 444 }
446 445
447 446 ptsp = (struct pt_ttys *)rqp->q_ptr;
448 447
449 448 /*
450 449 * Slave is going to close and doesn't want any new messages coming
451 450 * from the master side, so set pts_rdq to NULL. This should be done
452 451 * before call to qprocsoff() since slave can't process additional
453 452 * messages from the master after qprocsoff is called.
454 453 */
455 454 PT_ENTER_WRITE(ptsp);
456 455 mp = ptsp->pt_nullmsg;
457 456 ptsp->pt_nullmsg = NULL;
458 457 ptsp->pts_rdq = NULL;
459 458 PT_EXIT_WRITE(ptsp);
460 459
461 460 /*
462 461 * Drain the ouput
463 462 */
464 463 wqp = WR(rqp);
465 464 PT_ENTER_READ(ptsp);
466 465 while ((bp = getq(wqp)) != NULL) {
467 466 if (ptsp->ptm_rdq) {
468 467 putnext(ptsp->ptm_rdq, bp);
469 468 } else if (bp->b_datap->db_type == M_IOCTL) {
470 469 bp->b_datap->db_type = M_IOCNAK;
471 470 freemsg(bp->b_cont);
472 471 bp->b_cont = NULL;
473 472 qreply(wqp, bp);
474 473 } else {
475 474 freemsg(bp);
476 475 }
477 476 }
478 477 /*
479 478 * qenable master side write queue so that it can flush
480 479 * its messages as slaves's read queue is going away
481 480 */
482 481 if (ptsp->ptm_rdq) {
483 482 if (mp)
484 483 putnext(ptsp->ptm_rdq, mp);
485 484 else
486 485 qenable(WR(ptsp->ptm_rdq));
487 486 } else
488 487 freemsg(mp);
489 488 PT_EXIT_READ(ptsp);
490 489
491 490 qprocsoff(rqp);
492 491
493 492 rqp->q_ptr = NULL;
494 493 WR(rqp)->q_ptr = NULL;
495 494
496 495 ptms_close(ptsp, PTSOPEN | PTSTTY);
497 496
498 497 return (0);
499 498 }
500 499
501 500
502 501 /*
503 502 * The wput procedure will only handle flush messages.
504 503 * All other messages are queued and the write side
505 504 * service procedure sends them off to the master side.
506 505 */
507 506 static void
508 507 ptswput(queue_t *qp, mblk_t *mp)
509 508 {
510 509 struct pt_ttys *ptsp;
511 510 struct iocblk *iocp;
512 511 unsigned char type = mp->b_datap->db_type;
513 512
514 513 DBG(("entering ptswput\n"));
515 514 ASSERT(qp->q_ptr);
516 515
517 516 ptsp = (struct pt_ttys *)qp->q_ptr;
518 517 PT_ENTER_READ(ptsp);
519 518 if (ptsp->ptm_rdq == NULL) {
520 519 DBG(("in write put proc but no master\n"));
521 520 /*
522 521 * NAK ioctl as slave side read queue is gone.
523 522 * Or else free the message.
524 523 */
525 524 if (mp->b_datap->db_type == M_IOCTL) {
526 525 mp->b_datap->db_type = M_IOCNAK;
527 526 freemsg(mp->b_cont);
528 527 mp->b_cont = NULL;
529 528 qreply(qp, mp);
530 529 } else
531 530 freemsg(mp);
532 531 PT_EXIT_READ(ptsp);
533 532 return;
534 533 }
535 534
536 535 if (type >= QPCTL) {
537 536 switch (type) {
538 537
539 538 /*
540 539 * if write queue request, flush slave's write
541 540 * queue and send FLUSHR to ptm. If read queue
542 541 * request, send FLUSHR to ptm.
543 542 */
544 543 case M_FLUSH:
545 544 DBG(("pts got flush request\n"));
546 545 if (*mp->b_rptr & FLUSHW) {
547 546
548 547 DBG(("got FLUSHW, flush pts write Q\n"));
549 548 if (*mp->b_rptr & FLUSHBAND)
550 549 /*
551 550 * if it is a FLUSHBAND, do flushband.
552 551 */
553 552 flushband(qp, *(mp->b_rptr + 1), FLUSHDATA);
554 553 else
555 554 flushq(qp, FLUSHDATA);
556 555
557 556 *mp->b_rptr &= ~FLUSHW;
558 557 if ((*mp->b_rptr & FLUSHR) == 0) {
559 558 /*
560 559 * FLUSHW only. Change to FLUSHR and putnext
561 560 * to ptm, then we are done.
562 561 */
563 562 *mp->b_rptr |= FLUSHR;
564 563 if (ptsp->ptm_rdq)
565 564 putnext(ptsp->ptm_rdq, mp);
566 565 break;
567 566 } else {
568 567 mblk_t *nmp;
569 568
570 569 /* It is a FLUSHRW. Duplicate the mblk */
571 570 nmp = copyb(mp);
572 571 if (nmp) {
573 572 /*
574 573 * Change FLUSHW to FLUSHR before
575 574 * putnext to ptm.
576 575 */
577 576 DBG(("putnext nmp(FLUSHR) to ptm\n"));
578 577 *nmp->b_rptr |= FLUSHR;
579 578 if (ptsp->ptm_rdq)
580 579 putnext(ptsp->ptm_rdq, nmp);
581 580 }
582 581 }
583 582 }
584 583 /*
585 584 * Since the packet module will toss any
586 585 * M_FLUSHES sent to the master's stream head
587 586 * read queue, we simply turn it around here.
588 587 */
589 588 if (*mp->b_rptr & FLUSHR) {
590 589 ASSERT(RD(qp)->q_first == NULL);
591 590 DBG(("qreply(qp) turning FLUSHR around\n"));
592 591 qreply(qp, mp);
593 592 } else {
594 593 freemsg(mp);
595 594 }
596 595 break;
597 596
598 597 case M_READ:
599 598 /* Caused by ldterm - can not pass to master */
600 599 freemsg(mp);
601 600 break;
602 601
603 602 default:
604 603 if (ptsp->ptm_rdq)
605 604 putnext(ptsp->ptm_rdq, mp);
606 605 break;
607 606 }
608 607 PT_EXIT_READ(ptsp);
609 608 return;
610 609 }
611 610
612 611 switch (type) {
613 612
614 613 case M_IOCTL:
615 614 /*
616 615 * For case PTSSTTY set the flag PTSTTY and ACK
617 616 * the ioctl so that the user program can push
618 617 * the associated modules to get tty semantics.
619 618 * See bugid 4025044
620 619 */
621 620 iocp = (struct iocblk *)mp->b_rptr;
622 621 switch (iocp->ioc_cmd) {
623 622 default:
624 623 break;
625 624
626 625 case PTSSTTY:
627 626 if (ptsp->pt_state & PTSTTY) {
628 627 mp->b_datap->db_type = M_IOCNAK;
629 628 iocp->ioc_error = EEXIST;
630 629 } else {
631 630 mp->b_datap->db_type = M_IOCACK;
632 631 mutex_enter(&ptsp->pt_lock);
633 632 ptsp->pt_state |= PTSTTY;
634 633 mutex_exit(&ptsp->pt_lock);
635 634 iocp->ioc_error = 0;
636 635 }
637 636 iocp->ioc_count = 0;
638 637 qreply(qp, mp);
639 638 PT_EXIT_READ(ptsp);
640 639 return;
641 640 }
642 641
643 642 default:
644 643 /*
645 644 * send other messages to the master
646 645 */
647 646 DBG(("put msg on slave's write queue\n"));
648 647 (void) putq(qp, mp);
649 648 break;
650 649 }
651 650
652 651 PT_EXIT_READ(ptsp);
653 652 DBG(("return from ptswput()\n"));
654 653 }
655 654
656 655
657 656 /*
658 657 * enable the write side of the master. This triggers the
659 658 * master to send any messages queued on its write side to
660 659 * the read side of this slave.
661 660 */
662 661 static void
663 662 ptsrsrv(queue_t *qp)
664 663 {
665 664 struct pt_ttys *ptsp;
666 665
667 666 DBG(("entering ptsrsrv\n"));
668 667 ASSERT(qp->q_ptr);
669 668
670 669 ptsp = (struct pt_ttys *)qp->q_ptr;
671 670 PT_ENTER_READ(ptsp);
672 671 if (ptsp->ptm_rdq == NULL) {
673 672 DBG(("in read srv proc but no master\n"));
674 673 PT_EXIT_READ(ptsp);
675 674 return;
676 675 }
677 676 qenable(WR(ptsp->ptm_rdq));
678 677 PT_EXIT_READ(ptsp);
679 678 DBG(("leaving ptsrsrv\n"));
680 679 }
681 680
682 681 /*
683 682 * If there are messages on this queue that can be sent to
684 683 * master, send them via putnext(). Else, if queued messages
685 684 * cannot be sent, leave them on this queue. If priority
686 685 * messages on this queue, send them to master no matter what.
687 686 */
688 687 static void
689 688 ptswsrv(queue_t *qp)
690 689 {
691 690 struct pt_ttys *ptsp;
692 691 queue_t *ptm_rdq;
693 692 mblk_t *mp;
694 693
695 694 DBG(("entering ptswsrv\n"));
696 695 ASSERT(qp->q_ptr);
697 696
698 697 ptsp = (struct pt_ttys *)qp->q_ptr;
699 698 PT_ENTER_READ(ptsp);
700 699 if (ptsp->ptm_rdq == NULL) {
701 700 DBG(("in write srv proc but no master\n"));
702 701 /*
703 702 * Free messages on the write queue and send
704 703 * NAK for any M_IOCTL type messages to wakeup
705 704 * the user process waiting for ACK/NAK from
706 705 * the ioctl invocation
707 706 */
708 707 while ((mp = getq(qp)) != NULL) {
709 708 if (mp->b_datap->db_type == M_IOCTL) {
710 709 mp->b_datap->db_type = M_IOCNAK;
711 710 freemsg(mp->b_cont);
712 711 mp->b_cont = NULL;
713 712 qreply(qp, mp);
714 713 } else
715 714 freemsg(mp);
716 715 }
717 716 PT_EXIT_READ(ptsp);
718 717 return;
719 718 } else {
720 719 ptm_rdq = ptsp->ptm_rdq;
721 720 }
722 721
723 722 /*
724 723 * while there are messages on this write queue...
725 724 */
726 725 while ((mp = getq(qp)) != NULL) {
727 726 /*
728 727 * if don't have control message and cannot put
729 728 * msg. on master's read queue, put it back on
730 729 * this queue.
731 730 */
732 731 if (mp->b_datap->db_type <= QPCTL &&
733 732 !bcanputnext(ptm_rdq, mp->b_band)) {
734 733 DBG(("put msg. back on Q\n"));
735 734 (void) putbq(qp, mp);
736 735 break;
737 736 }
738 737 /*
739 738 * else send the message up master's stream
740 739 */
741 740 DBG(("send message to master\n"));
742 741 putnext(ptm_rdq, mp);
743 742 }
744 743 DBG(("leaving ptswsrv\n"));
745 744 PT_EXIT_READ(ptsp);
746 745 }
↓ open down ↓ |
536 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX