Print this page
8634 epoll fails to wake on certain edge-triggered conditions
8635 epoll should not emit POLLNVAL
8636 recursive epoll should emit EPOLLRDNORM
Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com>
Reviewed by: Robert Mustacchi <rm@joyent.com>
Reviewed by: Toomas Soome <tsoome@me.com>
Reviewed by: Igor Kozhukhov <igor@dilos.org>
| Split |
Close |
| Expand all |
| Collapse all |
--- old/usr/src/uts/common/io/srn.c
+++ new/usr/src/uts/common/io/srn.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 /*
23 23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 24 * Use is subject to license terms.
25 + * Copyright 2017 Joyent, Inc.
25 26 */
26 27
27 28
28 29 /*
29 30 * srn Provide apm-like interfaces to Xorg
30 31 */
31 32
32 33 #include <sys/types.h>
33 34 #include <sys/errno.h>
34 35 #include <sys/modctl.h>
35 36 #include <sys/conf.h> /* driver flags and functions */
36 37 #include <sys/open.h> /* OTYP_CHR definition */
37 38 #include <sys/stat.h> /* S_IFCHR definition */
38 39 #include <sys/pathname.h> /* name -> dev_info xlation */
39 40 #include <sys/kmem.h> /* memory alloc stuff */
40 41 #include <sys/debug.h>
41 42 #include <sys/pm.h>
42 43 #include <sys/ddi.h>
43 44 #include <sys/sunddi.h>
44 45 #include <sys/epm.h>
45 46 #include <sys/vfs.h>
46 47 #include <sys/mode.h>
47 48 #include <sys/mkdev.h>
48 49 #include <sys/promif.h>
49 50 #include <sys/consdev.h>
50 51 #include <sys/ddi_impldefs.h>
51 52 #include <sys/poll.h>
52 53 #include <sys/note.h>
53 54 #include <sys/taskq.h>
54 55 #include <sys/policy.h>
55 56 #include <sys/srn.h>
56 57
57 58 /*
58 59 * Minor number is instance<<8 + clone minor from range 1-255;
59 60 * But only one will be allocated
60 61 */
61 62 #define SRN_MINOR_TO_CLONE(minor) ((minor) & (SRN_MAX_CLONE - 1))
62 63 #define SU 0x002
63 64 #define SG 0x004
64 65
65 66 extern kmutex_t srn_clone_lock; /* protects srn_clones array */
66 67 extern kcondvar_t srn_clones_cv[SRN_MAX_CLONE];
67 68 extern uint_t srn_poll_cnt[SRN_MAX_CLONE];
68 69
69 70 /*
70 71 * The soft state of the srn driver. Since there will only be
71 72 * one of these, just reference it through a static struct.
72 73 */
73 74 static struct srnstate {
74 75 dev_info_t *srn_dip; /* ptr to our dev_info node */
75 76 int srn_instance; /* for ddi_get_instance() */
76 77 uchar_t srn_clones[SRN_MAX_CLONE]; /* unique opens */
77 78 struct cred *srn_cred[SRN_MAX_CLONE]; /* cred for each open */
78 79 int srn_type[SRN_MAX_CLONE]; /* type of handshake */
79 80 int srn_delivered[SRN_MAX_CLONE];
80 81 srn_event_info_t srn_pending[SRN_MAX_CLONE];
81 82 int srn_fault[SRN_MAX_CLONE];
82 83 } srn = { NULL, -1};
83 84 typedef struct srnstate *srn_state_t;
84 85
85 86 kcondvar_t srn_clones_cv[SRN_MAX_CLONE];
86 87 uint_t srn_poll_cnt[SRN_MAX_CLONE]; /* count of events for poll */
87 88 int srn_apm_count;
88 89 int srn_autosx_count;
89 90 /* Number of seconds to wait for clients to ack a poll */
90 91 int srn_timeout = 10;
91 92
92 93 struct pollhead srn_pollhead[SRN_MAX_CLONE];
93 94
94 95 static int srn_open(dev_t *, int, int, cred_t *);
95 96 static int srn_close(dev_t, int, int, cred_t *);
96 97 static int srn_ioctl(dev_t, int, intptr_t, int, cred_t *, int *);
97 98 static int srn_chpoll(dev_t, short, int, short *, struct pollhead **);
98 99
99 100 static struct cb_ops srn_cb_ops = {
100 101 srn_open, /* open */
101 102 srn_close, /* close */
102 103 nodev, /* strategy */
103 104 nodev, /* print */
104 105 nodev, /* dump */
105 106 nodev, /* read */
106 107 nodev, /* write */
107 108 srn_ioctl, /* ioctl */
108 109 nodev, /* devmap */
109 110 nodev, /* mmap */
110 111 nodev, /* segmap */
111 112 srn_chpoll, /* poll */
112 113 ddi_prop_op, /* prop_op */
113 114 NULL, /* streamtab */
114 115 D_NEW | D_MP /* driver compatibility flag */
115 116 };
116 117
117 118 static int srn_getinfo(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg,
118 119 void **result);
119 120 static int srn_attach(dev_info_t *dip, ddi_attach_cmd_t cmd);
120 121 static int srn_detach(dev_info_t *dip, ddi_detach_cmd_t cmd);
121 122 static void srn_notify(int type, int event);
122 123
123 124 static struct dev_ops srn_ops = {
124 125 DEVO_REV, /* devo_rev */
125 126 0, /* refcnt */
126 127 srn_getinfo, /* info */
127 128 nulldev, /* identify */
128 129 nulldev, /* probe */
129 130 srn_attach, /* attach */
130 131 srn_detach, /* detach */
131 132 nodev, /* reset */
132 133 &srn_cb_ops, /* driver operations */
133 134 NULL, /* bus operations */
134 135 NULL, /* power */
135 136 ddi_quiesce_not_needed, /* quiesce */
136 137 };
137 138
138 139 static struct modldrv modldrv = {
139 140 &mod_driverops,
140 141 "srn driver",
141 142 &srn_ops
142 143 };
143 144
144 145 static struct modlinkage modlinkage = {
145 146 MODREV_1, &modldrv, 0
146 147 };
147 148
148 149 /* Local functions */
149 150
150 151 int
151 152 _init(void)
152 153 {
153 154 return (mod_install(&modlinkage));
154 155 }
155 156
156 157 int
157 158 _fini(void)
158 159 {
159 160 return (mod_remove(&modlinkage));
160 161 }
161 162
162 163 int
163 164 _info(struct modinfo *modinfop)
164 165 {
165 166 return (mod_info(&modlinkage, modinfop));
166 167 }
167 168
168 169 static int
169 170 srn_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
170 171 {
171 172 int i;
172 173 extern void (*srn_signal)(int, int);
173 174
174 175 switch (cmd) {
175 176
176 177 case DDI_ATTACH:
177 178 if (srn.srn_instance != -1) /* Only allow one instance */
178 179 return (DDI_FAILURE);
179 180 srn.srn_instance = ddi_get_instance(dip);
180 181 if (ddi_create_minor_node(dip, "srn", S_IFCHR,
181 182 (srn.srn_instance << 8) + 0, DDI_PSEUDO, 0)
182 183 != DDI_SUCCESS) {
183 184 return (DDI_FAILURE);
184 185 }
185 186 srn.srn_dip = dip; /* srn_init and getinfo depend on it */
186 187
187 188 for (i = 0; i < SRN_MAX_CLONE; i++)
188 189 cv_init(&srn_clones_cv[i], NULL, CV_DEFAULT, NULL);
189 190
190 191 srn.srn_instance = ddi_get_instance(dip);
191 192 mutex_enter(&srn_clone_lock);
192 193 srn_signal = srn_notify;
193 194 mutex_exit(&srn_clone_lock);
194 195 ddi_report_dev(dip);
195 196 return (DDI_SUCCESS);
196 197
197 198 default:
198 199 return (DDI_FAILURE);
199 200 }
200 201 }
201 202
202 203 /* ARGSUSED */
203 204 static int
204 205 srn_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
205 206 {
206 207 int i;
207 208 extern int srn_inuse;
208 209 extern void (*srn_signal)(int, int);
209 210
210 211 switch (cmd) {
211 212 case DDI_DETACH:
212 213
213 214 mutex_enter(&srn_clone_lock);
214 215 while (srn_inuse) {
215 216 mutex_exit(&srn_clone_lock);
216 217 delay(1);
217 218 mutex_enter(&srn_clone_lock);
218 219 }
219 220 srn_signal = NULL;
220 221 mutex_exit(&srn_clone_lock);
221 222
222 223 for (i = 0; i < SRN_MAX_CLONE; i++)
223 224 cv_destroy(&srn_clones_cv[i]);
224 225
225 226 ddi_remove_minor_node(dip, NULL);
226 227 srn.srn_instance = -1;
227 228 return (DDI_SUCCESS);
228 229
229 230 default:
230 231 return (DDI_FAILURE);
231 232 }
232 233 }
233 234
234 235
235 236 #ifdef DEBUG
236 237 char *srn_cmd_string;
237 238 int srn_cmd;
238 239 #endif
239 240
240 241 /*
241 242 * Returns true if permission granted by credentials
242 243 * XXX
243 244 */
244 245 static int
245 246 srn_perms(int perm, cred_t *cr)
|
↓ open down ↓ |
211 lines elided |
↑ open up ↑ |
246 247 {
247 248 if ((perm & SU) && secpolicy_power_mgmt(cr) == 0) /* privileged? */
248 249 return (1);
249 250 if ((perm & SG) && (crgetgid(cr) == 0)) /* group 0 is ok */
250 251 return (1);
251 252 return (0);
252 253 }
253 254
254 255 static int
255 256 srn_chpoll(dev_t dev, short events, int anyyet, short *reventsp,
256 - struct pollhead **phpp)
257 + struct pollhead **phpp)
257 258 {
258 259 extern struct pollhead srn_pollhead[];
259 260 int clone;
260 261
261 262 clone = SRN_MINOR_TO_CLONE(getminor(dev));
262 263 if ((events & (POLLIN | POLLRDNORM)) && srn_poll_cnt[clone]) {
263 264 *reventsp |= (POLLIN | POLLRDNORM);
264 265 } else {
265 266 *reventsp = 0;
266 - if (!anyyet) {
267 - *phpp = &srn_pollhead[clone];
268 - }
269 267 }
268 +
269 + if ((*reventsp == 0 && !anyyet) || (events & POLLET)) {
270 + *phpp = &srn_pollhead[clone];
271 + }
270 272 return (0);
271 273 }
272 274
273 275 /*ARGSUSED*/
274 276 static int
275 277 srn_getinfo(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result)
276 278 {
277 279 dev_t dev;
278 280 int instance;
279 281
280 282 switch (infocmd) {
281 283 case DDI_INFO_DEVT2DEVINFO:
282 284 if (srn.srn_instance == -1)
283 285 return (DDI_FAILURE);
284 286 *result = srn.srn_dip;
285 287 return (DDI_SUCCESS);
286 288
287 289 case DDI_INFO_DEVT2INSTANCE:
288 290 dev = (dev_t)arg;
289 291 instance = getminor(dev) >> 8;
290 292 *result = (void *)(uintptr_t)instance;
291 293 return (DDI_SUCCESS);
292 294
293 295 default:
294 296 return (DDI_FAILURE);
295 297 }
296 298 }
297 299
298 300
299 301 /*ARGSUSED1*/
300 302 static int
301 303 srn_open(dev_t *devp, int flag, int otyp, cred_t *cr)
302 304 {
303 305 int clone;
304 306
305 307 if (otyp != OTYP_CHR)
306 308 return (EINVAL);
307 309
308 310 mutex_enter(&srn_clone_lock);
309 311 for (clone = 1; clone < SRN_MAX_CLONE - 1; clone++)
310 312 if (!srn.srn_clones[clone])
311 313 break;
312 314
313 315 if (clone == SRN_MAX_CLONE) {
314 316 mutex_exit(&srn_clone_lock);
315 317 return (ENXIO);
316 318 }
317 319 srn.srn_cred[clone] = cr;
318 320 ASSERT(srn_apm_count >= 0);
319 321 srn_apm_count++;
320 322 srn.srn_type[clone] = SRN_TYPE_APM;
321 323 crhold(cr);
322 324
323 325 *devp = makedevice(getmajor(*devp), (srn.srn_instance << 8) +
324 326 clone);
325 327 srn.srn_clones[clone] = 1;
326 328 srn.srn_cred[clone] = cr;
327 329 crhold(cr);
328 330 mutex_exit(&srn_clone_lock);
329 331 PMD(PMD_SX, ("srn open OK\n"))
330 332 return (0);
331 333 }
332 334
333 335 /*ARGSUSED1*/
334 336 static int
335 337 srn_close(dev_t dev, int flag, int otyp, cred_t *cr)
336 338 {
337 339 int clone;
338 340
339 341 if (otyp != OTYP_CHR)
340 342 return (EINVAL);
341 343
342 344 clone = SRN_MINOR_TO_CLONE(getminor(dev));
343 345 PMD(PMD_SX, ("srn_close: minor %x, clone %x\n", getminor(dev),
344 346 clone))
345 347 mutex_enter(&srn_clone_lock);
346 348 crfree(srn.srn_cred[clone]);
347 349 srn.srn_cred[clone] = 0;
348 350 srn_poll_cnt[clone] = 0;
349 351 srn.srn_fault[clone] = 0;
350 352 if (srn.srn_pending[clone].ae_type || srn.srn_delivered[clone]) {
351 353 srn.srn_pending[clone].ae_type = 0;
352 354 srn.srn_delivered[clone] = 0;
353 355 cv_signal(&srn_clones_cv[clone]);
354 356 }
355 357 switch (srn.srn_type[clone]) {
356 358 case SRN_TYPE_AUTOSX:
357 359 ASSERT(srn_autosx_count);
358 360 srn_autosx_count--;
359 361 break;
360 362 case SRN_TYPE_APM:
361 363 ASSERT(srn_apm_count);
362 364 srn_apm_count--;
363 365 break;
364 366 default:
365 367 ASSERT(0);
366 368 return (EINVAL);
367 369 }
368 370 srn.srn_clones[clone] = 0;
369 371 mutex_exit(&srn_clone_lock);
370 372 return (0);
371 373 }
372 374
373 375 /*ARGSUSED*/
374 376 static int
375 377 srn_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *cr, int *rval_p)
376 378 {
377 379 int clone = SRN_MINOR_TO_CLONE(getminor(dev));
378 380
379 381 PMD(PMD_SX, ("ioctl: %x: begin\n", cmd))
380 382
381 383 switch (cmd) {
382 384 case SRN_IOC_NEXTEVENT:
383 385 case SRN_IOC_SUSPEND:
384 386 case SRN_IOC_RESUME:
385 387 case SRN_IOC_AUTOSX:
386 388 break;
387 389 default:
388 390 return (ENOTTY);
389 391 }
390 392
391 393 if (!srn_perms(SU | SG, srn.srn_cred[clone])) {
392 394 return (EPERM);
393 395 }
394 396 switch (cmd) {
395 397 case SRN_IOC_AUTOSX:
396 398 PMD(PMD_SX, ("SRN_IOC_AUTOSX entered\n"))
397 399 mutex_enter(&srn_clone_lock);
398 400 if (!srn.srn_clones[clone]) {
399 401 PMD(PMD_SX, (" ioctl !srn_clones--EINVAL\n"))
400 402 mutex_exit(&srn_clone_lock);
401 403 return (EINVAL);
402 404 }
403 405 if (srn.srn_pending[clone].ae_type) {
404 406 PMD(PMD_SX, ("AUTOSX while pending--EBUSY\n"))
405 407 mutex_exit(&srn_clone_lock);
406 408 return (EBUSY);
407 409 }
408 410 if (srn.srn_type[clone] == SRN_TYPE_AUTOSX) {
409 411 PMD(PMD_SX, ("AUTOSX already--EBUSY\n"))
410 412 mutex_exit(&srn_clone_lock);
411 413 return (EBUSY);
412 414 }
413 415 ASSERT(srn.srn_type[clone] == SRN_TYPE_APM);
414 416 srn.srn_type[clone] = SRN_TYPE_AUTOSX;
415 417 srn.srn_fault[clone] = 0;
416 418 srn_apm_count--;
417 419 ASSERT(srn_apm_count >= 0);
418 420 ASSERT(srn_autosx_count >= 0);
419 421 srn_autosx_count++;
420 422 mutex_exit(&srn_clone_lock);
421 423 PMD(PMD_SX, ("SRN_IOC_AUTOSX returns success\n"))
422 424 return (0);
423 425
424 426 case SRN_IOC_NEXTEVENT:
425 427 /*
426 428 * return the next suspend or resume event; there should
427 429 * be one, cause we only get called if we've signalled a
428 430 * poll data completion
429 431 * then wake up the kernel thread sleeping for the delivery
430 432 */
431 433 PMD(PMD_SX, ("SRN_IOC_NEXTEVENT entered\n"))
432 434 if (srn.srn_fault[clone]) {
433 435 PMD(PMD_SX, ("SRN_IOC_NEXTEVENT clone %d fault "
434 436 "cleared\n", clone))
435 437 srn.srn_fault[clone] = 0;
436 438 }
437 439 mutex_enter(&srn_clone_lock);
438 440 if (srn_poll_cnt[clone] == 0) {
439 441 mutex_exit(&srn_clone_lock);
440 442 PMD(PMD_SX, ("SRN_IOC_NEXTEVENT clone %d "
441 443 "EWOULDBLOCK\n", clone))
442 444 return (EWOULDBLOCK);
443 445 }
444 446 ASSERT(srn.srn_pending[clone].ae_type);
445 447 if (ddi_copyout(&srn.srn_pending[clone], (void *)arg,
446 448 sizeof (srn_event_info_t), mode) != 0) {
447 449 mutex_exit(&srn_clone_lock);
448 450 PMD(PMD_SX, ("SRN_IOC_NEXTEVENT clone %d EFAULT\n",
449 451 clone))
450 452 return (EFAULT);
451 453 }
452 454 if (srn.srn_type[clone] == SRN_TYPE_APM)
453 455 srn.srn_delivered[clone] =
454 456 srn.srn_pending[clone].ae_type;
455 457 PMD(PMD_SX, ("SRN_IOC_NEXTEVENT clone %d delivered %x\n",
456 458 clone, srn.srn_pending[clone].ae_type))
457 459 srn_poll_cnt[clone] = 0;
458 460 mutex_exit(&srn_clone_lock);
459 461 return (0);
460 462
461 463 case SRN_IOC_SUSPEND:
462 464 /* ack suspend */
463 465 PMD(PMD_SX, ("SRN_IOC_SUSPEND entered clone %d\n", clone))
464 466 if (srn.srn_fault[clone]) {
465 467 PMD(PMD_SX, ("SRN_IOC_SUSPEND clone %d fault "
466 468 "cleared\n", clone))
467 469 srn.srn_fault[clone] = 0;
468 470 }
469 471 mutex_enter(&srn_clone_lock);
470 472 if (srn.srn_delivered[clone] != SRN_SUSPEND_REQ) {
471 473 mutex_exit(&srn_clone_lock);
472 474 PMD(PMD_SX, ("SRN_IOC_SUSPEND EINVAL\n"))
473 475 return (EINVAL);
474 476 }
475 477 srn.srn_delivered[clone] = 0;
476 478 srn.srn_pending[clone].ae_type = 0;
477 479 /* notify the kernel suspend thread to continue */
478 480 PMD(PMD_SX, ("SRN_IOC_SUSPEND clone %d ok\n", clone))
479 481 cv_signal(&srn_clones_cv[clone]);
480 482 mutex_exit(&srn_clone_lock);
481 483 return (0);
482 484
483 485 case SRN_IOC_RESUME:
484 486 /* ack resume */
485 487 PMD(PMD_SX, ("SRN_IOC_RESUME entered clone %d\n", clone))
486 488 if (srn.srn_fault[clone]) {
487 489 PMD(PMD_SX, ("SRN_IOC_RESUME clone %d fault "
488 490 "cleared\n", clone))
489 491 srn.srn_fault[clone] = 0;
490 492 }
491 493 mutex_enter(&srn_clone_lock);
492 494 if (srn.srn_delivered[clone] != SRN_NORMAL_RESUME) {
493 495 mutex_exit(&srn_clone_lock);
494 496 PMD(PMD_SX, ("SRN_IOC_RESUME EINVAL\n"))
495 497 return (EINVAL);
496 498 }
497 499 srn.srn_delivered[clone] = 0;
498 500 srn.srn_pending[clone].ae_type = 0;
499 501 /* notify the kernel resume thread to continue */
500 502 PMD(PMD_SX, ("SRN_IOC_RESUME ok for clone %d\n", clone))
501 503 cv_signal(&srn_clones_cv[clone]);
502 504 mutex_exit(&srn_clone_lock);
503 505 return (0);
504 506
505 507 default:
506 508 PMD(PMD_SX, ("srn_ioctl unknown cmd EINVAL\n"))
507 509 return (EINVAL);
508 510 }
509 511 }
510 512 /*
511 513 * A very simple handshake with the srn driver,
512 514 * only one outstanding event at a time.
513 515 * The OS delivers the event and depending on type,
514 516 * either blocks waiting for the ack, or drives on
515 517 */
516 518 void
517 519 srn_notify(int type, int event)
518 520 {
519 521 int clone, count;
520 522 PMD(PMD_SX, ("srn_notify entered with type %d, event 0x%x\n",
521 523 type, event));
522 524 ASSERT(mutex_owned(&srn_clone_lock));
523 525 switch (type) {
524 526 case SRN_TYPE_APM:
525 527 if (srn_apm_count == 0) {
526 528 PMD(PMD_SX, ("no apm types\n"))
527 529 return;
528 530 }
529 531 count = srn_apm_count;
530 532 break;
531 533 case SRN_TYPE_AUTOSX:
532 534 if (srn_autosx_count == 0) {
533 535 PMD(PMD_SX, ("no autosx types\n"))
534 536 return;
535 537 }
536 538 count = srn_autosx_count;
537 539 break;
538 540 default:
539 541 ASSERT(0);
540 542 break;
541 543 }
542 544 ASSERT(count > 0);
543 545 PMD(PMD_SX, ("count %d\n", count))
544 546 for (clone = 0; clone < SRN_MAX_CLONE; clone++) {
545 547 if (srn.srn_type[clone] == type) {
546 548 #ifdef DEBUG
547 549 if (type == SRN_TYPE_APM && !srn.srn_fault[clone]) {
548 550 ASSERT(srn.srn_pending[clone].ae_type == 0);
549 551 ASSERT(srn_poll_cnt[clone] == 0);
550 552 ASSERT(srn.srn_delivered[clone] == 0);
551 553 }
552 554 #endif
553 555 srn.srn_pending[clone].ae_type = event;
554 556 srn_poll_cnt[clone] = 1;
555 557 PMD(PMD_SX, ("pollwake %d\n", clone))
556 558 pollwakeup(&srn_pollhead[clone], (POLLRDNORM | POLLIN));
557 559 count--;
558 560 if (count == 0)
559 561 break;
560 562 }
561 563 }
562 564 if (type == SRN_TYPE_AUTOSX) { /* we don't wait */
563 565 PMD(PMD_SX, ("Not waiting for AUTOSX ack\n"))
564 566 return;
565 567 }
566 568 ASSERT(type == SRN_TYPE_APM);
567 569 /* otherwise wait for acks */
568 570 restart:
569 571 /*
570 572 * We wait until all of the pending events are cleared.
571 573 * We have to start over every time we do a cv_wait because
572 574 * we give up the mutex and can be re-entered
573 575 */
574 576 for (clone = 1; clone < SRN_MAX_CLONE; clone++) {
575 577 if (srn.srn_clones[clone] == 0 ||
576 578 srn.srn_type[clone] != SRN_TYPE_APM)
577 579 continue;
578 580 if (srn.srn_pending[clone].ae_type && !srn.srn_fault[clone]) {
579 581 PMD(PMD_SX, ("srn_notify waiting for ack for clone %d, "
580 582 "event %x\n", clone, event))
581 583 if (cv_timedwait(&srn_clones_cv[clone],
582 584 &srn_clone_lock, ddi_get_lbolt() +
583 585 drv_usectohz(srn_timeout * 1000000)) == -1) {
584 586 /*
585 587 * Client didn't respond, mark it as faulted
586 588 * and continue as if a regular signal.
587 589 */
588 590 PMD(PMD_SX, ("srn_notify: clone %d did not "
589 591 "ack event %x\n", clone, event))
590 592 cmn_err(CE_WARN, "srn_notify: clone %d did "
591 593 "not ack event %x\n", clone, event);
592 594 srn.srn_fault[clone] = 1;
593 595 }
594 596 goto restart;
595 597 }
596 598 }
597 599 PMD(PMD_SX, ("srn_notify done with %x\n", event))
598 600 }
|
↓ open down ↓ |
319 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX