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