1/*
2 * Copyright (c) 2010 Apple Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * 1.  Redistributions of source code must retain the above copyright
11 *     notice, this list of conditions and the following disclaimer.
12 * 2.  Redistributions in binary form must reproduce the above copyright
13 *     notice, this list of conditions and the following disclaimer in the
14 *     documentation and/or other materials provided with the distribution.
15 * 3.  Neither the name of Apple Inc. ("Apple") nor the names of its
16 *     contributors may be used to endorse or promote products derived from
17 *     this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
20 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
23 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
26 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 *
30 * Portions of this software have been released under the following terms:
31 *
32 * (c) Copyright 1989-1993 OPEN SOFTWARE FOUNDATION, INC.
33 * (c) Copyright 1989-1993 HEWLETT-PACKARD COMPANY
34 * (c) Copyright 1989-1993 DIGITAL EQUIPMENT CORPORATION
35 *
36 * To anyone who acknowledges that this file is provided "AS IS"
37 * without any express or implied warranty:
38 * permission to use, copy, modify, and distribute this file for any
39 * purpose is hereby granted without fee, provided that the above
40 * copyright notices and this notice appears in all source code copies,
41 * and that none of the names of Open Software Foundation, Inc., Hewlett-
42 * Packard Company or Digital Equipment Corporation be used
43 * in advertising or publicity pertaining to distribution of the software
44 * without specific, written prior permission.  Neither Open Software
45 * Foundation, Inc., Hewlett-Packard Company nor Digital
46 * Equipment Corporation makes any representations about the suitability
47 * of this software for any purpose.
48 *
49 * Copyright (c) 2007, Novell, Inc. All rights reserved.
50 * Redistribution and use in source and binary forms, with or without
51 * modification, are permitted provided that the following conditions
52 * are met:
53 *
54 * 1.  Redistributions of source code must retain the above copyright
55 *     notice, this list of conditions and the following disclaimer.
56 * 2.  Redistributions in binary form must reproduce the above copyright
57 *     notice, this list of conditions and the following disclaimer in the
58 *     documentation and/or other materials provided with the distribution.
59 * 3.  Neither the name of Novell Inc. nor the names of its contributors
60 *     may be used to endorse or promote products derived from this
61 *     this software without specific prior written permission.
62 *
63 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
64 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
65 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
66 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY
67 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
68 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
69 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
70 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
71 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
72 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
73 *
74 * @APPLE_LICENSE_HEADER_END@
75 */
76
77/*
78**
79**  NAME:
80**
81**      dgccallt.c
82**
83**  FACILITY:
84**
85**      Remote Procedure Call (RPC)
86**
87**  ABSTRACT:
88**
89**  DG protocol service routines.  Handle client call table (CCALLT).
90**
91**
92*/
93
94#include <dg.h>
95#include <dgcall.h>
96#include <dgccall.h>
97#include <dgccallt.h>
98
99/*
100 * R P C _ _ D G _ C C A L L T _ I N S E R T
101 *
102 * Add a client call handle to the CCALLT.  Increment the call handle's reference
103 * count.
104 */
105
106PRIVATE void rpc__dg_ccallt_insert
107(
108    rpc_dg_ccall_p_t ccall
109)
110{
111    unsigned16 probe = ccall->c.actid_hash % RPC_DG_CCALLT_SIZE;
112
113    RPC_LOCK_ASSERT(0);
114
115    ccall->c.next = (rpc_dg_call_p_t) rpc_g_dg_ccallt[probe];
116    rpc_g_dg_ccallt[probe] = ccall;
117    RPC_DG_CALL_REFERENCE(&ccall->c);
118}
119
120/*
121 * R P C _ _ D G _ C C A L L T _ R E M O V E
122 *
123 * Remove a client call handle from the CCALLT.  Decrement the call
124 * handle's reference count.  This routine can be called only if there
125 * are references to the CCALL other than the one from the CCALLT.
126 */
127
128PRIVATE void rpc__dg_ccallt_remove
129(
130    rpc_dg_ccall_p_t ccall
131)
132{
133    unsigned16 probe = ccall->c.actid_hash % RPC_DG_CCALLT_SIZE;
134    rpc_dg_ccall_p_t scan_ccall, prev_scan_ccall;
135
136    RPC_LOCK_ASSERT(0);
137    RPC_DG_CALL_LOCK_ASSERT(&ccall->c);
138    assert(ccall->c.refcnt > 1);
139
140    /*
141     * Scan down the hash chain.
142     */
143
144    scan_ccall = rpc_g_dg_ccallt[probe];
145    prev_scan_ccall = NULL;
146
147    while (scan_ccall != NULL) {
148        if (scan_ccall == ccall) {
149            if (prev_scan_ccall == NULL)
150                rpc_g_dg_ccallt[probe] = (rpc_dg_ccall_p_t) scan_ccall->c.next;
151            else
152                prev_scan_ccall->c.next = scan_ccall->c.next;
153            RPC_DG_CCALL_RELEASE_NO_UNLOCK(&scan_ccall);
154            return;
155        }
156        else {
157            prev_scan_ccall = scan_ccall;
158            scan_ccall = (rpc_dg_ccall_p_t) scan_ccall->c.next;
159        }
160    }
161
162    assert(false);          /* Shouldn't ever fail to find the ccall */
163}
164
165/*
166 * R P C _ _ D G _ C C A L L T _ L O O K U P
167 *
168 * Find a client call handle in the CCALLT based on an activity ID and
169 * probe hint (ahint).  Return the ccall or NULL if no matching entry
170 * is found.  Note that a probe_hint of RPC_C_DG_NO_HINT can be used if
171 * the caller doesn't have a hint.  If we're returning a ccall, it will
172 * be locked and have it's reference count incremented already.
173 */
174
175PRIVATE rpc_dg_ccall_p_t rpc__dg_ccallt_lookup
176(
177    uuid_p_t actid,
178    unsigned32 probe_hint
179)
180{
181    rpc_dg_ccall_p_t ccall;
182    unsigned16 probe;
183    unsigned32 st;
184    boolean once = false;
185
186    RPC_LOCK_ASSERT(0);
187
188    /*
189     * Determine the hash chain to use
190     */
191
192    if (probe_hint == RPC_C_DG_NO_HINT || probe_hint >= RPC_DG_CCALLT_SIZE)
193        probe = rpc__dg_uuid_hash(actid) % RPC_DG_CCALLT_SIZE;
194    else
195        probe = probe_hint;
196
197    /*
198     * Scan down the probe chain, reserve and return a matching SCTE.
199     */
200
201RETRY:
202    ccall = rpc_g_dg_ccallt[probe];
203
204    while (ccall != NULL)
205    {
206        if (UUID_EQ(*actid, ccall->c.call_actid, &st))
207        {
208            RPC_DG_CALL_LOCK(&ccall->c);
209            RPC_DG_CALL_REFERENCE(&ccall->c);
210            return(ccall);
211        }
212        else
213            ccall = (rpc_dg_ccall_p_t) ccall->c.next;
214    }
215
216    /*
217     * No matching entry found.  If we used the provided hint, try
218     * recomputing the probe and if this yields a new probe, give it
219     * one more try.
220     */
221
222    if (probe == probe_hint && !once)
223    {
224        once = true;
225        probe = rpc__dg_uuid_hash(actid) % RPC_DG_CCALLT_SIZE;
226        if (probe != probe_hint)
227            goto RETRY;
228    }
229
230    return(NULL);
231}
232
233/*
234 * R P C _ _ D G _ C C A L L T _ F O R K _ H A N D L E R
235 *
236 * Handle fork related processing for this module.
237 */
238PRIVATE void rpc__dg_ccallt_fork_handler
239(
240    rpc_fork_stage_id_t stage
241)
242{
243    unsigned32 i;
244
245    switch ((int)stage)
246    {
247        case RPC_C_PREFORK:
248            break;
249        case RPC_C_POSTFORK_PARENT:
250            break;
251        case RPC_C_POSTFORK_CHILD:
252            /*
253             * Clear out the Client Call Handle Table
254             */
255
256            for (i = 0; i < RPC_DG_CCALLT_SIZE; i++)
257                rpc_g_dg_ccallt[i] = NULL;
258            break;
259    }
260}
261