*** empty log message ***
[arla.git] / rx / rx_multi.c
blobcb0c3eb32b07927450636b517f2a58af25823df1
1 /*
2 ****************************************************************************
3 * Copyright IBM Corporation 1988, 1989 - All Rights Reserved *
4 * *
5 * Permission to use, copy, modify, and distribute this software and its *
6 * documentation for any purpose and without fee is hereby granted, *
7 * provided that the above copyright notice appear in all copies and *
8 * that both that copyright notice and this permission notice appear in *
9 * supporting documentation, and that the name of IBM not be used in *
10 * advertising or publicity pertaining to distribution of the software *
11 * without specific, written prior permission. *
12 * *
13 * IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL *
14 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL IBM *
15 * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY *
16 * DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER *
17 * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING *
18 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. *
19 ****************************************************************************
22 #include "rx_locl.h"
24 RCSID("$Id$");
26 static void multi_Ready(struct rx_call *, struct multi_handle *, void *);
28 /* multi.c and multi.h, together with some rxgen hooks, provide a way of making multiple, but similar, rx calls to multiple hosts simultaneously */
31 struct multi_handle *
32 multi_Init(struct rx_connection **conns, int nConns)
34 struct rx_call **calls;
35 short *ready;
36 struct multi_handle *mh;
37 int i;
40 * Note: all structures that are possibly referenced by other processes
41 * must be allocated. In some kernels variables allocated on a process
42 * stack will not be accessible to other processes
44 calls = (struct rx_call **) osi_Alloc(sizeof(struct rx_call *) * nConns);
45 ready = (short *) osi_Alloc(sizeof(short *) * nConns);
46 mh = (struct multi_handle *) osi_Alloc(sizeof(struct multi_handle));
47 if (!calls || !ready || !mh)
48 osi_Panic("multi_Rx: no mem\n");
49 mh->calls = calls;
50 mh->nextReady = mh->firstNotReady = mh->ready = ready;
51 mh->nReady = 0;
52 mh->nConns = nConns;
53 for (i = 0; i < nConns; i++) {
54 struct rx_call *call;
56 call = mh->calls[i] = rx_NewCall(conns[i]);
57 rx_SetArrivalProc(call, multi_Ready, mh, NULL);
59 return mh;
63 * Return the user's connection index of the most recently ready call; that
64 * is, a call that has received at least one reply packet
66 int
67 multi_Select(struct multi_handle *mh)
69 SPLVAR;
70 NETPRI;
71 if (mh->nextReady == mh->firstNotReady) {
72 if (mh->nReady == mh->nConns) {
73 USERPRI;
74 return -1;
76 osi_rxSleep(mh);
78 USERPRI;
79 return *mh->nextReady++;
83 * Called by Rx when the first reply packet of a call is received, or the
84 * call is aborted.
86 static void
87 multi_Ready(struct rx_call *call, struct multi_handle *mh, void *unused)
89 int callindex;
90 for (callindex = 0; callindex < RX_MAXCALLS; callindex++)
91 if (mh->calls[callindex] == call)
92 break;
93 if (callindex >= RX_MAXCALLS)
94 abort();
95 *mh->firstNotReady++ = callindex;
96 mh->nReady++;
97 osi_rxWakeup(mh);
101 * Called when the multi rx call is over, or when the user aborts it
102 * (by using the macro multi_Abort)
104 void
105 multi_Finalize(struct multi_handle *mh)
107 int i;
108 int nCalls = mh->nConns;
110 for (i = 0; i < nCalls; i++) {
111 struct rx_call *call = mh->calls[i];
113 if (call)
114 rx_EndCall(call, RX_USER_ABORT);
116 osi_Free(mh->calls, sizeof(struct rx_call *) * nCalls);
117 osi_Free(mh->ready, sizeof(short *) * nCalls);