2 ****************************************************************************
3 * Copyright IBM Corporation 1988, 1989 - All Rights Reserved *
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. *
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 ****************************************************************************
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 */
32 multi_Init(struct rx_connection
**conns
, int nConns
)
34 struct rx_call
**calls
;
36 struct multi_handle
*mh
;
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");
50 mh
->nextReady
= mh
->firstNotReady
= mh
->ready
= ready
;
53 for (i
= 0; i
< nConns
; i
++) {
56 call
= mh
->calls
[i
] = rx_NewCall(conns
[i
]);
57 rx_SetArrivalProc(call
, multi_Ready
, mh
, NULL
);
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
67 multi_Select(struct multi_handle
*mh
)
71 if (mh
->nextReady
== mh
->firstNotReady
) {
72 if (mh
->nReady
== mh
->nConns
) {
79 return *mh
->nextReady
++;
83 * Called by Rx when the first reply packet of a call is received, or the
87 multi_Ready(struct rx_call
*call
, struct multi_handle
*mh
, void *unused
)
90 for (callindex
= 0; callindex
< RX_MAXCALLS
; callindex
++)
91 if (mh
->calls
[callindex
] == call
)
93 if (callindex
>= RX_MAXCALLS
)
95 *mh
->firstNotReady
++ = callindex
;
101 * Called when the multi rx call is over, or when the user aborts it
102 * (by using the macro multi_Abort)
105 multi_Finalize(struct multi_handle
*mh
)
108 int nCalls
= mh
->nConns
;
110 for (i
= 0; i
< nCalls
; i
++) {
111 struct rx_call
*call
= mh
->calls
[i
];
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
);