rx: Reorganise includes
[openafs.git] / src / rx / rx_multi.c
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  *
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
8  */
9
10 #include <afsconfig.h>
11 #include <afs/param.h>
12
13
14 #ifdef  KERNEL
15 #include "afs/sysincludes.h"
16 #endif
17
18 #include "rx.h"
19
20 /*
21  * multi.c and multi.h, together with some rxgen hooks, provide a way of
22  * making multiple, but similar, rx calls to multiple hosts simultaneously
23  */
24
25 struct multi_handle *
26 multi_Init(struct rx_connection **conns, int nConns)
27 {
28     struct rx_call **calls;
29     short *ready;
30     struct multi_handle *mh;
31     int i;
32
33     /*
34      * Note: all structures that are possibly referenced by other
35      * processes must be allocated.  In some kernels variables allocated on
36      * a process stack will not be accessible to other processes
37      */
38
39     calls = (struct rx_call **)osi_Alloc(sizeof(struct rx_call *) * nConns);
40     ready = (short *)osi_Alloc(sizeof(short *) * nConns);
41     mh = (struct multi_handle *)osi_Alloc(sizeof(struct multi_handle));
42     if (!calls || !ready || !mh)
43         osi_Panic("multi_Rx: no mem\n");
44     mh->calls = calls;
45     mh->nextReady = mh->firstNotReady = mh->ready = ready;
46     mh->nReady = 0;
47     mh->nConns = nConns;
48
49 #ifdef RX_ENABLE_LOCKS
50     MUTEX_INIT(&mh->lock, "rx_multi_lock", MUTEX_DEFAULT, 0);
51     CV_INIT(&mh->cv, "rx_multi_cv", CV_DEFAULT, 0);
52 #endif /* RX_ENABLE_LOCKS */
53     for (i = 0; i < nConns; i++) {
54         struct rx_call *call;
55         call = mh->calls[i] = rx_NewCall(conns[i]);
56         rx_SetArrivalProc(call, multi_Ready, (void *) mh, i);
57     }
58     return mh;
59 }
60
61 /* Return the user's connection index of the most recently ready call; that is, a call that has received at least one reply packet */
62 int
63 multi_Select(struct multi_handle *mh)
64 {
65     int index;
66     SPLVAR;
67     NETPRI;
68 #ifdef RX_ENABLE_LOCKS
69     MUTEX_ENTER(&mh->lock);
70 #endif /* RX_ENABLE_LOCKS */
71     while (mh->nextReady == mh->firstNotReady) {
72         if (mh->nReady == mh->nConns) {
73 #ifdef RX_ENABLE_LOCKS
74             MUTEX_EXIT(&mh->lock);
75 #endif /* RX_ENABLE_LOCKS */
76             USERPRI;
77             return -1;
78         }
79 #ifdef RX_ENABLE_LOCKS
80         CV_WAIT(&mh->cv, &mh->lock);
81 #else /* RX_ENABLE_LOCKS */
82         osi_rxSleep(mh);
83 #endif /* RX_ENABLE_LOCKS */
84     }
85     index = *(mh->nextReady);
86     (mh->nextReady) += 1;
87 #ifdef RX_ENABLE_LOCKS
88     MUTEX_EXIT(&mh->lock);
89 #endif /* RX_ENABLE_LOCKS */
90     USERPRI;
91     return index;
92 }
93
94 /* Called by Rx when the first reply packet of a call is received, or the call is aborted. */
95 void
96 multi_Ready(struct rx_call *call, void *amh,
97             int index)
98 {
99     struct multi_handle *mh = (struct multi_handle *)amh;
100 #ifdef RX_ENABLE_LOCKS
101     MUTEX_ENTER(&mh->lock);
102 #endif /* RX_ENABLE_LOCKS */
103     *mh->firstNotReady++ = index;
104     mh->nReady++;
105 #ifdef RX_ENABLE_LOCKS
106     CV_SIGNAL(&mh->cv);
107     MUTEX_EXIT(&mh->lock);
108 #else /* RX_ENABLE_LOCKS */
109     osi_rxWakeup(mh);
110 #endif /* RX_ENABLE_LOCKS */
111 }
112
113 /* Called when the multi rx call is over, or when the user aborts it (by using the macro multi_Abort) */
114 void
115 multi_Finalize(struct multi_handle *mh)
116 {
117     int i;
118     int nCalls = mh->nConns;
119     for (i = 0; i < nCalls; i++) {
120         struct rx_call *call = mh->calls[i];
121         if (call)
122             rx_EndCall(call, RX_USER_ABORT);
123     }
124 #ifdef RX_ENABLE_LOCKS
125     MUTEX_DESTROY(&mh->lock);
126     CV_DESTROY(&mh->cv);
127 #endif /* RX_ENABLE_LOCKS */
128     osi_Free(mh->calls, sizeof(struct rx_call *) * nCalls);
129     osi_Free(mh->ready, sizeof(short *) * nCalls);
130     osi_Free(mh, sizeof(struct multi_handle));
131 }
132
133 /* ignores all remaining multiRx calls */
134 void
135 multi_Finalize_Ignore(struct multi_handle *mh)
136 {
137     int i;
138     int nCalls = mh->nConns;
139     for (i = 0; i < nCalls; i++) {
140         struct rx_call *call = mh->calls[i];
141         if (call)
142             rx_EndCall(call, 0);
143     }
144 #ifdef RX_ENABLE_LOCKS
145     MUTEX_DESTROY(&mh->lock);
146     CV_DESTROY(&mh->cv);
147 #endif /* RX_ENABLE_LOCKS */
148     osi_Free(mh->calls, sizeof(struct rx_call *) * nCalls);
149     osi_Free(mh->ready, sizeof(short *) * nCalls);
150     osi_Free(mh, sizeof(struct multi_handle));
151 }