Print this page
XXXX introduce drv_sectohz


 970                                 p->cku_err.re_errno = EIO;
 971 
 972                         RPCLOG(1, "clnt_cots_kcallit: transport failed: %d\n",
 973                             p->cku_err.re_errno);
 974 
 975                         break;
 976 
 977                 default:
 978                         /*
 979                          * We delay here because it is better to err
 980                          * on the side of caution. If we got here then
 981                          * status could have been RPC_SUCCESS, but we
 982                          * know that we did not get a connection, so
 983                          * force the rpc status to RPC_CANTCONNECT.
 984                          */
 985                         p->cku_err.re_status = RPC_CANTCONNECT;
 986                         p->cku_err.re_errno = EIO;
 987                         break;
 988                 }
 989                 if (delay_first == TRUE)
 990                         ticks = clnt_cots_min_tout * drv_usectohz(1000000);
 991                 goto cots_done;
 992         }
 993 
 994         /*
 995          * If we've never sent any request on this connection (send count
 996          * is zero, or the connection has been reset), cache the
 997          * the connection's create time and send a request (possibly a retry)
 998          */
 999         if ((p->cku_flags & CKU_SENT) == 0 ||
1000             p->cku_ctime != cm_entry->x_ctime) {
1001                 p->cku_ctime = cm_entry->x_ctime;
1002 
1003         } else if ((p->cku_flags & CKU_SENT) && (p->cku_flags & CKU_ONQUEUE) &&
1004             (call->call_reply != NULL ||
1005             p->cku_recv_attempts < clnt_cots_maxrecv)) {
1006 
1007                 /*
1008                  * If we've sent a request and our call is on the dispatch
1009                  * queue and we haven't made too many receive attempts, then
1010                  * don't re-send, just receive.


1102 
1103         wq = cm_entry->x_wq;
1104         waitsecs = 0;
1105 
1106 dispatch_again:
1107         status = clnt_dispatch_send(wq, mp, call, p->cku_xid,
1108             (p->cku_flags & CKU_ONQUEUE));
1109 
1110         if ((status == RPC_CANTSEND) && (call->call_reason == ENOBUFS)) {
1111                 /*
1112                  * QFULL condition, allow some time for queue to drain
1113                  * and try again. Give up after waiting for all timeout
1114                  * specified for the call, or zone is going away.
1115                  */
1116                 max_waitsecs = wait.tv_sec ? wait.tv_sec : clnt_cots_min_tout;
1117                 if ((waitsecs++ < max_waitsecs) &&
1118                     !(zone_status_get(curproc->p_zone) >=
1119                     ZONE_IS_SHUTTING_DOWN)) {
1120 
1121                         /* wait 1 sec for queue to drain */
1122                         if (clnt_delay(drv_usectohz(1000000),
1123                             h->cl_nosignal) == EINTR) {
1124                                 p->cku_err.re_errno = EINTR;
1125                                 p->cku_err.re_status = RPC_INTR;
1126 
1127                                 goto cots_done;
1128                         }
1129 
1130                         /* and try again */
1131                         goto dispatch_again;
1132                 }
1133                 p->cku_err.re_status = status;
1134                 p->cku_err.re_errno = call->call_reason;
1135                 DTRACE_PROBE(krpc__e__clntcots__kcallit__cantsend);
1136 
1137                 goto cots_done;
1138         }
1139 
1140         if (waitsecs) {
1141                 /* adjust timeout to account for time wait to send */
1142                 wait.tv_sec -= waitsecs;


1166         mutex_enter(&call->call_lock);
1167         interrupted = 0;
1168         if (call->call_status == RPC_TIMEDOUT) {
1169                 /*
1170                  * Indicate that the lwp is not to be stopped while waiting
1171                  * for this network traffic.  This is to avoid deadlock while
1172                  * debugging a process via /proc and also to avoid recursive
1173                  * mutex_enter()s due to NFS page faults while stopping
1174                  * (NFS holds locks when it calls here).
1175                  */
1176                 clock_t cv_wait_ret;
1177                 clock_t timout;
1178                 clock_t oldlbolt;
1179 
1180                 klwp_t *lwp = ttolwp(curthread);
1181 
1182                 if (lwp != NULL)
1183                         lwp->lwp_nostop++;
1184 
1185                 oldlbolt = ddi_get_lbolt();
1186                 timout = wait.tv_sec * drv_usectohz(1000000) +
1187                     drv_usectohz(wait.tv_usec) + oldlbolt;
1188                 /*
1189                  * Iterate until the call_status is changed to something
1190                  * other that RPC_TIMEDOUT, or if cv_timedwait_sig() returns
1191                  * something <=0 zero. The latter means that we timed
1192                  * out.
1193                  */
1194                 if (h->cl_nosignal)
1195                         while ((cv_wait_ret = cv_timedwait(&call->call_cv,
1196                             &call->call_lock, timout)) > 0 &&
1197                             call->call_status == RPC_TIMEDOUT)
1198                                 ;
1199                 else
1200                         while ((cv_wait_ret = cv_timedwait_sig(
1201                             &call->call_cv,
1202                             &call->call_lock, timout)) > 0 &&
1203                             call->call_status == RPC_TIMEDOUT)
1204                                 ;
1205 
1206                 switch (cv_wait_ret) {


1215                 case -1:
1216                         /* cv_timedwait_sig() timed out */
1217                         break;
1218                 default:
1219 
1220                         /*
1221                          * We were cv_signaled(). If we didn't
1222                          * get a successful call_status and returned
1223                          * before time expired, delay up to clnt_cots_min_tout
1224                          * seconds so that the caller doesn't immediately
1225                          * try to call us again and thus force the
1226                          * same condition that got us here (such
1227                          * as a RPC_XPRTFAILED due to the server not
1228                          * listening on the end-point.
1229                          */
1230                         if (call->call_status != RPC_SUCCESS) {
1231                                 clock_t curlbolt;
1232                                 clock_t diff;
1233 
1234                                 curlbolt = ddi_get_lbolt();
1235                                 ticks = clnt_cots_min_tout *
1236                                     drv_usectohz(1000000);
1237                                 diff = curlbolt - oldlbolt;
1238                                 if (diff < ticks) {
1239                                         delay_first = TRUE;
1240                                         if (diff > 0)
1241                                                 ticks -= diff;
1242                                 }
1243                         }
1244                         break;
1245                 }
1246 
1247                 if (lwp != NULL)
1248                         lwp->lwp_nostop--;
1249         }
1250         /*
1251          * Get the reply message, if any.  This will be freed at the end
1252          * whether or not an error occurred.
1253          */
1254         mp = call->call_reply;
1255         call->call_reply = NULL;
1256 


1698         clock_t timout, cv_stat;
1699         enum clnt_stat clstat;
1700         unsigned int old_state;
1701 
1702         ASSERT(MUTEX_HELD(&connmgr_lock));
1703         /*
1704          * We wait for the transport connection to be made, or an
1705          * indication that it could not be made.
1706          */
1707         clstat = RPC_TIMEDOUT;
1708         interrupted = FALSE;
1709 
1710         old_state = cm_entry->x_state_flags;
1711         /*
1712          * Now loop until cv_timedwait{_sig} returns because of
1713          * a signal(0) or timeout(-1) or cv_signal(>0). But it may be
1714          * cv_signalled for various other reasons too. So loop
1715          * until there is a state change on the connection.
1716          */
1717 
1718         timout = waitp->tv_sec * drv_usectohz(1000000) +
1719             drv_usectohz(waitp->tv_usec) + ddi_get_lbolt();
1720 
1721         if (nosignal) {
1722                 while ((cv_stat = cv_timedwait(&cm_entry->x_conn_cv,
1723                     &connmgr_lock, timout)) > 0 &&
1724                     cm_entry->x_state_flags == old_state)
1725                         ;
1726         } else {
1727                 while ((cv_stat = cv_timedwait_sig(&cm_entry->x_conn_cv,
1728                     &connmgr_lock, timout)) > 0 &&
1729                     cm_entry->x_state_flags == old_state)
1730                         ;
1731 
1732                 if (cv_stat == 0) /* got intr signal? */
1733                         interrupted = TRUE;
1734         }
1735 
1736         if ((cm_entry->x_state_flags & (X_BADSTATES|X_CONNECTED)) ==
1737             X_CONNECTED) {
1738                 clstat = RPC_SUCCESS;


2336          * wait for it to complete the connection.
2337          */
2338         if (cm_entry->x_thread == TRUE) {
2339                 rpcerr->re_status = connmgr_cwait(cm_entry, waitp, nosignal);
2340 
2341                 if (rpcerr->re_status != RPC_SUCCESS) {
2342                         mutex_exit(&connmgr_lock);
2343                         connmgr_release(cm_entry);
2344                         return (NULL);
2345                 }
2346         } else {
2347                 bool_t connected;
2348                 calllist_t call;
2349 
2350                 cm_entry->x_thread = TRUE;
2351 
2352                 while (cm_entry->x_needrel == TRUE) {
2353                         cm_entry->x_needrel = FALSE;
2354 
2355                         connmgr_sndrel(cm_entry);
2356                         delay(drv_usectohz(1000000));
2357 
2358                         mutex_enter(&connmgr_lock);
2359                 }
2360 
2361                 /*
2362                  * If we need to send a T_DISCON_REQ, send one.
2363                  */
2364                 connmgr_dis_and_wait(cm_entry);
2365 
2366                 mutex_exit(&connmgr_lock);
2367 
2368                 bzero(&call, sizeof (call));
2369                 cv_init(&call.call_cv, NULL, CV_DEFAULT, NULL);
2370 
2371                 connected = connmgr_connect(cm_entry, cm_entry->x_wq,
2372                     destaddr, addrfmly, &call, &cm_entry->x_tidu_size,
2373                     reconnect, waitp, nosignal, cr);
2374 
2375                 *rpcerr = call.call_err;
2376                 cv_destroy(&call.call_cv);


2452         for (;;) {
2453                 while (cm_entry->x_needdis == TRUE) {
2454                         RPCLOG(8, "connmgr_dis_and_wait: need "
2455                             "T_DISCON_REQ for connection 0x%p\n",
2456                             (void *)cm_entry);
2457                         cm_entry->x_needdis = FALSE;
2458                         cm_entry->x_waitdis = TRUE;
2459 
2460                         connmgr_snddis(cm_entry);
2461 
2462                         mutex_enter(&connmgr_lock);
2463                 }
2464 
2465                 if (cm_entry->x_waitdis == TRUE) {
2466                         clock_t timout;
2467 
2468                         RPCLOG(8, "connmgr_dis_and_wait waiting for "
2469                             "T_DISCON_REQ's ACK for connection %p\n",
2470                             (void *)cm_entry);
2471 
2472                         timout = clnt_cots_min_conntout * drv_usectohz(1000000);
2473 
2474                         /*
2475                          * The TPI spec says that the T_DISCON_REQ
2476                          * will get acknowledged, but in practice
2477                          * the ACK may never get sent. So don't
2478                          * block forever.
2479                          */
2480                         (void) cv_reltimedwait(&cm_entry->x_dis_cv,
2481                             &connmgr_lock, timout, TR_CLOCK_TICK);
2482                 }
2483                 /*
2484                  * If we got the ACK, break. If we didn't,
2485                  * then send another T_DISCON_REQ.
2486                  */
2487                 if (cm_entry->x_waitdis == FALSE) {
2488                         break;
2489                 } else {
2490                         RPCLOG(8, "connmgr_dis_and_wait: did"
2491                             "not get T_DISCON_REQ's ACK for "
2492                             "connection  %p\n", (void *)cm_entry);


3691 {
3692         (void) zone_key_delete(zone_cots_key);
3693 }
3694 
3695 /*
3696  * Wait for TPI ack, returns success only if expected ack is received
3697  * within timeout period.
3698  */
3699 
3700 static int
3701 waitforack(calllist_t *e, t_scalar_t ack_prim, const struct timeval *waitp,
3702     bool_t nosignal)
3703 {
3704         union T_primitives *tpr;
3705         clock_t timout;
3706         int cv_stat = 1;
3707 
3708         ASSERT(MUTEX_HELD(&clnt_pending_lock));
3709         while (e->call_reply == NULL) {
3710                 if (waitp != NULL) {
3711                         timout = waitp->tv_sec * drv_usectohz(MICROSEC) +
3712                             drv_usectohz(waitp->tv_usec);
3713                         if (nosignal)
3714                                 cv_stat = cv_reltimedwait(&e->call_cv,
3715                                     &clnt_pending_lock, timout, TR_CLOCK_TICK);
3716                         else
3717                                 cv_stat = cv_reltimedwait_sig(&e->call_cv,
3718                                     &clnt_pending_lock, timout, TR_CLOCK_TICK);
3719                 } else {
3720                         if (nosignal)
3721                                 cv_wait(&e->call_cv, &clnt_pending_lock);
3722                         else
3723                                 cv_stat = cv_wait_sig(&e->call_cv,
3724                                     &clnt_pending_lock);
3725                 }
3726                 if (cv_stat == -1)
3727                         return (ETIME);
3728                 if (cv_stat == 0)
3729                         return (EINTR);
3730                 /*
3731                  * if we received an error from the server and we know a reply


 970                                 p->cku_err.re_errno = EIO;
 971 
 972                         RPCLOG(1, "clnt_cots_kcallit: transport failed: %d\n",
 973                             p->cku_err.re_errno);
 974 
 975                         break;
 976 
 977                 default:
 978                         /*
 979                          * We delay here because it is better to err
 980                          * on the side of caution. If we got here then
 981                          * status could have been RPC_SUCCESS, but we
 982                          * know that we did not get a connection, so
 983                          * force the rpc status to RPC_CANTCONNECT.
 984                          */
 985                         p->cku_err.re_status = RPC_CANTCONNECT;
 986                         p->cku_err.re_errno = EIO;
 987                         break;
 988                 }
 989                 if (delay_first == TRUE)
 990                         ticks = drv_sectohz(clnt_cots_min_tout);
 991                 goto cots_done;
 992         }
 993 
 994         /*
 995          * If we've never sent any request on this connection (send count
 996          * is zero, or the connection has been reset), cache the
 997          * the connection's create time and send a request (possibly a retry)
 998          */
 999         if ((p->cku_flags & CKU_SENT) == 0 ||
1000             p->cku_ctime != cm_entry->x_ctime) {
1001                 p->cku_ctime = cm_entry->x_ctime;
1002 
1003         } else if ((p->cku_flags & CKU_SENT) && (p->cku_flags & CKU_ONQUEUE) &&
1004             (call->call_reply != NULL ||
1005             p->cku_recv_attempts < clnt_cots_maxrecv)) {
1006 
1007                 /*
1008                  * If we've sent a request and our call is on the dispatch
1009                  * queue and we haven't made too many receive attempts, then
1010                  * don't re-send, just receive.


1102 
1103         wq = cm_entry->x_wq;
1104         waitsecs = 0;
1105 
1106 dispatch_again:
1107         status = clnt_dispatch_send(wq, mp, call, p->cku_xid,
1108             (p->cku_flags & CKU_ONQUEUE));
1109 
1110         if ((status == RPC_CANTSEND) && (call->call_reason == ENOBUFS)) {
1111                 /*
1112                  * QFULL condition, allow some time for queue to drain
1113                  * and try again. Give up after waiting for all timeout
1114                  * specified for the call, or zone is going away.
1115                  */
1116                 max_waitsecs = wait.tv_sec ? wait.tv_sec : clnt_cots_min_tout;
1117                 if ((waitsecs++ < max_waitsecs) &&
1118                     !(zone_status_get(curproc->p_zone) >=
1119                     ZONE_IS_SHUTTING_DOWN)) {
1120 
1121                         /* wait 1 sec for queue to drain */
1122                         if (clnt_delay(drv_sectohz(1),
1123                             h->cl_nosignal) == EINTR) {
1124                                 p->cku_err.re_errno = EINTR;
1125                                 p->cku_err.re_status = RPC_INTR;
1126 
1127                                 goto cots_done;
1128                         }
1129 
1130                         /* and try again */
1131                         goto dispatch_again;
1132                 }
1133                 p->cku_err.re_status = status;
1134                 p->cku_err.re_errno = call->call_reason;
1135                 DTRACE_PROBE(krpc__e__clntcots__kcallit__cantsend);
1136 
1137                 goto cots_done;
1138         }
1139 
1140         if (waitsecs) {
1141                 /* adjust timeout to account for time wait to send */
1142                 wait.tv_sec -= waitsecs;


1166         mutex_enter(&call->call_lock);
1167         interrupted = 0;
1168         if (call->call_status == RPC_TIMEDOUT) {
1169                 /*
1170                  * Indicate that the lwp is not to be stopped while waiting
1171                  * for this network traffic.  This is to avoid deadlock while
1172                  * debugging a process via /proc and also to avoid recursive
1173                  * mutex_enter()s due to NFS page faults while stopping
1174                  * (NFS holds locks when it calls here).
1175                  */
1176                 clock_t cv_wait_ret;
1177                 clock_t timout;
1178                 clock_t oldlbolt;
1179 
1180                 klwp_t *lwp = ttolwp(curthread);
1181 
1182                 if (lwp != NULL)
1183                         lwp->lwp_nostop++;
1184 
1185                 oldlbolt = ddi_get_lbolt();
1186                 timout = drv_sectohz(wait.tv_sec) +
1187                     drv_usectohz(wait.tv_usec) + oldlbolt;
1188                 /*
1189                  * Iterate until the call_status is changed to something
1190                  * other that RPC_TIMEDOUT, or if cv_timedwait_sig() returns
1191                  * something <=0 zero. The latter means that we timed
1192                  * out.
1193                  */
1194                 if (h->cl_nosignal)
1195                         while ((cv_wait_ret = cv_timedwait(&call->call_cv,
1196                             &call->call_lock, timout)) > 0 &&
1197                             call->call_status == RPC_TIMEDOUT)
1198                                 ;
1199                 else
1200                         while ((cv_wait_ret = cv_timedwait_sig(
1201                             &call->call_cv,
1202                             &call->call_lock, timout)) > 0 &&
1203                             call->call_status == RPC_TIMEDOUT)
1204                                 ;
1205 
1206                 switch (cv_wait_ret) {


1215                 case -1:
1216                         /* cv_timedwait_sig() timed out */
1217                         break;
1218                 default:
1219 
1220                         /*
1221                          * We were cv_signaled(). If we didn't
1222                          * get a successful call_status and returned
1223                          * before time expired, delay up to clnt_cots_min_tout
1224                          * seconds so that the caller doesn't immediately
1225                          * try to call us again and thus force the
1226                          * same condition that got us here (such
1227                          * as a RPC_XPRTFAILED due to the server not
1228                          * listening on the end-point.
1229                          */
1230                         if (call->call_status != RPC_SUCCESS) {
1231                                 clock_t curlbolt;
1232                                 clock_t diff;
1233 
1234                                 curlbolt = ddi_get_lbolt();
1235                                 ticks = drv_sectohz(clnt_cots_min_tout);

1236                                 diff = curlbolt - oldlbolt;
1237                                 if (diff < ticks) {
1238                                         delay_first = TRUE;
1239                                         if (diff > 0)
1240                                                 ticks -= diff;
1241                                 }
1242                         }
1243                         break;
1244                 }
1245 
1246                 if (lwp != NULL)
1247                         lwp->lwp_nostop--;
1248         }
1249         /*
1250          * Get the reply message, if any.  This will be freed at the end
1251          * whether or not an error occurred.
1252          */
1253         mp = call->call_reply;
1254         call->call_reply = NULL;
1255 


1697         clock_t timout, cv_stat;
1698         enum clnt_stat clstat;
1699         unsigned int old_state;
1700 
1701         ASSERT(MUTEX_HELD(&connmgr_lock));
1702         /*
1703          * We wait for the transport connection to be made, or an
1704          * indication that it could not be made.
1705          */
1706         clstat = RPC_TIMEDOUT;
1707         interrupted = FALSE;
1708 
1709         old_state = cm_entry->x_state_flags;
1710         /*
1711          * Now loop until cv_timedwait{_sig} returns because of
1712          * a signal(0) or timeout(-1) or cv_signal(>0). But it may be
1713          * cv_signalled for various other reasons too. So loop
1714          * until there is a state change on the connection.
1715          */
1716 
1717         timout = drv_sectohz(waitp->tv_sec) +
1718             drv_usectohz(waitp->tv_usec) + ddi_get_lbolt();
1719 
1720         if (nosignal) {
1721                 while ((cv_stat = cv_timedwait(&cm_entry->x_conn_cv,
1722                     &connmgr_lock, timout)) > 0 &&
1723                     cm_entry->x_state_flags == old_state)
1724                         ;
1725         } else {
1726                 while ((cv_stat = cv_timedwait_sig(&cm_entry->x_conn_cv,
1727                     &connmgr_lock, timout)) > 0 &&
1728                     cm_entry->x_state_flags == old_state)
1729                         ;
1730 
1731                 if (cv_stat == 0) /* got intr signal? */
1732                         interrupted = TRUE;
1733         }
1734 
1735         if ((cm_entry->x_state_flags & (X_BADSTATES|X_CONNECTED)) ==
1736             X_CONNECTED) {
1737                 clstat = RPC_SUCCESS;


2335          * wait for it to complete the connection.
2336          */
2337         if (cm_entry->x_thread == TRUE) {
2338                 rpcerr->re_status = connmgr_cwait(cm_entry, waitp, nosignal);
2339 
2340                 if (rpcerr->re_status != RPC_SUCCESS) {
2341                         mutex_exit(&connmgr_lock);
2342                         connmgr_release(cm_entry);
2343                         return (NULL);
2344                 }
2345         } else {
2346                 bool_t connected;
2347                 calllist_t call;
2348 
2349                 cm_entry->x_thread = TRUE;
2350 
2351                 while (cm_entry->x_needrel == TRUE) {
2352                         cm_entry->x_needrel = FALSE;
2353 
2354                         connmgr_sndrel(cm_entry);
2355                         delay(drv_sectohz(1));
2356 
2357                         mutex_enter(&connmgr_lock);
2358                 }
2359 
2360                 /*
2361                  * If we need to send a T_DISCON_REQ, send one.
2362                  */
2363                 connmgr_dis_and_wait(cm_entry);
2364 
2365                 mutex_exit(&connmgr_lock);
2366 
2367                 bzero(&call, sizeof (call));
2368                 cv_init(&call.call_cv, NULL, CV_DEFAULT, NULL);
2369 
2370                 connected = connmgr_connect(cm_entry, cm_entry->x_wq,
2371                     destaddr, addrfmly, &call, &cm_entry->x_tidu_size,
2372                     reconnect, waitp, nosignal, cr);
2373 
2374                 *rpcerr = call.call_err;
2375                 cv_destroy(&call.call_cv);


2451         for (;;) {
2452                 while (cm_entry->x_needdis == TRUE) {
2453                         RPCLOG(8, "connmgr_dis_and_wait: need "
2454                             "T_DISCON_REQ for connection 0x%p\n",
2455                             (void *)cm_entry);
2456                         cm_entry->x_needdis = FALSE;
2457                         cm_entry->x_waitdis = TRUE;
2458 
2459                         connmgr_snddis(cm_entry);
2460 
2461                         mutex_enter(&connmgr_lock);
2462                 }
2463 
2464                 if (cm_entry->x_waitdis == TRUE) {
2465                         clock_t timout;
2466 
2467                         RPCLOG(8, "connmgr_dis_and_wait waiting for "
2468                             "T_DISCON_REQ's ACK for connection %p\n",
2469                             (void *)cm_entry);
2470 
2471                         timout = drv_sectohz(clnt_cots_min_conntout);
2472 
2473                         /*
2474                          * The TPI spec says that the T_DISCON_REQ
2475                          * will get acknowledged, but in practice
2476                          * the ACK may never get sent. So don't
2477                          * block forever.
2478                          */
2479                         (void) cv_reltimedwait(&cm_entry->x_dis_cv,
2480                             &connmgr_lock, timout, TR_CLOCK_TICK);
2481                 }
2482                 /*
2483                  * If we got the ACK, break. If we didn't,
2484                  * then send another T_DISCON_REQ.
2485                  */
2486                 if (cm_entry->x_waitdis == FALSE) {
2487                         break;
2488                 } else {
2489                         RPCLOG(8, "connmgr_dis_and_wait: did"
2490                             "not get T_DISCON_REQ's ACK for "
2491                             "connection  %p\n", (void *)cm_entry);


3690 {
3691         (void) zone_key_delete(zone_cots_key);
3692 }
3693 
3694 /*
3695  * Wait for TPI ack, returns success only if expected ack is received
3696  * within timeout period.
3697  */
3698 
3699 static int
3700 waitforack(calllist_t *e, t_scalar_t ack_prim, const struct timeval *waitp,
3701     bool_t nosignal)
3702 {
3703         union T_primitives *tpr;
3704         clock_t timout;
3705         int cv_stat = 1;
3706 
3707         ASSERT(MUTEX_HELD(&clnt_pending_lock));
3708         while (e->call_reply == NULL) {
3709                 if (waitp != NULL) {
3710                         timout = drv_sectohz(waitp->tv_sec) +
3711                             drv_usectohz(waitp->tv_usec);
3712                         if (nosignal)
3713                                 cv_stat = cv_reltimedwait(&e->call_cv,
3714                                     &clnt_pending_lock, timout, TR_CLOCK_TICK);
3715                         else
3716                                 cv_stat = cv_reltimedwait_sig(&e->call_cv,
3717                                     &clnt_pending_lock, timout, TR_CLOCK_TICK);
3718                 } else {
3719                         if (nosignal)
3720                                 cv_wait(&e->call_cv, &clnt_pending_lock);
3721                         else
3722                                 cv_stat = cv_wait_sig(&e->call_cv,
3723                                     &clnt_pending_lock);
3724                 }
3725                 if (cv_stat == -1)
3726                         return (ETIME);
3727                 if (cv_stat == 0)
3728                         return (EINTR);
3729                 /*
3730                  * if we received an error from the server and we know a reply