4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
30 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
31 /* All Rights Reserved */
33 * Portions of this source code were derived from Berkeley
34 * 4.3 BSD under license from the Regents of the University of
39 * This is the rpc server side idle loop
40 * Wait for input, call server program.
50 #include <sys/types.h>
57 extern const char __nsl_dom
[];
59 extern int __rpc_compress_pollfd(int, pollfd_t
*, pollfd_t
*);
60 extern bool_t
__is_a_userfd(int P_fd
);
61 extern void __destroy_userfd();
62 extern void clear_pollfd(int);
63 extern void set_pollfd(int /* fd */, short /* events */);
64 extern void svc_getreq_poll();
65 extern void (*__proc_cleanup_cb
)();
67 static void start_threads();
68 static void create_pipe();
69 static void clear_pipe();
70 static int select_next_pollfd();
71 static SVCXPRT
*make_xprt_copy();
72 static void _svc_run_mt();
73 static void _svc_run();
75 int _svc_prog_dispatch();
76 static void _svc_done_private();
78 extern rwlock_t svc_fd_lock
;
79 extern mutex_t svc_door_mutex
;
80 extern cond_t svc_door_waitcv
;
81 extern int svc_ndoorfds
;
82 extern void __svc_cleanup_door_xprts();
83 extern void __svc_free_xprtlist();
84 extern void __svc_getreq_user(struct pollfd
*);
87 * Maximum fragment size allowed for connection oriented connections.
88 * Zero means that no maximum size limit has been requested.
90 int __rpc_connmaxrec
= 0;
92 /* Inter-Record Timeout in secs for non-blocked connection RPC */
93 int __rpc_irtimeout
= 35;
96 * Request exclusive access to tcp and udp non-priv ports bound with a
99 bool_t __rpc_tp_exclbind
= FALSE
;
102 * Maximum number of outstanding connection indications (listen backlog).
104 static int __svc_lstnbklog
= 64; /* Chosen Arbitrarily */
107 * XXX - eventually, all mutexes and their initializations static
111 * Variables used for MT
113 int svc_mt_mode
; /* multi-threading mode */
115 int svc_pipe
[2]; /* pipe for breaking out of poll: read(0), write(1) */
117 /* BEGIN PROTECTED BY svc_mutex */
119 static int svc_thr_max
= 16; /* default maximum number of threads allowed */
121 static int svc_thr_total
; /* current number of threads */
123 static int svc_thr_active
; /* current number of threads active */
125 /* circular array of file descriptors with pending data */
127 #define CIRCULAR_BUFSIZE 1024
129 static int svc_pending_fds
[CIRCULAR_BUFSIZE
+1]; /* fds with pending data */
131 static int svc_next_pending
; /* next one to be processed */
133 static int svc_last_pending
; /* last one in list */
135 static int svc_total_pending
; /* total in list */
137 static int svc_thr_total_creates
; /* total created - stats */
139 static int svc_thr_total_create_errors
; /* total create errors - stats */
141 static int svc_waiters
; /* number of waiting threads */
143 /* END PROTECTED BY svc_mutex */
145 /* BEGIN PROTECTED BY svc_fd_lock: */
147 int svc_nfds
; /* total number of active file descriptors */
149 int svc_nfds_set
; /* total number of fd bits set in svc_fdset */
151 int svc_max_fd
= 0; /* largest active file descriptor */
153 int svc_npollfds
; /* total number of active pollfds */
155 int svc_npollfds_set
; /* total number of pollfd set in svc_pollfd */
157 int svc_max_pollfd
; /* largest active pollfd so far */
159 int svc_pollfd_allocd
; /* number of pollfd structures allocated */
161 /* END PROTECTED BY svc_fd_lock: */
163 /* BEGIN PROTECTED BY svc_thr_mutex */
165 #define POLLSET_EXTEND 256
166 static int svc_pollset_allocd
;
167 static struct pollfd
*svc_pollset
;
169 * array of file descriptors currently active
171 static int svc_polled
; /* no of fds polled in last poll() - input */
173 static int svc_pollfds
; /* no of active fds in last poll() - output */
175 static int svc_next_pollfd
; /* next fd to processin svc_pollset */
177 bool_t svc_polling
; /* true if a thread is polling */
179 /* END PROTECTED BY svc_thr_mutex */
181 /* BEGIN PROTECTED BY svc_exit_mutex */
183 static bool_t svc_exit_done
= TRUE
;
185 /* END PROTECTED BY svc_exit_mutex */
187 /* VARIABLES PROTECTED BY svc_mutex:
188 svc_thr_total, svc_thr_active, svc_pending_fds, svc_next_pending,
189 svc_last_pending, svc_total_pending, svc_thr_total_creates,
190 svc_thr_total_create_errors,
191 svcxprt_list_t::next, svcxprt_ext_t::my_xlist,
192 svc_thr_max, svc_waiters
195 /* VARIABLES PROTECTED BY svc_fd_lock:
196 svc_xports, svc_fdset, svc_nfds, svc_nfds_set, svc_max_fd,
197 svc_pollfd, svc_npollfds, svc_npollfds_set, svc_max_pollfd
200 /* VARIABLES PROTECTED BY svc_thr_mutex:
201 svc_pollset, svc_pollfds, svc_next_pollfd, svc_polling
202 svc_pollset_allocd, svc_polled
205 /* VARIABLES PROTECTED BY svc_exit_mutex:
209 /* VARIABLES READABLE WITHOUT LOCK:
210 svc_thr_total, svc_thr_active, svc_thr_total_creates,
211 svc_thr_total_create_errors,
212 svc_xports, svc_nfds, svc_nfds_set, svc_max_fd,
213 svc_npollfds, svc_npollfds_set, svc_max_pollfd,
214 svc_pollfds, svc_next_pollfd, svc_exit_done, svc_polling,
215 svc_thr_max, svc_waiters
218 /* VARIABLES PROTECTED BY "program_logic":
219 rpc_msg::, svc_req::, svcxprt_ext_t::flags, svc_mt_mode,
220 svcxprt_ext_t::parent
224 svc_exit_mutex, svc_thr_mutex, svc_mutex, svc_fd_lock
231 /* NO OTHER THREADS ARE RUNNING */
233 svc_exit_done
= FALSE
;
235 while ((svc_npollfds
> 0 || svc_ndoorfds
> 0) && !svc_exit_done
) {
236 if (svc_npollfds
> 0) {
237 switch (svc_mt_mode
) {
238 case RPC_SVC_MT_NONE
:
248 (void) mutex_lock(&svc_door_mutex
);
249 if (svc_ndoorfds
> 0)
250 (void) cond_wait(&svc_door_waitcv
, &svc_door_mutex
);
251 (void) mutex_unlock(&svc_door_mutex
);
257 * This function causes svc_run() to exit by destroying all
269 (void) mutex_lock(&svc_exit_mutex
);
271 (void) mutex_unlock(&svc_exit_mutex
);
274 svc_exit_done
= TRUE
;
275 for (fd
= 0; fd
< svc_max_pollfd
; fd
++) {
276 xprt
= svc_xports
[fd
];
281 __svc_free_xprtlist();
282 __svc_cleanup_door_xprts();
283 (void) mutex_unlock(&svc_exit_mutex
);
285 if (svc_mt_mode
!= RPC_SVC_MT_NONE
) {
286 (void) mutex_lock(&svc_mutex
);
287 (void) cond_broadcast(&svc_thr_fdwait
);
288 (void) mutex_unlock(&svc_mutex
);
290 (void) write(svc_pipe
[1], &dummy
, sizeof (dummy
));
293 (void) mutex_lock(&svc_door_mutex
);
294 (void) cond_signal(&svc_door_waitcv
); /* wake up door dispatching */
295 (void) mutex_unlock(&svc_door_mutex
);
297 /* destroy reactor information if any */
303 * this funtion is called with svc_fd_lock and svc_thr_mutex
307 alloc_pollset(int npollfds
)
309 if (npollfds
> svc_pollset_allocd
) {
312 svc_pollset_allocd
+= POLLSET_EXTEND
;
313 } while (npollfds
> svc_pollset_allocd
);
314 tmp
= reallocarray(svc_pollset
, svc_pollset_allocd
,
317 syslog(LOG_ERR
, "alloc_pollset: out of memory");
328 sigset_t set
, oldset
;
333 * Block SIGALRM while doing work. Unblock it while doing poll().
334 * This is so that services like rpc.rstatd can cause the poll()
335 * to be interrupted due to alarm() but that we don't end up in
336 * an MT-unsafe signal handler at an inopportune time.
338 (void) sigemptyset(&set
);
339 (void) sigaddset(&set
, SIGALRM
);
340 (void) sigprocmask(SIG_BLOCK
, &set
, &oldset
);
341 while (!svc_exit_done
) {
343 * Check whether there is any server fd on which we may want
346 (void) rw_rdlock(&svc_fd_lock
);
347 if (alloc_pollset(svc_npollfds
) == -1)
349 npollfds
= __rpc_compress_pollfd(svc_max_pollfd
,
350 svc_pollfd
, svc_pollset
);
351 (void) rw_unlock(&svc_fd_lock
);
353 break; /* None waiting, hence return */
355 (void) sigprocmask(SIG_SETMASK
, &oldset
, NULL
);
356 i
= poll(svc_pollset
, npollfds
, -1);
357 (void) sigprocmask(SIG_BLOCK
, &set
, &oldset
);
361 * We ignore all errors, continuing with the assumption
362 * that it was set by the signal handlers (or any
363 * other outside event) and not caused by poll().
368 svc_getreq_poll(svc_pollset
, i
);
371 (void) sigprocmask(SIG_SETMASK
, &oldset
, NULL
);
375 * In _svc_run_mt, myfd is linked with mypollfd
376 * svc_pollset[mypollfd].fd == myfd
377 * However, in some cases, the link can not be made, thus we define the
378 * following values for these special cases
381 INVALID_POLLFD
= -200,
389 int n_polled
, dispatch
;
391 static bool_t first_time
= TRUE
;
392 bool_t main_thread
= FALSE
;
395 SVCXPRT
*parent_xprt
, *xprt
;
398 * Server is multi-threaded. Do "first time" initializations.
399 * Since only one thread exists in the beginning, there's no
400 * need for mutex protection for first time initializations.
405 svc_thr_total
= 1; /* this thread */
406 svc_next_pending
= svc_last_pending
= 0;
409 * Create a pipe for waking up the poll, if new
410 * descriptors have been added to svc_fdset.
415 /* OTHER THREADS ARE RUNNING */
422 * svc_thr_mutex prevents more than one thread from
423 * trying to select a descriptor to process further.
424 * svc_thr_mutex is unlocked after a thread selects
425 * a descriptor on which to receive data. If there are
426 * no such descriptors, the thread will poll with
427 * svc_thr_mutex locked, after unlocking all other
428 * locks. This prevents more than one thread from
429 * trying to poll at the same time.
431 (void) mutex_lock(&svc_thr_mutex
);
432 (void) mutex_lock(&svc_mutex
);
435 mypollfd
= INVALID_POLLFD
;
438 * Check if there are any descriptors with data pending.
440 if (svc_total_pending
> 0) {
441 myfd
= svc_pending_fds
[svc_next_pending
++];
442 mypollfd
= FD_FROM_PENDING
;
443 if (svc_next_pending
> CIRCULAR_BUFSIZE
)
444 svc_next_pending
= 0;
449 * Get the next active file descriptor to process.
451 if (myfd
== -1 && svc_pollfds
== 0) {
453 * svc_pollset is empty; do polling
458 * if there are no file descriptors, return
460 (void) rw_rdlock(&svc_fd_lock
);
461 if (svc_npollfds
== 0 ||
462 alloc_pollset(svc_npollfds
+ 1) == -1) {
463 (void) rw_unlock(&svc_fd_lock
);
466 (void) mutex_unlock(&svc_mutex
);
467 (void) mutex_unlock(&svc_thr_mutex
);
475 npollfds
= __rpc_compress_pollfd(svc_max_pollfd
,
476 svc_pollfd
, svc_pollset
);
477 (void) rw_unlock(&svc_fd_lock
);
481 * There are file descriptors, but none of them
482 * are available for polling. If this is the
483 * main thread, or if no thread is waiting,
484 * wait on condition variable, otherwise exit.
487 (void) mutex_unlock(&svc_thr_mutex
);
488 if ((!main_thread
) && svc_waiters
> 0) {
490 (void) mutex_unlock(&svc_mutex
);
495 while (svc_npollfds_set
== 0 &&
497 svc_total_pending
== 0 &&
500 (void) cond_wait(&svc_thr_fdwait
,
506 * Check exit flag. If this is not the main
511 (void) mutex_unlock(&svc_mutex
);
517 (void) mutex_unlock(&svc_mutex
);
522 * We're ready to poll. Always set svc_pipe[0]
523 * as the last one, since the poll will occasionally
524 * need to be interrupted. Release svc_mutex for
525 * the duration of the poll, but hold on to
526 * svc_thr_mutex, as we don't want any other thread
529 svc_pollset
[npollfds
].fd
= svc_pipe
[0];
530 svc_pollset
[npollfds
].events
= MASKVAL
;
535 (void) mutex_unlock(&svc_mutex
);
536 n_polled
= poll(svc_pollset
, npollfds
+ 1, -1);
537 (void) mutex_lock(&svc_mutex
);
542 * Check if information returned indicates one
543 * or more closed fd's; find and remove any such
546 for (i
= 0; i
<= npollfds
; i
++) {
547 if (svc_pollset
[i
].revents
& POLLNVAL
) {
548 /* Overwrite svc_pollset[i] */
549 for (j
= i
; j
< npollfds
; j
++)
552 (void) memset(&svc_pollset
[j
],
553 0, sizeof (struct pollfd
));
559 } while (n_polled
<= 0);
563 * If there's data in the pipe, clear it.
565 if (svc_pollset
[npollfds
].revents
) {
568 svc_pollset
[npollfds
].revents
= 0;
570 svc_polled
= npollfds
;
571 svc_pollfds
= n_polled
;
579 (void) mutex_unlock(&svc_mutex
);
580 (void) mutex_unlock(&svc_thr_mutex
);
589 * If no descriptor is active, continue.
591 if (svc_pollfds
== 0)
592 goto continue_with_locks
;
596 * If a file descriptor has already not been selected,
597 * choose a file descriptor.
598 * svc_pollfds and svc_next_pollfd are updated.
601 if (select_next_pollfd(&myfd
, &mypollfd
) == -1)
602 goto continue_with_locks
;
606 * Check to see if new threads need to be started.
607 * Count of threads that could be gainfully employed is
608 * obtained as follows:
609 * - count 1 for poller
610 * - count 1 for this request
611 * - count active file descriptors (svc_pollfds)
612 * - count pending file descriptors
614 * (svc_thr_total - svc_thr_active) are already available.
615 * This thread is one of the available threads.
617 * Number of new threads should not exceed
618 * (svc_thr_max - svc_thr_total).
620 if (svc_thr_total
< svc_thr_max
&&
621 svc_mt_mode
== RPC_SVC_MT_AUTO
&& !svc_exit_done
) {
622 n_new
= 1 + 1 + svc_pollfds
+ svc_total_pending
-
623 (svc_thr_total
- svc_thr_active
);
624 if (n_new
> (svc_thr_max
- svc_thr_total
))
625 n_new
= svc_thr_max
- svc_thr_total
;
627 start_threads(n_new
);
631 * Get parent xprt. It is possible for the parent service
632 * handle to be destroyed by now, due to a race condition.
633 * Check for this, and if so, log a warning and go on.
635 parent_xprt
= svc_xports
[myfd
];
636 if (parent_xprt
== NULL
) {
637 /* Check if it is not a user FD */
638 if (__is_a_userfd(myfd
) == TRUE
)
639 __svc_getreq_user(&(svc_pollset
[mypollfd
]));
640 goto continue_with_locks
;
642 /* LINTED pointer alignment */
643 if (svc_defunct(parent_xprt
) || svc_failed(parent_xprt
))
644 goto continue_with_locks
;
647 * Make a copy of parent xprt, update svc_fdset.
649 if ((xprt
= make_xprt_copy(parent_xprt
)) == NULL
)
650 goto continue_with_locks
;
653 * Keep track of active threads in automatic mode.
655 if (svc_mt_mode
== RPC_SVC_MT_AUTO
)
659 * Release mutexes so other threads can get going.
661 (void) mutex_unlock(&svc_mutex
);
662 (void) mutex_unlock(&svc_thr_mutex
);
672 /* LINTED pointer alignment */
673 msg
= SVCEXT(xprt
)->msg
;
674 /* LINTED pointer alignment */
675 r
= SVCEXT(xprt
)->req
;
676 /* LINTED pointer alignment */
677 cred_area
= SVCEXT(xprt
)->cred_area
;
680 msg
->rm_call
.cb_cred
.oa_base
= cred_area
;
681 msg
->rm_call
.cb_verf
.oa_base
=
682 &(cred_area
[MAX_AUTH_BYTES
]);
683 r
->rq_clntcred
= &(cred_area
[2 * MAX_AUTH_BYTES
]);
686 * receive RPC message
688 if ((dispatch
= SVC_RECV(xprt
, msg
))) {
689 if (svc_mt_mode
!= RPC_SVC_MT_NONE
)
690 /* LINTED pointer alignment */
691 svc_flags(xprt
) |= SVC_ARGS_CHECK
;
692 dispatch
= _svc_prog_dispatch(xprt
, msg
, r
);
695 * Call cleanup procedure if set.
697 if (__proc_cleanup_cb
!= NULL
)
698 (*__proc_cleanup_cb
)(xprt
);
703 * Finish up, if automatic mode, or not dispatched.
705 if (svc_mt_mode
== RPC_SVC_MT_AUTO
|| !dispatch
) {
706 /* LINTED pointer alignment */
707 if (svc_flags(xprt
) & SVC_ARGS_CHECK
)
709 (void) mutex_lock(&svc_mutex
);
710 _svc_done_private(xprt
);
711 if (svc_mt_mode
== RPC_SVC_MT_AUTO
) {
713 * not active any more
718 * If not main thread, exit unless
719 * there's some immediate work.
723 svc_total_pending
<= 0 &&
729 (void) cond_broadcast(
732 (void) mutex_unlock(&svc_mutex
);
737 (void) mutex_unlock(&svc_mutex
);
746 * start_threads() - Start specified number of threads.
749 start_threads(int num_threads
)
753 assert(MUTEX_HELD(&svc_mutex
));
755 for (i
= 0; i
< num_threads
; i
++) {
756 if (thr_create(NULL
, 0, (void *(*)(void *))_svc_run_mt
, NULL
,
757 THR_DETACHED
, NULL
) == 0) {
759 svc_thr_total_creates
++;
761 svc_thr_total_create_errors
++;
768 * create_pipe() - create pipe for breaking out of poll.
773 if (pipe(svc_pipe
) == -1) {
774 syslog(LOG_ERR
, dgettext(__nsl_dom
,
775 "RPC: svc could not create pipe - exiting"));
778 if (fcntl(svc_pipe
[0], F_SETFL
, O_NONBLOCK
) == -1) {
779 syslog(LOG_ERR
, dgettext(__nsl_dom
,
780 "RPC: svc pipe error - exiting"));
783 if (fcntl(svc_pipe
[1], F_SETFL
, O_NONBLOCK
) == -1) {
784 syslog(LOG_ERR
, dgettext(__nsl_dom
,
785 "RPC: svc pipe error - exiting"));
792 * clear_pipe() - Empty data in pipe.
801 i
= read(svc_pipe
[0], buf
, sizeof (buf
));
802 } while (i
== sizeof (buf
));
807 * select_next_pollfd() - Select the next active fd in svc_pollset.
810 select_next_pollfd(int *fd
, int *pollfdIndex
)
814 assert(MUTEX_HELD(&svc_thr_mutex
));
815 assert(MUTEX_HELD(&svc_mutex
));
817 for (i
= svc_next_pollfd
; svc_pollfds
> 0 && i
< svc_polled
; i
++) {
818 if (svc_pollset
[i
].revents
) {
821 * No more special case for POLLNVAL, because it may
822 * be linked with a user file descriptot callback
824 svc_next_pollfd
= i
+ 1;
826 *fd
= svc_pollset
[i
].fd
;
832 svc_next_pollfd
= svc_pollfds
= 0;
834 *pollfdIndex
= INVALID_POLLFD
;
840 * make_xprt_copy() - make a copy of the parent xprt.
841 * Clear fd bit in svc_fdset.
844 make_xprt_copy(SVCXPRT
*parent
)
846 /* LINTED pointer alignment */
847 SVCXPRT_LIST
*xlist
= SVCEXT(parent
)->my_xlist
;
850 int fd
= parent
->xp_fd
;
852 assert(MUTEX_HELD(&svc_mutex
));
856 xlist
->next
= xret
->next
;
859 /* LINTED pointer alignment */
860 svc_flags(xprt
) = svc_flags(parent
);
862 xprt
= svc_copy(parent
);
865 /* LINTED pointer alignment */
866 SVCEXT(parent
)->refcnt
++;
867 (void) rw_wrlock(&svc_fd_lock
);
869 (void) rw_unlock(&svc_fd_lock
);
875 * _svc_done_private() - return copies to library.
878 _svc_done_private(SVCXPRT
*xprt
)
881 SVCXPRT_LIST
*xhead
, *xlist
;
883 assert(MUTEX_HELD(&svc_mutex
));
885 /* LINTED pointer alignment */
886 if ((parent
= SVCEXT(xprt
)->parent
) == NULL
)
889 /* LINTED pointer alignment */
890 xhead
= SVCEXT(parent
)->my_xlist
;
891 /* LINTED pointer alignment */
892 xlist
= SVCEXT(xprt
)->my_xlist
;
893 xlist
->next
= xhead
->next
;
896 /* LINTED pointer alignment */
897 SVCEXT(parent
)->refcnt
--;
900 * Propagate any error flags. This is done in both directions to
901 * ensure that if one child gets an error, everyone will see it
902 * (even if there are multiple outstanding children) and the
903 * transport will get closed.
905 /* LINTED pointer alignment */
906 svc_flags(xprt
) |= svc_flags(parent
);
907 /* LINTED pointer alignment */
908 if (svc_failed(xprt
) || svc_defunct(xprt
)) {
909 /* LINTED pointer alignment */
910 svc_flags(parent
) |= (svc_flags(xprt
) &
911 (SVC_FAILED
| SVC_DEFUNCT
));
912 /* LINTED pointer alignment */
913 if (SVCEXT(parent
)->refcnt
== 0)
914 _svc_destroy_private(xprt
);
919 svc_done(SVCXPRT
*xprt
)
921 if (svc_mt_mode
!= RPC_SVC_MT_USER
)
925 * Make sure file descriptor is released in user mode.
926 * If the xprt is a door, do nothing: this work is performed by
927 * svc_door.c's return_xprt_copy() routine, which is basically a
928 * door-specific copy of _svc_done_private().
930 /* LINTED pointer alignment */
931 if (svc_type(xprt
) == SVC_DOOR
)
934 /* LINTED pointer alignment */
935 if (svc_flags(xprt
) & SVC_ARGS_CHECK
)
938 (void) mutex_lock(&svc_mutex
);
939 _svc_done_private(xprt
);
940 (void) mutex_unlock(&svc_mutex
);
945 * Mark argument completion. Release file descriptor.
948 svc_args_done(SVCXPRT
*xprt
)
951 /* LINTED pointer alignment */
952 SVCXPRT
*parent
= SVCEXT(xprt
)->parent
;
953 bool_t wake_up_poller
;
956 /* LINTED pointer alignment */
957 svc_flags(xprt
) |= svc_flags(parent
);
958 /* LINTED pointer alignment */
959 svc_flags(xprt
) &= ~SVC_ARGS_CHECK
;
960 /* LINTED pointer alignment */
961 if (svc_failed(xprt
) || svc_defunct(parent
))
964 /* LINTED pointer alignment */
965 if (svc_type(xprt
) == SVC_CONNECTION
&&
966 (stat
= SVC_STAT(xprt
)) != XPRT_IDLE
) {
967 if (stat
== XPRT_MOREREQS
) {
968 (void) mutex_lock(&svc_mutex
);
969 svc_pending_fds
[svc_last_pending
++] = xprt
->xp_fd
;
970 if (svc_last_pending
> CIRCULAR_BUFSIZE
)
971 svc_last_pending
= 0;
973 (void) mutex_unlock(&svc_mutex
);
974 wake_up_poller
= FALSE
;
982 (void) rw_wrlock(&svc_fd_lock
);
983 set_pollfd(xprt
->xp_fd
, MASKVAL
);
984 (void) rw_unlock(&svc_fd_lock
);
985 wake_up_poller
= TRUE
;
988 if (!wake_up_poller
|| !svc_polling
) {
990 * Wake up any waiting threads.
992 (void) mutex_lock(&svc_mutex
);
993 if (svc_waiters
> 0) {
994 (void) cond_broadcast(&svc_thr_fdwait
);
995 (void) mutex_unlock(&svc_mutex
);
998 (void) mutex_unlock(&svc_mutex
);
1002 * Wake up any polling thread.
1005 (void) write(svc_pipe
[1], &dummy
, sizeof (dummy
));
1010 __rpc_legal_connmaxrec(int suggested
) {
1011 if (suggested
== -1) {
1012 /* Supply default */
1013 return (RPC_MAXDATASIZE
+ 2*sizeof (uint32_t));
1014 } else if (suggested
< 0) {
1016 } else if (suggested
> 0) {
1017 /* Round down to multiple of BYTES_PER_XDR_UNIT */
1018 suggested
-= suggested
% BYTES_PER_XDR_UNIT
;
1019 /* If possible, allow for two fragment headers */
1020 if (suggested
< MAXINT
-(2*sizeof (uint32_t))) {
1021 /* Allow for two fragment headers */
1022 suggested
+= 2 * sizeof (uint32_t);
1026 if (suggested
< sizeof (struct rpc_msg
)) {
1035 rpc_control(int op
, void *info
)
1040 case RPC_SVC_MTMODE_SET
:
1041 tmp
= *((int *)info
);
1042 if (tmp
!= RPC_SVC_MT_NONE
&& tmp
!= RPC_SVC_MT_AUTO
&&
1043 tmp
!= RPC_SVC_MT_USER
)
1045 if (svc_mt_mode
!= RPC_SVC_MT_NONE
&& svc_mt_mode
!= tmp
)
1049 case RPC_SVC_MTMODE_GET
:
1050 *((int *)info
) = svc_mt_mode
;
1052 case RPC_SVC_THRMAX_SET
:
1053 if ((tmp
= *((int *)info
)) < 1)
1055 (void) mutex_lock(&svc_mutex
);
1057 (void) mutex_unlock(&svc_mutex
);
1059 case RPC_SVC_THRMAX_GET
:
1060 *((int *)info
) = svc_thr_max
;
1062 case RPC_SVC_THRTOTAL_GET
:
1063 *((int *)info
) = svc_thr_total
;
1065 case RPC_SVC_THRCREATES_GET
:
1066 *((int *)info
) = svc_thr_total_creates
;
1068 case RPC_SVC_THRERRORS_GET
:
1069 *((int *)info
) = svc_thr_total_create_errors
;
1071 case RPC_SVC_USE_POLLFD
:
1072 if (*((int *)info
) && !__rpc_use_pollfd_done
) {
1073 __rpc_use_pollfd_done
= 1;
1077 case RPC_SVC_CONNMAXREC_SET
:
1078 tmp
= __rpc_legal_connmaxrec(*(int *)info
);
1080 __rpc_connmaxrec
= tmp
;
1085 case RPC_SVC_CONNMAXREC_GET
:
1086 *((int *)info
) = __rpc_connmaxrec
;
1088 case RPC_SVC_IRTIMEOUT_SET
:
1089 tmp
= *((int *)info
);
1091 __rpc_irtimeout
= tmp
;
1097 * No mutex necessary as _EXCLBIND_SET will/should only
1098 * be used before an RPC daemon goes mt-hot.
1100 case __RPC_SVC_EXCLBIND_SET
:
1102 __rpc_tp_exclbind
= *((bool_t
*)info
);
1106 case __RPC_SVC_EXCLBIND_GET
:
1108 *((bool_t
*)info
) = __rpc_tp_exclbind
;
1113 case __RPC_SVC_LSTNBKLOG_SET
:
1116 __svc_lstnbklog
= tmp
;
1120 case __RPC_SVC_LSTNBKLOG_GET
:
1121 *(int *)info
= __svc_lstnbklog
;