2 * Copyright 2000, International Business Machines Corporation and others.
5 * This software has been released under the terms of the IBM Public
6 * License. For details, see the LICENSE file in the top-level source
7 * directory or online at http://www.openafs.org/dl/license10.html
10 #include <afsconfig.h>
11 #include <afs/param.h>
15 #include "afs/sysincludes.h"
22 * multi.c and multi.h, together with some rxgen hooks, provide a way of
23 * making multiple, but similar, rx calls to multiple hosts simultaneously
27 multi_Init(struct rx_connection **conns, int nConns)
29 struct rx_call **calls;
31 struct multi_handle *mh;
35 * Note: all structures that are possibly referenced by other
36 * processes must be allocated. In some kernels variables allocated on
37 * a process stack will not be accessible to other processes
40 calls = (struct rx_call **)osi_Alloc(sizeof(struct rx_call *) * nConns);
41 ready = (short *)osi_Alloc(sizeof(short *) * nConns);
42 mh = (struct multi_handle *)osi_Alloc(sizeof(struct multi_handle));
43 if (!calls || !ready || !mh)
44 osi_Panic("multi_Rx: no mem\n");
46 mh->nextReady = mh->firstNotReady = mh->ready = ready;
50 #ifdef RX_ENABLE_LOCKS
51 MUTEX_INIT(&mh->lock, "rx_multi_lock", MUTEX_DEFAULT, 0);
52 CV_INIT(&mh->cv, "rx_multi_cv", CV_DEFAULT, 0);
53 #endif /* RX_ENABLE_LOCKS */
54 for (i = 0; i < nConns; i++) {
56 call = mh->calls[i] = rx_NewCall(conns[i]);
57 rx_SetArrivalProc(call, multi_Ready, (void *) mh, i);
62 /* Return the user's connection index of the most recently ready call; that is, a call that has received at least one reply packet */
64 multi_Select(struct multi_handle *mh)
69 #ifdef RX_ENABLE_LOCKS
70 MUTEX_ENTER(&mh->lock);
71 #endif /* RX_ENABLE_LOCKS */
72 while (mh->nextReady == mh->firstNotReady) {
73 if (mh->nReady == mh->nConns) {
74 #ifdef RX_ENABLE_LOCKS
75 MUTEX_EXIT(&mh->lock);
76 #endif /* RX_ENABLE_LOCKS */
80 #ifdef RX_ENABLE_LOCKS
81 CV_WAIT(&mh->cv, &mh->lock);
82 #else /* RX_ENABLE_LOCKS */
84 #endif /* RX_ENABLE_LOCKS */
86 index = *(mh->nextReady);
88 #ifdef RX_ENABLE_LOCKS
89 MUTEX_EXIT(&mh->lock);
90 #endif /* RX_ENABLE_LOCKS */
95 /* Called by Rx when the first reply packet of a call is received, or the call is aborted. */
97 multi_Ready(struct rx_call *call, void *amh,
100 struct multi_handle *mh = (struct multi_handle *)amh;
101 #ifdef RX_ENABLE_LOCKS
102 MUTEX_ENTER(&mh->lock);
103 #endif /* RX_ENABLE_LOCKS */
104 *mh->firstNotReady++ = index;
106 #ifdef RX_ENABLE_LOCKS
108 MUTEX_EXIT(&mh->lock);
109 #else /* RX_ENABLE_LOCKS */
111 #endif /* RX_ENABLE_LOCKS */
114 /* Called when the multi rx call is over, or when the user aborts it (by using the macro multi_Abort) */
116 multi_Finalize(struct multi_handle *mh)
119 int nCalls = mh->nConns;
120 for (i = 0; i < nCalls; i++) {
121 struct rx_call *call = mh->calls[i];
123 rx_EndCall(call, RX_USER_ABORT);
125 #ifdef RX_ENABLE_LOCKS
126 MUTEX_DESTROY(&mh->lock);
128 #endif /* RX_ENABLE_LOCKS */
129 osi_Free(mh->calls, sizeof(struct rx_call *) * nCalls);
130 osi_Free(mh->ready, sizeof(short *) * nCalls);
131 osi_Free(mh, sizeof(struct multi_handle));
134 /* ignores all remaining multiRx calls */
136 multi_Finalize_Ignore(struct multi_handle *mh)
139 int nCalls = mh->nConns;
140 for (i = 0; i < nCalls; i++) {
141 struct rx_call *call = mh->calls[i];
145 #ifdef RX_ENABLE_LOCKS
146 MUTEX_DESTROY(&mh->lock);
148 #endif /* RX_ENABLE_LOCKS */
149 osi_Free(mh->calls, sizeof(struct rx_call *) * nCalls);
150 osi_Free(mh->ready, sizeof(short *) * nCalls);
151 osi_Free(mh, sizeof(struct multi_handle));